commit 021baa5

shrub  ·  2026-07-14 21:24:37 +0000 UTC
parent 021baa5
init
161 files changed,  +83231, -0
A README
A dis.c
A gen.c
A gen.h
A gst.c
A gst.h
A hash.c
A hash.h
A i2c.c
A i2c.h
A io.c
A io.h
A mem.c
A mem.h
A menu.c
A menu.h
A net.c
A net.h
A nor.c
A nor.h
A png.c
A png.h
A ppm.c
A ppm.h
A psg.c
A psg.h
A rom.db
A sms.c
A sms.h
A tern.c
A tern.h
A test.c
A util.c
A util.h
A vdp.c
A vdp.h
A vgm.h
A wave.c
A wave.h
A zdis.c
A zip.c
A zip.h
+2644, -0
   1@@ -0,0 +1,2644 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "68kinst.h"
   8+#include <string.h>
   9+#include <stdio.h>
  10+
  11+uint32_t sign_extend16(uint32_t val)
  12+{
  13+	return (val & 0x8000) ? val | 0xFFFF0000 : val;
  14+}
  15+
  16+uint32_t sign_extend8(uint32_t val)
  17+{
  18+	return (val & 0x80) ? val | 0xFFFFFF00 : val;
  19+}
  20+
  21+uint16_t *m68k_decode_op_ex(uint16_t *cur, uint8_t mode, uint8_t reg, uint8_t size, m68k_op_info *dst)
  22+{
  23+	uint16_t ext, tmp;
  24+	dst->addr_mode = mode;
  25+	switch(mode)
  26+	{
  27+	case MODE_REG:
  28+	case MODE_AREG:
  29+	case MODE_AREG_INDIRECT:
  30+	case MODE_AREG_POSTINC:
  31+	case MODE_AREG_PREDEC:
  32+		dst->params.regs.pri = reg;
  33+		break;
  34+	case MODE_AREG_DISPLACE:
  35+		ext = *(++cur);
  36+		dst->params.regs.pri = reg;
  37+		dst->params.regs.displacement = sign_extend16(ext);
  38+		break;
  39+	case MODE_AREG_INDEX_MEM:
  40+		dst->params.regs.pri = reg;
  41+		ext = *(++cur);
  42+		dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
  43+#ifdef M68020
  44+		dst->params.regs.scale = ext >> 9 & 3;
  45+		if (ext & 0x100)
  46+		{
  47+			dst->params.regs.disp_sizes = ext >> 4 & 3;
  48+			switch (dst->params.regs.disp_sizes)
  49+			{
  50+			case 0:
  51+				//reserved
  52+				return NULL;
  53+			case 1:
  54+				dst->params.regs.displacement = 0;
  55+				break;
  56+			case 2:
  57+				dst->params.regs.displacement = sign_extend16(*(cur++));
  58+				break;
  59+			case 3:
  60+				tmp = *(cur++);
  61+				dst->params.regs.displacement = tmp << 16 | *(cur++);
  62+				break;
  63+			}
  64+			if (ext & 0x3)
  65+			{
  66+				//memory indirect
  67+				switch (ext & 0xC4)
  68+				{
  69+				case 0x00:
  70+					dst->addr_mode = MODE_AREG_PREINDEX;
  71+					break;
  72+				case 0x04:
  73+					dst->addr_mode = MODE_AREG_POSTINDEX;
  74+					break;
  75+				case 0x40:
  76+					dst->addr_mode = MODE_AREG_MEM_INDIRECT;
  77+					break;
  78+				case 0x80:
  79+					dst->addr_mode = MODE_PREINDEX;
  80+					break;
  81+				case 0x84:
  82+					dst->addr_mode = MODE_POSTINDEX;
  83+					break;
  84+				case 0xC0:
  85+					dst->addr_mode = MODE_MEM_INDIRECT;
  86+					break;
  87+				}
  88+				dst->params.regs.disp_sizes |= ext << 4 & 0x30;
  89+				switch (ext & 0x3)
  90+				{
  91+				case 0:
  92+					//reserved
  93+					return NULL;
  94+				case 1:
  95+					dst->params.regs.outer_disp = 0;
  96+					break;
  97+				case 2:
  98+					dst->params.regs.outer_disp = sign_extend16(*(cur++));
  99+					break;
 100+				case 3:
 101+					tmp = *(cur++);
 102+					dst->params.regs.outer_disp = tmp << 16 | *(cur++);
 103+					break;
 104+				}
 105+			} else {
 106+				switch (ext >> 6 & 3)
 107+				{
 108+				case 0:
 109+					dst->addr_mode = MODE_AREG_INDEX_BASE_DISP;
 110+					break;
 111+				case 1:
 112+					dst->addr_mode = MODE_AREG_BASE_DISP;
 113+					break;
 114+				case 2:
 115+					dst->addr_mode = MODE_INDEX_BASE_DISP;
 116+					break;
 117+				case 3:
 118+					dst->addr_mode = MODE_BASE_DISP;
 119+					break;
 120+				}
 121+			}
 122+		} else {
 123+#endif
 124+			dst->addr_mode = MODE_AREG_INDEX_DISP8;
 125+			dst->params.regs.displacement = sign_extend8(ext&0xFF);
 126+#ifdef M68020
 127+		}
 128+#endif
 129+		break;
 130+	case MODE_PC_INDIRECT_ABS_IMMED:
 131+		switch(reg)
 132+		{
 133+		case 0:
 134+			dst->addr_mode = MODE_ABSOLUTE_SHORT;
 135+			ext = *(++cur);
 136+			dst->params.immed = sign_extend16(ext);
 137+			break;
 138+		case 1:
 139+			dst->addr_mode = MODE_ABSOLUTE;
 140+			ext = *(++cur);
 141+			dst->params.immed = ext << 16 | *(++cur);
 142+			break;
 143+		case 3:
 144+			ext = *(++cur);
 145+			dst->params.regs.sec = ext >> 11;//includes areg/dreg bit, reg num and word/long bit
 146+#ifdef M68020
 147+			dst->params.regs.scale = ext >> 9 & 3;
 148+			if (ext & 0x100)
 149+			{
 150+				dst->params.regs.disp_sizes = ext >> 4 & 3;
 151+				switch (dst->params.regs.disp_sizes)
 152+				{
 153+				case 0:
 154+					//reserved
 155+					return NULL;
 156+				case 1:
 157+					dst->params.regs.displacement = 0;
 158+					break;
 159+				case 2:
 160+					dst->params.regs.displacement = sign_extend16(*(cur++));
 161+					break;
 162+				case 3:
 163+					tmp = *(cur++);
 164+					dst->params.regs.displacement = tmp << 16 | *(cur++);
 165+					break;
 166+				}
 167+				if (ext & 0x3)
 168+				{
 169+					//memory indirect
 170+					switch (ext & 0xC4)
 171+					{
 172+					case 0x00:
 173+						dst->addr_mode = MODE_PC_PREINDEX;
 174+						break;
 175+					case 0x04:
 176+						dst->addr_mode = MODE_PC_POSTINDEX;
 177+						break;
 178+					case 0x40:
 179+						dst->addr_mode = MODE_PC_MEM_INDIRECT;
 180+						break;
 181+					case 0x80:
 182+						dst->addr_mode = MODE_ZPC_PREINDEX;
 183+						break;
 184+					case 0x84:
 185+						dst->addr_mode = MODE_ZPC_POSTINDEX;
 186+						break;
 187+					case 0xC0:
 188+						dst->addr_mode = MODE_ZPC_MEM_INDIRECT;
 189+						break;
 190+					}
 191+					dst->params.regs.disp_sizes |= ext << 4 & 0x30;
 192+					switch (ext & 0x3)
 193+					{
 194+					case 0:
 195+						//reserved
 196+						return NULL;
 197+					case 1:
 198+						dst->params.regs.outer_disp = 0;
 199+						break;
 200+					case 2:
 201+						dst->params.regs.outer_disp = sign_extend16(*(cur++));
 202+						break;
 203+					case 3:
 204+						tmp = *(cur++);
 205+						dst->params.regs.outer_disp = tmp << 16 | *(cur++);
 206+						break;
 207+					}
 208+				} else {
 209+					switch (ext >> 6 & 3)
 210+					{
 211+					case 0:
 212+						dst->addr_mode = MODE_PC_INDEX_BASE_DISP;
 213+						break;
 214+					case 1:
 215+						dst->addr_mode = MODE_PC_BASE_DISP;
 216+						break;
 217+					case 2:
 218+						dst->addr_mode = MODE_ZPC_INDEX_BASE_DISP;
 219+						break;
 220+					case 3:
 221+						dst->addr_mode = MODE_ZPC_BASE_DISP;
 222+						break;
 223+					}
 224+				}
 225+			} else {
 226+#endif
 227+				dst->addr_mode = MODE_PC_INDEX_DISP8;
 228+				dst->params.regs.displacement = sign_extend8(ext&0xFF);
 229+#ifdef M68020
 230+			}
 231+#endif
 232+			break;
 233+		case 2:
 234+			dst->addr_mode = MODE_PC_DISPLACE;
 235+			ext = *(++cur);
 236+			dst->params.regs.displacement = sign_extend16(ext);
 237+			break;
 238+		case 4:
 239+			dst->addr_mode = MODE_IMMEDIATE;
 240+			ext = *(++cur);
 241+			switch (size)
 242+			{
 243+			case OPSIZE_BYTE:
 244+				dst->params.immed = ext & 0xFF;
 245+				break;
 246+			case OPSIZE_WORD:
 247+				dst->params.immed = ext;
 248+				break;
 249+			case OPSIZE_LONG:
 250+				dst->params.immed = ext << 16 | *(++cur);
 251+				break;
 252+			}
 253+			break;
 254+		default:
 255+			return NULL;
 256+		}
 257+		break;
 258+	}
 259+	return cur;
 260+}
 261+
 262+uint8_t m68k_valid_immed_dst(m68k_op_info *dst)
 263+{
 264+	if (dst->addr_mode == MODE_AREG || dst->addr_mode == MODE_IMMEDIATE) {
 265+		return 0;
 266+	}
 267+	return 1;
 268+}
 269+
 270+uint8_t m68k_valid_immed_limited_dst(m68k_op_info *dst)
 271+{
 272+	if (dst->addr_mode == MODE_AREG || dst->addr_mode > MODE_ABSOLUTE) {
 273+		return 0;
 274+	}
 275+	return 1;
 276+}
 277+
 278+uint8_t m68k_valid_full_arith_dst(m68k_op_info *dst)
 279+{
 280+	if (dst->addr_mode < MODE_AREG_INDIRECT || dst->addr_mode > MODE_ABSOLUTE) {
 281+		return 0;
 282+	}
 283+	return 1;
 284+}
 285+
 286+uint8_t m68k_valid_movem_dst(m68k_op_info *dst)
 287+{
 288+	if (dst->addr_mode == MODE_REG || dst->addr_mode == MODE_AREG_POSTINC) {
 289+		return 0;
 290+	}
 291+	return m68k_valid_immed_limited_dst(dst);
 292+}
 293+
 294+uint16_t *m68k_decode_op(uint16_t *cur, uint8_t size, m68k_op_info *dst)
 295+{
 296+	uint8_t mode = (*cur >> 3) & 0x7;
 297+	uint8_t reg = *cur & 0x7;
 298+	return m68k_decode_op_ex(cur, mode, reg, size, dst);
 299+}
 300+
 301+void m68k_decode_cond(uint16_t op, m68kinst * decoded)
 302+{
 303+	decoded->extra.cond = (op >> 0x8) & 0xF;
 304+}
 305+
 306+uint8_t m68k_reg_quick_field(uint16_t op)
 307+{
 308+	return (op >> 9) & 0x7;
 309+}
 310+
 311+uint16_t * m68k_decode(uint16_t * istream, m68kinst * decoded, uint32_t address)
 312+{
 313+	uint16_t *start = istream;
 314+	uint8_t optype = *istream >> 12;
 315+	uint8_t size;
 316+	uint8_t reg;
 317+	uint8_t opmode;
 318+	uint32_t immed;
 319+	decoded->op = M68K_INVALID;
 320+	decoded->src.addr_mode = decoded->dst.addr_mode = MODE_UNUSED;
 321+	decoded->variant = VAR_NORMAL;
 322+	decoded->address = address;
 323+	switch(optype)
 324+	{
 325+	case BIT_MOVEP_IMMED:
 326+		if ((*istream & 0x138) == 0x108) {
 327+			//MOVEP
 328+			decoded->op = M68K_MOVEP;
 329+			decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
 330+			if (*istream & 0x80) {
 331+				//memory dest
 332+				decoded->src.addr_mode = MODE_REG;
 333+				decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
 334+				decoded->dst.addr_mode = MODE_AREG_DISPLACE;
 335+				decoded->dst.params.regs.pri = *istream & 0x7;
 336+				decoded->dst.params.regs.displacement = *(++istream);
 337+			} else {
 338+				//memory source
 339+				decoded->dst.addr_mode = MODE_REG;
 340+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
 341+				decoded->src.addr_mode = MODE_AREG_DISPLACE;
 342+				decoded->src.params.regs.pri = *istream & 0x7;
 343+				decoded->src.params.regs.displacement = *(++istream);
 344+			}
 345+		} else if (*istream & 0x100) {
 346+			//BTST, BCHG, BCLR, BSET
 347+			switch ((*istream >> 6) & 0x3)
 348+			{
 349+			case 0:
 350+				decoded->op = M68K_BTST;
 351+				break;
 352+			case 1:
 353+				decoded->op = M68K_BCHG;
 354+				break;
 355+			case 2:
 356+				decoded->op = M68K_BCLR;
 357+				break;
 358+			case 3:
 359+				decoded->op = M68K_BSET;
 360+				break;
 361+			}
 362+			decoded->src.addr_mode = MODE_REG;
 363+			decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
 364+			decoded->extra.size = OPSIZE_BYTE;
 365+			istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
 366+			if (
 367+				!istream || decoded->dst.addr_mode == MODE_AREG 
 368+				|| (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
 369+			) {
 370+				decoded->op = M68K_INVALID;
 371+				break;
 372+			}
 373+			if (decoded->dst.addr_mode == MODE_REG) {
 374+				decoded->extra.size = OPSIZE_LONG;
 375+			}
 376+		} else if ((*istream & 0xF00) == 0x800) {
 377+			//BTST, BCHG, BCLR, BSET
 378+			switch ((*istream >> 6) & 0x3)
 379+			{
 380+			case 0:
 381+				decoded->op = M68K_BTST;
 382+				break;
 383+			case 1:
 384+				decoded->op = M68K_BCHG;
 385+				break;
 386+			case 2:
 387+				decoded->op = M68K_BCLR;
 388+				break;
 389+			case 3:
 390+				decoded->op = M68K_BSET;
 391+				break;
 392+			}
 393+			opmode = (*istream >> 3) & 0x7;
 394+			reg = *istream & 0x7;
 395+			decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
 396+			decoded->src.params.immed = *(++istream) & 0xFF;
 397+			decoded->extra.size = OPSIZE_BYTE;
 398+			istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
 399+			if (
 400+				!istream || !m68k_valid_immed_dst(&decoded->dst)
 401+				|| (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
 402+			) {
 403+				decoded->op = M68K_INVALID;
 404+				break;
 405+			}
 406+			if (decoded->dst.addr_mode == MODE_REG) {
 407+				decoded->extra.size = OPSIZE_LONG;
 408+			}
 409+		} else if ((*istream & 0xC0) == 0xC0) {
 410+#ifdef M68020
 411+			//CMP2, CHK2, CAS, CAS2, RTM, CALLM
 412+#endif
 413+		} else {
 414+			switch ((*istream >> 9) & 0x7)
 415+			{
 416+			case 0:
 417+				if ((*istream & 0xFF) == 0x3C) {
 418+					decoded->op = M68K_ORI_CCR;
 419+					decoded->extra.size = OPSIZE_BYTE;
 420+					decoded->src.addr_mode = MODE_IMMEDIATE;
 421+					decoded->src.params.immed = *(++istream) & 0xFF;
 422+				} else if((*istream & 0xFF) == 0x7C) {
 423+					decoded->op = M68K_ORI_SR;
 424+					decoded->extra.size = OPSIZE_WORD;
 425+					decoded->src.addr_mode = MODE_IMMEDIATE;
 426+					decoded->src.params.immed = *(++istream);
 427+				} else {
 428+					decoded->op = M68K_OR;
 429+					decoded->variant = VAR_IMMEDIATE;
 430+					decoded->src.addr_mode = MODE_IMMEDIATE;
 431+					decoded->extra.size = size = (*istream >> 6) & 3;
 432+					reg = *istream & 0x7;
 433+					opmode = (*istream >> 3) & 0x7;
 434+					switch (size)
 435+					{
 436+					case OPSIZE_BYTE:
 437+						decoded->src.params.immed = *(++istream) & 0xFF;
 438+						break;
 439+					case OPSIZE_WORD:
 440+						decoded->src.params.immed = *(++istream);
 441+						break;
 442+					case OPSIZE_LONG:
 443+						immed = *(++istream);
 444+						decoded->src.params.immed = immed << 16 | *(++istream);
 445+						break;
 446+					}
 447+					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
 448+					if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 449+						decoded->op = M68K_INVALID;
 450+						break;
 451+					}
 452+				}
 453+				break;
 454+			case 1:
 455+				//ANDI, ANDI to CCR, ANDI to SR
 456+				if ((*istream & 0xFF) == 0x3C) {
 457+					decoded->op = M68K_ANDI_CCR;
 458+					decoded->extra.size = OPSIZE_BYTE;
 459+					decoded->src.addr_mode = MODE_IMMEDIATE;
 460+					decoded->src.params.immed = *(++istream) & 0xFF;
 461+				} else if((*istream & 0xFF) == 0x7C) {
 462+					decoded->op = M68K_ANDI_SR;
 463+					decoded->extra.size = OPSIZE_WORD;
 464+					decoded->src.addr_mode = MODE_IMMEDIATE;
 465+					decoded->src.params.immed = *(++istream);
 466+				} else {
 467+					decoded->op = M68K_AND;
 468+					decoded->variant = VAR_IMMEDIATE;
 469+					decoded->src.addr_mode = MODE_IMMEDIATE;
 470+					decoded->extra.size = size = (*istream >> 6) & 3;
 471+					reg = *istream & 0x7;
 472+					opmode = (*istream >> 3) & 0x7;
 473+					switch (size)
 474+					{
 475+					case OPSIZE_BYTE:
 476+						decoded->src.params.immed = *(++istream) & 0xFF;
 477+						break;
 478+					case OPSIZE_WORD:
 479+						decoded->src.params.immed = *(++istream);
 480+						break;
 481+					case OPSIZE_LONG:
 482+						immed = *(++istream);
 483+						decoded->src.params.immed = immed << 16 | *(++istream);
 484+						break;
 485+					}
 486+					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
 487+					if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 488+						decoded->op = M68K_INVALID;
 489+						break;
 490+					}
 491+				}
 492+				break;
 493+			case 2:
 494+				decoded->op = M68K_SUB;
 495+				decoded->variant = VAR_IMMEDIATE;
 496+				decoded->src.addr_mode = MODE_IMMEDIATE;
 497+				decoded->extra.size = size = (*istream >> 6) & 3;
 498+				reg = *istream & 0x7;
 499+				opmode = (*istream >> 3) & 0x7;
 500+				switch (size)
 501+				{
 502+				case OPSIZE_BYTE:
 503+					decoded->src.params.immed = *(++istream) & 0xFF;
 504+					break;
 505+				case OPSIZE_WORD:
 506+					decoded->src.params.immed = *(++istream);
 507+					break;
 508+				case OPSIZE_LONG:
 509+					immed = *(++istream);
 510+					decoded->src.params.immed = immed << 16 | *(++istream);
 511+					break;
 512+				}
 513+				istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
 514+				if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 515+					decoded->op = M68K_INVALID;
 516+					break;
 517+				}
 518+				break;
 519+			case 3:
 520+				decoded->op = M68K_ADD;
 521+				decoded->variant = VAR_IMMEDIATE;
 522+				decoded->src.addr_mode = MODE_IMMEDIATE;
 523+				decoded->extra.size = size = (*istream >> 6) & 3;
 524+				reg = *istream & 0x7;
 525+				opmode = (*istream >> 3) & 0x7;
 526+				switch (size)
 527+				{
 528+				case OPSIZE_BYTE:
 529+					decoded->src.params.immed = *(++istream) & 0xFF;
 530+					break;
 531+				case OPSIZE_WORD:
 532+					decoded->src.params.immed = *(++istream);
 533+					break;
 534+				case OPSIZE_LONG:
 535+					immed = *(++istream);
 536+					decoded->src.params.immed = immed << 16 | *(++istream);
 537+					break;
 538+				}
 539+				istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
 540+				if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 541+					decoded->op = M68K_INVALID;
 542+					break;
 543+				}
 544+				break;
 545+			case 4:
 546+				//BTST, BCHG, BCLR, BSET
 547+				//Seems like this should be unnecessary since bit instructions are explicitly handled above
 548+				//Possible this is redundant or the case above is overly restrictive
 549+				//TODO: Investigate whether this can be removed
 550+				switch ((*istream >> 6) & 0x3)
 551+				{
 552+				case 0:
 553+					decoded->op = M68K_BTST;
 554+					break;
 555+				case 1:
 556+					decoded->op = M68K_BCHG;
 557+					break;
 558+				case 2:
 559+					decoded->op = M68K_BCLR;
 560+					break;
 561+				case 3:
 562+					decoded->op = M68K_BSET;
 563+					break;
 564+				}
 565+				decoded->src.addr_mode = MODE_IMMEDIATE_WORD;
 566+				decoded->src.params.immed = *(++istream) & 0xFF;
 567+				istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
 568+				if (
 569+					!istream || !m68k_valid_immed_dst(&decoded->dst) 
 570+					|| (decoded->op != M68K_BTST && !m68k_valid_immed_limited_dst(&decoded->dst))
 571+				) {
 572+					decoded->op = M68K_INVALID;
 573+					break;
 574+				}
 575+				break;
 576+			case 5:
 577+				//EORI, EORI to CCR, EORI to SR
 578+				if ((*istream & 0xFF) == 0x3C) {
 579+					decoded->op = M68K_EORI_CCR;
 580+					decoded->extra.size = OPSIZE_BYTE;
 581+					decoded->src.addr_mode = MODE_IMMEDIATE;
 582+					decoded->src.params.immed = *(++istream) & 0xFF;
 583+				} else if((*istream & 0xFF) == 0x7C) {
 584+					decoded->op = M68K_EORI_SR;
 585+					decoded->extra.size = OPSIZE_WORD;
 586+					decoded->src.addr_mode = MODE_IMMEDIATE;
 587+					decoded->src.params.immed = *(++istream);
 588+				} else {
 589+					decoded->op = M68K_EOR;
 590+					decoded->variant = VAR_IMMEDIATE;
 591+					decoded->src.addr_mode = MODE_IMMEDIATE;
 592+					decoded->extra.size = size = (*istream >> 6) & 3;
 593+					reg = *istream & 0x7;
 594+					opmode = (*istream >> 3) & 0x7;
 595+					switch (size)
 596+					{
 597+					case OPSIZE_BYTE:
 598+						decoded->src.params.immed = *(++istream) & 0xFF;
 599+						break;
 600+					case OPSIZE_WORD:
 601+						decoded->src.params.immed = *(++istream);
 602+						break;
 603+					case OPSIZE_LONG:
 604+						immed = *(++istream);
 605+						decoded->src.params.immed = immed << 16 | *(++istream);
 606+						break;
 607+					}
 608+					istream = m68k_decode_op_ex(istream, opmode, reg, size, &(decoded->dst));
 609+					if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 610+						decoded->op = M68K_INVALID;
 611+						break;
 612+					}
 613+				}
 614+				break;
 615+			case 6:
 616+				decoded->op = M68K_CMP;
 617+				decoded->variant = VAR_IMMEDIATE;
 618+				decoded->extra.size = (*istream >> 6) & 0x3;
 619+				decoded->src.addr_mode = MODE_IMMEDIATE;
 620+				reg = *istream & 0x7;
 621+				opmode = (*istream >> 3) & 0x7;
 622+				switch (decoded->extra.size)
 623+				{
 624+				case OPSIZE_BYTE:
 625+					decoded->src.params.immed = *(++istream) & 0xFF;
 626+					break;
 627+				case OPSIZE_WORD:
 628+					decoded->src.params.immed = *(++istream);
 629+					break;
 630+				case OPSIZE_LONG:
 631+					immed = *(++istream);
 632+					decoded->src.params.immed = (immed << 16) | *(++istream);
 633+					break;
 634+				}
 635+				istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
 636+				if (!istream || !m68k_valid_immed_limited_dst(&(decoded->dst))) {
 637+					decoded->op = M68K_INVALID;
 638+					break;
 639+				}
 640+				break;
 641+			case 7:
 642+#ifdef M68010
 643+				decoded->op = M68K_MOVES;
 644+				decoded->extra.size = *istream >> 6 & 0x3;
 645+				immed = *(++istream);
 646+				reg = immed  >> 12 & 0x7;
 647+				opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
 648+				if (immed & 0x800) {
 649+					decoded->src.addr_mode = opmode;
 650+					decoded->src.params.regs.pri = reg;
 651+					m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->dst));
 652+				} else {
 653+					m68k_decode_op_ex(istream, *start >> 3 & 0x7, *start & 0x7, decoded->extra.size, &(decoded->src));
 654+					decoded->dst.addr_mode = opmode;
 655+					decoded->dst.params.regs.pri = reg;
 656+				}
 657+#endif
 658+				break;
 659+			}
 660+		}
 661+		break;
 662+	case MOVE_BYTE:
 663+	case MOVE_LONG:
 664+	case MOVE_WORD:
 665+		decoded->op = M68K_MOVE;
 666+		decoded->extra.size = optype == MOVE_BYTE ? OPSIZE_BYTE : (optype == MOVE_WORD ? OPSIZE_WORD : OPSIZE_LONG);
 667+		opmode = (*istream >> 6) & 0x7;
 668+		reg = m68k_reg_quick_field(*istream);
 669+		istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
 670+		if (!istream || (decoded->src.addr_mode == MODE_AREG && optype == MOVE_BYTE)) {
 671+			decoded->op = M68K_INVALID;
 672+			break;
 673+		}
 674+		istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
 675+		if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (decoded->dst.addr_mode == MODE_AREG && optype == MOVE_BYTE)) {
 676+			decoded->op = M68K_INVALID;
 677+			break;
 678+		}
 679+		break;
 680+	case MISC:
 681+
 682+		if ((*istream & 0x1C0) == 0x1C0) {
 683+			decoded->op = M68K_LEA;
 684+			decoded->extra.size = OPSIZE_LONG;
 685+			decoded->dst.addr_mode = MODE_AREG;
 686+			decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
 687+			istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
 688+			if (
 689+				!istream || decoded->src.addr_mode == MODE_REG || decoded->src.addr_mode == MODE_AREG 
 690+				|| decoded->src.addr_mode == MODE_AREG_POSTINC || decoded->src.addr_mode == MODE_AREG_PREDEC
 691+				|| decoded->src.addr_mode == MODE_IMMEDIATE
 692+			) {
 693+				decoded->op = M68K_INVALID;
 694+				break;
 695+			}
 696+		} else {
 697+			if (*istream & 0x100) {
 698+				decoded->op = M68K_CHK;
 699+				if ((*istream & 0x180) == 0x180) {
 700+					decoded->extra.size = OPSIZE_WORD;
 701+				} else {
 702+					//only on M68020+
 703+#ifdef M68020
 704+					decoded->extra.size = OPSIZE_LONG;
 705+#else
 706+					decoded->op = M68K_INVALID;
 707+					break;
 708+#endif
 709+				}
 710+				decoded->dst.addr_mode = MODE_REG;
 711+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
 712+				istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
 713+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
 714+					decoded->op = M68K_INVALID;
 715+					break;
 716+				}
 717+			} else {
 718+				opmode = (*istream >> 3) & 0x7;
 719+				if ((*istream & 0xB80) == 0x880 && opmode != MODE_REG && opmode != MODE_AREG) {
 720+					//TODO: Check for invalid modes that are dependent on direction
 721+					decoded->op = M68K_MOVEM;
 722+					decoded->extra.size = *istream & 0x40 ? OPSIZE_LONG : OPSIZE_WORD;
 723+					reg = *istream & 0x7;
 724+					if(*istream & 0x400) {
 725+						decoded->dst.addr_mode = MODE_REG;
 726+						decoded->dst.params.immed = *(++istream);
 727+						istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->src));
 728+						if (!istream || decoded->src.addr_mode == MODE_AREG_PREDEC || decoded->src.addr_mode == MODE_IMMEDIATE) {
 729+							decoded->op = M68K_INVALID;
 730+							break;
 731+						}
 732+						if (decoded->src.addr_mode == MODE_PC_DISPLACE || decoded->src.addr_mode == MODE_PC_INDEX_DISP8) {
 733+							//adjust displacement to account for extra instruction word
 734+							decoded->src.params.regs.displacement += 2;
 735+						}
 736+					} else {
 737+						decoded->src.addr_mode = MODE_REG;
 738+						decoded->src.params.immed = *(++istream);
 739+						istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, &(decoded->dst));
 740+						if (!istream || !m68k_valid_movem_dst(&decoded->dst)) {
 741+							decoded->op = M68K_INVALID;
 742+							break;
 743+						}
 744+					}
 745+				} else {
 746+					optype = (*istream >> 9) & 0x7;
 747+					size = (*istream >> 6) & 0x3;
 748+					switch(optype)
 749+					{
 750+					case 0:
 751+						//Move from SR or NEGX
 752+						if (size == OPSIZE_INVALID) {
 753+							decoded->op = M68K_MOVE_FROM_SR;
 754+							size = OPSIZE_WORD;
 755+						} else {
 756+							decoded->op = M68K_NEGX;
 757+						}
 758+						decoded->extra.size = size;
 759+						istream= m68k_decode_op(istream, size, &(decoded->dst));
 760+						if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 761+							decoded->op = M68K_INVALID;
 762+							break;
 763+						}
 764+						break;
 765+					case 1:
 766+						//MOVE from CCR or CLR
 767+						if (size == OPSIZE_INVALID) {
 768+#ifdef M68010
 769+							decoded->op = M68K_MOVE_FROM_CCR;
 770+							size = OPSIZE_WORD;
 771+#else
 772+							break;
 773+#endif
 774+						} else {
 775+							decoded->op = M68K_CLR;
 776+						}
 777+						decoded->extra.size = size;
 778+						istream= m68k_decode_op(istream, size, &(decoded->dst));
 779+						if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 780+							decoded->op = M68K_INVALID;
 781+							break;
 782+						}
 783+						break;
 784+					case 2:
 785+						//MOVE to CCR or NEG
 786+						if (size == OPSIZE_INVALID) {
 787+							decoded->op = M68K_MOVE_CCR;
 788+							size = OPSIZE_WORD;
 789+							istream= m68k_decode_op(istream, size, &(decoded->src));
 790+							if (!istream || decoded->src.addr_mode == MODE_AREG) {
 791+								decoded->op = M68K_INVALID;
 792+								break;
 793+							}
 794+						} else {
 795+							decoded->op = M68K_NEG;
 796+							istream= m68k_decode_op(istream, size, &(decoded->dst));
 797+							if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 798+								decoded->op = M68K_INVALID;
 799+								break;
 800+							}
 801+						}
 802+						decoded->extra.size = size;
 803+						break;
 804+					case 3:
 805+						//MOVE to SR or NOT
 806+						if (size == OPSIZE_INVALID) {
 807+							decoded->op = M68K_MOVE_SR;
 808+							size = OPSIZE_WORD;
 809+							istream= m68k_decode_op(istream, size, &(decoded->src));
 810+							if (!istream || decoded->src.addr_mode == MODE_AREG) {
 811+								decoded->op = M68K_INVALID;
 812+								break;
 813+							}
 814+						} else {
 815+							decoded->op = M68K_NOT;
 816+							istream= m68k_decode_op(istream, size, &(decoded->dst));
 817+							if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 818+								decoded->op = M68K_INVALID;
 819+								break;
 820+							}
 821+						}
 822+						decoded->extra.size = size;
 823+						break;
 824+					case 4:
 825+						//EXT, EXTB, LINK.l, NBCD, SWAP, BKPT, PEA
 826+						switch((*istream >> 3) & 0x3F)
 827+						{
 828+						case 1:
 829+#ifdef M68020
 830+							decoded->op = M68K_LINK;
 831+							decoded->extra.size = OPSIZE_LONG;
 832+							reg = *istream & 0x7;
 833+							immed = *(++istream) << 16;
 834+							immed |= *(++istream);
 835+#endif
 836+							break;
 837+						case 8:
 838+							decoded->op = M68K_SWAP;
 839+							decoded->src.addr_mode = MODE_REG;
 840+							decoded->src.params.regs.pri = *istream & 0x7;
 841+							decoded->extra.size = OPSIZE_WORD;
 842+							break;
 843+						case 9:
 844+#ifdef M68010
 845+							decoded->op = M68K_BKPT;
 846+							decoded->src.addr_mode = MODE_IMMEDIATE;
 847+							decoded->extra.size = OPSIZE_UNSIZED;
 848+							decoded->src.params.immed = *istream & 0x7;
 849+#endif
 850+							break;
 851+						case 0x10:
 852+							decoded->op = M68K_EXT;
 853+							decoded->dst.addr_mode = MODE_REG;
 854+							decoded->dst.params.regs.pri = *istream & 0x7;
 855+							decoded->extra.size = OPSIZE_WORD;
 856+							break;
 857+						case 0x18:
 858+							decoded->op = M68K_EXT;
 859+							decoded->dst.addr_mode = MODE_REG;
 860+							decoded->dst.params.regs.pri = *istream & 0x7;
 861+							decoded->extra.size = OPSIZE_LONG;
 862+							break;
 863+						case 0x38:
 864+#ifdef M68020
 865+#endif
 866+							break;
 867+						default:
 868+							if (!(*istream & 0x1C0)) {
 869+								decoded->op = M68K_NBCD;
 870+								decoded->extra.size = OPSIZE_BYTE;
 871+								istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
 872+								if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 873+									decoded->op = M68K_INVALID;
 874+									break;
 875+								}
 876+							} else if((*istream & 0x1C0) == 0x40) {
 877+								decoded->op = M68K_PEA;
 878+								decoded->extra.size = OPSIZE_LONG;
 879+								istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
 880+								if (
 881+									!istream || decoded->src.addr_mode == MODE_REG || decoded->src.addr_mode == MODE_AREG 
 882+									|| decoded->src.addr_mode == MODE_AREG_POSTINC || decoded->src.addr_mode == MODE_AREG_PREDEC
 883+									|| decoded->src.addr_mode == MODE_IMMEDIATE
 884+								) {
 885+									decoded->op = M68K_INVALID;
 886+									break;
 887+								}
 888+							}
 889+						}
 890+						break;
 891+					case 5:
 892+						//BGND, ILLEGAL, TAS, TST
 893+						optype = *istream & 0xFF;
 894+						if (optype == 0xFA) {
 895+							//BGND - CPU32 only
 896+						} else if (optype == 0xFC) {
 897+							decoded->op = M68K_ILLEGAL;
 898+							decoded->extra.size = OPSIZE_UNSIZED;
 899+						} else {
 900+							if (size == OPSIZE_INVALID) {
 901+								decoded->op = M68K_TAS;
 902+								decoded->extra.size = OPSIZE_BYTE;
 903+								istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
 904+								if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
 905+									decoded->op = M68K_INVALID;
 906+									break;
 907+								}
 908+							} else {
 909+								decoded->op = M68K_TST;
 910+								decoded->extra.size = size;
 911+								istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
 912+								if (!istream) {
 913+									decoded->op = M68K_INVALID;
 914+									break;
 915+								}
 916+#ifndef M68020
 917+								if (!m68k_valid_immed_limited_dst(&decoded->src)) {
 918+									decoded->op = M68K_INVALID;
 919+									break;
 920+								}
 921+#endif
 922+							}
 923+						}
 924+						break;
 925+					case 6:
 926+						//MULU, MULS, DIVU, DIVUL, DIVS, DIVSL
 927+#ifdef M68020
 928+						//TODO: Implement these for 68020+ support
 929+#endif
 930+						break;
 931+					case 7:
 932+						//TRAP, LINK.w, UNLNK, MOVE USP, RESET, NOP, STOP, RTE, RTD, RTS, TRAPV, RTR, MOVEC, JSR, JMP
 933+						if (*istream & 0x80) {
 934+							//JSR, JMP
 935+							if (*istream & 0x40) {
 936+								decoded->op = M68K_JMP;
 937+							} else {
 938+								decoded->op = M68K_JSR;
 939+							}
 940+							decoded->extra.size = OPSIZE_UNSIZED;
 941+							istream = m68k_decode_op(istream, OPSIZE_UNSIZED, &(decoded->src));
 942+							if (
 943+								!istream 
 944+								|| (decoded->src.addr_mode < MODE_AREG_DISPLACE && decoded->src.addr_mode != MODE_AREG_INDIRECT)
 945+								|| decoded->src.addr_mode == MODE_IMMEDIATE
 946+							) {
 947+								decoded->op = M68K_INVALID;
 948+								break;
 949+							}
 950+						} else {
 951+							//it would appear bit 6 needs to be set for it to be a valid instruction here
 952+							if (!(*istream & 0x40)) {
 953+								decoded->op = M68K_INVALID;
 954+								break;
 955+							}
 956+							switch((*istream >> 3) & 0x7)
 957+							{
 958+							case 0:
 959+							case 1:
 960+								//TRAP
 961+								decoded->op = M68K_TRAP;
 962+								decoded->extra.size = OPSIZE_UNSIZED;
 963+								decoded->src.addr_mode = MODE_IMMEDIATE;
 964+								decoded->src.params.immed = *istream & 0xF;
 965+								break;
 966+							case 2:
 967+								//LINK.w
 968+								decoded->op = M68K_LINK;
 969+								decoded->extra.size = OPSIZE_WORD;
 970+								decoded->src.addr_mode = MODE_AREG;
 971+								decoded->src.params.regs.pri = *istream & 0x7;
 972+								decoded->dst.addr_mode = MODE_IMMEDIATE;
 973+								decoded->dst.params.immed = sign_extend16(*(++istream));
 974+								break;
 975+							case 3:
 976+								//UNLK
 977+								decoded->op = M68K_UNLK;
 978+								decoded->extra.size = OPSIZE_UNSIZED;
 979+								decoded->dst.addr_mode = MODE_AREG;
 980+								decoded->dst.params.regs.pri = *istream & 0x7;
 981+								break;
 982+							case 4:
 983+							case 5:
 984+								//MOVE USP
 985+								decoded->op = M68K_MOVE_USP;
 986+								if (*istream & 0x8) {
 987+									decoded->dst.addr_mode = MODE_AREG;
 988+									decoded->dst.params.regs.pri = *istream & 0x7;
 989+								} else {
 990+									decoded->src.addr_mode = MODE_AREG;
 991+									decoded->src.params.regs.pri = *istream & 0x7;
 992+								}
 993+								break;
 994+							case 6:
 995+								decoded->extra.size = OPSIZE_UNSIZED;
 996+								switch(*istream & 0x7)
 997+								{
 998+								case 0:
 999+									decoded->op = M68K_RESET;
1000+									break;
1001+								case 1:
1002+									decoded->op = M68K_NOP;
1003+									break;
1004+								case 2:
1005+									decoded->op = M68K_STOP;
1006+									decoded->src.addr_mode = MODE_IMMEDIATE;
1007+									decoded->src.params.immed =*(++istream);
1008+									break;
1009+								case 3:
1010+									decoded->op = M68K_RTE;
1011+									break;
1012+								case 4:
1013+#ifdef M68010
1014+									decoded->op = M68K_RTD;
1015+									decoded->src.addr_mode = MODE_IMMEDIATE;
1016+									decoded->src.params.immed =*(++istream);
1017+#endif
1018+									break;
1019+								case 5:
1020+									decoded->op = M68K_RTS;
1021+									break;
1022+								case 6:
1023+									decoded->op = M68K_TRAPV;
1024+									break;
1025+								case 7:
1026+									decoded->op = M68K_RTR;
1027+									break;
1028+								}
1029+								break;
1030+							case 7:
1031+								//MOVEC
1032+#ifdef M68010
1033+								decoded->op = M68K_MOVEC;
1034+								immed = *(++istream);
1035+								reg = immed >> 12 & 0x7;
1036+								opmode = immed & 0x8000 ? MODE_AREG : MODE_REG;
1037+								immed &= 0xFFF;
1038+								if (immed & 0x800) {
1039+									if (immed > MAX_HIGH_CR) {
1040+										decoded->op = M68K_INVALID;
1041+										break;
1042+									} else {
1043+										immed = immed - 0x800 + CR_USP;
1044+									}
1045+								} else {
1046+									if (immed > MAX_LOW_CR) {
1047+										decoded->op = M68K_INVALID;
1048+										break;
1049+									}
1050+								}
1051+								if (*start & 1) {
1052+									decoded->src.addr_mode = opmode;
1053+									decoded->src.params.regs.pri = reg;
1054+									decoded->dst.params.immed = immed;
1055+								} else {
1056+									decoded->dst.addr_mode = opmode;
1057+									decoded->dst.params.regs.pri = reg;
1058+									decoded->src.params.immed = immed;
1059+								}
1060+#endif
1061+								break;
1062+							}
1063+						}
1064+						break;
1065+					}
1066+				}
1067+			}
1068+		}
1069+		break;
1070+	case QUICK_ARITH_LOOP:
1071+		size = (*istream >> 6) & 3;
1072+		if (size == 0x3) {
1073+			//DBcc, TRAPcc or Scc
1074+			m68k_decode_cond(*istream, decoded);
1075+			if (((*istream >> 3) & 0x7) == 1) {
1076+				decoded->op = M68K_DBCC;
1077+				decoded->src.addr_mode = MODE_IMMEDIATE;
1078+				decoded->dst.addr_mode = MODE_REG;
1079+				decoded->dst.params.regs.pri = *istream & 0x7;
1080+				decoded->src.params.immed = sign_extend16(*(++istream));
1081+			} else if(((*istream >> 3) & 0x7) == 1 && (*istream & 0x7) > 1 && (*istream & 0x7) < 5) {
1082+#ifdef M68020
1083+				decoded->op = M68K_TRAPCC;
1084+				decoded->src.addr_mode = MODE_IMMEDIATE;
1085+				//TODO: Figure out what to do with OPMODE and optional extention words
1086+#endif
1087+			} else {
1088+				decoded->op = M68K_SCC;
1089+				decoded->extra.cond = (*istream >> 8) & 0xF;
1090+				istream = m68k_decode_op(istream, OPSIZE_BYTE, &(decoded->dst));
1091+				if (!istream || !m68k_valid_immed_limited_dst(&decoded->dst)) {
1092+					decoded->op = M68K_INVALID;
1093+					break;
1094+				}
1095+			}
1096+		} else {
1097+			//ADDQ, SUBQ
1098+			decoded->variant = VAR_QUICK;
1099+			decoded->extra.size = size;
1100+			decoded->src.addr_mode = MODE_IMMEDIATE;
1101+			immed = m68k_reg_quick_field(*istream);
1102+			if (!immed) {
1103+				immed = 8;
1104+			}
1105+			decoded->src.params.immed = immed;
1106+			if (*istream & 0x100) {
1107+				decoded->op = M68K_SUB;
1108+			} else {
1109+				decoded->op = M68K_ADD;
1110+			}
1111+			istream = m68k_decode_op(istream, size, &(decoded->dst));
1112+			if (!istream || decoded->dst.addr_mode > MODE_ABSOLUTE || (size == OPSIZE_BYTE && decoded->dst.addr_mode == MODE_AREG)) {
1113+				decoded->op = M68K_INVALID;
1114+				break;
1115+			}
1116+		}
1117+		break;
1118+	case BRANCH:
1119+		m68k_decode_cond(*istream, decoded);
1120+		decoded->op = decoded->extra.cond == COND_FALSE ? M68K_BSR : M68K_BCC;
1121+		decoded->src.addr_mode = MODE_IMMEDIATE;
1122+		immed = *istream & 0xFF;
1123+		if (immed == 0) {
1124+			decoded->variant = VAR_WORD;
1125+			immed = *(++istream);
1126+			immed = sign_extend16(immed);
1127+#ifdef M68020
1128+		} else if (immed == 0xFF) {
1129+			decoded->variant = VAR_LONG;
1130+			immed = *(++istream) << 16;
1131+			immed |= *(++istream);
1132+#endif
1133+		} else {
1134+			decoded->variant = VAR_BYTE;
1135+			immed = sign_extend8(immed);
1136+		}
1137+		decoded->src.params.immed = immed;
1138+		break;
1139+	case MOVEQ:
1140+		if (*istream & 0x100) {
1141+			decoded->op = M68K_INVALID;
1142+			break;
1143+		}
1144+		decoded->op = M68K_MOVE;
1145+		decoded->variant = VAR_QUICK;
1146+		decoded->extra.size = OPSIZE_LONG;
1147+		decoded->src.addr_mode = MODE_IMMEDIATE;
1148+		decoded->src.params.immed = sign_extend8(*istream & 0xFF);
1149+		decoded->dst.addr_mode = MODE_REG;
1150+		decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1151+		immed = *istream & 0xFF;
1152+		break;
1153+	case OR_DIV_SBCD:
1154+		//for OR, if opmode bit 2 is 1, then src = Dn, dst = <ea>
1155+		opmode = (*istream >> 6) & 0x7;
1156+		size = opmode & 0x3;
1157+		if (size == OPSIZE_INVALID || (opmode & 0x4 && !(*istream & 0x30))) {
1158+			switch(opmode)
1159+			{
1160+			case 3:
1161+				decoded->op = M68K_DIVU;
1162+				decoded->extra.size = OPSIZE_WORD;
1163+				decoded->dst.addr_mode = MODE_REG;
1164+				decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
1165+				istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
1166+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1167+					decoded->op = M68K_INVALID;
1168+					break;
1169+				}
1170+				break;
1171+			case 4:
1172+				decoded->op = M68K_SBCD;
1173+				decoded->extra.size = OPSIZE_BYTE;
1174+				decoded->dst.addr_mode = decoded->src.addr_mode = *istream & 0x8 ? MODE_AREG_PREDEC : MODE_REG;
1175+				decoded->src.params.regs.pri = *istream & 0x7;
1176+				decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
1177+				break;
1178+			case 5:
1179+	#ifdef M68020
1180+	#endif
1181+				break;
1182+			case 6:
1183+	#ifdef M68020
1184+	#endif
1185+				break;
1186+			case 7:
1187+				decoded->op = M68K_DIVS;
1188+				decoded->extra.size = OPSIZE_WORD;
1189+				decoded->dst.addr_mode = MODE_REG;
1190+				decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
1191+				istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
1192+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1193+					decoded->op = M68K_INVALID;
1194+					break;
1195+				}
1196+				break;
1197+			}
1198+		} else {
1199+			decoded->op = M68K_OR;
1200+			decoded->extra.size = size;
1201+			if (opmode & 0x4) {
1202+				decoded->src.addr_mode = MODE_REG;
1203+				decoded->src.params.regs.pri = (*istream >> 9) & 0x7;
1204+				istream = m68k_decode_op(istream, size, &(decoded->dst));
1205+				if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) {
1206+					decoded->op = M68K_INVALID;
1207+					break;
1208+				}
1209+			} else {
1210+				decoded->dst.addr_mode = MODE_REG;
1211+				decoded->dst.params.regs.pri = (*istream >> 9) & 0x7;
1212+				istream = m68k_decode_op(istream, size, &(decoded->src));
1213+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1214+					decoded->op = M68K_INVALID;
1215+					break;
1216+				}
1217+			}
1218+		}
1219+		break;
1220+	case SUB_SUBX:
1221+		size = (*istream >> 6) & 0x3;
1222+		decoded->op = M68K_SUB;
1223+		if (*istream & 0x100) {
1224+			//<ea> destination, SUBA.l or SUBX
1225+			if (*istream & 0x30 || size == OPSIZE_INVALID) {
1226+				if (size == OPSIZE_INVALID) {
1227+					//SUBA.l
1228+					decoded->extra.size = OPSIZE_LONG;
1229+					decoded->dst.addr_mode = MODE_AREG;
1230+					decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1231+					istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
1232+					if (!istream) {
1233+						decoded->op = M68K_INVALID;
1234+						break;
1235+					}
1236+				} else {
1237+					decoded->extra.size = size;
1238+					decoded->src.addr_mode = MODE_REG;
1239+					decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
1240+					istream = m68k_decode_op(istream, size, &(decoded->dst));
1241+					if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) {
1242+						decoded->op = M68K_INVALID;
1243+						break;
1244+					}
1245+				}
1246+			} else {
1247+				//SUBX
1248+				decoded->op = M68K_SUBX;
1249+				decoded->extra.size = size;
1250+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1251+				decoded->src.params.regs.pri = *istream & 0x7;
1252+				if (*istream & 0x8) {
1253+					decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
1254+				} else {
1255+					decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
1256+				}
1257+			}
1258+		} else {
1259+			if (size == OPSIZE_INVALID) {
1260+				//SUBA.w
1261+				decoded->extra.size = OPSIZE_WORD;
1262+				decoded->dst.addr_mode = MODE_AREG;
1263+			} else {
1264+				decoded->extra.size = size;
1265+				decoded->dst.addr_mode = MODE_REG;
1266+			}
1267+			decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1268+			istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
1269+			if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) {
1270+				decoded->op = M68K_INVALID;
1271+				break;
1272+			}
1273+		}
1274+		break;
1275+	case A_LINE:
1276+		decoded->op = M68K_A_LINE_TRAP;
1277+		break;
1278+	case CMP_XOR:
1279+		size = (*istream >> 6) & 0x3;
1280+		decoded->op = M68K_CMP;
1281+		if (*istream & 0x100) {
1282+			//CMPM or CMPA.l or EOR
1283+			if (size == OPSIZE_INVALID) {
1284+				decoded->extra.size = OPSIZE_LONG;
1285+				decoded->dst.addr_mode = MODE_AREG;
1286+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1287+				istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
1288+				if (!istream) {
1289+					decoded->op = M68K_INVALID;
1290+					break;
1291+				}
1292+			} else {
1293+				reg = m68k_reg_quick_field(*istream);
1294+				istream = m68k_decode_op(istream, size, &(decoded->dst));
1295+				if (!istream) {
1296+					decoded->op = M68K_INVALID;
1297+					break;
1298+				}
1299+				decoded->extra.size = size;
1300+				if (decoded->dst.addr_mode == MODE_AREG) {
1301+					//CMPM
1302+					decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG_POSTINC;
1303+					decoded->src.params.regs.pri = decoded->dst.params.regs.pri;
1304+					decoded->dst.params.regs.pri = reg;
1305+				} else if (!m68k_valid_immed_limited_dst(&decoded->dst)){
1306+					decoded->op = M68K_INVALID;
1307+					break;
1308+				} else {
1309+					//EOR
1310+					decoded->op = M68K_EOR;
1311+					decoded->src.addr_mode = MODE_REG;
1312+					decoded->src.params.regs.pri = reg;
1313+				}
1314+			}
1315+		} else {
1316+			//CMP or CMPA.w
1317+			if (size == OPSIZE_INVALID) {
1318+				decoded->extra.size = OPSIZE_WORD;
1319+				decoded->dst.addr_mode = MODE_AREG;
1320+			} else {
1321+				decoded->extra.size = size;
1322+				decoded->dst.addr_mode = MODE_REG;
1323+			}
1324+			decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1325+			istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
1326+			if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) {
1327+				decoded->op = M68K_INVALID;
1328+				break;
1329+			}
1330+		}
1331+		break;
1332+	case AND_MUL_ABCD_EXG:
1333+		//page 575 for summary
1334+		//EXG opmodes:
1335+		//01000 -data regs
1336+		//01001 -addr regs
1337+		//10001 -one of each
1338+		//AND opmodes:
1339+		//operand order bit + 2 size bits (00 - 10)
1340+		//no address register direct addressing
1341+		//data register direct not allowed when <ea> is the source (operand order bit of 1)
1342+		if (*istream & 0x100) {
1343+			if ((*istream & 0xC0) == 0xC0) {
1344+				decoded->op = M68K_MULS;
1345+				decoded->extra.size = OPSIZE_WORD;
1346+				decoded->dst.addr_mode = MODE_REG;
1347+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1348+				istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
1349+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1350+					decoded->op = M68K_INVALID;
1351+					break;
1352+				}
1353+			} else if(!(*istream & 0xF0)) {
1354+				decoded->op = M68K_ABCD;
1355+				decoded->extra.size = OPSIZE_BYTE;
1356+				decoded->src.params.regs.pri = *istream & 0x7;
1357+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1358+				decoded->dst.addr_mode = decoded->src.addr_mode = (*istream & 8) ? MODE_AREG_PREDEC : MODE_REG;
1359+			} else if(!(*istream & 0x30)) {
1360+				decoded->op = M68K_EXG;
1361+				decoded->extra.size = OPSIZE_LONG;
1362+				decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
1363+				decoded->dst.params.regs.pri = *istream & 0x7;
1364+				if (*istream & 0x8) {
1365+					if (*istream & 0x80) {
1366+						decoded->src.addr_mode = MODE_REG;
1367+						decoded->dst.addr_mode = MODE_AREG;
1368+					} else {
1369+						decoded->src.addr_mode = decoded->dst.addr_mode = MODE_AREG;
1370+					}
1371+				} else if (*istream & 0x40) {
1372+					decoded->src.addr_mode = decoded->dst.addr_mode = MODE_REG;
1373+				} else {
1374+					decoded->op = M68K_INVALID;
1375+					break;
1376+				}
1377+			} else {
1378+				decoded->op = M68K_AND;
1379+				decoded->extra.size = (*istream >> 6) & 0x3;
1380+				decoded->src.addr_mode = MODE_REG;
1381+				decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
1382+				istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->dst));
1383+				if (!istream || !m68k_valid_full_arith_dst(&(decoded->dst))) {
1384+					decoded->op = M68K_INVALID;
1385+					break;
1386+				}
1387+			}
1388+		} else {
1389+			if ((*istream & 0xC0) == 0xC0) {
1390+				decoded->op = M68K_MULU;
1391+				decoded->extra.size = OPSIZE_WORD;
1392+				decoded->dst.addr_mode = MODE_REG;
1393+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1394+				istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->src));
1395+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1396+					decoded->op = M68K_INVALID;
1397+					break;
1398+				}
1399+			} else {
1400+				decoded->op = M68K_AND;
1401+				decoded->extra.size = (*istream >> 6) & 0x3;
1402+				decoded->dst.addr_mode = MODE_REG;
1403+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1404+				istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
1405+				if (!istream || decoded->src.addr_mode == MODE_AREG) {
1406+					decoded->op = M68K_INVALID;
1407+					break;
1408+				}
1409+			}
1410+		}
1411+		break;
1412+	case ADD_ADDX:
1413+		size = (*istream >> 6) & 0x3;
1414+		decoded->op = M68K_ADD;
1415+		if (*istream & 0x100) {
1416+			//<ea> destination, ADDA.l or ADDX
1417+			if (*istream & 0x30 || size == OPSIZE_INVALID) {
1418+				if (size == OPSIZE_INVALID) {
1419+					//ADDA.l
1420+					decoded->extra.size = OPSIZE_LONG;
1421+					decoded->dst.addr_mode = MODE_AREG;
1422+					decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1423+					istream = m68k_decode_op(istream, OPSIZE_LONG, &(decoded->src));
1424+					if (!istream) {
1425+						decoded->op = M68K_INVALID;
1426+						break;
1427+					}
1428+				} else {
1429+					decoded->extra.size = size;
1430+					decoded->src.addr_mode = MODE_REG;
1431+					decoded->src.params.regs.pri = m68k_reg_quick_field(*istream);
1432+					istream = m68k_decode_op(istream, size, &(decoded->dst));
1433+					if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) {
1434+						decoded->op = M68K_INVALID;
1435+						break;
1436+					}
1437+				}
1438+			} else {
1439+				//ADDX
1440+				decoded->op = M68K_ADDX;
1441+				decoded->extra.size = size;
1442+				decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1443+				decoded->src.params.regs.pri = *istream & 0x7;
1444+				if (*istream & 0x8) {
1445+					decoded->dst.addr_mode = decoded->src.addr_mode = MODE_AREG_PREDEC;
1446+				} else {
1447+					decoded->dst.addr_mode = decoded->src.addr_mode = MODE_REG;
1448+				}
1449+			}
1450+		} else {
1451+			if (size == OPSIZE_INVALID) {
1452+				//ADDA.w
1453+				decoded->extra.size = OPSIZE_WORD;
1454+				decoded->dst.addr_mode = MODE_AREG;
1455+			} else {
1456+				decoded->extra.size = size;
1457+				decoded->dst.addr_mode = MODE_REG;
1458+			}
1459+			decoded->dst.params.regs.pri = m68k_reg_quick_field(*istream);
1460+			istream = m68k_decode_op(istream, decoded->extra.size, &(decoded->src));
1461+			if (!istream || (decoded->src.addr_mode == MODE_AREG && decoded->extra.size == OPSIZE_BYTE)) {
1462+				decoded->op = M68K_INVALID;
1463+				break;
1464+			}
1465+		}
1466+		break;
1467+	case SHIFT_ROTATE:
1468+		if ((*istream & 0x8C0) == 0xC0) {
1469+			switch((*istream >> 8) & 0x7)
1470+			{
1471+			case 0:
1472+				decoded->op = M68K_ASR;
1473+				break;
1474+			case 1:
1475+				decoded->op = M68K_ASL;
1476+				break;
1477+			case 2:
1478+				decoded->op = M68K_LSR;
1479+				break;
1480+			case 3:
1481+				decoded->op = M68K_LSL;
1482+				break;
1483+			case 4:
1484+				decoded->op = M68K_ROXR;
1485+				break;
1486+			case 5:
1487+				decoded->op = M68K_ROXL;
1488+				break;
1489+			case 6:
1490+				decoded->op = M68K_ROR;
1491+				break;
1492+			case 7:
1493+				decoded->op = M68K_ROL;
1494+				break;
1495+			}
1496+			decoded->extra.size = OPSIZE_WORD;
1497+			istream = m68k_decode_op(istream, OPSIZE_WORD, &(decoded->dst));
1498+			if (!istream || !m68k_valid_full_arith_dst(&decoded->dst)) {
1499+				decoded->op = M68K_INVALID;
1500+				break;
1501+			}
1502+		} else if((*istream & 0xC0) != 0xC0) {
1503+			switch(((*istream >> 2) & 0x6) | ((*istream >> 8) & 1))
1504+			{
1505+			case 0:
1506+				decoded->op = M68K_ASR;
1507+				break;
1508+			case 1:
1509+				decoded->op = M68K_ASL;
1510+				break;
1511+			case 2:
1512+				decoded->op = M68K_LSR;
1513+				break;
1514+			case 3:
1515+				decoded->op = M68K_LSL;
1516+				break;
1517+			case 4:
1518+				decoded->op = M68K_ROXR;
1519+				break;
1520+			case 5:
1521+				decoded->op = M68K_ROXL;
1522+				break;
1523+			case 6:
1524+				decoded->op = M68K_ROR;
1525+				break;
1526+			case 7:
1527+				decoded->op = M68K_ROL;
1528+				break;
1529+			}
1530+			decoded->extra.size = (*istream >> 6) & 0x3;
1531+			immed = (*istream >> 9) & 0x7;
1532+			if (*istream & 0x20) {
1533+				decoded->src.addr_mode = MODE_REG;
1534+				decoded->src.params.regs.pri = immed;
1535+			} else {
1536+				decoded->src.addr_mode = MODE_IMMEDIATE;
1537+				if (!immed) {
1538+					immed = 8;
1539+				}
1540+				decoded->src.params.immed = immed;
1541+				decoded->variant = VAR_QUICK;
1542+			}
1543+			decoded->dst.addr_mode = MODE_REG;
1544+			decoded->dst.params.regs.pri = *istream & 0x7;
1545+
1546+		} else {
1547+#ifdef M68020
1548+			//TODO: Implement bitfield instructions for M68020+ support
1549+			switch (*istream >> 8 & 7)
1550+			{
1551+			case 0:
1552+				decoded->op = M68K_BFTST; //<ea>
1553+				break;
1554+			case 1:
1555+				decoded->op = M68K_BFEXTU; //<ea>, Dn
1556+				break;
1557+			case 2:
1558+				decoded->op = M68K_BFCHG; //<ea>
1559+				break;
1560+			case 3:
1561+				decoded->op = M68K_BFEXTS; //<ea>, Dn
1562+				break;
1563+			case 4:
1564+				decoded->op = M68K_BFCLR; //<ea>
1565+				break;
1566+			case 5:
1567+				decoded->op = M68K_BFFFO; //<ea>, Dn
1568+				break;
1569+			case 6:
1570+				decoded->op = M68K_BFSET; //<ea>
1571+				break;
1572+			case 7:
1573+				decoded->op = M68K_BFINS; //Dn, <ea>
1574+				break;
1575+			}
1576+			opmode = *istream >> 3 & 0x7;
1577+			reg = *istream & 0x7;
1578+			m68k_op_info *ea, *other;
1579+			if (decoded->op == M68K_BFEXTU || decoded->op == M68K_BFEXTS || decoded->op == M68K_BFFFO)
1580+			{
1581+				ea = &(decoded->src);
1582+				other = &(decoded->dst);
1583+			} else {
1584+				ea = &(decoded->dst);
1585+				other = &(decoded->dst);
1586+			}
1587+			if (*istream & 0x100)
1588+			{
1589+				immed = *(istream++);
1590+				other->addr_mode = MODE_REG;
1591+				other->params.regs.pri = immed >> 12 & 0x7;
1592+			} else {
1593+				immed = *(istream++);
1594+			}
1595+			decoded->extra.size = OPSIZE_UNSIZED;
1596+			istream = m68k_decode_op_ex(istream, opmode, reg, decoded->extra.size, ea);
1597+			ea->addr_mode |= M68K_FLAG_BITFIELD;
1598+			ea->bitfield = immed & 0xFFF;
1599+#endif
1600+		}
1601+		break;
1602+	case F_LINE:
1603+		//TODO: Decode FPU instructions for members of the 68K family with an FPU
1604+		decoded->op = M68K_F_LINE_TRAP;
1605+		break;
1606+	}
1607+	if (decoded->op == M68K_INVALID) {
1608+		decoded->src.params.immed = *start;
1609+		decoded->bytes = 2;
1610+		return start + 1;
1611+	}
1612+	decoded->bytes = 2 * (istream + 1 - start);
1613+	return istream+1;
1614+}
1615+
1616+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs)
1617+{
1618+	if(inst->op == M68K_BCC || inst->op == M68K_BSR || inst->op == M68K_DBCC) {
1619+		return inst->address + 2 + inst->src.params.immed;
1620+	} else if(inst->op == M68K_JMP || inst->op == M68K_JSR) {
1621+		uint32_t ret = 0;
1622+		switch(inst->src.addr_mode)
1623+		{
1624+		case MODE_AREG_INDIRECT:
1625+			ret = aregs[inst->src.params.regs.pri];
1626+			break;
1627+		case MODE_AREG_DISPLACE:
1628+			ret = aregs[inst->src.params.regs.pri] + inst->src.params.regs.displacement;
1629+			break;
1630+		case MODE_AREG_INDEX_DISP8: {
1631+			uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
1632+			ret = aregs[inst->src.params.regs.pri];
1633+			uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
1634+			if (inst->src.params.regs.sec & 1) {
1635+				//32-bit index register
1636+				ret += regfile[sec_reg];
1637+			} else {
1638+				//16-bit index register
1639+				if (regfile[sec_reg] & 0x8000) {
1640+					ret += (0xFFFF0000 | regfile[sec_reg]);
1641+				} else {
1642+					ret += regfile[sec_reg];
1643+				}
1644+			}
1645+			ret += inst->src.params.regs.displacement;
1646+			break;
1647+		}
1648+		case MODE_PC_DISPLACE:
1649+			ret = inst->src.params.regs.displacement + inst->address + 2;
1650+			break;
1651+		case MODE_PC_INDEX_DISP8: {
1652+			uint8_t sec_reg = inst->src.params.regs.sec >> 1 & 0x7;
1653+			ret = inst->address + 2;
1654+			uint32_t * regfile = inst->src.params.regs.sec & 0x10 ? aregs : dregs;
1655+			if (inst->src.params.regs.sec & 1) {
1656+				//32-bit index register
1657+				ret += regfile[sec_reg];
1658+			} else {
1659+				//16-bit index register
1660+				if (regfile[sec_reg] & 0x8000) {
1661+					ret += (0xFFFF0000 | regfile[sec_reg]);
1662+				} else {
1663+					ret += regfile[sec_reg];
1664+				}
1665+			}
1666+			ret += inst->src.params.regs.displacement;
1667+			break;
1668+		}
1669+		case MODE_ABSOLUTE:
1670+		case MODE_ABSOLUTE_SHORT:
1671+			ret = inst->src.params.immed;
1672+			break;
1673+		}
1674+		return ret;
1675+	}
1676+	return 0;
1677+}
1678+
1679+uint8_t m68k_is_branch(m68kinst * inst)
1680+{
1681+	return (inst->op == M68K_BCC && inst->extra.cond != COND_FALSE)
1682+		|| (inst->op == M68K_DBCC && inst->extra.cond != COND_TRUE)
1683+		|| inst->op == M68K_BSR || inst->op == M68K_JMP || inst->op == M68K_JSR;
1684+}
1685+
1686+uint8_t m68k_is_noncall_branch(m68kinst * inst)
1687+{
1688+	return m68k_is_branch(inst) && inst->op != M68K_BSR && inst->op != M68K_JSR;
1689+}
1690+
1691+
1692+char * mnemonics[] = {
1693+	"abcd",
1694+	"add",
1695+	"addx",
1696+	"and",
1697+	"andi",//ccr
1698+	"andi",//sr
1699+	"asl",
1700+	"asr",
1701+	"bcc",
1702+	"bchg",
1703+	"bclr",
1704+	"bset",
1705+	"bsr",
1706+	"btst",
1707+	"chk",
1708+	"clr",
1709+	"cmp",
1710+	"dbcc",
1711+	"divs",
1712+	"divu",
1713+	"eor",
1714+	"eori",//ccr
1715+	"eori",//sr
1716+	"exg",
1717+	"ext",
1718+	"illegal",
1719+	"jmp",
1720+	"jsr",
1721+	"lea",
1722+	"link",
1723+	"lsl",
1724+	"lsr",
1725+	"move",
1726+	"move",//ccr
1727+	"move",//from_sr
1728+	"move",//sr
1729+	"move",//usp
1730+	"movem",
1731+	"movep",
1732+	"muls",
1733+	"mulu",
1734+	"nbcd",
1735+	"neg",
1736+	"negx",
1737+	"nop",
1738+	"not",
1739+	"or",
1740+	"ori",//ccr
1741+	"ori",//sr
1742+	"pea",
1743+	"reset",
1744+	"rol",
1745+	"ror",
1746+	"roxl",
1747+	"roxr",
1748+	"rte",
1749+	"rtr",
1750+	"rts",
1751+	"sbcd",
1752+	"scc",
1753+	"stop",
1754+	"sub",
1755+	"subx",
1756+	"swap",
1757+	"tas",
1758+	"trap",
1759+	"trapv",
1760+	"tst",
1761+	"unlk",
1762+	"invalid",
1763+#ifdef M68010
1764+	"bkpt",
1765+	"move", //from ccr
1766+	"movec",
1767+	"moves",
1768+	"rtd",
1769+#endif
1770+#ifdef M68020
1771+	"bfchg",
1772+	"bfclr",
1773+	"bfexts",
1774+	"bfextu",
1775+	"bfffo",
1776+	"bfins",
1777+	"bfset",
1778+	"bftst",
1779+	"callm",
1780+	"cas",
1781+	"cas2",
1782+	"chk2",
1783+	"cmp2",
1784+	"cpbcc",
1785+	"cpdbcc",
1786+	"cpgen",
1787+	"cprestore",
1788+	"cpsave",
1789+	"cpscc",
1790+	"cptrapcc",
1791+	"divsl",
1792+	"divul",
1793+	"extb",
1794+	"pack",
1795+	"rtm",
1796+	"trapcc",
1797+	"unpk"
1798+#endif
1799+};
1800+
1801+char * cond_mnem[] = {
1802+	"ra",
1803+	"f",
1804+	"hi",
1805+	"ls",
1806+	"cc",
1807+	"cs",
1808+	"ne",
1809+	"eq",
1810+	"vc",
1811+	"vs",
1812+	"pl",
1813+	"mi",
1814+	"ge",
1815+	"lt",
1816+	"gt",
1817+	"le"
1818+};
1819+#ifdef M68010
1820+char * cr_mnem[] = {
1821+	"SFC",
1822+	"DFC",
1823+#ifdef M68020
1824+	"CACR",
1825+#endif
1826+	"USP",
1827+	"VBR",
1828+#ifdef M68020
1829+	"CAAR",
1830+	"MSP",
1831+	"ISP"
1832+#endif
1833+};
1834+#endif
1835+
1836+int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
1837+{
1838+	char * c = need_comma ? "," : "";
1839+	int ret = 0;
1840+#ifdef M68020
1841+	uint8_t addr_mode = decoded->addr_mode & (~M68K_FLAG_BITFIELD);
1842+#else
1843+	uint8_t addr_mode = decoded->addr_mode;
1844+#endif
1845+	switch(addr_mode)
1846+	{
1847+	case MODE_REG:
1848+		ret = sprintf(dst, "%s d%d", c, decoded->params.regs.pri);
1849+		break;
1850+	case MODE_AREG:
1851+		ret = sprintf(dst, "%s a%d", c, decoded->params.regs.pri);
1852+		break;
1853+	case MODE_AREG_INDIRECT:
1854+		ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
1855+		break;
1856+	case MODE_AREG_POSTINC:
1857+		ret = sprintf(dst, "%s (a%d)+", c, decoded->params.regs.pri);
1858+		break;
1859+	case MODE_AREG_PREDEC:
1860+		ret = sprintf(dst, "%s -(a%d)", c, decoded->params.regs.pri);
1861+		break;
1862+	case MODE_AREG_DISPLACE:
1863+		ret = sprintf(dst, "%s (%d, a%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri);
1864+		break;
1865+	case MODE_AREG_INDEX_DISP8:
1866+#ifdef M68020
1867+		if (decoded->params.regs.scale)
1868+		{
1869+			ret = sprintf(dst, "%s (%d, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1870+		} else {
1871+#endif
1872+			ret = sprintf(dst, "%s (%d, a%d, %c%d.%c)", c, decoded->params.regs.displacement, decoded->params.regs.pri, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
1873+#ifdef M68020
1874+		}
1875+#endif
1876+		break;
1877+#ifdef M68020
1878+	case MODE_AREG_INDEX_BASE_DISP:
1879+		if (decoded->params.regs.disp_sizes > 1)
1880+		{
1881+			ret = sprintf(dst, "%s (%d.%c, a%d, %c%d.%c*%d)", c, decoded->params.regs.displacement,
1882+			              decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri,
1883+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1884+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1885+		} else {
1886+			ret = sprintf(dst, "%s (a%d, %c%d.%c*%d)", c, decoded->params.regs.pri,
1887+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1888+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1889+		}
1890+		break;
1891+	case MODE_AREG_PREINDEX:
1892+		switch (decoded->params.regs.disp_sizes)
1893+		{
1894+		case 0x11:
1895+			//no base displacement or outer displacement
1896+			ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d])", c, decoded->params.regs.pri,
1897+						  (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1898+						  (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1899+			break;
1900+		case 0x12:
1901+		case 0x13:
1902+			//base displacement only
1903+			ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d])", c, decoded->params.regs.displacement,
1904+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
1905+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1906+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1907+			break;
1908+		case 0x21:
1909+		case 0x31:
1910+			//outer displacement only
1911+			ret = sprintf(dst, "%s ([a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.pri,
1912+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1913+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
1914+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1915+			break;
1916+		case 0x22:
1917+		case 0x23:
1918+		case 0x32:
1919+		case 0x33:
1920+			//both outer and inner displacement
1921+			ret = sprintf(dst, "%s ([%d.%c, a%d, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
1922+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
1923+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1924+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
1925+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1926+			break;
1927+		}
1928+		break;
1929+	case MODE_AREG_POSTINDEX:
1930+		switch (decoded->params.regs.disp_sizes)
1931+		{
1932+		case 0x11:
1933+			//no base displacement or outer displacement
1934+			ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d)", c, decoded->params.regs.pri,
1935+						  (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1936+						  (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1937+			break;
1938+		case 0x12:
1939+		case 0x13:
1940+			//base displacement only
1941+			ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d)", c, decoded->params.regs.displacement,
1942+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
1943+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1944+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
1945+			break;
1946+		case 0x21:
1947+		case 0x31:
1948+			//outer displacement only
1949+			ret = sprintf(dst, "%s ([a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.pri,
1950+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1951+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
1952+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1953+			break;
1954+		case 0x22:
1955+		case 0x23:
1956+		case 0x32:
1957+		case 0x33:
1958+			//both outer and inner displacement
1959+			ret = sprintf(dst, "%s ([%d.%c, a%d], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
1960+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
1961+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
1962+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
1963+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1964+			break;
1965+		}
1966+		break;
1967+	case MODE_AREG_MEM_INDIRECT:
1968+		switch (decoded->params.regs.disp_sizes)
1969+		{
1970+		case 0x11:
1971+			//no base displacement or outer displacement
1972+			ret = sprintf(dst, "%s ([a%d])", c, decoded->params.regs.pri);
1973+			break;
1974+		case 0x12:
1975+		case 0x13:
1976+			//base displacement only
1977+			ret = sprintf(dst, "%s ([%d.%c, a%d])", c, decoded->params.regs.displacement,
1978+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri);
1979+			break;
1980+		case 0x21:
1981+		case 0x31:
1982+			//outer displacement only
1983+			ret = sprintf(dst, "%s ([a%d], %d.%c)", c, decoded->params.regs.pri, decoded->params.regs.outer_disp,
1984+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1985+			break;
1986+		case 0x22:
1987+		case 0x23:
1988+		case 0x32:
1989+		case 0x33:
1990+			//both outer and inner displacement
1991+			ret = sprintf(dst, "%s ([%d.%c, a%d], %d.%c)", c, decoded->params.regs.displacement,
1992+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.pri,
1993+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
1994+			break;
1995+		}
1996+		break;
1997+	case MODE_AREG_BASE_DISP:
1998+		if (decoded->params.regs.disp_sizes > 1)
1999+		{
2000+			ret = sprintf(dst, "%s (%d.%c, a%d)", c, decoded->params.regs.displacement,
2001+			              decoded->params.regs.disp_sizes == 2 ? 'w' : 'l', decoded->params.regs.pri);
2002+		} else {
2003+			//this is a lossy representation of the encoded instruction
2004+			//not sure if there's a better way to print it though
2005+			ret = sprintf(dst, "%s (a%d)", c, decoded->params.regs.pri);
2006+		}
2007+		break;
2008+	case MODE_INDEX_BASE_DISP:
2009+		if (decoded->params.regs.disp_sizes > 1)
2010+		{
2011+			ret = sprintf(dst, "%s (%d.%c, %c%d.%c*%d)", c, decoded->params.regs.displacement,
2012+			              decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
2013+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2014+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2015+		} else {
2016+			ret = sprintf(dst, "%s (%c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2017+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2018+			              1 << decoded->params.regs.scale);
2019+		}
2020+		break;
2021+	case MODE_PREINDEX:
2022+		switch (decoded->params.regs.disp_sizes)
2023+		{
2024+		case 0x11:
2025+			//no base displacement or outer displacement
2026+			ret = sprintf(dst, "%s ([%c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2027+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2028+			              1 << decoded->params.regs.scale);
2029+			break;
2030+		case 0x12:
2031+		case 0x13:
2032+			//base displacement only
2033+			ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d])", c, decoded->params.regs.displacement,
2034+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2035+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2036+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2037+			break;
2038+		case 0x21:
2039+		case 0x31:
2040+			//outer displacement only
2041+			ret = sprintf(dst, "%s ([%c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2042+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2043+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2044+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2045+			break;
2046+		case 0x22:
2047+		case 0x23:
2048+		case 0x32:
2049+		case 0x33:
2050+			//both outer and inner displacement
2051+			ret = sprintf(dst, "%s ([%d.%c, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
2052+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2053+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2054+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2055+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2056+			break;
2057+		}
2058+		break;
2059+	case MODE_POSTINDEX:
2060+		switch (decoded->params.regs.disp_sizes)
2061+		{
2062+		case 0x11:
2063+			//no base displacement or outer displacement
2064+			ret = sprintf(dst, "%s ([], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2065+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2066+			              1 << decoded->params.regs.scale);
2067+			break;
2068+		case 0x12:
2069+		case 0x13:
2070+			//base displacement only
2071+			ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d)", c, decoded->params.regs.displacement,
2072+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2073+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2074+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2075+			break;
2076+		case 0x21:
2077+		case 0x31:
2078+			//outer displacement only
2079+			ret = sprintf(dst, "%s ([], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2080+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2081+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2082+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2083+			break;
2084+		case 0x22:
2085+		case 0x23:
2086+		case 0x32:
2087+		case 0x33:
2088+			//both outer and inner displacement
2089+			ret = sprintf(dst, "%s ([%d.%c], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
2090+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2091+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2092+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2093+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2094+			break;
2095+		}
2096+		break;
2097+	case MODE_MEM_INDIRECT:
2098+		switch (decoded->params.regs.disp_sizes)
2099+		{
2100+		case 0x11:
2101+			//no base displacement or outer displacement
2102+			ret = sprintf(dst, "%s ([])", c);
2103+			break;
2104+		case 0x12:
2105+		case 0x13:
2106+			//base displacement only
2107+			ret = sprintf(dst, "%s ([%d.%c])", c, decoded->params.regs.displacement,
2108+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2109+			break;
2110+		case 0x21:
2111+		case 0x31:
2112+			//outer displacement only
2113+			ret = sprintf(dst, "%s ([], %d.%c)", c, decoded->params.regs.outer_disp,
2114+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2115+			break;
2116+		case 0x22:
2117+		case 0x23:
2118+		case 0x32:
2119+		case 0x33:
2120+			//both outer and inner displacement
2121+			ret = sprintf(dst, "%s ([%d.%c], %d.%c)", c, decoded->params.regs.displacement,
2122+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
2123+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2124+			break;
2125+		}
2126+		break;
2127+	case MODE_BASE_DISP:
2128+		if (decoded->params.regs.disp_sizes > 1)
2129+		{
2130+			ret = sprintf(dst, "%s (%d.%c)", c, decoded->params.regs.displacement,
2131+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2132+		} else {
2133+			ret = sprintf(dst, "%s ()", c);
2134+		}
2135+		break;
2136+#endif
2137+	case MODE_IMMEDIATE:
2138+	case MODE_IMMEDIATE_WORD:
2139+		ret = sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed);
2140+		break;
2141+	case MODE_ABSOLUTE_SHORT:
2142+		if (labels) {
2143+			ret = sprintf(dst, "%s ", c);
2144+			ret += label_fun(dst+ret, decoded->params.immed, data);
2145+			strcat(dst+ret, ".w");
2146+			ret = ret + 2;
2147+		} else {
2148+			ret = sprintf(dst, "%s $%X.w", c, decoded->params.immed);
2149+		}
2150+		break;
2151+	case MODE_ABSOLUTE:
2152+		if (labels) {
2153+			ret = sprintf(dst, "%s ", c);
2154+			ret += label_fun(dst+ret, decoded->params.immed, data);
2155+			strcat(dst+ret, ".l");
2156+			ret = ret + 2;
2157+		} else {
2158+			ret = sprintf(dst, "%s $%X", c, decoded->params.immed);
2159+		}
2160+		break;
2161+	case MODE_PC_DISPLACE:
2162+		if (labels) {
2163+			ret = sprintf(dst, "%s ", c);
2164+			ret += label_fun(dst+ret, address + 2 + decoded->params.regs.displacement, data);
2165+			strcat(dst+ret, "(pc)");
2166+			ret = ret + 4;
2167+		} else {
2168+			ret = sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement);
2169+		}
2170+		break;
2171+	case MODE_PC_INDEX_DISP8:
2172+#ifdef M68020
2173+		if (decoded->params.regs.scale)
2174+		{
2175+			ret = sprintf(dst, "%s (%d, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2176+		} else {
2177+#endif
2178+			ret = sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
2179+#ifdef M68020
2180+		}
2181+#endif
2182+		break;
2183+#ifdef M68020
2184+	case MODE_PC_INDEX_BASE_DISP:
2185+		if (decoded->params.regs.disp_sizes > 1)
2186+		{
2187+			ret = sprintf(dst, "%s (%d.%c, pc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
2188+			              decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
2189+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2190+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2191+		} else {
2192+			ret = sprintf(dst, "%s (pc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2193+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2194+			              1 << decoded->params.regs.scale);
2195+		}
2196+		break;
2197+	case MODE_PC_PREINDEX:
2198+		switch (decoded->params.regs.disp_sizes)
2199+		{
2200+		case 0x11:
2201+			//no base displacement or outer displacement
2202+			ret = sprintf(dst, "%s ([pc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2203+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2204+			              1 << decoded->params.regs.scale);
2205+			break;
2206+		case 0x12:
2207+		case 0x13:
2208+			//base displacement only
2209+			ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
2210+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2211+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2212+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2213+			break;
2214+		case 0x21:
2215+		case 0x31:
2216+			//outer displacement only
2217+			ret = sprintf(dst, "%s ([pc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2218+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2219+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2220+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2221+			break;
2222+		case 0x22:
2223+		case 0x23:
2224+		case 0x32:
2225+		case 0x33:
2226+			//both outer and inner displacement
2227+			ret = sprintf(dst, "%s ([%d.%c, pc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
2228+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2229+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2230+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2231+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2232+			break;
2233+		}
2234+		break;
2235+	case MODE_PC_POSTINDEX:
2236+		switch (decoded->params.regs.disp_sizes)
2237+		{
2238+		case 0x11:
2239+			//no base displacement or outer displacement
2240+			ret = sprintf(dst, "%s ([pc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2241+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2242+			              1 << decoded->params.regs.scale);
2243+			break;
2244+		case 0x12:
2245+		case 0x13:
2246+			//base displacement only
2247+			ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
2248+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2249+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2250+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2251+			break;
2252+		case 0x21:
2253+		case 0x31:
2254+			//outer displacement only
2255+			ret = sprintf(dst, "%s ([pc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2256+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2257+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2258+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2259+			break;
2260+		case 0x22:
2261+		case 0x23:
2262+		case 0x32:
2263+		case 0x33:
2264+			//both outer and inner displacement
2265+			ret = sprintf(dst, "%s ([%d.%c, pc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
2266+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2267+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2268+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2269+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2270+			break;
2271+		}
2272+		break;
2273+	case MODE_PC_MEM_INDIRECT:
2274+		switch (decoded->params.regs.disp_sizes)
2275+		{
2276+		case 0x11:
2277+			//no base displacement or outer displacement
2278+			ret = sprintf(dst, "%s ([pc])", c);
2279+			break;
2280+		case 0x12:
2281+		case 0x13:
2282+			//base displacement only
2283+			ret = sprintf(dst, "%s ([%d.%c, pc])", c, decoded->params.regs.displacement,
2284+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2285+			break;
2286+		case 0x21:
2287+		case 0x31:
2288+			//outer displacement only
2289+			ret = sprintf(dst, "%s ([pc], %d.%c)", c, decoded->params.regs.outer_disp,
2290+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2291+			break;
2292+		case 0x22:
2293+		case 0x23:
2294+		case 0x32:
2295+		case 0x33:
2296+			//both outer and inner displacement
2297+			ret = sprintf(dst, "%s ([%d.%c, pc], %d.%c)", c, decoded->params.regs.displacement,
2298+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
2299+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2300+			break;
2301+		}
2302+		break;
2303+	case MODE_PC_BASE_DISP:
2304+		if (decoded->params.regs.disp_sizes > 1)
2305+		{
2306+			ret = sprintf(dst, "%s (%d.%c, pc)", c, decoded->params.regs.displacement,
2307+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2308+		} else {
2309+			ret = sprintf(dst, "%s (pc)", c);
2310+		}
2311+		break;
2312+	case MODE_ZPC_INDEX_BASE_DISP:
2313+		if (decoded->params.regs.disp_sizes > 1)
2314+		{
2315+			ret = sprintf(dst, "%s (%d.%c, zpc, %c%d.%c*%d)", c, decoded->params.regs.displacement,
2316+			              decoded->params.regs.disp_sizes == 2 ? 'w' : 'l',
2317+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2318+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2319+		} else {
2320+			ret = sprintf(dst, "%s (zpc, %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2321+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2322+			              1 << decoded->params.regs.scale);
2323+		}
2324+		break;
2325+	case MODE_ZPC_PREINDEX:
2326+		switch (decoded->params.regs.disp_sizes)
2327+		{
2328+		case 0x11:
2329+			//no base displacement or outer displacement
2330+			ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d])", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2331+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2332+			              1 << decoded->params.regs.scale);
2333+			break;
2334+		case 0x12:
2335+		case 0x13:
2336+			//base displacement only
2337+			ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d])", c, decoded->params.regs.displacement,
2338+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2339+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2340+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2341+			break;
2342+		case 0x21:
2343+		case 0x31:
2344+			//outer displacement only
2345+			ret = sprintf(dst, "%s ([zpc, %c%d.%c*%d], %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2346+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2347+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2348+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2349+			break;
2350+		case 0x22:
2351+		case 0x23:
2352+		case 0x32:
2353+		case 0x33:
2354+			//both outer and inner displacement
2355+			ret = sprintf(dst, "%s ([%d.%c, zpc, %c%d.%c*%d], %d.%c)", c, decoded->params.regs.displacement,
2356+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2357+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2358+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2359+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2360+			break;
2361+		}
2362+		break;
2363+	case MODE_ZPC_POSTINDEX:
2364+		switch (decoded->params.regs.disp_sizes)
2365+		{
2366+		case 0x11:
2367+			//no base displacement or outer displacement
2368+			ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2369+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2370+			              1 << decoded->params.regs.scale);
2371+			break;
2372+		case 0x12:
2373+		case 0x13:
2374+			//base displacement only
2375+			ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d)", c, decoded->params.regs.displacement,
2376+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2377+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2378+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale);
2379+			break;
2380+		case 0x21:
2381+		case 0x31:
2382+			//outer displacement only
2383+			ret = sprintf(dst, "%s ([zpc], %c%d.%c*%d, %d.%c)", c, (decoded->params.regs.sec & 0x10) ? 'a': 'd',
2384+			              (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w',
2385+			              1 << decoded->params.regs.scale, decoded->params.regs.outer_disp,
2386+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2387+			break;
2388+		case 0x22:
2389+		case 0x23:
2390+		case 0x32:
2391+		case 0x33:
2392+			//both outer and inner displacement
2393+			ret = sprintf(dst, "%s ([%d.%c, zpc], %c%d.%c*%d, %d.%c)", c, decoded->params.regs.displacement,
2394+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l',
2395+			              (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7,
2396+			              (decoded->params.regs.sec & 1) ? 'l': 'w', 1 << decoded->params.regs.scale,
2397+			              decoded->params.regs.outer_disp, decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2398+			break;
2399+		}
2400+		break;
2401+	case MODE_ZPC_MEM_INDIRECT:
2402+		switch (decoded->params.regs.disp_sizes)
2403+		{
2404+		case 0x11:
2405+			//no base displacement or outer displacement
2406+			ret = sprintf(dst, "%s ([zpc])", c);
2407+			break;
2408+		case 0x12:
2409+		case 0x13:
2410+			//base displacement only
2411+			ret = sprintf(dst, "%s ([%d.%c, zpc])", c, decoded->params.regs.displacement,
2412+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2413+			break;
2414+		case 0x21:
2415+		case 0x31:
2416+			//outer displacement only
2417+			ret = sprintf(dst, "%s ([zpc], %d.%c)", c, decoded->params.regs.outer_disp,
2418+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2419+			break;
2420+		case 0x22:
2421+		case 0x23:
2422+		case 0x32:
2423+		case 0x33:
2424+			//both outer and inner displacement
2425+			ret = sprintf(dst, "%s ([%d.%c, zpc], %d.%c)", c, decoded->params.regs.displacement,
2426+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l', decoded->params.regs.outer_disp,
2427+			              decoded->params.regs.disp_sizes & 0x30 == 0x20 ? 'w' : 'l');
2428+			break;
2429+		}
2430+		break;
2431+	case MODE_ZPC_BASE_DISP:
2432+		if (decoded->params.regs.disp_sizes > 1)
2433+		{
2434+			ret = sprintf(dst, "%s (%d.%c, zpc)", c, decoded->params.regs.displacement,
2435+			              decoded->params.regs.disp_sizes & 3 == 2 ? 'w' : 'l');
2436+		} else {
2437+			ret = sprintf(dst, "%s (zpc)", c);
2438+		}
2439+		break;
2440+#endif
2441+	default:
2442+		ret = 0;
2443+	}
2444+#ifdef M68020
2445+	if (decoded->addr_mode & M68K_FLAG_BITFIELD)
2446+	{
2447+		switch (decoded->bitfield & 0x820)
2448+		{
2449+		case 0:
2450+			return ret + sprintf(dst+ret, " {$%X:%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
2451+		case 0x20:
2452+			return ret + sprintf(dst+ret, " {$%X:d%d}", decoded->bitfield >> 6 & 0x1F, decoded->bitfield & 0x7);
2453+		case 0x800:
2454+			return ret + sprintf(dst+ret, " {d%d:%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x1F ? decoded->bitfield & 0x1F : 32);
2455+		case 0x820:
2456+			return ret + sprintf(dst+ret, " {d%d:d%d}", decoded->bitfield >> 6 & 0x7, decoded->bitfield & 0x7);
2457+		}
2458+	}
2459+#endif
2460+	return ret;
2461+}
2462+
2463+int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address, format_label_fun label_fun, void * data)
2464+{
2465+	int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
2466+	char *rtype, *last_rtype;
2467+	int oplen;
2468+	if (decoded->addr_mode == MODE_REG) {
2469+		if (other->addr_mode == MODE_AREG_PREDEC) {
2470+			bit = 15;
2471+			dir = -1;
2472+		} else {
2473+			dir = 1;
2474+			bit = 0;
2475+		}
2476+		if (need_comma) {
2477+			strcat(dst, ", ");
2478+			oplen = 2;
2479+		} else {
2480+			strcat(dst, " ");
2481+			oplen = 1;
2482+		}
2483+		for (reg=0; bit < 16 && bit > -1; bit += dir, reg++) {
2484+			if (decoded->params.immed & (1 << bit)) {
2485+				if (reg > 7) {
2486+					rtype = "a";
2487+					regnum = reg - 8;
2488+				} else {
2489+					rtype = "d";
2490+					regnum = reg;
2491+				}
2492+				if (last >= 0 && last == regnum - 1 && lastreg == reg - 1) {
2493+					last = regnum;
2494+					lastreg = reg;
2495+				} else if(last >= 0) {
2496+					if (first != last) {
2497+						oplen += sprintf(dst + oplen, "-%s%d/%s%d",last_rtype, last, rtype, regnum);
2498+					} else {
2499+						oplen += sprintf(dst + oplen, "/%s%d", rtype, regnum);
2500+					}
2501+					first = last = regnum;
2502+					last_rtype = rtype;
2503+					lastreg = reg;
2504+				} else {
2505+					oplen += sprintf(dst + oplen, "%s%d", rtype, regnum);
2506+					first = last = regnum;
2507+					last_rtype = rtype;
2508+					lastreg = reg;
2509+				}
2510+			}
2511+		}
2512+		if (last >= 0 && last != first) {
2513+			oplen += sprintf(dst + oplen, "-%s%d", last_rtype, last);
2514+		}
2515+		return oplen;
2516+	} else {
2517+		return m68k_disasm_op(decoded, dst, need_comma, labels, address, label_fun, data);
2518+	}
2519+}
2520+
2521+int m68k_default_label_fun(char * dst, uint32_t address, void * data)
2522+{
2523+	return sprintf(dst, "ADR_%X", address);
2524+}
2525+
2526+int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels, format_label_fun label_fun, void * data)
2527+{
2528+	int ret,op1len;
2529+	uint8_t size;
2530+	char * special_op = "CCR";
2531+	switch (decoded->op)
2532+	{
2533+	case M68K_BCC:
2534+	case M68K_DBCC:
2535+	case M68K_SCC:
2536+		ret = strlen(mnemonics[decoded->op]) - 2;
2537+		memcpy(dst, mnemonics[decoded->op], ret);
2538+		dst[ret] = 0;
2539+		strcpy(dst+ret, cond_mnem[decoded->extra.cond]);
2540+		ret = strlen(dst);
2541+		if (decoded->op != M68K_SCC) {
2542+			if (labels) {
2543+				if (decoded->op == M68K_DBCC) {
2544+					ret += sprintf(dst+ret, " d%d, ", decoded->dst.params.regs.pri);
2545+					ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
2546+				} else {
2547+					dst[ret++] = ' ';
2548+					ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
2549+				}
2550+			} else {
2551+				if (decoded->op == M68K_DBCC) {
2552+					ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
2553+				} else {
2554+					ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
2555+				}
2556+			}
2557+			return ret;
2558+		}
2559+		break;
2560+	case M68K_BSR:
2561+		if (labels) {
2562+			ret = sprintf(dst, "bsr%s ", decoded->variant == VAR_BYTE ? ".s" : "");
2563+			ret += label_fun(dst+ret, decoded->address + 2 + decoded->src.params.immed, data);
2564+		} else {
2565+			ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
2566+		}
2567+		return ret;
2568+	case M68K_MOVE_FROM_SR:
2569+		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
2570+		ret += sprintf(dst + ret, " SR");
2571+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address, label_fun, data);
2572+		return ret;
2573+	case M68K_ANDI_SR:
2574+	case M68K_EORI_SR:
2575+	case M68K_MOVE_SR:
2576+	case M68K_ORI_SR:
2577+		special_op = "SR";
2578+	case M68K_ANDI_CCR:
2579+	case M68K_EORI_CCR:
2580+	case M68K_MOVE_CCR:
2581+	case M68K_ORI_CCR:
2582+		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
2583+		ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
2584+		ret += sprintf(dst + ret, ", %s", special_op);
2585+		return ret;
2586+	case M68K_MOVE_USP:
2587+		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
2588+		if (decoded->src.addr_mode != MODE_UNUSED) {
2589+			ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
2590+			ret += sprintf(dst + ret, ", USP");
2591+		} else {
2592+			ret += sprintf(dst + ret, "USP, ");
2593+			ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
2594+		}
2595+		return ret;
2596+	case M68K_INVALID:
2597+		ret = sprintf(dst, "dc.w $%X", decoded->src.params.immed);
2598+		return ret;
2599+#ifdef M68010
2600+	case M68K_MOVEC:
2601+		ret = sprintf(dst, "%s ", mnemonics[decoded->op]);
2602+		if (decoded->src.addr_mode == MODE_UNUSED) {
2603+			ret += sprintf(dst + ret, "%s, ", cr_mnem[decoded->src.params.immed]);
2604+			ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
2605+		} else {
2606+			ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
2607+			ret += sprintf(dst + ret, ", %s", cr_mnem[decoded->dst.params.immed]);
2608+		}
2609+		return ret;
2610+#endif
2611+	default:
2612+		size = decoded->extra.size;
2613+		uint8_t is_quick = decoded->variant == VAR_QUICK && decoded->op != M68K_ASL && decoded->op != M68K_ASR 
2614+			&& decoded->op != M68K_LSL && decoded->op != M68K_LSR && decoded->op != M68K_ROXR && decoded->op != M68K_ROXL
2615+			&& decoded->op != M68K_ROR && decoded->op != M68K_ROL;
2616+		ret = sprintf(dst, "%s%s%s",
2617+				mnemonics[decoded->op],
2618+				is_quick ? "q" : (decoded->variant == VAR_IMMEDIATE ? "i" : ""),
2619+				size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
2620+	}
2621+	if (decoded->op == M68K_MOVEM) {
2622+		op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address, label_fun, data);
2623+		ret += op1len;
2624+		ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address, label_fun, data);
2625+	} else {
2626+		op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address, label_fun, data);
2627+		ret += op1len;
2628+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address, label_fun, data);
2629+	}
2630+	return ret;
2631+}
2632+
2633+int m68k_disasm(m68kinst * decoded, char * dst)
2634+{
2635+	return m68k_disasm_ex(decoded, dst, 0, NULL, NULL);
2636+}
2637+
2638+int m68k_disasm_labels(m68kinst * decoded, char * dst, format_label_fun label_fun, void * data)
2639+{
2640+	if (!label_fun)
2641+	{
2642+		label_fun = m68k_default_label_fun;
2643+	}
2644+	return m68k_disasm_ex(decoded, dst, 1, label_fun, data);
2645+}
+347, -0
  1@@ -0,0 +1,347 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef M68KINST_H_
  8+#define M68KINST_H_
  9+
 10+#include <stdint.h>
 11+
 12+#ifdef M68030
 13+#define M68020
 14+#endif
 15+#ifdef M68020
 16+#define M68010
 17+#endif
 18+
 19+typedef enum {
 20+	BIT_MOVEP_IMMED = 0,
 21+	MOVE_BYTE,
 22+	MOVE_LONG,
 23+	MOVE_WORD,
 24+	MISC,
 25+	QUICK_ARITH_LOOP,
 26+	BRANCH,
 27+	MOVEQ,
 28+	OR_DIV_SBCD,
 29+	SUB_SUBX,
 30+	A_LINE,
 31+	CMP_XOR,
 32+	AND_MUL_ABCD_EXG,
 33+	ADD_ADDX,
 34+	SHIFT_ROTATE,
 35+	F_LINE
 36+} m68k_optypes;
 37+
 38+typedef enum {
 39+	M68K_ABCD,
 40+	M68K_ADD,
 41+	M68K_ADDX,
 42+	M68K_AND,
 43+	M68K_ANDI_CCR,
 44+	M68K_ANDI_SR,
 45+	M68K_ASL,
 46+	M68K_ASR,
 47+	M68K_BCC,
 48+	M68K_BCHG,
 49+	M68K_BCLR,
 50+	M68K_BSET,
 51+	M68K_BSR,
 52+	M68K_BTST,
 53+	M68K_CHK,
 54+	M68K_CLR,
 55+	M68K_CMP,
 56+	M68K_DBCC,
 57+	M68K_DIVS,
 58+	M68K_DIVU,
 59+	M68K_EOR,
 60+	M68K_EORI_CCR,
 61+	M68K_EORI_SR,
 62+	M68K_EXG,
 63+	M68K_EXT,
 64+	M68K_ILLEGAL,
 65+	M68K_JMP,
 66+	M68K_JSR,
 67+	M68K_LEA,
 68+	M68K_LINK,
 69+	M68K_LSL,
 70+	M68K_LSR,
 71+	M68K_MOVE,
 72+	M68K_MOVE_CCR,
 73+	M68K_MOVE_FROM_SR,
 74+	M68K_MOVE_SR,
 75+	M68K_MOVE_USP,
 76+	M68K_MOVEM,
 77+	M68K_MOVEP,
 78+	M68K_MULS,
 79+	M68K_MULU,
 80+	M68K_NBCD,
 81+	M68K_NEG,
 82+	M68K_NEGX,
 83+	M68K_NOP,
 84+	M68K_NOT,
 85+	M68K_OR,
 86+	M68K_ORI_CCR,
 87+	M68K_ORI_SR,
 88+	M68K_PEA,
 89+	M68K_RESET,
 90+	M68K_ROL,
 91+	M68K_ROR,
 92+	M68K_ROXL,
 93+	M68K_ROXR,
 94+	M68K_RTE,
 95+	M68K_RTR,
 96+	M68K_RTS,
 97+	M68K_SBCD,
 98+	M68K_SCC,
 99+	M68K_STOP,
100+	M68K_SUB,
101+	M68K_SUBX,
102+	M68K_SWAP,
103+	M68K_TAS,
104+	M68K_TRAP,
105+	M68K_TRAPV,
106+	M68K_TST,
107+	M68K_UNLK,
108+	M68K_INVALID,
109+	M68K_A_LINE_TRAP,
110+	M68K_F_LINE_TRAP,
111+#ifdef M68010
112+	M68K_BKPT,
113+	M68K_MOVE_FROM_CCR,
114+	M68K_MOVEC,
115+	M68K_MOVES,
116+	M68K_RTD,
117+#endif
118+#ifdef M68020
119+	M68K_BFCHG,
120+	M68K_BFCLR,
121+	M68K_BFEXTS,
122+	M68K_BFEXTU,
123+	M68K_BFFFO,
124+	M68K_BFINS,
125+	M68K_BFSET,
126+	M68K_BFTST,
127+	M68K_CALLM,
128+	M68K_CAS,
129+	M68K_CAS2,
130+	M68K_CHK2,
131+	M68K_CMP2,
132+	M68K_CP_BCC,
133+	M68K_CP_DBCC,
134+	M68K_CP_GEN,
135+	M68K_CP_RESTORE,
136+	M68K_CP_SAVE,
137+	M68K_CP_SCC,
138+	M68K_CP_TRAPCC,
139+	M68K_DIVSL,
140+	M68K_DIVUL,
141+	M68K_EXTB,
142+	M68K_PACK,
143+	M68K_RTM,
144+	M68K_TRAPCC,
145+	M68K_UNPK,
146+#endif
147+} m68K_op;
148+
149+typedef enum {
150+	VAR_NORMAL,
151+	VAR_QUICK,
152+	VAR_IMMEDIATE,
153+	VAR_BYTE,
154+	VAR_WORD,
155+	VAR_LONG
156+} m68K_variant;
157+
158+typedef enum {
159+	OPSIZE_BYTE=0,
160+	OPSIZE_WORD,
161+	OPSIZE_LONG,
162+	OPSIZE_INVALID,
163+	OPSIZE_UNSIZED
164+} m68K_opsizes;
165+
166+typedef enum {
167+//actual addressing mode field values
168+	MODE_REG = 0,
169+	MODE_AREG,
170+	MODE_AREG_INDIRECT,
171+	MODE_AREG_POSTINC,
172+	MODE_AREG_PREDEC,
173+	MODE_AREG_DISPLACE,
174+	MODE_AREG_INDEX_MEM, //bunch of relatively complicated modes
175+	MODE_PC_INDIRECT_ABS_IMMED, //Modes that use the program counter, an absolute address or immediate value
176+//expanded values
177+	MODE_AREG_INDEX_DISP8,
178+#ifdef M68020
179+	MODE_AREG_INDEX_BASE_DISP,
180+	MODE_AREG_PREINDEX,
181+	MODE_AREG_POSTINDEX,
182+	MODE_AREG_MEM_INDIRECT,
183+	MODE_AREG_BASE_DISP,
184+	MODE_INDEX_BASE_DISP,
185+	MODE_PREINDEX,
186+	MODE_POSTINDEX,
187+	MODE_MEM_INDIRECT,
188+	MODE_BASE_DISP,
189+#endif
190+	MODE_ABSOLUTE_SHORT,
191+	MODE_ABSOLUTE,
192+	MODE_PC_DISPLACE,
193+	MODE_PC_INDEX_DISP8,
194+#ifdef M68020
195+	MODE_PC_INDEX_BASE_DISP,
196+	MODE_PC_PREINDEX,
197+	MODE_PC_POSTINDEX,
198+	MODE_PC_MEM_INDIRECT,
199+	MODE_PC_BASE_DISP,
200+	MODE_ZPC_INDEX_BASE_DISP,
201+	MODE_ZPC_PREINDEX,
202+	MODE_ZPC_POSTINDEX,
203+	MODE_ZPC_MEM_INDIRECT,
204+	MODE_ZPC_BASE_DISP,
205+#endif
206+	MODE_IMMEDIATE,
207+	MODE_IMMEDIATE_WORD,//used to indicate an immediate operand that only uses a single extension word even for a long operation
208+	MODE_UNUSED
209+} m68k_addr_modes;
210+#ifdef M68020
211+#define M68K_FLAG_BITFIELD 0x80
212+#endif
213+
214+typedef enum {
215+	COND_TRUE,
216+	COND_FALSE,
217+	COND_HIGH,
218+	COND_LOW_SAME,
219+	COND_CARRY_CLR,
220+	COND_CARRY_SET,
221+	COND_NOT_EQ,
222+	COND_EQ,
223+	COND_OVERF_CLR,
224+	COND_OVERF_SET,
225+	COND_PLUS,
226+	COND_MINUS,
227+	COND_GREATER_EQ,
228+	COND_LESS,
229+	COND_GREATER,
230+	COND_LESS_EQ
231+} m68K_condition;
232+
233+#ifdef M68010
234+typedef enum {
235+	CR_SFC,
236+	CR_DFC,
237+#ifdef M68020
238+	CR_CACR,
239+#endif
240+	CR_USP,
241+	CR_VBR,
242+#ifdef M68020
243+	CR_CAAR,
244+	CR_MSP,
245+	CR_ISP
246+#endif
247+} m68k_control_reg;
248+
249+#ifdef M68020
250+#define MAX_HIGH_CR 0x804
251+#define MAX_LOW_CR 0x002
252+#else
253+#define MAX_HIGH_CR 0x801
254+#define MAX_LOW_CR 0x001
255+#endif
256+
257+#endif
258+
259+typedef struct {
260+#ifdef M68020
261+	uint16_t bitfield;
262+#endif
263+	uint8_t  addr_mode;
264+	union {
265+		struct {
266+			uint8_t pri;
267+			uint8_t sec;
268+#ifdef M68020
269+			uint8_t scale;
270+			uint8_t disp_sizes;
271+#endif
272+			int32_t displacement;
273+#ifdef M68020
274+			int32_t outer_disp;
275+#endif
276+		} regs;
277+		uint32_t immed;
278+	} params;
279+} m68k_op_info;
280+
281+typedef struct m68kinst {
282+	uint8_t op;
283+	uint8_t variant;
284+	union {
285+		uint8_t size;
286+		uint8_t cond;
287+	} extra;
288+	uint8_t bytes;
289+	uint32_t address;
290+	m68k_op_info src;
291+	m68k_op_info dst;
292+} m68kinst;
293+
294+typedef enum {
295+	VECTOR_RESET_STACK,
296+	VECTOR_RESET_PC,
297+	VECTOR_ACCESS_FAULT,
298+	VECTOR_ADDRESS_ERROR,
299+	VECTOR_ILLEGAL_INST,
300+	VECTOR_INT_DIV_ZERO,
301+	VECTOR_CHK,
302+	VECTOR_TRAPV,
303+	VECTOR_PRIV_VIOLATION,
304+	VECTOR_TRACE,
305+	VECTOR_LINE_1010,
306+	VECTOR_LINE_1111,
307+	VECTOR_COPROC_VIOLATION=13,
308+	VECTOR_FORMAT_ERROR,
309+	VECTOR_UNINIT_INTERRUPT,
310+	VECTOR_SPURIOUS_INTERRUPT=24,
311+	VECTOR_INT_1,
312+	VECTOR_INT_2,
313+	VECTOR_INT_3,
314+	VECTOR_INT_4,
315+	VECTOR_INT_5,
316+	VECTOR_INT_6,
317+	VECTOR_INT_7,
318+	VECTOR_TRAP_0,
319+	VECTOR_TRAP_1,
320+	VECTOR_TRAP_2,
321+	VECTOR_TRAP_3,
322+	VECTOR_TRAP_4,
323+	VECTOR_TRAP_5,
324+	VECTOR_TRAP_6,
325+	VECTOR_TRAP_7,
326+	VECTOR_TRAP_8,
327+	VECTOR_TRAP_9,
328+	VECTOR_TRAP_10,
329+	VECTOR_TRAP_11,
330+	VECTOR_TRAP_12,
331+	VECTOR_TRAP_13,
332+	VECTOR_TRAP_14,
333+	VECTOR_TRAP_15,
334+	VECTOR_USER0 = 64
335+} m68k_vector;
336+
337+typedef int (*format_label_fun)(char * dst, uint32_t address, void * data);
338+
339+uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address);
340+uint32_t m68k_branch_target(m68kinst * inst, uint32_t *dregs, uint32_t *aregs);
341+uint8_t m68k_is_branch(m68kinst * inst);
342+uint8_t m68k_is_noncall_branch(m68kinst * inst);
343+int m68k_disasm(m68kinst * decoded, char * dst);
344+int m68k_disasm_labels(m68kinst * decoded, char * dst, format_label_fun label_fun, void * data);
345+int m68k_default_label_fun(char * dst, uint32_t address, void * data);
346+
347+#endif
348+
+674, -0
  1@@ -0,0 +1,674 @@
  2+                    GNU GENERAL PUBLIC LICENSE
  3+                       Version 3, 29 June 2007
  4+
  5+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
  6+ Everyone is permitted to copy and distribute verbatim copies
  7+ of this license document, but changing it is not allowed.
  8+
  9+                            Preamble
 10+
 11+  The GNU General Public License is a free, copyleft license for
 12+software and other kinds of works.
 13+
 14+  The licenses for most software and other practical works are designed
 15+to take away your freedom to share and change the works.  By contrast,
 16+the GNU General Public License is intended to guarantee your freedom to
 17+share and change all versions of a program--to make sure it remains free
 18+software for all its users.  We, the Free Software Foundation, use the
 19+GNU General Public License for most of our software; it applies also to
 20+any other work released this way by its authors.  You can apply it to
 21+your programs, too.
 22+
 23+  When we speak of free software, we are referring to freedom, not
 24+price.  Our General Public Licenses are designed to make sure that you
 25+have the freedom to distribute copies of free software (and charge for
 26+them if you wish), that you receive source code or can get it if you
 27+want it, that you can change the software or use pieces of it in new
 28+free programs, and that you know you can do these things.
 29+
 30+  To protect your rights, we need to prevent others from denying you
 31+these rights or asking you to surrender the rights.  Therefore, you have
 32+certain responsibilities if you distribute copies of the software, or if
 33+you modify it: responsibilities to respect the freedom of others.
 34+
 35+  For example, if you distribute copies of such a program, whether
 36+gratis or for a fee, you must pass on to the recipients the same
 37+freedoms that you received.  You must make sure that they, too, receive
 38+or can get the source code.  And you must show them these terms so they
 39+know their rights.
 40+
 41+  Developers that use the GNU GPL protect your rights with two steps:
 42+(1) assert copyright on the software, and (2) offer you this License
 43+giving you legal permission to copy, distribute and/or modify it.
 44+
 45+  For the developers' and authors' protection, the GPL clearly explains
 46+that there is no warranty for this free software.  For both users' and
 47+authors' sake, the GPL requires that modified versions be marked as
 48+changed, so that their problems will not be attributed erroneously to
 49+authors of previous versions.
 50+
 51+  Some devices are designed to deny users access to install or run
 52+modified versions of the software inside them, although the manufacturer
 53+can do so.  This is fundamentally incompatible with the aim of
 54+protecting users' freedom to change the software.  The systematic
 55+pattern of such abuse occurs in the area of products for individuals to
 56+use, which is precisely where it is most unacceptable.  Therefore, we
 57+have designed this version of the GPL to prohibit the practice for those
 58+products.  If such problems arise substantially in other domains, we
 59+stand ready to extend this provision to those domains in future versions
 60+of the GPL, as needed to protect the freedom of users.
 61+
 62+  Finally, every program is threatened constantly by software patents.
 63+States should not allow patents to restrict development and use of
 64+software on general-purpose computers, but in those that do, we wish to
 65+avoid the special danger that patents applied to a free program could
 66+make it effectively proprietary.  To prevent this, the GPL assures that
 67+patents cannot be used to render the program non-free.
 68+
 69+  The precise terms and conditions for copying, distribution and
 70+modification follow.
 71+
 72+                       TERMS AND CONDITIONS
 73+
 74+  0. Definitions.
 75+
 76+  "This License" refers to version 3 of the GNU General Public License.
 77+
 78+  "Copyright" also means copyright-like laws that apply to other kinds of
 79+works, such as semiconductor masks.
 80+
 81+  "The Program" refers to any copyrightable work licensed under this
 82+License.  Each licensee is addressed as "you".  "Licensees" and
 83+"recipients" may be individuals or organizations.
 84+
 85+  To "modify" a work means to copy from or adapt all or part of the work
 86+in a fashion requiring copyright permission, other than the making of an
 87+exact copy.  The resulting work is called a "modified version" of the
 88+earlier work or a work "based on" the earlier work.
 89+
 90+  A "covered work" means either the unmodified Program or a work based
 91+on the Program.
 92+
 93+  To "propagate" a work means to do anything with it that, without
 94+permission, would make you directly or secondarily liable for
 95+infringement under applicable copyright law, except executing it on a
 96+computer or modifying a private copy.  Propagation includes copying,
 97+distribution (with or without modification), making available to the
 98+public, and in some countries other activities as well.
 99+
100+  To "convey" a work means any kind of propagation that enables other
101+parties to make or receive copies.  Mere interaction with a user through
102+a computer network, with no transfer of a copy, is not conveying.
103+
104+  An interactive user interface displays "Appropriate Legal Notices"
105+to the extent that it includes a convenient and prominently visible
106+feature that (1) displays an appropriate copyright notice, and (2)
107+tells the user that there is no warranty for the work (except to the
108+extent that warranties are provided), that licensees may convey the
109+work under this License, and how to view a copy of this License.  If
110+the interface presents a list of user commands or options, such as a
111+menu, a prominent item in the list meets this criterion.
112+
113+  1. Source Code.
114+
115+  The "source code" for a work means the preferred form of the work
116+for making modifications to it.  "Object code" means any non-source
117+form of a work.
118+
119+  A "Standard Interface" means an interface that either is an official
120+standard defined by a recognized standards body, or, in the case of
121+interfaces specified for a particular programming language, one that
122+is widely used among developers working in that language.
123+
124+  The "System Libraries" of an executable work include anything, other
125+than the work as a whole, that (a) is included in the normal form of
126+packaging a Major Component, but which is not part of that Major
127+Component, and (b) serves only to enable use of the work with that
128+Major Component, or to implement a Standard Interface for which an
129+implementation is available to the public in source code form.  A
130+"Major Component", in this context, means a major essential component
131+(kernel, window system, and so on) of the specific operating system
132+(if any) on which the executable work runs, or a compiler used to
133+produce the work, or an object code interpreter used to run it.
134+
135+  The "Corresponding Source" for a work in object code form means all
136+the source code needed to generate, install, and (for an executable
137+work) run the object code and to modify the work, including scripts to
138+control those activities.  However, it does not include the work's
139+System Libraries, or general-purpose tools or generally available free
140+programs which are used unmodified in performing those activities but
141+which are not part of the work.  For example, Corresponding Source
142+includes interface definition files associated with source files for
143+the work, and the source code for shared libraries and dynamically
144+linked subprograms that the work is specifically designed to require,
145+such as by intimate data communication or control flow between those
146+subprograms and other parts of the work.
147+
148+  The Corresponding Source need not include anything that users
149+can regenerate automatically from other parts of the Corresponding
150+Source.
151+
152+  The Corresponding Source for a work in source code form is that
153+same work.
154+
155+  2. Basic Permissions.
156+
157+  All rights granted under this License are granted for the term of
158+copyright on the Program, and are irrevocable provided the stated
159+conditions are met.  This License explicitly affirms your unlimited
160+permission to run the unmodified Program.  The output from running a
161+covered work is covered by this License only if the output, given its
162+content, constitutes a covered work.  This License acknowledges your
163+rights of fair use or other equivalent, as provided by copyright law.
164+
165+  You may make, run and propagate covered works that you do not
166+convey, without conditions so long as your license otherwise remains
167+in force.  You may convey covered works to others for the sole purpose
168+of having them make modifications exclusively for you, or provide you
169+with facilities for running those works, provided that you comply with
170+the terms of this License in conveying all material for which you do
171+not control copyright.  Those thus making or running the covered works
172+for you must do so exclusively on your behalf, under your direction
173+and control, on terms that prohibit them from making any copies of
174+your copyrighted material outside their relationship with you.
175+
176+  Conveying under any other circumstances is permitted solely under
177+the conditions stated below.  Sublicensing is not allowed; section 10
178+makes it unnecessary.
179+
180+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
181+
182+  No covered work shall be deemed part of an effective technological
183+measure under any applicable law fulfilling obligations under article
184+11 of the WIPO copyright treaty adopted on 20 December 1996, or
185+similar laws prohibiting or restricting circumvention of such
186+measures.
187+
188+  When you convey a covered work, you waive any legal power to forbid
189+circumvention of technological measures to the extent such circumvention
190+is effected by exercising rights under this License with respect to
191+the covered work, and you disclaim any intention to limit operation or
192+modification of the work as a means of enforcing, against the work's
193+users, your or third parties' legal rights to forbid circumvention of
194+technological measures.
195+
196+  4. Conveying Verbatim Copies.
197+
198+  You may convey verbatim copies of the Program's source code as you
199+receive it, in any medium, provided that you conspicuously and
200+appropriately publish on each copy an appropriate copyright notice;
201+keep intact all notices stating that this License and any
202+non-permissive terms added in accord with section 7 apply to the code;
203+keep intact all notices of the absence of any warranty; and give all
204+recipients a copy of this License along with the Program.
205+
206+  You may charge any price or no price for each copy that you convey,
207+and you may offer support or warranty protection for a fee.
208+
209+  5. Conveying Modified Source Versions.
210+
211+  You may convey a work based on the Program, or the modifications to
212+produce it from the Program, in the form of source code under the
213+terms of section 4, provided that you also meet all of these conditions:
214+
215+    a) The work must carry prominent notices stating that you modified
216+    it, and giving a relevant date.
217+
218+    b) The work must carry prominent notices stating that it is
219+    released under this License and any conditions added under section
220+    7.  This requirement modifies the requirement in section 4 to
221+    "keep intact all notices".
222+
223+    c) You must license the entire work, as a whole, under this
224+    License to anyone who comes into possession of a copy.  This
225+    License will therefore apply, along with any applicable section 7
226+    additional terms, to the whole of the work, and all its parts,
227+    regardless of how they are packaged.  This License gives no
228+    permission to license the work in any other way, but it does not
229+    invalidate such permission if you have separately received it.
230+
231+    d) If the work has interactive user interfaces, each must display
232+    Appropriate Legal Notices; however, if the Program has interactive
233+    interfaces that do not display Appropriate Legal Notices, your
234+    work need not make them do so.
235+
236+  A compilation of a covered work with other separate and independent
237+works, which are not by their nature extensions of the covered work,
238+and which are not combined with it such as to form a larger program,
239+in or on a volume of a storage or distribution medium, is called an
240+"aggregate" if the compilation and its resulting copyright are not
241+used to limit the access or legal rights of the compilation's users
242+beyond what the individual works permit.  Inclusion of a covered work
243+in an aggregate does not cause this License to apply to the other
244+parts of the aggregate.
245+
246+  6. Conveying Non-Source Forms.
247+
248+  You may convey a covered work in object code form under the terms
249+of sections 4 and 5, provided that you also convey the
250+machine-readable Corresponding Source under the terms of this License,
251+in one of these ways:
252+
253+    a) Convey the object code in, or embodied in, a physical product
254+    (including a physical distribution medium), accompanied by the
255+    Corresponding Source fixed on a durable physical medium
256+    customarily used for software interchange.
257+
258+    b) Convey the object code in, or embodied in, a physical product
259+    (including a physical distribution medium), accompanied by a
260+    written offer, valid for at least three years and valid for as
261+    long as you offer spare parts or customer support for that product
262+    model, to give anyone who possesses the object code either (1) a
263+    copy of the Corresponding Source for all the software in the
264+    product that is covered by this License, on a durable physical
265+    medium customarily used for software interchange, for a price no
266+    more than your reasonable cost of physically performing this
267+    conveying of source, or (2) access to copy the
268+    Corresponding Source from a network server at no charge.
269+
270+    c) Convey individual copies of the object code with a copy of the
271+    written offer to provide the Corresponding Source.  This
272+    alternative is allowed only occasionally and noncommercially, and
273+    only if you received the object code with such an offer, in accord
274+    with subsection 6b.
275+
276+    d) Convey the object code by offering access from a designated
277+    place (gratis or for a charge), and offer equivalent access to the
278+    Corresponding Source in the same way through the same place at no
279+    further charge.  You need not require recipients to copy the
280+    Corresponding Source along with the object code.  If the place to
281+    copy the object code is a network server, the Corresponding Source
282+    may be on a different server (operated by you or a third party)
283+    that supports equivalent copying facilities, provided you maintain
284+    clear directions next to the object code saying where to find the
285+    Corresponding Source.  Regardless of what server hosts the
286+    Corresponding Source, you remain obligated to ensure that it is
287+    available for as long as needed to satisfy these requirements.
288+
289+    e) Convey the object code using peer-to-peer transmission, provided
290+    you inform other peers where the object code and Corresponding
291+    Source of the work are being offered to the general public at no
292+    charge under subsection 6d.
293+
294+  A separable portion of the object code, whose source code is excluded
295+from the Corresponding Source as a System Library, need not be
296+included in conveying the object code work.
297+
298+  A "User Product" is either (1) a "consumer product", which means any
299+tangible personal property which is normally used for personal, family,
300+or household purposes, or (2) anything designed or sold for incorporation
301+into a dwelling.  In determining whether a product is a consumer product,
302+doubtful cases shall be resolved in favor of coverage.  For a particular
303+product received by a particular user, "normally used" refers to a
304+typical or common use of that class of product, regardless of the status
305+of the particular user or of the way in which the particular user
306+actually uses, or expects or is expected to use, the product.  A product
307+is a consumer product regardless of whether the product has substantial
308+commercial, industrial or non-consumer uses, unless such uses represent
309+the only significant mode of use of the product.
310+
311+  "Installation Information" for a User Product means any methods,
312+procedures, authorization keys, or other information required to install
313+and execute modified versions of a covered work in that User Product from
314+a modified version of its Corresponding Source.  The information must
315+suffice to ensure that the continued functioning of the modified object
316+code is in no case prevented or interfered with solely because
317+modification has been made.
318+
319+  If you convey an object code work under this section in, or with, or
320+specifically for use in, a User Product, and the conveying occurs as
321+part of a transaction in which the right of possession and use of the
322+User Product is transferred to the recipient in perpetuity or for a
323+fixed term (regardless of how the transaction is characterized), the
324+Corresponding Source conveyed under this section must be accompanied
325+by the Installation Information.  But this requirement does not apply
326+if neither you nor any third party retains the ability to install
327+modified object code on the User Product (for example, the work has
328+been installed in ROM).
329+
330+  The requirement to provide Installation Information does not include a
331+requirement to continue to provide support service, warranty, or updates
332+for a work that has been modified or installed by the recipient, or for
333+the User Product in which it has been modified or installed.  Access to a
334+network may be denied when the modification itself materially and
335+adversely affects the operation of the network or violates the rules and
336+protocols for communication across the network.
337+
338+  Corresponding Source conveyed, and Installation Information provided,
339+in accord with this section must be in a format that is publicly
340+documented (and with an implementation available to the public in
341+source code form), and must require no special password or key for
342+unpacking, reading or copying.
343+
344+  7. Additional Terms.
345+
346+  "Additional permissions" are terms that supplement the terms of this
347+License by making exceptions from one or more of its conditions.
348+Additional permissions that are applicable to the entire Program shall
349+be treated as though they were included in this License, to the extent
350+that they are valid under applicable law.  If additional permissions
351+apply only to part of the Program, that part may be used separately
352+under those permissions, but the entire Program remains governed by
353+this License without regard to the additional permissions.
354+
355+  When you convey a copy of a covered work, you may at your option
356+remove any additional permissions from that copy, or from any part of
357+it.  (Additional permissions may be written to require their own
358+removal in certain cases when you modify the work.)  You may place
359+additional permissions on material, added by you to a covered work,
360+for which you have or can give appropriate copyright permission.
361+
362+  Notwithstanding any other provision of this License, for material you
363+add to a covered work, you may (if authorized by the copyright holders of
364+that material) supplement the terms of this License with terms:
365+
366+    a) Disclaiming warranty or limiting liability differently from the
367+    terms of sections 15 and 16 of this License; or
368+
369+    b) Requiring preservation of specified reasonable legal notices or
370+    author attributions in that material or in the Appropriate Legal
371+    Notices displayed by works containing it; or
372+
373+    c) Prohibiting misrepresentation of the origin of that material, or
374+    requiring that modified versions of such material be marked in
375+    reasonable ways as different from the original version; or
376+
377+    d) Limiting the use for publicity purposes of names of licensors or
378+    authors of the material; or
379+
380+    e) Declining to grant rights under trademark law for use of some
381+    trade names, trademarks, or service marks; or
382+
383+    f) Requiring indemnification of licensors and authors of that
384+    material by anyone who conveys the material (or modified versions of
385+    it) with contractual assumptions of liability to the recipient, for
386+    any liability that these contractual assumptions directly impose on
387+    those licensors and authors.
388+
389+  All other non-permissive additional terms are considered "further
390+restrictions" within the meaning of section 10.  If the Program as you
391+received it, or any part of it, contains a notice stating that it is
392+governed by this License along with a term that is a further
393+restriction, you may remove that term.  If a license document contains
394+a further restriction but permits relicensing or conveying under this
395+License, you may add to a covered work material governed by the terms
396+of that license document, provided that the further restriction does
397+not survive such relicensing or conveying.
398+
399+  If you add terms to a covered work in accord with this section, you
400+must place, in the relevant source files, a statement of the
401+additional terms that apply to those files, or a notice indicating
402+where to find the applicable terms.
403+
404+  Additional terms, permissive or non-permissive, may be stated in the
405+form of a separately written license, or stated as exceptions;
406+the above requirements apply either way.
407+
408+  8. Termination.
409+
410+  You may not propagate or modify a covered work except as expressly
411+provided under this License.  Any attempt otherwise to propagate or
412+modify it is void, and will automatically terminate your rights under
413+this License (including any patent licenses granted under the third
414+paragraph of section 11).
415+
416+  However, if you cease all violation of this License, then your
417+license from a particular copyright holder is reinstated (a)
418+provisionally, unless and until the copyright holder explicitly and
419+finally terminates your license, and (b) permanently, if the copyright
420+holder fails to notify you of the violation by some reasonable means
421+prior to 60 days after the cessation.
422+
423+  Moreover, your license from a particular copyright holder is
424+reinstated permanently if the copyright holder notifies you of the
425+violation by some reasonable means, this is the first time you have
426+received notice of violation of this License (for any work) from that
427+copyright holder, and you cure the violation prior to 30 days after
428+your receipt of the notice.
429+
430+  Termination of your rights under this section does not terminate the
431+licenses of parties who have received copies or rights from you under
432+this License.  If your rights have been terminated and not permanently
433+reinstated, you do not qualify to receive new licenses for the same
434+material under section 10.
435+
436+  9. Acceptance Not Required for Having Copies.
437+
438+  You are not required to accept this License in order to receive or
439+run a copy of the Program.  Ancillary propagation of a covered work
440+occurring solely as a consequence of using peer-to-peer transmission
441+to receive a copy likewise does not require acceptance.  However,
442+nothing other than this License grants you permission to propagate or
443+modify any covered work.  These actions infringe copyright if you do
444+not accept this License.  Therefore, by modifying or propagating a
445+covered work, you indicate your acceptance of this License to do so.
446+
447+  10. Automatic Licensing of Downstream Recipients.
448+
449+  Each time you convey a covered work, the recipient automatically
450+receives a license from the original licensors, to run, modify and
451+propagate that work, subject to this License.  You are not responsible
452+for enforcing compliance by third parties with this License.
453+
454+  An "entity transaction" is a transaction transferring control of an
455+organization, or substantially all assets of one, or subdividing an
456+organization, or merging organizations.  If propagation of a covered
457+work results from an entity transaction, each party to that
458+transaction who receives a copy of the work also receives whatever
459+licenses to the work the party's predecessor in interest had or could
460+give under the previous paragraph, plus a right to possession of the
461+Corresponding Source of the work from the predecessor in interest, if
462+the predecessor has it or can get it with reasonable efforts.
463+
464+  You may not impose any further restrictions on the exercise of the
465+rights granted or affirmed under this License.  For example, you may
466+not impose a license fee, royalty, or other charge for exercise of
467+rights granted under this License, and you may not initiate litigation
468+(including a cross-claim or counterclaim in a lawsuit) alleging that
469+any patent claim is infringed by making, using, selling, offering for
470+sale, or importing the Program or any portion of it.
471+
472+  11. Patents.
473+
474+  A "contributor" is a copyright holder who authorizes use under this
475+License of the Program or a work on which the Program is based.  The
476+work thus licensed is called the contributor's "contributor version".
477+
478+  A contributor's "essential patent claims" are all patent claims
479+owned or controlled by the contributor, whether already acquired or
480+hereafter acquired, that would be infringed by some manner, permitted
481+by this License, of making, using, or selling its contributor version,
482+but do not include claims that would be infringed only as a
483+consequence of further modification of the contributor version.  For
484+purposes of this definition, "control" includes the right to grant
485+patent sublicenses in a manner consistent with the requirements of
486+this License.
487+
488+  Each contributor grants you a non-exclusive, worldwide, royalty-free
489+patent license under the contributor's essential patent claims, to
490+make, use, sell, offer for sale, import and otherwise run, modify and
491+propagate the contents of its contributor version.
492+
493+  In the following three paragraphs, a "patent license" is any express
494+agreement or commitment, however denominated, not to enforce a patent
495+(such as an express permission to practice a patent or covenant not to
496+sue for patent infringement).  To "grant" such a patent license to a
497+party means to make such an agreement or commitment not to enforce a
498+patent against the party.
499+
500+  If you convey a covered work, knowingly relying on a patent license,
501+and the Corresponding Source of the work is not available for anyone
502+to copy, free of charge and under the terms of this License, through a
503+publicly available network server or other readily accessible means,
504+then you must either (1) cause the Corresponding Source to be so
505+available, or (2) arrange to deprive yourself of the benefit of the
506+patent license for this particular work, or (3) arrange, in a manner
507+consistent with the requirements of this License, to extend the patent
508+license to downstream recipients.  "Knowingly relying" means you have
509+actual knowledge that, but for the patent license, your conveying the
510+covered work in a country, or your recipient's use of the covered work
511+in a country, would infringe one or more identifiable patents in that
512+country that you have reason to believe are valid.
513+
514+  If, pursuant to or in connection with a single transaction or
515+arrangement, you convey, or propagate by procuring conveyance of, a
516+covered work, and grant a patent license to some of the parties
517+receiving the covered work authorizing them to use, propagate, modify
518+or convey a specific copy of the covered work, then the patent license
519+you grant is automatically extended to all recipients of the covered
520+work and works based on it.
521+
522+  A patent license is "discriminatory" if it does not include within
523+the scope of its coverage, prohibits the exercise of, or is
524+conditioned on the non-exercise of one or more of the rights that are
525+specifically granted under this License.  You may not convey a covered
526+work if you are a party to an arrangement with a third party that is
527+in the business of distributing software, under which you make payment
528+to the third party based on the extent of your activity of conveying
529+the work, and under which the third party grants, to any of the
530+parties who would receive the covered work from you, a discriminatory
531+patent license (a) in connection with copies of the covered work
532+conveyed by you (or copies made from those copies), or (b) primarily
533+for and in connection with specific products or compilations that
534+contain the covered work, unless you entered into that arrangement,
535+or that patent license was granted, prior to 28 March 2007.
536+
537+  Nothing in this License shall be construed as excluding or limiting
538+any implied license or other defenses to infringement that may
539+otherwise be available to you under applicable patent law.
540+
541+  12. No Surrender of Others' Freedom.
542+
543+  If conditions are imposed on you (whether by court order, agreement or
544+otherwise) that contradict the conditions of this License, they do not
545+excuse you from the conditions of this License.  If you cannot convey a
546+covered work so as to satisfy simultaneously your obligations under this
547+License and any other pertinent obligations, then as a consequence you may
548+not convey it at all.  For example, if you agree to terms that obligate you
549+to collect a royalty for further conveying from those to whom you convey
550+the Program, the only way you could satisfy both those terms and this
551+License would be to refrain entirely from conveying the Program.
552+
553+  13. Use with the GNU Affero General Public License.
554+
555+  Notwithstanding any other provision of this License, you have
556+permission to link or combine any covered work with a work licensed
557+under version 3 of the GNU Affero General Public License into a single
558+combined work, and to convey the resulting work.  The terms of this
559+License will continue to apply to the part which is the covered work,
560+but the special requirements of the GNU Affero General Public License,
561+section 13, concerning interaction through a network will apply to the
562+combination as such.
563+
564+  14. Revised Versions of this License.
565+
566+  The Free Software Foundation may publish revised and/or new versions of
567+the GNU General Public License from time to time.  Such new versions will
568+be similar in spirit to the present version, but may differ in detail to
569+address new problems or concerns.
570+
571+  Each version is given a distinguishing version number.  If the
572+Program specifies that a certain numbered version of the GNU General
573+Public License "or any later version" applies to it, you have the
574+option of following the terms and conditions either of that numbered
575+version or of any later version published by the Free Software
576+Foundation.  If the Program does not specify a version number of the
577+GNU General Public License, you may choose any version ever published
578+by the Free Software Foundation.
579+
580+  If the Program specifies that a proxy can decide which future
581+versions of the GNU General Public License can be used, that proxy's
582+public statement of acceptance of a version permanently authorizes you
583+to choose that version for the Program.
584+
585+  Later license versions may give you additional or different
586+permissions.  However, no additional obligations are imposed on any
587+author or copyright holder as a result of your choosing to follow a
588+later version.
589+
590+  15. Disclaimer of Warranty.
591+
592+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
593+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
594+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
595+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
596+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
597+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
598+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
599+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
600+
601+  16. Limitation of Liability.
602+
603+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
604+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
605+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
606+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
607+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
608+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
609+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
610+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
611+SUCH DAMAGES.
612+
613+  17. Interpretation of Sections 15 and 16.
614+
615+  If the disclaimer of warranty and limitation of liability provided
616+above cannot be given local legal effect according to their terms,
617+reviewing courts shall apply local law that most closely approximates
618+an absolute waiver of all civil liability in connection with the
619+Program, unless a warranty or assumption of liability accompanies a
620+copy of the Program in return for a fee.
621+
622+                     END OF TERMS AND CONDITIONS
623+
624+            How to Apply These Terms to Your New Programs
625+
626+  If you develop a new program, and you want it to be of the greatest
627+possible use to the public, the best way to achieve this is to make it
628+free software which everyone can redistribute and change under these terms.
629+
630+  To do so, attach the following notices to the program.  It is safest
631+to attach them to the start of each source file to most effectively
632+state the exclusion of warranty; and each file should have at least
633+the "copyright" line and a pointer to where the full notice is found.
634+
635+    <one line to give the program's name and a brief idea of what it does.>
636+    Copyright (C) <year>  <name of author>
637+
638+    This program is free software: you can redistribute it and/or modify
639+    it under the terms of the GNU General Public License as published by
640+    the Free Software Foundation, either version 3 of the License, or
641+    (at your option) any later version.
642+
643+    This program is distributed in the hope that it will be useful,
644+    but WITHOUT ANY WARRANTY; without even the implied warranty of
645+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
646+    GNU General Public License for more details.
647+
648+    You should have received a copy of the GNU General Public License
649+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
650+
651+Also add information on how to contact you by electronic and paper mail.
652+
653+  If the program does terminal interaction, make it output a short
654+notice like this when it starts in an interactive mode:
655+
656+    <program>  Copyright (C) <year>  <name of author>
657+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
658+    This is free software, and you are welcome to redistribute it
659+    under certain conditions; type `show c' for details.
660+
661+The hypothetical commands `show w' and `show c' should show the appropriate
662+parts of the General Public License.  Of course, your program's commands
663+might be different; for a GUI interface, you would use an "about box".
664+
665+  You should also get your employer (if you work as a programmer) or school,
666+if any, to sign a "copyright disclaimer" for the program, if necessary.
667+For more information on this, and how to apply and follow the GNU GPL, see
668+<http://www.gnu.org/licenses/>.
669+
670+  The GNU General Public License does not permit incorporating your program
671+into proprietary programs.  If your program is a subroutine library, you
672+may consider it more useful to permit linking proprietary applications with
673+the library.  If this is what you want to do, use the GNU Lesser General
674+Public License instead of this License.  But first, please read
675+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
A README
+577, -0
  1@@ -0,0 +1,577 @@
  2+BlastEm 0.6.0 shrub edition
  3+---------------------------
  4+this is my personal branch of the blastem mega drive emulator. it has been modified
  5+to cut out code that i do not need and add other things i do need. the changes made 
  6+include but are not limited t0:
  7+
  8+- new wayland renderer only
  9+- use system zlib, not vendored
 10+- ninja based build
 11+- no nuklear ui, sdl, fbdev or gl support
 12+
 13+to compile, you will need wayland, pkg-config, a and a zlib.
 14+
 15+i'd also like to note that i don't approve of this projects license and wish
 16+i could offer it under something else.
 17+
 18+the original readme is preserved below, and you check out the original blastem 
 19+project at https://www.retrodev.com/blastem/
 20+
 21+Installation
 22+------------
 23+
 24+Extract this archive to a directory of your choosing.
 25+
 26+NOTE: Prior to version 0.4.1, BlastEm was still using Unixy locations for config
 27+and save files. If you're upgrading from a previous version on Windows, you will
 28+need to move them manually. For config files, the relevant paths are in the
 29+previous paragraph. For save files, move all the directories found in 
 30+%userprofile%\.local\share\blastem to %localappdata%\blastem
 31+
 32+Usage
 33+-----
 34+
 35+This version of BlastEm has a GUI that allows access to most configuration options.
 36+Simply start BlastEm without passing a ROM filename on the command line to access
 37+the main menu. You can also access the menu by hitting the button mapped to the ui.exit
 38+action (default Esc).
 39+
 40+If Open GL is disabled or unavaible, or you explicitly request it, the old ROM-based UI
 41+will be used instead. This UI does not support configuration so you will need to modify
 42+the configuration file manually if you use it. See the rest of this README for instructions
 43+on modifying the configuration file.
 44+
 45+Some operations are currently only supported through the command line. To get a
 46+list of supported command line options on Linux or OSX type:
 47+
 48+    ./blastem -h
 49+    
 50+From within your BlastEm directory. On Windows type:
 51+    
 52+    blastem.exe -h
 53+    
 54+Lock-On Support
 55+---------------
 56+
 57+This version of BlastEm has some preliminary support for Sonic & Knuckles lock
 58+on technology. This is available via both the menu and the command line. To use
 59+it from the menu, first load Sonic & Knuckles normally. Enter the menu (mapped
 60+to the Escape key by default) and select the "Lock On" option to select a ROM
 61+to lock on. The system will then reload with the combined game. To use it from
 62+the command line, specify the Sonic & Knuckles ROM as the primary ROM and
 63+specify the ROM to be locked on using the -o option. As an example:
 64+
 65+    ./blastem ~/romz/sonic_and_knuckles.bin -o ~/romz/sonic3.bin
 66+    
 67+Please note that Sonic 2 lock-on does not work at this time.
 68+
 69+Configuration
 70+-------------
 71+
 72+Configuration is read from the file at $HOME/.config/blastem/blastem.cfg on
 73+Unix-like systems and %localappdata%\blastem\blastem.cfg if it exists.
 74+Othwerise it is read from default.cfg from the same directory as the BlastEm
 75+executable. Sections are denoted by a section name followed by an open curly 
 76+bracket, the section's contents and a closing curly bracket. Individual
 77+configuration values are set by entering the value's name followed by a space
 78+or tab and followed by the desired value.
 79+
 80+Bindings
 81+--------
 82+
 83+The keys subsection of bindings maps keyboard keys to gamepad buttons or UI
 84+actions. The key name goes on the left and the action is on the right.
 85+Most keys are named for the character they produce when pressed. For keys that
 86+don't correspond to a normal character, check the list below:
 87+
 88+  Name       | Description
 89+  -----------------
 90+  up           Up arrow
 91+  down         Down arrow
 92+  left         Left arrow
 93+  right        Right arrow
 94+  space
 95+  tab
 96+  backspace    Backspace on PC keyboards, Delete on Mac keyboards
 97+  esc
 98+  delete
 99+  lshift       Left shift
100+  rshift       Right shift
101+  lctrl        Left control
102+  rctrl        Right control
103+  lalt         Left alt on PC keyboards, Option on Mac keyboards
104+  ralt         Right alt on PC keyboards, Option on Mac keyboards
105+  home
106+  end
107+  pageup
108+  pagedown
109+  f1
110+  f2
111+  f3
112+  f4
113+  f5
114+  f6
115+  f7
116+  f8
117+  f9
118+  f10
119+  f11
120+  f12
121+  select
122+  play
123+  search
124+  back
125+
126+The pads subsection is used to map gamepads and joysticks. Gamepads that are
127+recognized, can have their buttons and axes mapped with semantic names. 
128+Xbox 360, PS4 and PS3 style names are supported. Unrecognized gamepads can be 
129+mapped using numeric button and axis ids. The following button names are
130+recognized by BlastEm:
131+	a, cross
132+	b, circle
133+	x, square
134+	y, trinagle
135+	start, options
136+	back, select, share
137+	guide
138+	leftbutton, l1
139+	rightbutton, r1
140+	leftstick, l3
141+	rightstick, r3
142+The following axis names are recognized by BlastEm:
143+	leftx
144+	lefty
145+	rightx
146+	righty
147+	lefttrigger, l2
148+	righttrigger, r2
149+	
150+
151+The mice subsection is used to map mice to emulated Mega/Sega mice. The default
152+configuration maps both the first and second host mice to the first emulated
153+mouse. This should not need modification for most users.
154+
155+One special mapping deserves a mention. By default, the 'r' key is mapped to
156+ui.release_mouse. When operating in windowed mode the mouse has a capture
157+behavior. Mouse events are ignored until you click in the window. The mouse
158+will then be "captured" and the cursor will be both made invisible and locked
159+to the window. The ui.release_mouse binding releases the mouse so it can be
160+used normally.
161+
162+UI Actions
163+----------
164+
165+This section lists the various "UI" actions that can be triggered by a key or
166+gamepad binding.
167+
168+ui.release_mouse             Releases the mouse if it is currently captured
169+ui.plane_debug               Toggles the VDP plane debug view
170+ui.vram_debug                Toggles the VDP VRAM debug view
171+ui.cram_debug                Toggles the VDP CRAM debug view
172+ui.compositing_debug         Toggles the VDP compositing debug view
173+ui.vdp_debug_mode            Cycles the mode/palette of the VDP debug view
174+                             that currently has focus
175+ui.enter_debugger            Enters the debugger for the main CPU of the
176+							 currently emulated system
177+ui.screenshot                Takes an internal screenshot
178+ui.exit                      Returns to the menu ROM if currently in a game
179+                             that was launched from the menu. Exits otherwise
180+ui.save_state                Saves a savestate to the quicksave slot
181+ui.set_speed.N               Selects a specific machine speed specified by N
182+                             which should be a number between 0-9. Speeds are
183+                             specified in the "clocks" section of the config				
184+ui.next_speed                Selects the next machine speed
185+ui.prev_speed                Selects the previous machine speed
186+ui.toggle_fullscreen         Toggles between fullscreen and windowed mode
187+ui.soft_reset                Resets a portion of the emulated machine
188+                             Equivalent to pushing the reset button on the
189+                             emulated device
190+ui.reload                    Reloads the current ROM from a file and performs
191+                             a hard reset of the emulated device
192+ui.sms_pause                 Triggers a press of the pause button when in SMS
193+                             mode
194+ui.toggle_keyboard_captured  Toggles the capture state of the host keyboard
195+                             when an emulated keyboard is present
196+		
197+IO
198+--
199+
200+This section controls which peripherals are attached to the emulated console.
201+IO assignments can be overridden by the ROM database when appropriate. For
202+instance, games with mouse support can automatically use the mouse and games
203+that only support 3-button pads can automatically force an appropriate pad.
204+Unforunately, the ROM database is not yet exhaustive so manual configuration
205+may be needed here in some cases.
206+
207+Video
208+-----
209+
210+The video section contains settings that affect the visual output of BlastEm.
211+
212+"aspect" is used to control the aspect ratio of the emulated display. The
213+default of 4:3 matches that of a standard definition television.
214+
215+"width" is used to control the window width when not in fullscreen mode.
216+
217+"height" is used to control the window height when not in fullscreen mode. If
218+left unspecified, it will be calculated from "width" and "aspect".
219+
220+"vertex_shader" and "fragment_shader" define the GLSL shader program that
221+produces the final image for each frame. Shaders can be used to add various
222+visual effects or enhancements. Currently BlastEm only ships with the default
223+shader and a "subtle" crt shader. If you write your own shaders, place them in 
224+$HOME/.config/blastem/shaders and then specify the basename of the new shader
225+files in the "vertex_shader" and "fragment_shader" config options. Note that
226+shaders are not available in the SDL fallback renderer.
227+
228+"scanlines" controls whether there is any emulation of the gaps between display
229+lines that are present when driving a CRT television with a 240p signal. This
230+emulation is very basic at the moment so this option is off by default.
231+
232+"vsync" controls whether the drawing of frames is synchronized to the monitor
233+refresh rate. Valid values for this setting are "off", "on" and "tear". The
234+latter will attempt to use the "late tear" option if it's available and normal
235+vsync otherwise. Currently it's recommended to leave this at the default of
236+"off" as it may not work well with the default "audio" sync method and the
237+"video" sync method will automatically enable "vsync". See "Sync Source and
238+VSync" for more details.
239+
240+"fullscreen" controls whether BlastEm starts in fullscreen or windowed mode.
241+This can be overridden on the command line with the -f flag. If fullscreen
242+is set to "off", -f will turn it on. Conversely, if fullscreen is set to "on"
243+in the config, -f will turn it off.
244+
245+"gl" controls whether OpenGL is used for rendering. The default value is on.
246+If it is set to off instead, the fallback renderer which uses SDL2's render API
247+will be used instead. This option is mostly useful for users on hardware that
248+lacks OpenGL 2 support. While BlastEm will fall back automatically even if gl
249+is set to on there will be a warning. Disabling gl eliminates this warning.
250+
251+"scaling" controls the type of scaling used for textures in both the GL and
252+SDL renderers. Valid values are "nearest" and "linear". Note that shaders also
253+impact how pixels are scaled.
254+
255+The "ntsc" and "pal" sub-sections control overscan settings for the emulated
256+video output for NTSC and PAL consoles respectively. More details are available
257+in the Overscan section.
258+
259+Overscan
260+--------
261+
262+Analog televisions generally don't display the entirety of a video frame. Some
263+portion is cropped at the edges of the display. This is called overscan.
264+Unfortunately, the amount of cropping performed varies considerably and is even
265+adjustable on many TV sets. To deal with this, BlastEm allows overscan to be
266+customized.
267+
268+Overscan values are specified in the "ntsc" and "pal" sub-sections of the
269+"video" section of the config file. The "overscan" sub-section contains four
270+settings for specifying the number of pixels cropped on each side of the
271+display: "top", "bottom", "left" and "right".
272+
273+The default settings hide the horizontal border completely for both NTSC and
274+PAL consoles. For the vertical borders, the NTSC overscan settings are chosen
275+to give square pixels with the default aspect ratio of 4:3. For PAL, the
276+default settings are set so that the PAL-exclusive V30 mode will produce a
277+visible border that is the same size as what is shown in V28 mode in NTSC. This
278+results in a slightly squished picture compared to NTSC which is probably
279+appropriate given that a PAL display has more lines than an NTSC one.
280+
281+Audio
282+-----
283+
284+The audio section contains settings that affect the audio output of BlastEm.
285+
286+"rate" selects the preferred sample rate for audio output. Your operating
287+system may not accept this value in which case a different rate will be chosen.
288+This should generally be either the native sample rate of your sound card or an
289+integral divisor of it. Most modern sound cards have a native output rate that
290+is a multiple of 48000 Hz so the default setting should work well for most users.
291+
292+"buffer size" controls how large of a buffer uses for audio data. Smaller values
293+will reduce latency, but too small of a value can lead to dropouts. 512 works
294+well for me, but a higher or lower value may be more appropriate for your system.
295+
296+"lowpass_cutoff" controls the cutoff, or knee, frequency of the RC-style
297+low-pass filter. The default value of 3390 Hz is supposedly what is present in
298+at least some Genesis/Megadrive models. Other models reportedly use an even
299+lower value.
300+
301+"gain" specifies the gain in decibels to be applied to the overall output.
302+
303+"fm_gain" specifies the gain to be applied to the emulated FM output before
304+mixing with the PSG.
305+
306+"psg_gain" specifies the gain to be applied to the emulated PSG output before
307+mixing with the FM chip.
308+
309+"fm_dac" controls the characteristics of the DAC in the emulated FM chip. If
310+this is set to "linear", then the DAC will have precise linear output similar
311+to the integrated YM3438 in later Gen/MD consoles. If it is set to "zero_offset",
312+there will be a larger gap between -1 and 0. This is commonly referred to as the
313+"ladder effect". This will also cause "leakage" on channels that are muted or
314+panned to one side in a similar manner to a discrete YM2612.
315+
316+
317+Clocks
318+------
319+
320+The clocks section contains settings that affect how fast things run.
321+
322+"m68k_divider" describes the relationsip between the master clock (which is
323+53693175 Hz for NTSC mode and 53203395 Hz for PAL mode). The default value of 7
324+matches the real hardware. Set this to a lower number to overclock the 68000
325+and set it to a higher number to underclock it.
326+
327+"max_cycles" controls how often the system is forced to synchronize all
328+hardware. BlastEm generally uses a sync on demand approach to synchronizing
329+components in the system. This can provide perfect synchronization for most
330+components, but since the Z80 can steal cycles from the 68000 at unpredictable
331+times 68000/Z80 synchronization is imperfect. The default value of 3420
332+corresponds to the number of master clock cycles per line. Larger numbers may
333+produce a modest performance improvement whereas smaller numbers will improve
334+68000/Z80 synchronization.
335+
336+"speeds" controls the speed of the overall emulated console at different
337+presets. Preset 0 is the default speed and should normally be set to 100. The
338+other presets enable the slow/turbo mode functionality.
339+
340+UI
341+--
342+
343+The UI section contains settings that affect the user interface.
344+
345+"rom" determines the path of the Genesis/Megadrive ROM that implements the UI.
346+Relative paths will be loaded relative to the BlastEm executable.
347+
348+"initial_path" specifies the starting path for the ROM browser. It can contain
349+the following special variables: $HOME, $EXEDIR. Additionally, variables
350+defined in the OS environment can be used.
351+
352+"remember_path" specifies whether BlastEm should remember the last path used in
353+the file browser. When it is set to "on", the last path will be remembered and
354+used instead of "initial_path" in subsequent runs. If it is set to "off", 
355+"initial_path" will always be used.
356+
357+"screenshot_path" specifies the directory "internal" screenshots will be saved
358+in. It accepts the same special variables as "initial_path".
359+
360+"screenshot_template" specifies a template for creating screenshot filenames.
361+It is specified as a format string for the C library function strftime
362+
363+"save_path" specifies the directory that savestates, SRAM and EEPROM data will
364+be saved in for a given game. It can contain the following special variables:
365+$HOME, $EXEDIR, $USERDATA, $ROMNAME. Like "initial_path" it can also reference
366+variables from the environment.
367+
368+"extensions" specifies the file extensions that should be displayed in the file
369+browser.
370+
371+"state_format" specifies the preferred format for saving save states. Valid
372+values are "native" (the default) and "gst". "native" save states do a better
373+job of preserving the state of the emulated system, but "gst" save states are
374+compatible with other emulators like Kega and Gens. This setting has no effect
375+for systems other than the Genesis/Mega Drive
376+
377+Path Variables
378+--------------
379+
380+This section explains the meaning of the special path variables referenced
381+in the previous section.
382+
383+$HOME      The home directory of the current user. On most Unix variants, it
384+           will be a subdirectory of /home. On Windows it will typically be a 
385+           subdirectory of C:\Users
386+$EXEDIR    The directory the BlastEm executable is located in
387+$USERDATA  This is an OS-specific path used for storing application specific
388+           user data. On Unix variants, it will be  $HOME/.local/share/blastem
389+           On Windows it will be %LOCALDATA%/blastem
390+$ROMNAME   The name of the currently loaded ROM file without the extension
391+
392+System
393+------
394+
395+"ram_init" determines how the RAM in the emulated system is initialized. The
396+default value of "zero" will cause all RAM to be zeroed out before the system
397+is started. Alternatively, "random" can be used to initialize RAM with values
398+from a pseudo-random number generator. This option is mostly useful for
399+developers that want to debug initialization issues in their code.
400+
401+"default_region" determines the console region that will be used when region
402+detection fails and when there are multiple valid regions. The default of 'U'
403+specifies a 60Hz "foreign" console.
404+
405+"sync_source" controls whether BlastEm uses audio or video output to control
406+execution speed. "video" can provide a smoother experience when your display
407+has a similar refresh rate to the emulated system, but has some limitations
408+in the current version. The default value is "audio".
409+
410+"megawifi" enables or disables support for MegaWiFi cart emulation. MegaWiFi
411+is a cartridge that contains WiFi hardware for network functionality. Enabling
412+this means that ROMs potentially have access to your network (and the internet)
413+which obviously has security implications. For this reason, it is disabled by
414+default. If you wish to try out MegaWiFi emulation, set this to "on". Note that
415+the support for MegaWiFi hardware is preliminary in this release.
416+
417+Debugger
418+--------
419+
420+BlastEm has an integrated command-line debugger loosely based on GDB's
421+interface. The interface is very rough at the moment. Available commands in the
422+68K debugger are:
423+    b ADDRESS            - Set a breakpoint at ADDRESS
424+    d BREAKPOINT         - Delete a 68K breakpoint
425+    co BREAKPOINT        - Run a list of debugger commands each time
426+                           BREAKPOINT is hit
427+    a ADDRESS            - Advance to address
428+    n                    - Advance to next instruction
429+    o                    - Advance to next instruction ignoring branches to
430+                           lower addresses (good for breaking out of loops)
431+    s                    - Advance to next instruction (follows bsr/jsr)
432+    c                    - Continue
433+    bt                   - Print a backtrace
434+    p[/(x|X|d|c)] VALUE  - Print a register or memory location
435+    di[/(x|X|d|c)] VALUE - Print a register or memory location each time
436+                           a breakpoint is hit
437+    vs                   - Print VDP sprite list
438+    vr                   - Print VDP register info
439+    zb ADDRESS           - Set a Z80 breakpoint
440+    zp[/(x|X|d|c)] VALUE - Display a Z80 value
441+    q                    - Quit BlastEm
442+Available commands in the Z80 debugger are:
443+    b  ADDRESS           - Set a breakpoint at ADDRESS
444+    de BREAKPOINT        - Delete a Z80 breakpoint
445+    a  ADDRESS           - Advance to address
446+    n                    - Advance to next instruction
447+    c                    - Continue
448+    p[/(x|X|d|c)] VALUE  - Print a register or memory location
449+    di[/(x|X|d|c)] VALUE - Print a register or memory location each time
450+                           a breakpoint is hit
451+    q                    - Quit BlastEm
452+
453+The -d flag can be used to cause BlastEm to start in the debugger.
454+Alternatively, you can use the ui.enter_debugger action (mapped to the 'u' key
455+by default) to enter the debugger while a game is running. To debug the menu
456+ROM, use the -dm flag.
457+
458+GDB Remote Debugging
459+--------------------
460+
461+In addition to the native debugger, BlastEm can also act as a GDB remote
462+debugging stub. To use this, you'll want to configure your Makefile to produce
463+both an ELF executable and a raw binary. Invoke an m68k-elf targeted gdb with
464+the ELF file. Once inside the gdb session, type:
465+
466+    target remote | BLASTEM_PATH/blastem ROM_FILE.bin -D
467+
468+where BLASTEM_PATH is the relative or absolute path to your BlastEm
469+installation and ROM_FILE.bin is the name of the raw binary for your program.
470+BlastEm will halt at the beginning of your program's entry point and return
471+control to GDB. This will allow you to set breakpoints before your code runs.
472+
473+On Windows, the procedure is slightly different. First run 
474+    blastem.exe ROM_FILE.bin -D
475+This will cause BlastEm to wait for a socket connection on port 1234. It will
476+appear to be frozen until gdb connects to it. Now open the ELF file in gdb
477+and type:
478+
479+    target remote :1234
480+
481+Trace points and watch points are not currently supported.
482+
483+Included Tools
484+--------------
485+
486+BlastEm ships with a few small utilities that leverage portions of the emulator
487+code.
488+    
489+    dis       - 68K disassembler
490+    zdis      - Z80 disassembler
491+    vgmplay   - Very basic VGM player
492+    stateview - GST save state viewer
493+    
494+Sync Source and VSync
495+-----
496+
497+This section includes information about using VSync with BlastEm. Currently,
498+the best way to use VSync is to set the sync source to "video". This will force
499+VSync on and use video output for controlling the speed of emulation. In this
500+mode, audio will have it's rate automatically adjusted to keep pace with video.
501+The code for this is still a bit immature, so you may experience dropouts or
502+pitch changes in this mode.
503+
504+If you experience problems, please switch back to the "audio" sync source,
505+which is the default. You can also enable vsync when using the "audio" sync
506+source by changing the "vsync" setting. This will generally work okay as long
507+as the emulated refresh rate is below your monitor refresh rate (even if only
508+slightly), but you will occassionally get a doubled frame (or frequently if
509+the refresh rates are very different).
510+
511+Turbo mode will currently not work when vsync is on, regardless of which sync
512+source is used. Slow mode will work with "audio" sync, but not "video" sync.
513+
514+--------------
515+
516+My work has been made much easier by the contributions of those in the Genesis
517+community past and present. I'd like to thank the people below for their help.
518+
519+Nemesis            - His work reverse engineering and documenting the VDP and
520+                     YM-2612 has saved me an immeasurable amount of time. I've
521+                     found both his sprite overflow test ROM and VDP FIFO
522+                     Testing ROM to be quite helpful.
523+
524+Charles MacDonald  - While it hasn't been updated in a while, I still find his
525+                     VDP document to be my favorite reference. His Genesis
526+                     hardware document has also come in handy.
527+
528+Eke-Eke            - Eke-Eke wrote a great document on the use of I2C EEPROM in
529+                     Genesis games and also left some useful very helpful 
530+                     comments about problematic games in Genesis Plus GX
531+					 
532+Sauraen            - Sauraen has analyzed the YM2203 and YM2612 dies and written
533+                     a VHDL operator implementation. These have been useful in
534+                     improving the accuracy of my YM2612 core.
535+
536+Alexey Khokholov   - Alexey (aka Nuke.YKT) has analyzed the YM3438 die and written
537+                     a fairly direct C implementation from that analysis. This
538+                     has been a useful reference for verifying and improving my
539+                     YM2612 core.
540+
541+Bart Trzynadlowski - His documents on the Genecyst save-state format and the
542+                     mapper used in Super Street Fighter 2 were definitely
543+                     appreciated.
544+                     
545+KanedaFR           - Kaneda's SpritesMind forum is a great resource for the
546+                     Sega development community.
547+					 
548+Titan              - Titan has created what are without a doubt the most
549+                     impressive demos on the Megadrive. Additionally, I am very
550+                     grateful for the documentation provided by Kabuto and the
551+                     assistance of Kabuto, Sik and Jorge in getting Overdrive 2
552+                     to run properly in BlastEm.
553+					 
554+flamewing          - flamewing created a very handy exhaustive test ROM for 68K
555+                     BCD instructions and documented the proper behavior for
556+                     certain BCD edge cases
557+
558+r57shell           - r57shell created a test ROM for 68K instruction sizes that
559+                     was invaluable in fixing the remaining bugs in my 68K instruction
560+                     decoder
561+
562+I'd also like to thank the following people who have performed compatibility
563+testing or submitted helpful bug reports
564+
565+micky, Sasha, lol-frank, Sik, Tim Lawrence, ComradeOj, Vladikcomper
566+
567+License
568+-------
569+
570+BlastEm is free software distributed under the terms of the GNU General Public
571+License version 3 or higher. This gives you the right to redistribute and/or
572+modify the program as long as you follow the terms of the license. See the file
573+COPYING for full license details.
574+
575+Binary releases of BlastEm are packaged with GLEW, SDL2 and zlib which have their
576+own licenses. See GLEW-LICENSE and SDL-LICENSE for details. For zlib license
577+information, please see zlib.h in the source code release.
578+
+192, -0
  1@@ -0,0 +1,192 @@
  2+#!/usr/bin/env python
  3+
  4+#OLD
  5+#0 - !SE
  6+#1 - !CAS
  7+#2 - A0
  8+#3 - A1
  9+#------
 10+#4 - A2
 11+#5 - A3
 12+#6 - A7
 13+#7 - EDCLK
 14+#------
 15+#8 - !HSYNC
 16+#9 - A4
 17+#A - A5
 18+#B - A6
 19+#------
 20+#C - !RAS
 21+#D - !WB/!WE
 22+#E - !DT/!OE
 23+#F - SC
 24+
 25+#NEW
 26+#0 - !IPL2
 27+#1 - !CAS
 28+#2 - A0
 29+#3 - A1
 30+#------
 31+#4 - A2
 32+#5 - A3
 33+#6 - A7
 34+#7 - !HSYNC
 35+#------
 36+#8 - !VSYNC
 37+#9 - A4
 38+#A - A5
 39+#B - A6
 40+#------
 41+#C - !RAS
 42+#D - !WB/!WE
 43+#E - !DT/!OE
 44+#F - SC
 45+
 46+
 47+#VRAM swizzling
 48+#A0 = V0
 49+#A1 = V1
 50+#A8 = V2
 51+#A9 = V3
 52+#A10 = V4
 53+#A11 = V5
 54+#A12 = V6
 55+#A13 = V7
 56+#A14 = V8
 57+#A15 = V9
 58+#--guesses follow--
 59+#A2 = V10
 60+#A3 = V11
 61+#A4 = V12
 62+#A5 = V13
 63+#A6 = V14
 64+#A7 = V15
 65+
 66+
 67+def get_addr(sample):
 68+	return ((sample >> 2) & 0xF) | ((sample >> 5) & 0x70) | ((sample << 1) & 0x80)
 69+
 70+def swizzle_addr(addr):
 71+	return (addr & 0x0003) | ((addr >> 6) & 0x03FC) | ((addr << 8) & 0xFC00)
 72+
 73+def print_addr_op(addr, addr_format, mode, samplenum, triggerpos, rate):
 74+	print '{0:{1}} ({2:{1}}) {3}@{4} ns'.format(swizzle_addr(addr), addr_format, addr, mode, (samplenum - triggerpos)*rate)
 75+
 76+def detect_rise(last, sample, bit):
 77+	mask = 1 << bit
 78+	return (not last & mask) and (sample & mask)
 79+	
 80+def detect_fall(last, sample, bit):
 81+	mask = 1 << bit
 82+	return (last & mask) and (not sample & mask)
 83+
 84+def detect_high(sample, bit):
 85+	mask = 1 << bit
 86+	return sample & mask
 87+
 88+
 89+ipl2 = 0x0
 90+cas = 0x1
 91+ras = 0xC
 92+vsync = 0x8
 93+hsync = 0x7
 94+wewb = 0xD
 95+oedt = 0xE
 96+sc = 0xF
 97+
 98+last = False
 99+state = 'begin'
100+triggerpos = 0
101+readcounter = 0
102+sillyread = 0
103+lastaddr = -1
104+edclk_ticks = 0
105+sc_ticks = 0
106+tick_start = False
107+#f = open('street_fighter_vram_100mhz_hsync_trig_2.ols')
108+#f = open('street_fighter_vram_50mhz_hsync_trig.ols')
109+from sys import argv,exit
110+if len(argv) < 2:
111+	print 'usage: analyze.py filename'
112+	exit(1)
113+if '-b' in argv:
114+	addr_format = '016b'
115+else:
116+	addr_format = '04X'
117+f = open(argv[1])
118+for line in f:
119+	if line.startswith(';TriggerPosition'):
120+		_,_,triggerpos = line.partition(':')
121+		triggerpos = int(triggerpos.strip())
122+	elif line.startswith(';Rate'):
123+		_,_,rate = line.partition(':')
124+		#convert to nanoseconds between samples
125+		rate = (1.0/float(rate.strip())) * 1000000000.0
126+	elif not line.startswith(';'):
127+		sample,_,samplenum = line.partition('@')
128+		samplenum = int(samplenum.strip())
129+		sample = int(sample, 16)
130+		if detect_rise(last, sample, sc):
131+			sc_ticks += 1
132+		if not (last is False):
133+			#detect falling edge of !HSYNC
134+			if detect_fall(last, sample, hsync):
135+				if readcounter:
136+					print readcounter, 'reads,', sillyread, 'redundant reads'
137+					readcounter = sillyread = 0
138+				if not tick_start is False:
139+					print 'SC:', sc_ticks, ' ticks, {0}MHz'.format(float(sc_ticks)/((rate * (samplenum-tick_start)) / 1000.0))
140+				tick_start = samplenum
141+				edclk_ticks = sc_ticks = 0
142+				print 'HSYNC Start @ {0} ns'.format((samplenum - triggerpos)*rate)
143+			#detect rising edge of !HSYNC
144+			elif detect_rise(last, sample, hsync):
145+				if not tick_start is False:
146+					float(edclk_ticks)/((rate * (samplenum-tick_start)) / 1000.0)
147+					print 'EDCLK:', edclk_ticks, ' ticks, {0}MHz'.format(float(edclk_ticks)/((rate * (samplenum-tick_start)) / 1000.0))
148+					print 'SC:', sc_ticks, ' ticks, {0}MHz'.format(float(sc_ticks)/((rate * (samplenum-tick_start)) / 1000.0))
149+				tick_start = samplenum
150+				edclk_ticks = sc_ticks = 0
151+				print 'HSYNC End @ {0} ns'.format((samplenum - triggerpos)*rate)
152+			if detect_fall(last, sample, vsync):
153+				print 'VSYNC Start @ {0} ns'.format((samplenum - triggerpos)*rate)
154+			elif detect_rise(last, sample, vsync):
155+				print 'VSYNC End @ {0} ns'.format((samplenum - triggerpos)*rate)
156+			if detect_fall(last, sample, ipl2):
157+				print 'IPL2 Low @ {0} ns'.format((samplenum - triggerpos)*rate)
158+			elif detect_rise(last, sample, ipl2):
159+				print 'IPL2 High @ {0} ns'.format((samplenum - triggerpos)*rate)
160+			if state == 'begin':
161+				#detect falling edge of !RAS
162+				if detect_fall(last, sample, ras):
163+					state = 'ras'
164+					row = get_addr(sample)
165+					mode = 'ram' if detect_high(sample, oedt) else 'read transfer'
166+				elif detect_fall(last, sample, cas) and detect_high(sample, oedt):
167+					state = 'cas'
168+			elif state == 'ras':
169+				if detect_fall(last, sample, cas):
170+					state = 'begin'
171+					col = get_addr(sample)
172+					addr = (row << 8) | col
173+					if mode == 'ram':
174+						state = 'ras_cas'
175+					else:
176+						print_addr_op(addr, addr_format, mode, samplenum, triggerpos, rate)
177+					lastaddr = addr
178+					#print '{0:04X} {1} - {2:02X}:{3:02X} - {0:016b}'.format(addr, mode, row, col)
179+			elif state == 'cas':
180+				if detect_fall(last, sample, ras):
181+					state = 'begin'
182+					print 'refresh@{0} ns'.format((samplenum - triggerpos)*rate)
183+			elif state == 'ras_cas':
184+				if detect_fall(last, sample, oedt):
185+					readcounter += 1
186+					if addr == lastaddr:
187+						sillyread += 1
188+					print_addr_op(addr, addr_format, 'read', samplenum, triggerpos, rate)
189+					state = 'begin'
190+				elif detect_fall(last, sample, wewb):
191+					print_addr_op(addr, addr_format, 'write', samplenum, triggerpos, rate)
192+					state = 'begin'
193+		last = sample
+197, -0
  1@@ -0,0 +1,197 @@
  2+#!/usr/bin/env python
  3+
  4+from zipfile import ZipFile
  5+from sys import exit, argv
  6+
  7+def detect_rise(last, sample, bit):
  8+	mask = 1 << bit
  9+	return (not last & mask) and (sample & mask)
 10+
 11+def detect_fall(last, sample, bit):
 12+	mask = 1 << bit
 13+	return (last & mask) and (not sample & mask)
 14+
 15+def detect_high(sample, bit):
 16+	mask = 1 << bit
 17+	return sample & mask
 18+
 19+def detect_low(sample, bit):
 20+	mask = 1 << bit
 21+	return not sample & mask
 22+	
 23+def get_value(sample, bits):
 24+	value = 0
 25+	for i in xrange(0, len(bits)):
 26+		bit = bits[i]
 27+		value |= (sample >> bit & 1) << i
 28+	return value
 29+	
 30+def swizzle_mode4(row, col):
 31+	return (col & 1) | (row << 1) | (col << 8 & 0xFE00)
 32+
 33+def analyze_delays(chanmap, datafile):
 34+	if 'M68K_CLK' in chanmap:
 35+		m68k_clk = chanmap['M68K CLK']
 36+	elif 'CLK' in chanmap:
 37+		m68k_clk = chanmap['CLK']
 38+	m_as = chanmap['!AS']
 39+	ram_oe = chanmap['RAM !LOE/!RFSH']
 40+	ram_ce = chanmap['RAM !CE']
 41+	last = False
 42+	prev = False
 43+	prevRefresh = False
 44+	clks = 0
 45+	as_start = 0
 46+	for line in datafile.readlines():
 47+		line = line.strip()
 48+		if line and not line.startswith(';'):
 49+			sample,_,num = line.partition('@')
 50+			sample = int(sample, 16)
 51+			if not (last is False):
 52+				if detect_rise(last, sample, m68k_clk):
 53+					clks = clks + 1
 54+				if detect_rise(last, sample, m_as):
 55+					as_clks  = clks - as_start
 56+					if as_clks > 2:
 57+						if not (prev is False):
 58+							print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks, 'delta since last delay:', as_start - prev
 59+						else:
 60+							print '!AS held for', as_clks, 'cycles starting (delay of ' + str(as_clks - 2) + ') at', as_start, 'and ending at', clks
 61+						prev = as_start
 62+				elif detect_fall(last, sample, m_as):
 63+					as_start = clks
 64+				if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
 65+					if prevRefresh is False:
 66+						print 'RAM refresh at ', clks
 67+					else:
 68+						print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
 69+					prevRefresh = clks
 70+			last = sample
 71+			
 72+def analyze_refresh(chanmap, datafile):
 73+	if 'M68K_CLK' in chanmap:
 74+		m68k_clk = chanmap['M68K CLK']
 75+	elif 'CLK' in chanmap:
 76+		m68k_clk = chanmap['CLK']
 77+	ram_oe = chanmap['RAM !LOE/!RFSH']
 78+	ram_ce = chanmap['RAM !CE']
 79+	clks = 0
 80+	last = False
 81+	prevRefresh = False
 82+	for line in datafile.readlines():
 83+		line = line.strip()
 84+		if line and not line.startswith(';'):
 85+			sample,_,num = line.partition('@')
 86+			sample = int(sample, 16)
 87+			if not (last is False):
 88+				if detect_rise(last, sample, m68k_clk):
 89+					clks = clks + 1
 90+				if detect_fall(last, sample, ram_oe) and detect_high( sample, ram_ce):
 91+					if prevRefresh is False:
 92+						print 'RAM refresh at ', clks
 93+					else:
 94+						print 'RAM refresh at', clks, 'delta since last:', clks-prevRefresh
 95+					prevRefresh = clks
 96+			last = sample
 97+			
 98+			
 99+table_start = 0x3800
100+table_end = table_start + 0x600
101+sat_start = 0x3E00 #0x3F00 
102+sat_xname = sat_start + 0x80
103+sat_end = sat_start + 0x100
104+
105+
106+def analyze_vram(chanmap, datafile):
107+	address_bits = [chanmap['AD{0}'.format(i)] for i in xrange(0, 8)]
108+	ras = chanmap['!RAS']
109+	cas = chanmap['!CAS']
110+	hsync = chanmap['!HSYNC']
111+	state = 'begin'
112+	last = False
113+	for line in datafile.readlines():
114+		line = line.strip()
115+		if line and not line.startswith(';'):
116+			sample,_,num = line.partition('@')
117+			sample = int(sample, 16)
118+			if not (last is False):
119+				if detect_fall(last, sample, hsync):
120+					print 'HSYNC low @ {0}'.format(num)
121+				elif detect_rise(last, sample, hsync):
122+					print 'HSYNC high @ {0}'.format(num)
123+				if state == 'begin':
124+					if detect_fall(last, sample, ras):
125+						state = 'ras'
126+						row = get_value(sample, address_bits)
127+					elif detect_fall(last, sample, cas):
128+						state = 'cas'
129+				elif state == 'ras':
130+					if detect_fall(last, sample, cas):
131+						col = get_value(sample, address_bits)
132+						address = swizzle_mode4(row, col)
133+						
134+						if address < table_end and address >= table_start:
135+							offset = (address - table_start)/2
136+							desc = 'Map Row {0} Col {1}'.format(offset / 32, offset & 31)
137+						elif address >= sat_start and address < sat_xname:
138+							offset = address - sat_start
139+							desc = 'Sprite {0} Y Read'.format(offset)
140+						elif address >= sat_xname and address < sat_end:
141+							offset = address - sat_xname
142+							desc = 'Sprite {0} X/Name Read'.format(offset / 2)
143+						else:
144+							desc = 'Tile {0} Row {1}'.format(address / 32, ((address / 4) & 7) + (0.5 if address & 2 else 0))
145+						print '{0:02X}:{1:02X} - {2:04X} @ {3} - {4}'.format(row, col, address, num, desc)
146+						state = 'begin'
147+				elif state == 'cas':
148+					if detect_fall(last, sample, ras):
149+						print 'refresh @ {0}'.format(num)
150+						state = 'begin'
151+			last = sample
152+			
153+def analyze_z80_mreq(chanmap, datafile):
154+	m1 = chanmap['!M1']
155+	mreq = chanmap['!MREQ']
156+	addressMask = 0x3FF
157+	last = None
158+	lastWasM1 = False
159+	for line in datafile.readlines():
160+		line = line.strip()
161+		if line and not line.startswith(';'):
162+			sample,_,num = line.partition('@')
163+			sample = int(sample, 16)
164+			if not (last is None):
165+				if detect_rise(last, sample, mreq):
166+					address = last & addressMask
167+					if detect_low(last, m1):
168+						print 'M1 read {0:02X} @ {1}'.format(address, num)
169+						lastWasM1 = True
170+					elif lastWasM1:
171+						print 'Refresh {0:02X} @ {1}'.format(address, num)
172+						lastWasM1 = False
173+					else:
174+						print 'Access {0:02X} @ {1}'.format(address, num)
175+			last = sample
176+
177+def main(args):
178+	if len(args) < 2:
179+		print 'Usage: analyze_olp.py filename'
180+		exit(1)
181+	olpfile = ZipFile(args[1], "r")
182+	channelfile = olpfile.open('channel.labels')
183+	channels = [line.strip() for line in channelfile.readlines()]
184+	channelfile.close()
185+	print channels
186+	chanmap = {}
187+	for i in xrange(0, len(channels)):
188+		chanmap[channels[i]] = i
189+	datafile = olpfile.open('data.ols')
190+	#analyze_delays(chanmap, datafile)
191+	#analyze_vram(chanmap, datafile)
192+	#analyze_refresh(chanmap, datafile)
193+	analyze_z80_mreq(chanmap, datafile)
194+	datafile.close()
195+	
196+
197+if __name__ == '__main__':
198+	main(argv)
+89, -0
 1@@ -0,0 +1,89 @@
 2+/*
 3+ Copyright 2015 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include <stdlib.h>
 8+#include <stdint.h>
 9+#include "arena.h"
10+
11+struct arena {
12+	void **used_blocks;
13+	void **free_blocks;
14+
15+	size_t used_count;
16+	size_t used_storage;
17+	size_t free_count;
18+	size_t free_storage;
19+};
20+
21+#define DEFAULT_STORAGE_SIZE 8
22+
23+static arena *current_arena;
24+
25+arena *get_current_arena()
26+{
27+	if (!current_arena) {
28+		current_arena = calloc(1, sizeof(arena));
29+	}
30+	return current_arena;
31+}
32+
33+arena *set_current_arena(arena *a)
34+{
35+	arena *tmp = current_arena;
36+	current_arena = a;
37+	return tmp;
38+}
39+
40+arena *start_new_arena()
41+{
42+	arena *tmp = current_arena;
43+	current_arena = NULL;
44+	return tmp;
45+}
46+
47+void track_block(void *block)
48+{
49+	arena *cur = get_current_arena();
50+	if (cur->used_count == cur->used_storage) {
51+		if (cur->used_storage) {
52+			cur->used_storage *= 2;
53+		} else {
54+			cur->used_storage = DEFAULT_STORAGE_SIZE;
55+		}
56+		cur->used_blocks = realloc(cur->used_blocks, cur->used_storage * sizeof(void *));
57+	}
58+	cur->used_blocks[cur->used_count++] = block;
59+}
60+
61+void mark_all_free()
62+{
63+	arena *cur = get_current_arena();
64+	if (!cur->free_blocks) {
65+		cur->free_blocks = cur->used_blocks;
66+		cur->free_storage = cur->used_storage;
67+		cur->free_count = cur->used_count;
68+		cur->used_count = cur->used_storage = 0;
69+		cur->used_blocks = NULL;
70+	} else {
71+		if (cur->free_storage < cur->used_count + cur->free_count) {
72+			cur->free_storage = cur->used_count + cur->free_count;
73+			cur->free_blocks = realloc(cur->free_blocks, cur->free_storage * sizeof(void*));
74+		}
75+		for (; cur->used_count > 0; cur->used_count--)
76+		{
77+			cur->free_blocks[cur->free_count++] = cur->used_blocks[cur->used_count-1];
78+		}
79+	}
80+}
81+
82+void *try_alloc_arena()
83+{
84+	if (!current_arena || !current_arena->free_count) {
85+		return NULL;
86+	}
87+	void *ret = current_arena->free_blocks[--current_arena->free_count];
88+	track_block(ret);
89+	return ret;
90+}
+18, -0
 1@@ -0,0 +1,18 @@
 2+/*
 3+ Copyright 2015 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef ARENA_H_
 8+#define ARENA_H_
 9+
10+typedef struct arena arena;
11+
12+arena *get_current_arena();
13+arena *set_current_arena(arena *a);
14+arena *start_new_arena();
15+void track_block(void *block);
16+void mark_all_free();
17+void *try_alloc_arena();
18+
19+#endif //ARENA_H_
+1, -0
1@@ -0,0 +1 @@
2+arrow.png,16,0,raw,nopal,interlace,sprite
+0, -0
+247, -0
  1@@ -0,0 +1,247 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "backend.h"
  8+#include <stdlib.h>
  9+
 10+deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest)
 11+{
 12+	deferred_addr * new_head = malloc(sizeof(deferred_addr));
 13+	new_head->next = old_head;
 14+	new_head->address = address & 0xFFFFFF;
 15+	new_head->dest = dest;
 16+	return new_head;
 17+}
 18+
 19+void remove_deferred_until(deferred_addr **head_ptr, deferred_addr * remove_to)
 20+{
 21+	for(deferred_addr *cur = *head_ptr; cur && cur != remove_to; cur = *head_ptr)
 22+	{
 23+		*head_ptr = cur->next;
 24+		free(cur);
 25+	}
 26+}
 27+
 28+void process_deferred(deferred_addr ** head_ptr, void * context, native_addr_func get_native)
 29+{
 30+	deferred_addr * cur = *head_ptr;
 31+	deferred_addr **last_next = head_ptr;
 32+	while(cur)
 33+	{
 34+		code_ptr native = get_native(context, cur->address);//get_native_address(opts->native_code_map, cur->address);
 35+		if (native) {
 36+			int32_t disp = native - (cur->dest + 4);
 37+			code_ptr out = cur->dest;
 38+			*(out++) = disp;
 39+			disp >>= 8;
 40+			*(out++) = disp;
 41+			disp >>= 8;
 42+			*(out++) = disp;
 43+			disp >>= 8;
 44+			*out = disp;
 45+			*last_next = cur->next;
 46+			free(cur);
 47+			cur = *last_next;
 48+		} else {
 49+			last_next = &(cur->next);
 50+			cur = cur->next;
 51+		}
 52+	}
 53+}
 54+
 55+memmap_chunk const *find_map_chunk(uint32_t address, cpu_options *opts, uint16_t flags, uint32_t *size_sum)
 56+{
 57+	if (size_sum) {
 58+		*size_sum = 0;
 59+	}
 60+	address &= opts->address_mask;
 61+	for (memmap_chunk const *cur = opts->memmap, *end = opts->memmap + opts->memmap_chunks; cur != end; cur++)
 62+	{
 63+		if (address >= cur->start && address < cur->end) {
 64+			return cur;
 65+		} else if (size_sum && (cur->flags & flags) == flags) {
 66+			*size_sum += chunk_size(opts, cur);
 67+		}
 68+	}
 69+	return NULL;
 70+}
 71+
 72+void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts)
 73+{
 74+	memmap_chunk const * memmap = opts->memmap;
 75+	address &= opts->address_mask;
 76+	for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++)
 77+	{
 78+		if (address >= memmap[chunk].start && address < memmap[chunk].end) {
 79+			if (!(memmap[chunk].flags & (MMAP_READ|MMAP_READ_CODE))) {
 80+				return NULL;
 81+			}
 82+			uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX
 83+				? mem_pointers[memmap[chunk].ptr_index]
 84+				: memmap[chunk].buffer;
 85+			if (!base) {
 86+				if (memmap[chunk].flags & MMAP_AUX_BUFF) {
 87+					return memmap[chunk].buffer + (address & memmap[chunk].aux_mask);
 88+				}
 89+				return NULL;
 90+			}
 91+			return base + (address & memmap[chunk].mask);
 92+		}
 93+	}
 94+	return NULL;
 95+}
 96+
 97+void * get_native_write_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts)
 98+{
 99+	memmap_chunk const * memmap = opts->memmap;
100+	address &= opts->address_mask;
101+	for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++)
102+	{
103+		if (address >= memmap[chunk].start && address < memmap[chunk].end) {
104+			if (!(memmap[chunk].flags & (MMAP_WRITE))) {
105+				return NULL;
106+			}
107+			uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX
108+				? mem_pointers[memmap[chunk].ptr_index]
109+				: memmap[chunk].buffer;
110+			if (!base) {
111+				if (memmap[chunk].flags & MMAP_AUX_BUFF) {
112+					return memmap[chunk].buffer + (address & memmap[chunk].aux_mask);
113+				}
114+				return NULL;
115+			}
116+			return base + (address & memmap[chunk].mask);
117+		}
118+	}
119+	return NULL;
120+}
121+
122+uint16_t read_word(uint32_t address, void **mem_pointers, cpu_options *opts, void *context)
123+{
124+	memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL);
125+	if (!chunk) {
126+		return 0xFFFF;
127+	}
128+	uint32_t offset = address & chunk->mask;
129+	if (chunk->flags & MMAP_READ) {
130+		uint8_t *base;
131+		if (chunk->flags & MMAP_PTR_IDX) {
132+			base = mem_pointers[chunk->ptr_index];
133+		} else {
134+			base = chunk->buffer;
135+		}
136+		if (base) {
137+			uint16_t val;
138+			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
139+				offset /= 2;
140+				val = base[offset];
141+				if (chunk->flags & MMAP_ONLY_ODD) {
142+					val |= 0xFF00;
143+				} else {
144+					val = val << 8 | 0xFF;
145+				}
146+			} else {
147+				val = *(uint16_t *)(base + offset);
148+			}
149+			return val;
150+		}
151+	}
152+	if ((!(chunk->flags & MMAP_READ) || (chunk->flags & MMAP_FUNC_NULL)) && chunk->read_16) {
153+		return chunk->read_16(offset, context);
154+	}
155+	return 0xFFFF;
156+}
157+
158+uint8_t read_byte(uint32_t address, void **mem_pointers, cpu_options *opts, void *context)
159+{
160+	memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL);
161+	if (!chunk) {
162+		return 0xFF;
163+	}
164+	uint32_t offset = address & chunk->mask;
165+	if (chunk->flags & MMAP_READ) {
166+		uint8_t *base;
167+		if (chunk->flags & MMAP_PTR_IDX) {
168+			base = mem_pointers[chunk->ptr_index];
169+		} else {
170+			base = chunk->buffer;
171+		}
172+		if (base) {
173+			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
174+				if (address & 1) {
175+					if (chunk->flags & MMAP_ONLY_EVEN) {
176+						return 0xFF;
177+					}
178+				} else if (chunk->flags & MMAP_ONLY_ODD) {
179+					return 0xFF;
180+				}
181+				offset /= 2;
182+			}
183+			return base[offset];
184+		}
185+	}
186+	if ((!(chunk->flags & MMAP_READ) || (chunk->flags & MMAP_FUNC_NULL)) && chunk->read_8) {
187+		return chunk->read_8(offset, context);
188+	}
189+	return 0xFF;
190+}
191+
192+void write_byte(uint32_t address, uint8_t value, void **mem_pointers, cpu_options *opts, void *context)
193+{
194+	memmap_chunk const *chunk = find_map_chunk(address, opts, 0, NULL);
195+	if (!chunk) {
196+		return;
197+	}
198+	uint32_t offset = address & chunk->mask;
199+	if (chunk->flags & MMAP_WRITE) {
200+		uint8_t *base;
201+		if (chunk->flags & MMAP_PTR_IDX) {
202+			base = mem_pointers[chunk->ptr_index];
203+		} else {
204+			base = chunk->buffer;
205+		}
206+		if (base) {
207+			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
208+				if (address & 1) {
209+					if (chunk->flags & MMAP_ONLY_EVEN) {
210+						return;
211+					}
212+				} else if (chunk->flags & MMAP_ONLY_ODD) {
213+					return;
214+				}
215+				offset /= 2;
216+			}
217+			base[offset] = value;
218+		}
219+	}
220+	if ((!(chunk->flags & MMAP_WRITE) || (chunk->flags & MMAP_FUNC_NULL)) && chunk->write_8) {
221+		chunk->write_8(offset, context, value);
222+	}
223+}
224+
225+uint32_t chunk_size(cpu_options *opts, memmap_chunk const *chunk)
226+{
227+	if (chunk->mask == opts->address_mask) {
228+		return chunk->end - chunk->start;
229+	} else {
230+		return chunk->mask + 1;
231+	}
232+}
233+
234+uint32_t ram_size(cpu_options *opts)
235+{
236+	uint32_t size = 0;
237+	for (int i = 0; i < opts->memmap_chunks; i++)
238+	{
239+		if (opts->memmap[i].flags & MMAP_CODE) {
240+			if (opts->memmap[i].mask == opts->address_mask) {
241+				size += opts->memmap[i].end - opts->memmap[i].start;
242+			} else {
243+				size += opts->memmap[i].mask + 1;
244+			}
245+		}
246+	}
247+	return size;
248+}
+107, -0
  1@@ -0,0 +1,107 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef BACKEND_H_
  8+#define BACKEND_H_
  9+
 10+#include <stdint.h>
 11+#include <stdio.h>
 12+#include "gen.h"
 13+
 14+#define INVALID_OFFSET 0xFFFFFFFF
 15+#define EXTENSION_WORD 0xFFFFFFFE
 16+#define CYCLE_NEVER 0xFFFFFFFF
 17+
 18+#if defined(X86_32) || defined(X86_64)
 19+typedef struct {
 20+	int32_t disp;
 21+	uint8_t mode;
 22+	uint8_t base;
 23+	uint8_t index;
 24+} host_ea;
 25+#else
 26+typedef struct {
 27+	int32_t disp;
 28+	uint8_t mode;
 29+	uint8_t base;
 30+} host_ea;
 31+#endif
 32+
 33+typedef struct {
 34+	uint8_t  *base;
 35+	int32_t  *offsets;
 36+} native_map_slot;
 37+
 38+typedef struct deferred_addr {
 39+	struct deferred_addr *next;
 40+	code_ptr             dest;
 41+	uint32_t             address;
 42+} deferred_addr;
 43+
 44+#include "memmap.h"
 45+#include "system.h"
 46+
 47+typedef struct {
 48+	uint32_t flags;
 49+	native_map_slot    *native_code_map;
 50+	deferred_addr      *deferred;
 51+	code_info          code;
 52+	uint8_t            **ram_inst_sizes;
 53+	memmap_chunk const *memmap;
 54+	code_ptr           save_context;
 55+	code_ptr           load_context;
 56+	code_ptr           handle_cycle_limit;
 57+	code_ptr           handle_cycle_limit_int;
 58+	code_ptr           handle_code_write;
 59+	code_ptr           handle_align_error_write;
 60+	code_ptr           handle_align_error_read;
 61+	system_str_fun_r8  debug_cmd_handler;
 62+	uint32_t           memmap_chunks;
 63+	uint32_t           address_mask;
 64+	uint32_t           max_address;
 65+	uint32_t           bus_cycles;
 66+	uint32_t           clock_divider;
 67+	uint32_t           move_pc_off;
 68+	uint32_t           move_pc_size;
 69+	int32_t            mem_ptr_off;
 70+	int32_t            ram_flags_off;
 71+	uint8_t            ram_flags_shift;
 72+	uint8_t            address_size;
 73+	uint8_t            byte_swap;
 74+	int8_t             context_reg;
 75+	int8_t             cycles;
 76+	int8_t             limit;
 77+	int8_t             scratch1;
 78+	int8_t             scratch2;
 79+	uint8_t            align_error_mask;
 80+} cpu_options;
 81+
 82+typedef uint8_t * (*native_addr_func)(void * context, uint32_t address);
 83+
 84+deferred_addr * defer_address(deferred_addr * old_head, uint32_t address, uint8_t *dest);
 85+void remove_deferred_until(deferred_addr **head_ptr, deferred_addr * remove_to);
 86+void process_deferred(deferred_addr ** head_ptr, void * context, native_addr_func get_native);
 87+
 88+void cycles(cpu_options *opts, uint32_t num);
 89+void check_cycles_int(cpu_options *opts, uint32_t address);
 90+void check_cycles(cpu_options * opts);
 91+void check_code_prologue(code_info *code);
 92+void log_address(cpu_options *opts, uint32_t address, char * format);
 93+
 94+void retranslate_calc(cpu_options *opts);
 95+void patch_for_retranslate(cpu_options *opts, code_ptr native_address, code_ptr handler);
 96+
 97+code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc);
 98+void * get_native_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts);
 99+void * get_native_write_pointer(uint32_t address, void ** mem_pointers, cpu_options * opts);
100+uint16_t read_word(uint32_t address, void **mem_pointers, cpu_options *opts, void *context);
101+uint8_t read_byte(uint32_t address, void **mem_pointers, cpu_options *opts, void *context);
102+void write_byte(uint32_t address, uint8_t value, void **mem_pointers, cpu_options *opts, void *context);
103+memmap_chunk const *find_map_chunk(uint32_t address, cpu_options *opts, uint16_t flags, uint32_t *size_sum);
104+uint32_t chunk_size(cpu_options *opts, memmap_chunk const *chunk);
105+uint32_t ram_size(cpu_options *opts);
106+
107+#endif //BACKEND_H_
108+
+322, -0
  1@@ -0,0 +1,322 @@
  2+#include "backend.h"
  3+#include "gen_x86.h"
  4+#include <string.h>
  5+
  6+void cycles(cpu_options *opts, uint32_t num)
  7+{
  8+	if (opts->limit < 0) {
  9+		sub_ir(&opts->code, num*opts->clock_divider, opts->cycles, SZ_D);
 10+	} else {
 11+		add_ir(&opts->code, num*opts->clock_divider, opts->cycles, SZ_D);
 12+	}
 13+}
 14+
 15+void check_cycles_int(cpu_options *opts, uint32_t address)
 16+{
 17+	code_info *code = &opts->code;
 18+	uint8_t cc;
 19+	if (opts->limit < 0) {
 20+		cmp_ir(code, 1, opts->cycles, SZ_D);
 21+		cc = CC_NS;
 22+	} else {
 23+		cmp_rr(code, opts->cycles, opts->limit, SZ_D);
 24+		cc = CC_A;
 25+	}
 26+	code_ptr jmp_off = code->cur+1;
 27+	jcc(code, cc, jmp_off+1);
 28+	mov_ir(code, address, opts->scratch1, SZ_D);
 29+	call(code, opts->handle_cycle_limit_int);
 30+	*jmp_off = code->cur - (jmp_off+1);
 31+}
 32+
 33+void retranslate_calc(cpu_options *opts)
 34+{
 35+	code_info *code = &opts->code;
 36+	code_info tmp = *code;
 37+	uint8_t cc;
 38+	if (opts->limit < 0) {
 39+		cmp_ir(code, 1, opts->cycles, SZ_D);
 40+		cc = CC_NS;
 41+	} else {
 42+		cmp_rr(code, opts->cycles, opts->limit, SZ_D);
 43+		cc = CC_A;
 44+	}
 45+	jcc(code, cc, code->cur+2);
 46+	opts->move_pc_off = code->cur - tmp.cur;
 47+	mov_ir(code, 0x1234, opts->scratch1, SZ_D);
 48+	opts->move_pc_size = code->cur - tmp.cur - opts->move_pc_off;
 49+	*code = tmp;
 50+}
 51+
 52+void patch_for_retranslate(cpu_options *opts, code_ptr native_address, code_ptr handler)
 53+{
 54+	if (!is_mov_ir(native_address)) {
 55+		//instruction is not already patched for either retranslation or a breakpoint
 56+		//copy original mov_ir instruction containing PC to beginning of native code area
 57+		memmove(native_address, native_address + opts->move_pc_off, opts->move_pc_size);
 58+	}
 59+	//jump to the retranslation handler
 60+	code_info tmp = {
 61+		.cur =  native_address + opts->move_pc_size,
 62+		.last = native_address + 256,
 63+		.stack_off = 0
 64+	};
 65+	jmp(&tmp, handler);
 66+}
 67+
 68+void check_cycles(cpu_options * opts)
 69+{
 70+	code_info *code = &opts->code;
 71+	uint8_t cc;
 72+	if (opts->limit < 0) {
 73+		cmp_ir(code, 1, opts->cycles, SZ_D);
 74+		cc = CC_NS;
 75+	} else {
 76+		cmp_rr(code, opts->cycles, opts->limit, SZ_D);
 77+		cc = CC_A;
 78+	}
 79+	check_alloc_code(code, MAX_INST_LEN*2);
 80+	code_ptr jmp_off = code->cur+1;
 81+	jcc(code, cc, jmp_off+1);
 82+	call(code, opts->handle_cycle_limit);
 83+	*jmp_off = code->cur - (jmp_off+1);
 84+}
 85+
 86+void log_address(cpu_options *opts, uint32_t address, char * format)
 87+{
 88+	code_info *code = &opts->code;
 89+	call(code, opts->save_context);
 90+	push_r(code, opts->context_reg);
 91+	mov_rr(code, opts->cycles, RDX, SZ_D);
 92+	mov_ir(code, (int64_t)format, RDI, SZ_PTR);
 93+	mov_ir(code, address, RSI, SZ_D);
 94+	call_args_abi(code, (code_ptr)printf, 3, RDI, RSI, RDX);
 95+	pop_r(code, opts->context_reg);
 96+	call(code, opts->load_context);
 97+}
 98+
 99+void check_code_prologue(code_info *code)
100+{
101+	check_alloc_code(code, MAX_INST_LEN*4);
102+}
103+
104+code_ptr gen_mem_fun(cpu_options * opts, memmap_chunk const * memmap, uint32_t num_chunks, ftype fun_type, code_ptr *after_inc)
105+{
106+	code_info *code = &opts->code;
107+	code_ptr start = code->cur;
108+	check_cycles(opts);
109+	uint8_t is_write = fun_type == WRITE_16 || fun_type == WRITE_8;
110+	uint8_t adr_reg = is_write ? opts->scratch2 : opts->scratch1;
111+	uint8_t size =  (fun_type == READ_16 || fun_type == WRITE_16) ? SZ_W : SZ_B;
112+	if (size != SZ_B && opts->align_error_mask) {
113+		test_ir(code, opts->align_error_mask, adr_reg, SZ_D);
114+		jcc(code, CC_NZ, is_write ? opts->handle_align_error_write : opts->handle_align_error_read);
115+	}
116+	cycles(opts, opts->bus_cycles);
117+	if (after_inc) {
118+		*after_inc = code->cur;
119+	}
120+	
121+	if (opts->address_size == SZ_D && opts->address_mask != 0xFFFFFFFF) {
122+		and_ir(code, opts->address_mask, adr_reg, SZ_D);
123+	} else if (opts->address_size == SZ_W && opts->address_mask != 0xFFFF) {
124+		and_ir(code, opts->address_mask, adr_reg, SZ_W);
125+	}
126+	code_ptr lb_jcc = NULL, ub_jcc = NULL;
127+	uint16_t access_flag = is_write ? MMAP_WRITE : MMAP_READ;
128+	uint32_t ram_flags_off = opts->ram_flags_off;
129+	uint32_t min_address = 0;
130+	uint32_t max_address = opts->max_address;
131+	for (uint32_t chunk = 0; chunk < num_chunks; chunk++)
132+	{
133+		if (memmap[chunk].start > min_address) {
134+			cmp_ir(code, memmap[chunk].start, adr_reg, opts->address_size);
135+			lb_jcc = code->cur + 1;
136+			jcc(code, CC_C, code->cur + 2);
137+		} else {
138+			min_address = memmap[chunk].end;
139+		}
140+		if (memmap[chunk].end < max_address) {
141+			cmp_ir(code, memmap[chunk].end, adr_reg, opts->address_size);
142+			ub_jcc = code->cur + 1;
143+			jcc(code, CC_NC, code->cur + 2);
144+		} else {
145+			max_address = memmap[chunk].start;
146+		}
147+
148+		if (memmap[chunk].mask != opts->address_mask) {
149+			and_ir(code, memmap[chunk].mask, adr_reg, opts->address_size);
150+		}
151+		void * cfun;
152+		switch (fun_type)
153+		{
154+		case READ_16:
155+			cfun = memmap[chunk].read_16;
156+			break;
157+		case READ_8:
158+			cfun = memmap[chunk].read_8;
159+			break;
160+		case WRITE_16:
161+			cfun = memmap[chunk].write_16;
162+			break;
163+		case WRITE_8:
164+			cfun = memmap[chunk].write_8;
165+			break;
166+		default:
167+			cfun = NULL;
168+		}
169+		if(memmap[chunk].flags & access_flag) {
170+			if (memmap[chunk].flags & MMAP_PTR_IDX) {
171+				if (memmap[chunk].flags & MMAP_FUNC_NULL) {
172+					cmp_irdisp(code, 0, opts->context_reg, opts->mem_ptr_off + sizeof(void*) * memmap[chunk].ptr_index, SZ_PTR);
173+					code_ptr not_null = code->cur + 1;
174+					jcc(code, CC_NZ, code->cur + 2);
175+					call(code, opts->save_context);
176+					if (is_write) {
177+						call_args_abi(code, cfun, 3, opts->scratch2, opts->context_reg, opts->scratch1);
178+						mov_rr(code, RAX, opts->context_reg, SZ_PTR);
179+					} else {
180+						push_r(code, opts->context_reg);
181+						call_args_abi(code, cfun, 2, opts->scratch1, opts->context_reg);
182+						pop_r(code, opts->context_reg);
183+						mov_rr(code, RAX, opts->scratch1, size);
184+					}
185+					jmp(code, opts->load_context);
186+
187+					*not_null = code->cur - (not_null + 1);
188+				}
189+				if ((opts->byte_swap || memmap[chunk].flags & MMAP_BYTESWAP) && size == SZ_B) {
190+					xor_ir(code, 1, adr_reg, opts->address_size);
191+				}
192+				if (opts->address_size != SZ_D) {
193+					movzx_rr(code, adr_reg, adr_reg, opts->address_size, SZ_D);
194+				}
195+				if (is_write && (memmap[chunk].flags & MMAP_CODE)) {
196+					push_r(code, adr_reg);
197+				}
198+				add_rdispr(code, opts->context_reg, opts->mem_ptr_off + sizeof(void*) * memmap[chunk].ptr_index, adr_reg, SZ_PTR);
199+				if (is_write) {
200+					mov_rrind(code, opts->scratch1, opts->scratch2, size);
201+					if (memmap[chunk].flags & MMAP_CODE) {
202+						pop_r(code, adr_reg);
203+					}
204+				} else {
205+					mov_rindr(code, opts->scratch1, opts->scratch1, size);
206+				}
207+			} else {
208+				uint8_t tmp_size = size;
209+				if (size == SZ_B) {
210+					if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) {
211+						bt_ir(code, 0, adr_reg, opts->address_size);
212+						code_ptr good_addr = code->cur + 1;
213+						jcc(code, (memmap[chunk].flags & MMAP_ONLY_ODD) ? CC_C : CC_NC, code->cur + 2);
214+						if (!is_write) {
215+							mov_ir(code, 0xFF, opts->scratch1, SZ_B);
216+						}
217+						retn(code);
218+						*good_addr = code->cur - (good_addr + 1);
219+						shr_ir(code, 1, adr_reg, opts->address_size);
220+					} else if (opts->byte_swap || memmap[chunk].flags & MMAP_BYTESWAP) {
221+						xor_ir(code, 1, adr_reg, opts->address_size);
222+					}
223+				} else if ((memmap[chunk].flags & MMAP_ONLY_ODD) || (memmap[chunk].flags & MMAP_ONLY_EVEN)) {
224+					tmp_size = SZ_B;
225+					shr_ir(code, 1, adr_reg, opts->address_size);
226+					if ((memmap[chunk].flags & MMAP_ONLY_EVEN) && is_write) {
227+						shr_ir(code, 8, opts->scratch1, SZ_W);
228+					}
229+				}
230+				if (opts->address_size != SZ_D) {
231+					movzx_rr(code, adr_reg, adr_reg, opts->address_size, SZ_D);
232+				}
233+				if ((intptr_t)memmap[chunk].buffer <= 0x7FFFFFFF && (intptr_t)memmap[chunk].buffer >= -2147483648) {
234+					if (is_write) {
235+						mov_rrdisp(code, opts->scratch1, opts->scratch2, (intptr_t)memmap[chunk].buffer, tmp_size);
236+					} else {
237+						mov_rdispr(code, opts->scratch1, (intptr_t)memmap[chunk].buffer, opts->scratch1, tmp_size);
238+					}
239+				} else {
240+					if (is_write) {
241+						push_r(code, opts->scratch2);
242+						mov_ir(code, (intptr_t)memmap[chunk].buffer, opts->scratch2, SZ_PTR);
243+						add_rdispr(code, RSP, 0, opts->scratch2, SZ_PTR);
244+						mov_rrind(code, opts->scratch1, opts->scratch2, tmp_size);
245+						if (is_write && (memmap[chunk].flags & MMAP_CODE)) {
246+							pop_r(code, opts->scratch2);
247+						} else {
248+							add_ir(code, sizeof(void*), RSP, SZ_PTR);
249+							code->stack_off -= sizeof(void *);
250+						}
251+					} else {
252+						push_r(code, opts->scratch2);
253+						mov_ir(code, (intptr_t)memmap[chunk].buffer, opts->scratch2, SZ_PTR);
254+						mov_rindexr(code, opts->scratch2, opts->scratch1, 1, opts->scratch1, tmp_size);
255+						pop_r(code, opts->scratch2);
256+					}
257+				}
258+				if (size != tmp_size && !is_write) {
259+					if (memmap[chunk].flags & MMAP_ONLY_EVEN) {
260+						shl_ir(code, 8, opts->scratch1, SZ_W);
261+						mov_ir(code, 0xFF, opts->scratch1, SZ_B);
262+					} else {
263+						or_ir(code, 0xFF00, opts->scratch1, SZ_W);
264+					}
265+				}
266+			}
267+			if (is_write && (memmap[chunk].flags & MMAP_CODE)) {
268+				mov_rr(code, opts->scratch2, opts->scratch1, opts->address_size);
269+				shr_ir(code, opts->ram_flags_shift, opts->scratch1, opts->address_size);
270+				bt_rrdisp(code, opts->scratch1, opts->context_reg, ram_flags_off, opts->address_size);
271+				code_ptr not_code = code->cur + 1;
272+				jcc(code, CC_NC, code->cur + 2);
273+				if (memmap[chunk].mask != opts->address_mask) {
274+					or_ir(code, memmap[chunk].start, opts->scratch2, opts->address_size);
275+				}
276+				call(code, opts->save_context);
277+				call_args(code, opts->handle_code_write, 2, opts->scratch2, opts->context_reg);
278+				mov_rr(code, RAX, opts->context_reg, SZ_PTR);
279+				jmp(code, opts->load_context);
280+				*not_code = code->cur - (not_code+1);
281+			}
282+			retn(code);
283+		} else if (cfun) {
284+			call(code, opts->save_context);
285+			if (is_write) {
286+				call_args_abi(code, cfun, 3, opts->scratch2, opts->context_reg, opts->scratch1);
287+				mov_rr(code, RAX, opts->context_reg, SZ_PTR);
288+			} else {
289+				push_r(code, opts->context_reg);
290+				call_args_abi(code, cfun, 2, opts->scratch1, opts->context_reg);
291+				pop_r(code, opts->context_reg);
292+				mov_rr(code, RAX, opts->scratch1, size);
293+			}
294+			jmp(code, opts->load_context);
295+		} else {
296+			//Not sure the best course of action here
297+			if (!is_write) {
298+				mov_ir(code, size == SZ_B ? 0xFF : 0xFFFF, opts->scratch1, size);
299+			}
300+			retn(code);
301+		}
302+		if (memmap[chunk].flags & MMAP_CODE) {
303+			if (memmap[chunk].mask == opts->address_mask) {
304+				ram_flags_off += (memmap[chunk].end - memmap[chunk].start) / (1 << opts->ram_flags_shift) / 8; ;
305+			} else {
306+				ram_flags_off += (memmap[chunk].mask + 1) /  (1 << opts->ram_flags_shift) / 8;;
307+			}
308+		}
309+		if (lb_jcc) {
310+			*lb_jcc = code->cur - (lb_jcc+1);
311+			lb_jcc = NULL;
312+		}
313+		if (ub_jcc) {
314+			*ub_jcc = code->cur - (ub_jcc+1);
315+			ub_jcc = NULL;
316+		}
317+	}
318+	if (!is_write) {
319+		mov_ir(code, size == SZ_B ? 0xFF : 0xFFFF, opts->scratch1, size);
320+	}
321+	retn(code);
322+	return start;
323+}
+1072, -0
   1@@ -0,0 +1,1072 @@
   2+#include <string.h>
   3+#include <stdlib.h>
   4+#include "render.h"
   5+#include "system.h"
   6+#include "io.h"
   7+#include "blastem.h"
   8+#include "saves.h"
   9+#include "util.h"
  10+#include "genesis.h"
  11+#include "sms.h"
  12+#include "menu.h"
  13+#include "bindings.h"
  14+#include "controller_info.h"
  15+enum {
  16+	BIND_NONE,
  17+	BIND_UI,
  18+	BIND_GAMEPAD,
  19+	BIND_MOUSE
  20+};
  21+
  22+typedef enum {
  23+	UI_DEBUG_MODE_INC,
  24+	UI_ENTER_DEBUGGER,
  25+	UI_SAVE_STATE,
  26+	UI_SET_SPEED,
  27+	UI_NEXT_SPEED,
  28+	UI_PREV_SPEED,
  29+	UI_RELEASE_MOUSE,
  30+	UI_TOGGLE_KEYBOARD_CAPTURE,
  31+	UI_SOFT_RESET,
  32+	UI_RELOAD,
  33+	UI_SMS_PAUSE,
  34+	UI_SCREENSHOT,
  35+	UI_EXIT,
  36+	UI_PLANE_DEBUG,
  37+	UI_VRAM_DEBUG,
  38+	UI_CRAM_DEBUG,
  39+	UI_COMPOSITE_DEBUG
  40+} ui_action;
  41+
  42+typedef struct {
  43+	uint8_t bind_type;
  44+	uint8_t subtype_a;
  45+	uint8_t subtype_b;
  46+} keybinding;
  47+
  48+typedef struct {
  49+	keybinding bindings[4];
  50+	uint8_t    state;
  51+} joydpad;
  52+
  53+typedef struct {
  54+	keybinding positive;
  55+	keybinding negative;
  56+	int16_t    value;
  57+} joyaxis;
  58+
  59+typedef struct {
  60+	keybinding *buttons;
  61+	joydpad    *dpads;
  62+	joyaxis    *axes;
  63+	uint32_t   num_buttons; //number of entries in the buttons array, not necessarily the number of buttons on the device
  64+	uint32_t   num_dpads;   //number of entries in the dpads array, not necessarily the number of dpads on the device
  65+	uint32_t   num_axes;    //number of entries in the axes array, not necessarily the number of dpads on the device
  66+} joystick;
  67+
  68+typedef struct {
  69+	keybinding buttons[MAX_MOUSE_BUTTONS];
  70+	keybinding motion;
  71+} mousebinding;
  72+
  73+#define DEFAULT_JOYBUTTON_ALLOC 12
  74+static keybinding *bindings[0x10000];
  75+static joystick joysticks[MAX_JOYSTICKS];
  76+static mousebinding mice[MAX_MICE];
  77+const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
  78+
  79+static void do_bind(keybinding *binding, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
  80+{
  81+	binding->bind_type = bind_type;
  82+	binding->subtype_a = subtype_a;
  83+	binding->subtype_b = subtype_b;
  84+}
  85+
  86+void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
  87+{
  88+	int bucket = keycode >> 15 & 0xFFFF;
  89+	if (!bindings[bucket]) {
  90+		bindings[bucket] = malloc(sizeof(keybinding) * 0x8000);
  91+		memset(bindings[bucket], 0, sizeof(keybinding) * 0x8000);
  92+	}
  93+	int idx = keycode & 0x7FFF;
  94+	do_bind(bindings[bucket] + idx, bind_type, subtype_a, subtype_b);
  95+}
  96+
  97+void bind_button(int joystick, int button, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
  98+{
  99+	if (joystick >= MAX_JOYSTICKS) {
 100+		return;
 101+	}
 102+	if (!joysticks[joystick].buttons) {
 103+		joysticks[joystick].num_buttons = button < DEFAULT_JOYBUTTON_ALLOC ? DEFAULT_JOYBUTTON_ALLOC : button + 1;
 104+		joysticks[joystick].buttons = calloc(joysticks[joystick].num_buttons, sizeof(keybinding));
 105+	} else if (joysticks[joystick].num_buttons <= button) {
 106+		uint32_t old_capacity = joysticks[joystick].num_buttons;
 107+		joysticks[joystick].num_buttons *= 2;
 108+		joysticks[joystick].buttons = realloc(joysticks[joystick].buttons, sizeof(keybinding) * joysticks[joystick].num_buttons);
 109+		memset(joysticks[joystick].buttons + old_capacity, 0, joysticks[joystick].num_buttons - old_capacity);
 110+	}
 111+	do_bind(joysticks[joystick].buttons + button, bind_type, subtype_a, subtype_b);
 112+}
 113+
 114+void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
 115+{
 116+	if (joystick >= MAX_JOYSTICKS) {
 117+		return;
 118+	}
 119+	if (!joysticks[joystick].dpads) {
 120+		//multiple D-pads/hats are not common, so don't allocate any extra space
 121+		joysticks[joystick].dpads = calloc(dpad+1, sizeof(joydpad));
 122+		joysticks[joystick].num_dpads = dpad+1;
 123+	} else if (joysticks[joystick].num_dpads <= dpad) {
 124+		uint32_t old_capacity = joysticks[joystick].num_dpads;
 125+		joysticks[joystick].num_dpads *= 2;
 126+		joysticks[joystick].dpads = realloc(joysticks[joystick].dpads, sizeof(joydpad) * joysticks[joystick].num_dpads);
 127+		memset(joysticks[joystick].dpads + old_capacity, 0, (joysticks[joystick].num_dpads - old_capacity) * sizeof(joydpad));
 128+	}
 129+	for (int i = 0; i < 4; i ++) {
 130+		if (dpadbits[i] & direction) {
 131+			do_bind(joysticks[joystick].dpads[dpad].bindings + i, bind_type, subtype_a, subtype_b);
 132+			break;
 133+		}
 134+	}
 135+}
 136+
 137+void bind_axis(int joystick, int axis, int positive, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b)
 138+{
 139+	if (joystick >= MAX_JOYSTICKS) {
 140+		return;
 141+	}
 142+	if (!joysticks[joystick].axes) {
 143+		//typical gamepad has 4 axes
 144+		joysticks[joystick].num_axes = axis+1 > 4 ? axis+1 : 4;
 145+		joysticks[joystick].axes = calloc(joysticks[joystick].num_axes, sizeof(joyaxis));
 146+	} else if (joysticks[joystick].num_axes <= axis) {
 147+		uint32_t old_capacity = joysticks[joystick].num_axes;
 148+		joysticks[joystick].num_axes *= 2;
 149+		joysticks[joystick].axes = realloc(joysticks[joystick].axes, sizeof(joyaxis) * joysticks[joystick].num_axes);
 150+		memset(joysticks[joystick].axes + old_capacity, 0, (joysticks[joystick].num_axes - old_capacity) * sizeof(joyaxis));
 151+	}
 152+	if (positive) {
 153+		do_bind(&joysticks[joystick].axes[axis].positive, bind_type, subtype_a, subtype_b);
 154+	} else {
 155+		do_bind(&joysticks[joystick].axes[axis].negative, bind_type, subtype_a, subtype_b);
 156+	}
 157+}
 158+
 159+void reset_joystick_bindings(int joystick)
 160+{
 161+	if (joystick >= MAX_JOYSTICKS) {
 162+		return;
 163+	}
 164+	if (joysticks[joystick].buttons) {
 165+		for (int i = 0; i < joysticks[joystick].num_buttons; i++)
 166+		{
 167+			joysticks[joystick].buttons[i].bind_type = BIND_NONE;
 168+		}
 169+	}
 170+	if (joysticks[joystick].dpads) {
 171+		for (int i = 0; i < joysticks[joystick].num_dpads; i++)
 172+		{
 173+			for (int dir = 0; dir < 4; dir++)
 174+			{
 175+				joysticks[joystick].dpads[i].bindings[dir].bind_type = BIND_NONE;
 176+			}
 177+		}
 178+	}
 179+	if (joysticks[joystick].axes) {
 180+		for (int i = 0; i < joysticks[joystick].num_axes; i++)
 181+		{
 182+			joysticks[joystick].axes[i].positive.bind_type = BIND_NONE;
 183+			joysticks[joystick].axes[i].negative.bind_type = BIND_NONE;
 184+		}
 185+	}
 186+}
 187+
 188+static uint8_t content_binds_enabled = 1;
 189+void set_content_binding_state(uint8_t enabled)
 190+{
 191+	content_binds_enabled = enabled;
 192+}
 193+
 194+void handle_binding_down(keybinding * binding)
 195+{
 196+	if (!current_system) {
 197+		return;
 198+	}
 199+	if (binding->bind_type == BIND_GAMEPAD && current_system && current_system->gamepad_down)
 200+	{
 201+		current_system->gamepad_down(current_system, binding->subtype_a, binding->subtype_b);
 202+	}
 203+	else if (binding->bind_type == BIND_MOUSE && current_system && current_system->mouse_down)
 204+	{
 205+		current_system->mouse_down(current_system, binding->subtype_a, binding->subtype_b);
 206+	}
 207+}
 208+
 209+static uint8_t keyboard_captured;
 210+void handle_keydown(int keycode, uint8_t scancode)
 211+{
 212+	int bucket = keycode >> 15 & 0xFFFF;
 213+	int idx = keycode & 0x7FFF;
 214+	keybinding * binding = bindings[bucket] ? bindings[bucket] + idx : NULL;
 215+	if (binding && (!keyboard_captured || (binding->bind_type == BIND_UI && binding->subtype_a == UI_TOGGLE_KEYBOARD_CAPTURE))) {
 216+		handle_binding_down(binding);
 217+	} else if (keyboard_captured && current_system && current_system->keyboard_down) {
 218+		current_system->keyboard_down(current_system, scancode);
 219+	}
 220+}
 221+
 222+void handle_joydown(int joystick, int button)
 223+{
 224+	if (joystick >= MAX_JOYSTICKS || button >= joysticks[joystick].num_buttons) {
 225+		return;
 226+	}
 227+	keybinding * binding = joysticks[joystick].buttons + button;
 228+	handle_binding_down(binding);
 229+}
 230+
 231+static uint8_t mouse_mode = MOUSE_NONE;
 232+static uint8_t mouse_captured;
 233+void handle_mousedown(int mouse, int button)
 234+{
 235+	if (mouse_mode == MOUSE_CAPTURE && !mouse_captured) {
 236+		mouse_captured = 1;
 237+		render_relative_mouse(1);
 238+		return;
 239+	}
 240+	if (mouse >= MAX_MICE || button > MAX_MOUSE_BUTTONS || button <= 0) {
 241+		return;
 242+	}
 243+	keybinding * binding = mice[mouse].buttons + button - 1;
 244+	handle_binding_down(binding);
 245+}
 246+
 247+static int current_speed = 0;
 248+static int num_speeds = 1;
 249+static uint32_t * speeds = NULL;
 250+
 251+static uint8_t mouse_captured;
 252+
 253+void handle_binding_up(keybinding * binding)
 254+{
 255+	uint8_t allow_content_binds = content_binds_enabled && current_system;
 256+	switch(binding->bind_type)
 257+	{
 258+	case BIND_GAMEPAD:
 259+		if (allow_content_binds && current_system->gamepad_up) {
 260+			current_system->gamepad_up(current_system, binding->subtype_a, binding->subtype_b);
 261+		}
 262+		break;
 263+	case BIND_MOUSE:
 264+		if (allow_content_binds && current_system->mouse_up) {
 265+			current_system->mouse_up(current_system, binding->subtype_a, binding->subtype_b);
 266+		}
 267+		break;
 268+	case BIND_UI:
 269+		switch (binding->subtype_a)
 270+		{
 271+		case UI_DEBUG_MODE_INC:
 272+			if (allow_content_binds) {
 273+				current_system->inc_debug_mode(current_system);
 274+			}
 275+			break;
 276+		case UI_ENTER_DEBUGGER:
 277+			if (allow_content_binds) {
 278+				current_system->enter_debugger = 1;
 279+			}
 280+			break;
 281+		case UI_SAVE_STATE:
 282+			if (allow_content_binds) {
 283+				current_system->save_state = QUICK_SAVE_SLOT+1;
 284+			}
 285+			break;
 286+		case UI_NEXT_SPEED:
 287+			if (allow_content_binds) {
 288+				current_speed++;
 289+				if (current_speed >= num_speeds) {
 290+					current_speed = 0;
 291+				}
 292+				printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
 293+				current_system->set_speed_percent(current_system, speeds[current_speed]);
 294+			}
 295+			break;
 296+		case UI_PREV_SPEED:
 297+			if (allow_content_binds) {
 298+				current_speed--;
 299+				if (current_speed < 0) {
 300+					current_speed = num_speeds - 1;
 301+				}
 302+				printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
 303+				current_system->set_speed_percent(current_system, speeds[current_speed]);
 304+			}
 305+			break;
 306+		case UI_SET_SPEED:
 307+			if (allow_content_binds) {
 308+				if (binding->subtype_b < num_speeds) {
 309+					current_speed = binding->subtype_b;
 310+					printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
 311+					current_system->set_speed_percent(current_system, speeds[current_speed]);
 312+				} else {
 313+					printf("Setting speed to %d\n", speeds[current_speed]);
 314+					current_system->set_speed_percent(current_system, speeds[current_speed]);
 315+				}
 316+			}
 317+			break;
 318+		case UI_RELEASE_MOUSE:
 319+			if (mouse_captured) {
 320+				mouse_captured = 0;
 321+				render_relative_mouse(0);
 322+			}
 323+			break;
 324+		case UI_TOGGLE_KEYBOARD_CAPTURE:
 325+			if (allow_content_binds && current_system->has_keyboard) {
 326+				keyboard_captured = !keyboard_captured;
 327+			}
 328+			break;
 329+		case UI_SOFT_RESET:
 330+			if (allow_content_binds) {
 331+				current_system->soft_reset(current_system);
 332+			}
 333+			break;
 334+		case UI_RELOAD:
 335+			if (allow_content_binds) {
 336+				reload_media();
 337+			}
 338+			break;
 339+		case UI_SMS_PAUSE:
 340+			if (allow_content_binds && current_system->gamepad_down) {
 341+				current_system->gamepad_down(current_system, GAMEPAD_MAIN_UNIT, MAIN_UNIT_PAUSE);
 342+			}
 343+			break;
 344+		case UI_SCREENSHOT: {
 345+			if (allow_content_binds) {
 346+				char *screenshot_base = tern_find_path(config, "ui\0screenshot_path\0", TVAL_PTR).ptrval;
 347+				if (!screenshot_base) {
 348+					screenshot_base = "$HOME";
 349+				}
 350+				tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir());
 351+				vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir());
 352+				screenshot_base = replace_vars(screenshot_base, vars, 1);
 353+				tern_free(vars);
 354+				time_t now = time(NULL);
 355+				struct tm local_store;
 356+				char fname_part[256];
 357+				char *template = tern_find_path(config, "ui\0screenshot_template\0", TVAL_PTR).ptrval;
 358+				if (!template) {
 359+					template = "blastem_%c.ppm";
 360+				}
 361+				strftime(fname_part, sizeof(fname_part), template, localtime_r(&now, &local_store));
 362+				char const *parts[] = {screenshot_base, PATH_SEP, fname_part};
 363+				char *path = alloc_concat_m(3, parts);
 364+				free(screenshot_base);
 365+				render_save_screenshot(path);
 366+			}
 367+			break;
 368+		}
 369+			case UI_EXIT:
 370+				current_system->request_exit(current_system);
 371+			if (current_system->type == SYSTEM_GENESIS) {
 372+				genesis_context *gen = (genesis_context *)current_system;
 373+				if (gen->extra) {
 374+					//TODO: More robust mechanism for detecting menu
 375+					menu_context *menu = gen->extra;
 376+					menu->external_game_load = 1;
 377+				}
 378+			}
 379+				break;
 380+		case UI_PLANE_DEBUG: 
 381+		case UI_VRAM_DEBUG: 
 382+		case UI_CRAM_DEBUG:
 383+		case UI_COMPOSITE_DEBUG:
 384+			if (allow_content_binds) {
 385+				vdp_context *vdp = NULL;
 386+				if (current_system->type == SYSTEM_GENESIS) {
 387+					genesis_context *gen = (genesis_context *)current_system;
 388+					vdp = gen->vdp;
 389+				} else if (current_system->type == SYSTEM_SMS) {
 390+					sms_context *sms = (sms_context *)current_system;
 391+					vdp = sms->vdp;
 392+				}
 393+				if (vdp) {
 394+					uint8_t debug_type;
 395+					switch(binding->subtype_a)
 396+					{
 397+					case UI_PLANE_DEBUG: debug_type = VDP_DEBUG_PLANE; break;
 398+					case UI_VRAM_DEBUG: debug_type = VDP_DEBUG_VRAM; break;
 399+					case UI_CRAM_DEBUG: debug_type = VDP_DEBUG_CRAM; break;
 400+					case UI_COMPOSITE_DEBUG: debug_type = VDP_DEBUG_COMPOSITE; break;
 401+					default: return;
 402+					}
 403+					vdp_toggle_debug_view(vdp, debug_type);
 404+				}
 405+				break;
 406+			}
 407+		}
 408+		break;
 409+	}
 410+}
 411+
 412+void handle_keyup(int keycode, uint8_t scancode)
 413+{
 414+	int bucket = keycode >> 15 & 0xFFFF;
 415+	int idx = keycode & 0x7FFF;
 416+	keybinding * binding = bindings[bucket] ? bindings[bucket] + idx : NULL;
 417+	if (binding && (!keyboard_captured || (binding->bind_type == BIND_UI && binding->subtype_a == UI_TOGGLE_KEYBOARD_CAPTURE))) {
 418+		handle_binding_up(binding);
 419+	} else if (keyboard_captured && current_system && current_system->keyboard_up) {
 420+		current_system->keyboard_up(current_system, scancode);
 421+	}
 422+}
 423+
 424+void handle_joyup(int joystick, int button)
 425+{
 426+	if (joystick >= MAX_JOYSTICKS  || button >= joysticks[joystick].num_buttons) {
 427+		return;
 428+	}
 429+	keybinding * binding = joysticks[joystick].buttons + button;
 430+	handle_binding_up(binding);
 431+}
 432+
 433+void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
 434+{
 435+	if (joystick >= MAX_JOYSTICKS  || dpadnum >= joysticks[joystick].num_dpads) {
 436+		return;
 437+	}
 438+	joydpad * dpad = joysticks[joystick].dpads + dpadnum;
 439+	uint8_t newdown = (value ^ dpad->state) & value;
 440+	uint8_t newup = ((~value) ^ (~dpad->state)) & (~value);
 441+	dpad->state = value;
 442+	for (int i = 0; i < 4; i++) {
 443+		if (newdown & dpadbits[i]) {
 444+			handle_binding_down(dpad->bindings + i);
 445+		} else if(newup & dpadbits[i]) {
 446+			handle_binding_up(dpad->bindings + i);
 447+		}
 448+	}
 449+}
 450+
 451+#define JOY_AXIS_THRESHOLD 2000
 452+
 453+void handle_joy_axis(int joystick, int axis, int16_t value)
 454+{
 455+	if (joystick >= MAX_JOYSTICKS  || axis >= joysticks[joystick].num_axes) {
 456+		return;
 457+	}
 458+	joyaxis *jaxis = joysticks[joystick].axes + axis;
 459+	int old_active = abs(jaxis->value) > JOY_AXIS_THRESHOLD;
 460+	int new_active = abs(value) > JOY_AXIS_THRESHOLD;
 461+	int old_pos = jaxis->value > 0;
 462+	int new_pos = value > 0;
 463+	jaxis->value = value;
 464+	if (old_active && (!new_active || old_pos != new_pos)) {
 465+		//previously activated direction is no longer active
 466+		handle_binding_up(old_pos ? &jaxis->positive : &jaxis->negative);
 467+	}
 468+	if (new_active && (!old_active || old_pos != new_pos)) {
 469+		//previously unactivated direction is now active
 470+		handle_binding_down(new_pos ? &jaxis->positive : &jaxis->negative);
 471+	}
 472+}
 473+
 474+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay)
 475+{
 476+	if (mouse >= MAX_MICE || !current_system) {
 477+		return;
 478+	}
 479+	if (mice[mouse].motion.bind_type == BIND_MOUSE && mice[mouse].motion.subtype_b == PSEUDO_BUTTON_MOTION) {
 480+		uint8_t target_mouse = mice[mouse].motion.subtype_a;
 481+		switch(mouse_mode)
 482+		{
 483+		case MOUSE_NONE:
 484+			break;
 485+		case MOUSE_ABSOLUTE: {
 486+			if (current_system->mouse_motion_absolute) {
 487+				float scale_x = (render_emulated_width() * 2.0f) / ((float)render_width());
 488+				float scale_y = (render_emulated_height() * 2.0f) / ((float)render_height());
 489+				int32_t adj_x = x * scale_x + 2 * render_overscan_left() - 2 * BORDER_LEFT;
 490+				int32_t adj_y = y * scale_y + 2 * render_overscan_top() - 4;
 491+				
 492+				current_system->mouse_motion_absolute(current_system, target_mouse, adj_x, adj_y);
 493+			}
 494+			break;
 495+		}
 496+		case MOUSE_RELATIVE: {
 497+			if (current_system->mouse_motion_relative) {
 498+				current_system->mouse_motion_relative(current_system, target_mouse, deltax, deltay);
 499+			}
 500+			break;
 501+		}
 502+		case MOUSE_CAPTURE: {
 503+			if (mouse_captured && current_system->mouse_motion_relative) {
 504+				current_system->mouse_motion_relative(current_system, target_mouse, deltax, deltay);
 505+			}
 506+			break;
 507+		}
 508+		}
 509+	} else {
 510+		handle_binding_up(&mice[mouse].motion);
 511+	}
 512+}
 513+
 514+void handle_mouseup(int mouse, int button)
 515+{
 516+	if (mouse >= MAX_MICE || button > MAX_MOUSE_BUTTONS || button <= 0) {
 517+		return;
 518+	}
 519+	keybinding * binding = mice[mouse].buttons + button - 1;
 520+	handle_binding_up(binding);
 521+}
 522+
 523+void bindings_release_capture(void)
 524+{
 525+	if (mouse_mode == MOUSE_RELATIVE || (mouse_mode == MOUSE_CAPTURE && mouse_captured)) {
 526+		render_relative_mouse(0);
 527+	}
 528+	keyboard_captured = 0;
 529+}
 530+
 531+void bindings_reacquire_capture(void)
 532+{
 533+	if (mouse_mode == MOUSE_RELATIVE || (mouse_mode == MOUSE_CAPTURE && mouse_captured)) {
 534+		render_relative_mouse(1);
 535+	}
 536+}
 537+
 538+int parse_binding_target(int device_num, char * target, tern_node * padbuttons, tern_node *mousebuttons, uint8_t * subtype_a, uint8_t * subtype_b)
 539+{
 540+	const int gpadslen = strlen("gamepads.");
 541+	const int mouselen = strlen("mouse.");
 542+	if (startswith(target, "gamepads.")) {
 543+		int padnum = target[gpadslen] == 'n' ? device_num + 1 : target[gpadslen] - '0';
 544+		if (padnum >= 1 && padnum <= 8) {
 545+			int button = tern_find_int(padbuttons, target + gpadslen + 1, 0);
 546+			if (button) {
 547+				*subtype_a = padnum;
 548+				*subtype_b = button;
 549+				return BIND_GAMEPAD;
 550+			} else {
 551+				if (target[gpadslen+1]) {
 552+					warning("Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1);
 553+				} else {
 554+					warning("Gamepad mapping string '%s' has no button component\n", target);
 555+				}
 556+			}
 557+		} else {
 558+			warning("Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
 559+		}
 560+	} else if(startswith(target, "mouse.")) {
 561+		int mousenum = target[mouselen] == 'n' ? device_num + 1 : target[mouselen] - '0';
 562+		if (mousenum >= 1 && mousenum <= 8) {
 563+			int button = tern_find_int(mousebuttons, target + mouselen + 1, 0);
 564+			if (button) {
 565+				*subtype_a = mousenum;
 566+				*subtype_b = button;
 567+				return BIND_MOUSE;
 568+			} else {
 569+				if (target[mouselen+1]) {
 570+					warning("Mouse mapping string '%s' refers to an invalid button '%s'\n", target, target + mouselen + 1);
 571+				} else {
 572+					warning("Mouse mapping string '%s' has no button component\n", target);
 573+				}
 574+			}
 575+		} else {
 576+			warning("Gamepad mapping string '%s' refers to an invalid mouse number %c\n", target, target[mouselen]);
 577+		}
 578+	} else if(startswith(target, "ui.")) {
 579+		if (!strcmp(target + 3, "vdp_debug_mode")) {
 580+			*subtype_a = UI_DEBUG_MODE_INC;
 581+		} else if(!strcmp(target + 3, "vdp_debug_pal")) {
 582+			//legacy binding, ignore
 583+			return 0;
 584+		} else if(!strcmp(target + 3, "enter_debugger")) {
 585+			*subtype_a = UI_ENTER_DEBUGGER;
 586+		} else if(!strcmp(target + 3, "save_state")) {
 587+			*subtype_a = UI_SAVE_STATE;
 588+		} else if(startswith(target + 3, "set_speed.")) {
 589+			*subtype_a = UI_SET_SPEED;
 590+			*subtype_b = atoi(target + 3 + strlen("set_speed."));
 591+		} else if(!strcmp(target + 3, "next_speed")) {
 592+			*subtype_a = UI_NEXT_SPEED;
 593+		} else if(!strcmp(target + 3, "prev_speed")) {
 594+			*subtype_a = UI_PREV_SPEED;
 595+		} else if(!strcmp(target + 3, "release_mouse")) {
 596+			*subtype_a = UI_RELEASE_MOUSE;
 597+		} else if(!strcmp(target + 3, "toggle_keyboard_captured")) {
 598+			*subtype_a = UI_TOGGLE_KEYBOARD_CAPTURE;
 599+		} else if (!strcmp(target + 3, "soft_reset")) {
 600+			*subtype_a = UI_SOFT_RESET;
 601+		} else if (!strcmp(target + 3, "reload")) {
 602+			*subtype_a = UI_RELOAD;
 603+		} else if (!strcmp(target + 3, "sms_pause")) {
 604+			*subtype_a = UI_SMS_PAUSE;
 605+		} else if (!strcmp(target + 3, "screenshot")) {
 606+			*subtype_a = UI_SCREENSHOT;
 607+		} else if(!strcmp(target + 3, "exit")) {
 608+			*subtype_a = UI_EXIT;
 609+		} else if (!strcmp(target + 3, "plane_debug")) {
 610+			*subtype_a = UI_PLANE_DEBUG;
 611+		} else if (!strcmp(target + 3, "vram_debug")) {
 612+			*subtype_a = UI_VRAM_DEBUG;
 613+		} else if (!strcmp(target + 3, "cram_debug")) {
 614+			*subtype_a = UI_CRAM_DEBUG;
 615+		} else if (!strcmp(target + 3, "compositing_debug")) {
 616+			*subtype_a = UI_COMPOSITE_DEBUG;
 617+		} else {
 618+			warning("Unreconized UI binding type %s\n", target);
 619+			return 0;
 620+		}
 621+		return BIND_UI;
 622+	} else {
 623+		warning("Unrecognized binding type %s\n", target);
 624+	}
 625+	return 0;
 626+}
 627+
 628+void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, tern_node *mousebuttons, char * prefix)
 629+{
 630+	char * curstr = NULL;
 631+	int len;
 632+	if (!cur) {
 633+		return;
 634+	}
 635+	char onec[2];
 636+	if (prefix) {
 637+		len = strlen(prefix);
 638+		curstr = malloc(len + 2);
 639+		memcpy(curstr, prefix, len);
 640+	} else {
 641+		curstr = onec;
 642+		len = 0;
 643+	}
 644+	curstr[len] = cur->el;
 645+	curstr[len+1] = 0;
 646+	if (cur->el) {
 647+		process_keys(cur->straight.next, special, padbuttons, mousebuttons, curstr);
 648+	} else {
 649+		int keycode = tern_find_int(special, curstr, 0);
 650+		if (!keycode) {
 651+			keycode = curstr[0];
 652+			if (curstr[1] != 0) {
 653+				warning("%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]);
 654+			}
 655+		}
 656+		char * target = cur->straight.value.ptrval;
 657+		uint8_t subtype_a = 0, subtype_b = 0;
 658+		int bindtype = parse_binding_target(0, target, padbuttons, mousebuttons, &subtype_a, &subtype_b);
 659+		bind_key(keycode, bindtype, subtype_a, subtype_b);
 660+	}
 661+	process_keys(cur->left, special, padbuttons, mousebuttons, prefix);
 662+	process_keys(cur->right, special, padbuttons, mousebuttons, prefix);
 663+	if (curstr && len) {
 664+		free(curstr);
 665+	}
 666+}
 667+
 668+void process_speeds(tern_node * cur, char * prefix)
 669+{
 670+	char * curstr = NULL;
 671+	int len;
 672+	if (!cur) {
 673+		return;
 674+	}
 675+	char onec[2];
 676+	if (prefix) {
 677+		len = strlen(prefix);
 678+		curstr = malloc(len + 2);
 679+		memcpy(curstr, prefix, len);
 680+	} else {
 681+		curstr = onec;
 682+		len = 0;
 683+	}
 684+	curstr[len] = cur->el;
 685+	curstr[len+1] = 0;
 686+	if (cur->el) {
 687+		process_speeds(cur->straight.next, curstr);
 688+	} else {
 689+		char *end;
 690+		long speed_index = strtol(curstr, &end, 10);
 691+		if (speed_index < 0 || end == curstr || *end) {
 692+			warning("%s is not a valid speed index", curstr);
 693+		} else {
 694+			if (speed_index >= num_speeds) {
 695+				speeds = realloc(speeds, sizeof(uint32_t) * (speed_index+1));
 696+				for(; num_speeds < speed_index + 1; num_speeds++) {
 697+					speeds[num_speeds] = 0;
 698+				}
 699+			}
 700+			speeds[speed_index] = atoi(cur->straight.value.ptrval);
 701+			if (speeds[speed_index] < 1) {
 702+				warning("%s is not a valid speed percentage, setting speed %d to 100", cur->straight.value.ptrval, speed_index);
 703+				speeds[speed_index] = 100;
 704+			}
 705+		}
 706+	}
 707+	process_speeds(cur->left, prefix);
 708+	process_speeds(cur->right, prefix);
 709+	if (curstr && len) {
 710+		free(curstr);
 711+	}
 712+}
 713+
 714+typedef struct {
 715+	tern_node *padbuttons;
 716+	tern_node *mousebuttons;
 717+	int       mouseidx;
 718+} pmb_state;
 719+
 720+void process_mouse_button(char *buttonstr, tern_val value, uint8_t valtype, void *data)
 721+{
 722+	pmb_state *state = data;
 723+	int buttonnum = atoi(buttonstr);
 724+	if (buttonnum < 1 || buttonnum > MAX_MOUSE_BUTTONS) {
 725+		warning("Mouse button %s is out of the supported range of 1-8\n", buttonstr);
 726+		return;
 727+	}
 728+	if (valtype != TVAL_PTR) {
 729+		warning("Mouse button %s is not a scalar value!\n", buttonstr);
 730+		return;
 731+	}
 732+	buttonnum--;
 733+	uint8_t subtype_a = 0, subtype_b = 0;
 734+	int bindtype = parse_binding_target(state->mouseidx, value.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 735+	mice[state->mouseidx].buttons[buttonnum].bind_type = bindtype;
 736+	mice[state->mouseidx].buttons[buttonnum].subtype_a = subtype_a;
 737+	mice[state->mouseidx].buttons[buttonnum].subtype_b = subtype_b;
 738+}
 739+
 740+void process_mouse(char *mousenum, tern_val value, uint8_t valtype, void *data)
 741+{
 742+	tern_node **buttonmaps = data;
 743+	if (valtype != TVAL_NODE) {
 744+		warning("Binding for mouse %s is a scalar!\n", mousenum);
 745+		return;
 746+	}
 747+	tern_node *mousedef = value.ptrval;
 748+	tern_node *padbuttons = buttonmaps[0];
 749+	tern_node *mousebuttons = buttonmaps[1];
 750+
 751+	int mouseidx = atoi(mousenum);
 752+	if (mouseidx < 0 || mouseidx >= MAX_MICE) {
 753+		warning("Mouse numbers must be between 0 and %d, but %d is not\n", MAX_MICE, mouseidx);
 754+		return;
 755+	}
 756+	char *motion = tern_find_ptr(mousedef, "motion");
 757+	if (motion) {
 758+		uint8_t subtype_a = 0, subtype_b = 0;
 759+		int bindtype = parse_binding_target(mouseidx, motion, padbuttons, mousebuttons, &subtype_a, &subtype_b);
 760+		mice[mouseidx].motion.bind_type = bindtype;
 761+		mice[mouseidx].motion.subtype_a = subtype_a;
 762+		mice[mouseidx].motion.subtype_b = subtype_b;
 763+	}
 764+	tern_node *buttons = tern_find_path(mousedef, "buttons\0\0", TVAL_NODE).ptrval;
 765+	if (buttons) {
 766+		pmb_state state = {padbuttons, mousebuttons, mouseidx};
 767+		tern_foreach(buttons, process_mouse_button, &state);
 768+	}
 769+}
 770+
 771+typedef struct {
 772+	int       padnum;
 773+	tern_node *padbuttons;
 774+	tern_node *mousebuttons;
 775+} pad_button_state;
 776+
 777+
 778+static long map_warning_pad = -1;
 779+void process_pad_button(char *key, tern_val val, uint8_t valtype, void *data)
 780+{
 781+	pad_button_state *state = data;
 782+	int hostpadnum = state->padnum;
 783+	if (valtype != TVAL_PTR) {
 784+		warning("Pad button %s has a non-scalar value\n", key);
 785+		return;
 786+	}
 787+	uint8_t subtype_a = 0, subtype_b = 0;
 788+	int bindtype = parse_binding_target(hostpadnum, val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 789+	char *end;
 790+	long hostbutton = strtol(key, &end, 10);
 791+	if (*end) {
 792+		//key is not a valid base 10 integer
 793+		hostbutton = render_translate_input_name(hostpadnum, key, 0);
 794+		if (hostbutton < 0) {
 795+			if (hostbutton == RENDER_INVALID_NAME) {
 796+				warning("%s is not a valid gamepad input name\n", key);
 797+			} else if (hostbutton == RENDER_NOT_MAPPED && hostpadnum != map_warning_pad) {
 798+				warning("No mapping exists for input %s on gamepad %d\n", key, hostpadnum);
 799+				map_warning_pad = hostpadnum;
 800+			}
 801+			return;
 802+		}
 803+		if (hostbutton & RENDER_DPAD_BIT) {
 804+			bind_dpad(hostpadnum, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b);
 805+			return;
 806+		} else if (hostbutton & RENDER_AXIS_BIT) {
 807+			bind_axis(hostpadnum, render_axis_part(hostbutton), hostbutton & RENDER_AXIS_POS, bindtype, subtype_a, subtype_b);
 808+			return;
 809+		}
 810+	}
 811+	bind_button(hostpadnum, hostbutton, bindtype, subtype_a, subtype_b);
 812+}
 813+
 814+void process_pad_axis(char *key, tern_val val, uint8_t valtype, void *data)
 815+{
 816+	key = strdup(key);
 817+	pad_button_state *state = data;
 818+	int hostpadnum = state->padnum;
 819+	if (valtype != TVAL_PTR) {
 820+		warning("Mapping for axis %s has a non-scalar value", key);
 821+		return;
 822+	}
 823+	uint8_t subtype_a = 0, subtype_b = 0;
 824+	int bindtype = parse_binding_target(hostpadnum, val.ptrval, state->padbuttons, state->mousebuttons, &subtype_a, &subtype_b);
 825+	char *modifier = strchr(key, '.');
 826+	int positive = 1;
 827+	if (modifier) {
 828+		*modifier = 0;
 829+		modifier++;
 830+		if (!strcmp("negative", modifier)) {
 831+			positive = 0;
 832+		} else if(strcmp("positive", modifier)) {
 833+			warning("Invalid axis modifier %s for axis %s on pad %d\n", modifier, key, hostpadnum);
 834+		}
 835+	}
 836+	char *end;
 837+	long axis = strtol(key, &end, 10);
 838+	if (*end) {
 839+		//key is not a valid base 10 integer
 840+		axis = render_translate_input_name(hostpadnum, key, 1);
 841+		if (axis < 0) {
 842+			if (axis == RENDER_INVALID_NAME) {
 843+				warning("%s is not a valid gamepad input name\n", key);
 844+			} else if (axis == RENDER_NOT_MAPPED && hostpadnum != map_warning_pad) {
 845+				warning("No mapping exists for input %s on gamepad %d\n", key, hostpadnum);
 846+				map_warning_pad = hostpadnum;
 847+			}
 848+			goto done;
 849+		}
 850+		if (axis & RENDER_DPAD_BIT) {
 851+			bind_dpad(hostpadnum, render_dpad_part(axis), render_direction_part(axis), bindtype, subtype_a, subtype_b);
 852+			goto done;
 853+		} else if (axis & RENDER_AXIS_BIT) {
 854+			axis = render_axis_part(axis);
 855+		} else {
 856+			bind_button(hostpadnum, axis, bindtype, subtype_a, subtype_b);
 857+			goto done;
 858+		}
 859+	}
 860+	bind_axis(hostpadnum, axis, positive, bindtype, subtype_a, subtype_b);
 861+done:
 862+	free(key);
 863+	return;
 864+}
 865+
 866+static tern_node *get_pad_buttons()
 867+{
 868+	static tern_node *padbuttons;
 869+	if (!padbuttons) {
 870+		padbuttons = tern_insert_int(NULL, ".up", DPAD_UP);
 871+		padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN);
 872+		padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT);
 873+		padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT);
 874+		padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A);
 875+		padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B);
 876+		padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C);
 877+		padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X);
 878+		padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
 879+		padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
 880+		padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
 881+		padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
 882+	}
 883+	return padbuttons;
 884+}
 885+
 886+static tern_node *get_mouse_buttons()
 887+{
 888+	static tern_node *mousebuttons;
 889+	if (!mousebuttons) {
 890+		mousebuttons = tern_insert_int(NULL, ".left", MOUSE_LEFT);
 891+		mousebuttons = tern_insert_int(mousebuttons, ".middle", MOUSE_MIDDLE);
 892+		mousebuttons = tern_insert_int(mousebuttons, ".right", MOUSE_RIGHT);
 893+		mousebuttons = tern_insert_int(mousebuttons, ".start", MOUSE_START);
 894+		mousebuttons = tern_insert_int(mousebuttons, ".motion", PSEUDO_BUTTON_MOTION);
 895+	}
 896+	return mousebuttons;
 897+}
 898+
 899+tern_node *get_binding_node_for_pad(int padnum)
 900+{
 901+	if (padnum > MAX_JOYSTICKS) {
 902+		return NULL;
 903+	}
 904+	tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
 905+	if (!pads) {
 906+		return NULL;
 907+	}
 908+	char numstr[11];
 909+	sprintf(numstr, "%d", padnum);
 910+	tern_node * pad = tern_find_node(pads, numstr);
 911+	if (!pad) {
 912+		char *type_id = render_joystick_type_id(padnum);
 913+		pad = tern_find_node(pads, type_id);
 914+		free(type_id);
 915+	}
 916+	if (!pad) {
 917+		controller_info info = get_controller_info(padnum);
 918+		char *key = make_controller_type_key(&info);
 919+		pad = tern_find_node(pads, key);
 920+		free(key);
 921+	}
 922+	if (!pad) {
 923+		pad = tern_find_node(pads, "default");
 924+	}
 925+	return pad;
 926+}
 927+
 928+void handle_joy_added(int joystick)
 929+{
 930+	tern_node *pad = get_binding_node_for_pad(joystick);
 931+	if (!pad) {
 932+		return;
 933+	}
 934+	tern_node * dpad_node = tern_find_node(pad, "dpads");
 935+	if (dpad_node) {
 936+		for (int dpad = 0; dpad < 10; dpad++)
 937+		{
 938+			char numstr[2] = {dpad + '0', 0};
 939+			tern_node * pad_dpad = tern_find_node(dpad_node, numstr);
 940+			char * dirs[] = {"up", "down", "left", "right"};
 941+			char *render_dirs[] = {"dpup", "dpdown", "dpleft", "dpright"};
 942+			int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
 943+			for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
 944+				char * target = tern_find_ptr(pad_dpad, dirs[dir]);
 945+				if (target) {
 946+					uint8_t subtype_a = 0, subtype_b = 0;
 947+					int bindtype = parse_binding_target(joystick, target, get_pad_buttons(), get_mouse_buttons(), &subtype_a, &subtype_b);
 948+					int32_t hostbutton = dpad >0 ? -1 : render_translate_input_name(joystick, render_dirs[dir], 0);
 949+					if (hostbutton < 0) {
 950+						//assume this is a raw dpad mapping
 951+						bind_dpad(joystick, dpad, dirnums[dir], bindtype, subtype_a, subtype_b);
 952+					} else if (hostbutton & RENDER_DPAD_BIT) {
 953+						bind_dpad(joystick, render_dpad_part(hostbutton), render_direction_part(hostbutton), bindtype, subtype_a, subtype_b);
 954+					} else if (hostbutton & RENDER_AXIS_BIT) {
 955+						//Assume controllers with axes for a d-pad use the conventional directions.
 956+						bind_axis(joystick, render_axis_part(hostbutton), dir == 1 || dir == 3 ? 1 : 0, bindtype, subtype_a, subtype_b);
 957+					} else {
 958+						bind_button(joystick, hostbutton, bindtype, subtype_a, subtype_b);
 959+					}
 960+				}
 961+			}
 962+		}
 963+	}
 964+	tern_node *button_node = tern_find_node(pad, "buttons");
 965+	if (button_node) {
 966+		pad_button_state state = {
 967+			.padnum = joystick,
 968+			.padbuttons = get_pad_buttons(),
 969+			.mousebuttons = get_mouse_buttons()
 970+		};
 971+		tern_foreach(button_node, process_pad_button, &state);
 972+	}
 973+	tern_node *axes_node = tern_find_node(pad, "axes");
 974+	if (axes_node) {
 975+		pad_button_state state = {
 976+			.padnum = joystick,
 977+			.padbuttons = get_pad_buttons(),
 978+			.mousebuttons = get_mouse_buttons()
 979+		};
 980+		tern_foreach(axes_node, process_pad_axis, &state);
 981+	}
 982+}
 983+
 984+//only handles keyboards and mice as gamepads are handled on hotplug events
 985+void set_bindings(void)
 986+{
 987+	tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
 988+	special = tern_insert_int(special, "down", RENDERKEY_DOWN);
 989+	special = tern_insert_int(special, "left", RENDERKEY_LEFT);
 990+	special = tern_insert_int(special, "right", RENDERKEY_RIGHT);
 991+	special = tern_insert_int(special, "enter", '\r');
 992+	special = tern_insert_int(special, "space", ' ');
 993+	special = tern_insert_int(special, "tab", '\t');
 994+	special = tern_insert_int(special, "backspace", '\b');
 995+	special = tern_insert_int(special, "esc", RENDERKEY_ESC);
 996+	special = tern_insert_int(special, "delete", RENDERKEY_DEL);
 997+	special = tern_insert_int(special, "lshift", RENDERKEY_LSHIFT);
 998+	special = tern_insert_int(special, "rshift", RENDERKEY_RSHIFT);
 999+	special = tern_insert_int(special, "lctrl", RENDERKEY_LCTRL);
1000+	special = tern_insert_int(special, "rctrl", RENDERKEY_RCTRL);
1001+	special = tern_insert_int(special, "lalt", RENDERKEY_LALT);
1002+	special = tern_insert_int(special, "ralt", RENDERKEY_RALT);
1003+	special = tern_insert_int(special, "home", RENDERKEY_HOME);
1004+	special = tern_insert_int(special, "end", RENDERKEY_END);
1005+	special = tern_insert_int(special, "pageup", RENDERKEY_PAGEUP);
1006+	special = tern_insert_int(special, "pagedown", RENDERKEY_PAGEDOWN);
1007+	special = tern_insert_int(special, "f1", RENDERKEY_F1);
1008+	special = tern_insert_int(special, "f2", RENDERKEY_F2);
1009+	special = tern_insert_int(special, "f3", RENDERKEY_F3);
1010+	special = tern_insert_int(special, "f4", RENDERKEY_F4);
1011+	special = tern_insert_int(special, "f5", RENDERKEY_F5);
1012+	special = tern_insert_int(special, "f6", RENDERKEY_F6);
1013+	special = tern_insert_int(special, "f7", RENDERKEY_F7);
1014+	special = tern_insert_int(special, "f8", RENDERKEY_F8);
1015+	special = tern_insert_int(special, "f9", RENDERKEY_F9);
1016+	special = tern_insert_int(special, "f10", RENDERKEY_F10);
1017+	special = tern_insert_int(special, "f11", RENDERKEY_F11);
1018+	special = tern_insert_int(special, "f12", RENDERKEY_F12);
1019+	special = tern_insert_int(special, "select", RENDERKEY_SELECT);
1020+	special = tern_insert_int(special, "play", RENDERKEY_PLAY);
1021+	special = tern_insert_int(special, "search", RENDERKEY_SEARCH);
1022+	special = tern_insert_int(special, "back", RENDERKEY_BACK);
1023+	special = tern_insert_int(special, "np0", RENDERKEY_NP0);
1024+	special = tern_insert_int(special, "np1", RENDERKEY_NP1);
1025+	special = tern_insert_int(special, "np2", RENDERKEY_NP2);
1026+	special = tern_insert_int(special, "np3", RENDERKEY_NP3);
1027+	special = tern_insert_int(special, "np4", RENDERKEY_NP4);
1028+	special = tern_insert_int(special, "np5", RENDERKEY_NP5);
1029+	special = tern_insert_int(special, "np6", RENDERKEY_NP6);
1030+	special = tern_insert_int(special, "np7", RENDERKEY_NP7);
1031+	special = tern_insert_int(special, "np8", RENDERKEY_NP8);
1032+	special = tern_insert_int(special, "np9", RENDERKEY_NP9);
1033+	special = tern_insert_int(special, "np/", RENDERKEY_NP_DIV);
1034+	special = tern_insert_int(special, "np*", RENDERKEY_NP_MUL);
1035+	special = tern_insert_int(special, "np-", RENDERKEY_NP_MIN);
1036+	special = tern_insert_int(special, "np+", RENDERKEY_NP_PLUS);
1037+	special = tern_insert_int(special, "npenter", RENDERKEY_NP_ENTER);
1038+	special = tern_insert_int(special, "np.", RENDERKEY_NP_STOP);
1039+
1040+	tern_node *padbuttons = get_pad_buttons();
1041+
1042+	tern_node *mousebuttons = get_mouse_buttons();
1043+	
1044+	tern_node * keys = tern_find_path(config, "bindings\0keys\0", TVAL_NODE).ptrval;
1045+	process_keys(keys, special, padbuttons, mousebuttons, NULL);
1046+	tern_free(special);
1047+	
1048+	memset(mice, 0, sizeof(mice));
1049+	tern_node * mice = tern_find_path(config, "bindings\0mice\0", TVAL_NODE).ptrval;
1050+	if (mice) {
1051+		tern_node *buttonmaps[2] = {padbuttons, mousebuttons};
1052+		tern_foreach(mice, process_mouse, buttonmaps);
1053+	}
1054+	tern_node * speed_nodes = tern_find_path(config, "clocks\0speeds\0", TVAL_NODE).ptrval;
1055+	speeds = malloc(sizeof(uint32_t));
1056+	speeds[0] = 100;
1057+	process_speeds(speed_nodes, NULL);
1058+	for (int i = 0; i < num_speeds; i++)
1059+	{
1060+		if (!speeds[i]) {
1061+			warning("Speed index %d was not set to a valid percentage!", i);
1062+			speeds[i] = 100;
1063+		}
1064+	}
1065+}
1066+
1067+void bindings_set_mouse_mode(uint8_t mode)
1068+{
1069+	mouse_mode = mode;
1070+	if (mode == MOUSE_RELATIVE) {
1071+		render_relative_mouse(1);
1072+	}
1073+}
+30, -0
 1@@ -0,0 +1,30 @@
 2+#ifndef BINDINGS_H_
 3+#define BINDINGS_H_
 4+#include <stdint.h>
 5+
 6+typedef enum {
 7+	MOUSE_NONE,     //mouse is ignored
 8+	MOUSE_ABSOLUTE, //really only useful for menu ROM
 9+	MOUSE_RELATIVE, //for full screen
10+	MOUSE_CAPTURE   //for windowed mode
11+} mouse_modes;
12+
13+void set_bindings(void);
14+void bindings_set_mouse_mode(uint8_t mode);
15+tern_node *get_binding_node_for_pad(int padnum);
16+void handle_keydown(int keycode, uint8_t scancode);
17+void handle_keyup(int keycode, uint8_t scancode);
18+void handle_joydown(int joystick, int button);
19+void handle_joyup(int joystick, int button);
20+void handle_joy_dpad(int joystick, int dpad, uint8_t state);
21+void handle_joy_axis(int joystick, int axis, int16_t value);
22+void handle_joy_added(int joystick);
23+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay);
24+void handle_mousedown(int mouse, int button);
25+void handle_mouseup(int mouse, int button);
26+
27+void bindings_release_capture(void);
28+void bindings_reacquire_capture(void);
29+void set_content_binding_state(uint8_t enabled);
30+
31+#endif //BINDINGS_H_
+122, -0
  1@@ -0,0 +1,122 @@
  2+#include <stdio.h>
  3+#include <stdlib.h>
  4+#include <stddef.h>
  5+#include <string.h>
  6+#include <time.h>
  7+#include <sys/select.h>
  8+
  9+#include "z80_to_x86.h"
 10+#include "util.h"
 11+
 12+uint8_t ram[64 * 1024];
 13+
 14+#define START_OFF 0x100
 15+#define OS_START 0xE400
 16+#define OS_RESET 0xE403
 17+int headless = 1;
 18+
 19+void z80_next_int_pulse(z80_context * context)
 20+{
 21+	context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER;
 22+}
 23+
 24+void render_errorbox(char *title, char *message)
 25+{
 26+}
 27+
 28+void render_infobox(char *title, char *message)
 29+{
 30+}
 31+
 32+void *console_write(uint32_t address, void *context, uint8_t value)
 33+{
 34+	putchar(value);
 35+	return context;
 36+}
 37+
 38+uint8_t console_read(uint32_t address, void *context)
 39+{
 40+	return getchar();
 41+}
 42+
 43+void *console_flush_write(uint32_t address, void *context, uint8_t value)
 44+{
 45+	fflush(stdout);
 46+	return context;
 47+}
 48+
 49+uint8_t console_status_read(uint32_t address, void *context)
 50+{
 51+	fd_set read_fds;
 52+	FD_ZERO(&read_fds);
 53+	struct timeval timeout;
 54+	timeout.tv_sec = 0;
 55+	timeout.tv_usec = 0;
 56+	FD_SET(fileno(stdin), &read_fds);
 57+	return select(fileno(stdin)+1, &read_fds, NULL, NULL, &timeout) > 0; 
 58+}
 59+
 60+time_t start;
 61+uint64_t total_cycles;
 62+void *exit_write(uint32_t address, void *context, uint8_t value)
 63+{
 64+	time_t duration = time(NULL) - start;
 65+	z80_context *z80 = context;
 66+	total_cycles += context->current_cycle;
 67+	printf("Effective clock speed: %f MHz\n", ((double)total_cycles) / (1000000.0 * duration));
 68+	exit(0);
 69+	return context;
 70+}
 71+
 72+const memmap_chunk z80_map[] = {
 73+	{ 0x0000, 0x10000,  0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, ram, NULL, NULL, NULL, NULL},
 74+};
 75+
 76+memmap_chunk io_map[] = {
 77+	{ 0x0, 0x1, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, console_read, console_write},
 78+	{ 0x1, 0x2, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, console_status_read, console_flush_write},
 79+	{ 0x2, 0x3, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, exit_write},
 80+};
 81+
 82+int main(int argc, char **argv)
 83+{
 84+	FILE *f = fopen("fake_cpm.bin", "rb");
 85+	long fsize = file_size(f);
 86+	if (fsize > sizeof(ram) - OS_START) {
 87+		fsize = sizeof(ram) - OS_START;
 88+	}
 89+	if (fread(ram + OS_START, 1, fsize, f) != fsize) {
 90+		fprintf(stderr, "Error reading from fake_cpm.bin\n");
 91+		exit(1);
 92+	}
 93+	f = fopen(argv[1], "rb");
 94+	fsize = file_size(f);
 95+	if (fsize > OS_START - START_OFF) {
 96+		fsize = OS_START - START_OFF;
 97+	}
 98+	if (fread(ram + START_OFF, 1, fsize, f) != fsize) {
 99+		fprintf(stderr, "Error reading from file %s\n", argv[1]);
100+		exit(1);
101+	}
102+	fclose(f);
103+	ram[0] = 0xC3;
104+	ram[1] = OS_RESET & 0xFF;
105+	ram[2] = OS_RESET >> 8;
106+	ram[5] = 0xC3;
107+	ram[6] = OS_START & 0xFF;
108+	ram[7] = OS_START >> 8;
109+	
110+	z80_options opts;
111+	z80_context *context;
112+	init_z80_opts(&opts, z80_map, 1, io_map, 3, 1, 0xFF);
113+	context = init_z80_context(&opts);
114+	start = time(NULL);
115+	for(;;)
116+	{
117+		z80_run(context, 1000000);
118+		total_cycles += context->current_cycle;
119+		context->current_cycle = 0;
120+		
121+	}
122+	return 0;
123+}
+628, -0
  1@@ -0,0 +1,628 @@
  2+/*
  3+ Copyright 2013-2016 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include <stdio.h>
  8+#include <stdlib.h>
  9+#include <string.h>
 10+#include <ctype.h>
 11+
 12+#include "system.h"
 13+#include "68kinst.h"
 14+#include "m68k_core.h"
 15+#include "z80_to_x86.h"
 16+#include "mem.h"
 17+#include "vdp.h"
 18+#include "render.h"
 19+#include "genesis.h"
 20+#include "gdb_remote.h"
 21+#include "gst.h"
 22+#include "util.h"
 23+#include "romdb.h"
 24+#include "terminal.h"
 25+#include "arena.h"
 26+#include "config.h"
 27+#include "bindings.h"
 28+#include "menu.h"
 29+#include "zip.h"
 30+#define BLASTEM_VERSION "0.6.2"
 31+
 32+int headless = 0;
 33+int exit_after = 0;
 34+int z80_enabled = 1;
 35+int frame_limit = 0;
 36+uint8_t use_native_states = 1;
 37+
 38+tern_node * config;
 39+
 40+#define SMD_HEADER_SIZE 512
 41+#define SMD_MAGIC1 0x03
 42+#define SMD_MAGIC2 0xAA
 43+#define SMD_MAGIC3 0xBB
 44+#define SMD_BLOCK_SIZE 0x4000
 45+
 46+#include <zlib.h>
 47+#define ROMFILE gzFile
 48+#define romopen gzopen
 49+#define romread gzfread
 50+#define romseek gzseek
 51+#define romgetc gzgetc
 52+#define romclose gzclose
 53+
 54+uint16_t *process_smd_block(uint16_t *dst, uint8_t *src, size_t bytes)
 55+{
 56+	for (uint8_t *low = src, *high = (src+bytes/2), *end = src+bytes; high < end; high++, low++) {
 57+		*(dst++) = *low << 8 | *high;
 58+	}
 59+	return dst;
 60+}
 61+
 62+int load_smd_rom(ROMFILE f, void **buffer)
 63+{
 64+	uint8_t block[SMD_BLOCK_SIZE];
 65+	romseek(f, SMD_HEADER_SIZE, SEEK_SET);
 66+
 67+	size_t filesize = 512 * 1024;
 68+	size_t readsize = 0;
 69+	uint16_t *dst, *buf;
 70+	dst = buf = malloc(filesize);
 71+	
 72+
 73+	size_t read;
 74+	do {
 75+		if ((readsize + SMD_BLOCK_SIZE > filesize)) {
 76+			filesize *= 2;
 77+			buf = realloc(buf, filesize);
 78+			dst = buf + readsize/sizeof(uint16_t);
 79+		}
 80+		read = romread(block, 1, SMD_BLOCK_SIZE, f);
 81+		if (read > 0) {
 82+			dst = process_smd_block(dst, block, read);
 83+			readsize += read;
 84+		}
 85+	} while(read > 0);
 86+	romclose(f);
 87+	
 88+	*buffer = buf;
 89+	
 90+	return readsize;
 91+}
 92+
 93+uint8_t is_smd_format(const char *filename, uint8_t *header)
 94+{
 95+	if (header[1] == SMD_MAGIC1 && header[8] == SMD_MAGIC2 && header[9] == SMD_MAGIC3) {
 96+		int i;
 97+		for (i = 3; i < 8; i++) {
 98+			if (header[i] != 0) {
 99+				return 0;
100+			}
101+		}
102+		if (i == 8) {
103+			if (header[2]) {
104+				fatal_error("%s is a split SMD ROM which is not currently supported", filename);
105+			}
106+			return 1;
107+		}
108+	}
109+	return 0;
110+}
111+
112+uint32_t load_rom_zip(const char *filename, void **dst)
113+{
114+	static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom", "smd"};
115+	const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts);
116+	zip_file *z = zip_open(filename);
117+	if (!z) {
118+		return 0;
119+	}
120+	
121+	for (uint32_t i = 0; i < z->num_entries; i++)
122+	{
123+		char *ext = path_extension(z->entries[i].name);
124+		if (!ext) {
125+			continue;
126+		}
127+		for (uint32_t j = 0; j < num_exts; j++)
128+		{
129+			if (!strcasecmp(ext, valid_exts[j])) {
130+				size_t out_size = nearest_pow2(z->entries[i].size);
131+				*dst = zip_read(z, i, &out_size);
132+				if (*dst) {
133+					if (is_smd_format(z->entries[i].name, *dst)) {
134+						size_t offset;
135+						for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE)
136+						{
137+							uint8_t tmp[SMD_BLOCK_SIZE];
138+							memcpy(tmp, *dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE);
139+							process_smd_block(*dst + offset, tmp, SMD_BLOCK_SIZE);
140+						}
141+						out_size = offset;
142+					}
143+					free(ext);
144+					zip_close(z);
145+					return out_size;
146+				}
147+			}
148+		}
149+		free(ext);
150+	}
151+	zip_close(z);
152+	return 0;
153+}
154+
155+uint32_t load_rom(const char * filename, void **dst, system_type *stype)
156+{
157+	uint8_t header[10];
158+	char *ext = path_extension(filename);
159+	if (ext && !strcasecmp(ext, "zip")) {
160+		free(ext);
161+		return load_rom_zip(filename, dst);
162+	}
163+	free(ext);
164+	ROMFILE f = romopen(filename, "rb");
165+	if (!f) {
166+		return 0;
167+	}
168+	if (sizeof(header) != romread(header, 1, sizeof(header), f)) {
169+		fatal_error("Error reading from %s\n", filename);
170+	}
171+	
172+	if (is_smd_format(filename, header)) {
173+		if (stype) {
174+			*stype = SYSTEM_GENESIS;
175+		}
176+		return load_smd_rom(f, dst);
177+	}
178+	
179+	size_t filesize = 512 * 1024;
180+	size_t readsize = sizeof(header);
181+		
182+	char *buf = malloc(filesize);
183+	memcpy(buf, header, readsize);
184+	
185+	size_t read;
186+	do {
187+		read = romread(buf + readsize, 1, filesize - readsize, f);
188+		if (read > 0) {
189+			readsize += read;
190+			if (readsize == filesize) {
191+				int one_more = romgetc(f);
192+				if (one_more >= 0) {
193+					filesize *= 2;
194+					buf = realloc(buf, filesize);
195+					buf[readsize++] = one_more;
196+				} else {
197+					read = 0;
198+				}
199+			}
200+		}
201+	} while (read > 0);
202+	
203+	*dst = buf;
204+	
205+	romclose(f);
206+	return readsize;
207+}
208+
209+
210+
211+int break_on_sync = 0;
212+char *save_state_path;
213+
214+
215+
216+
217+
218+char * save_filename;
219+system_header *current_system;
220+system_header *menu_system;
221+system_header *game_system;
222+void persist_save()
223+{
224+	if (!game_system) {
225+		return;
226+	}
227+	game_system->persist_save(game_system);
228+}
229+
230+char *title;
231+void update_title(char *rom_name)
232+{
233+	if (title) {
234+		free(title);
235+		title = NULL;
236+	}
237+	title = alloc_concat(rom_name, " - BlastEm");
238+	render_update_caption(title);
239+}
240+
241+static char *get_save_dir(system_media *media)
242+{
243+	char *savedir_template = tern_find_path(config, "ui\0save_path\0", TVAL_PTR).ptrval;
244+	if (!savedir_template) {
245+		savedir_template = "$USERDATA/blastem/$ROMNAME";
246+	}
247+	tern_node *vars = tern_insert_ptr(NULL, "ROMNAME", media->name);
248+	vars = tern_insert_ptr(vars, "HOME", get_home_dir());
249+	vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir());
250+	vars = tern_insert_ptr(vars, "USERDATA", (char *)get_userdata_dir());
251+	char *save_dir = replace_vars(savedir_template, vars, 1);
252+	tern_free(vars);
253+	if (!ensure_dir_exists(save_dir)) {
254+		warning("Failed to create save directory %s\n", save_dir);
255+	}
256+	return save_dir;
257+}
258+
259+void setup_saves(system_media *media, system_header *context)
260+{
261+	static uint8_t persist_save_registered;
262+	rom_info *info = &context->info;
263+	char *save_dir = get_save_dir(info->is_save_lock_on ? media->chain : media);
264+	char const *parts[] = {save_dir, PATH_SEP, info->save_type == SAVE_I2C ? "save.eeprom" : info->save_type == SAVE_NOR ? "save.nor" : "save.sram"};
265+	free(save_filename);
266+	save_filename = alloc_concat_m(3, parts);
267+	if (info->is_save_lock_on) {
268+		//initial save dir was calculated based on lock-on cartridge because that's where the save device is
269+		//save directory used for save states should still be located in the normal place
270+		free(save_dir);
271+		parts[0] = save_dir = get_save_dir(media);
272+	}
273+	if (use_native_states || context->type != SYSTEM_GENESIS) {
274+		parts[2] = "quicksave.state";
275+	} else {
276+		parts[2] = "quicksave.gst";
277+	}
278+	free(save_state_path);
279+	save_state_path = alloc_concat_m(3, parts);
280+	context->save_dir = save_dir;
281+	if (info->save_type != SAVE_NONE) {
282+		context->load_save(context);
283+		if (!persist_save_registered) {
284+			atexit(persist_save);
285+			persist_save_registered = 1;
286+		}
287+	}
288+}
289+
290+void apply_updated_config(void)
291+{
292+	render_config_updated();
293+	if (current_system && current_system->config_updated) {
294+		current_system->config_updated(current_system);
295+	}
296+}
297+
298+static system_media cart, lock_on;
299+void reload_media(void)
300+{
301+	if (!current_system) {
302+		return;
303+	}
304+	if (current_system->next_rom) {
305+		free(current_system->next_rom);
306+	}
307+	char const *parts[] = {
308+		cart.dir, PATH_SEP, cart.name, ".", cart.extension
309+	};
310+	char const **start = parts[0] ? parts : parts + 2;
311+	int num_parts = parts[0] ? 5 : 3;
312+	if (!parts[4]) {
313+		num_parts--;
314+	}
315+	current_system->next_rom = alloc_concat_m(num_parts, start);
316+	current_system->request_exit(current_system);
317+}
318+
319+void lockon_media(char *lock_on_path)
320+{
321+	reload_media();
322+	cart.chain = &lock_on;
323+	free(lock_on.dir);
324+	free(lock_on.name);
325+	free(lock_on.extension);
326+	lock_on.dir = path_dirname(lock_on_path);
327+	lock_on.name = basename_no_extension(lock_on_path);
328+	lock_on.extension = path_extension(lock_on_path);
329+	lock_on.size = load_rom(lock_on_path, &lock_on.buffer, NULL);
330+}
331+
332+static uint32_t opts = 0;
333+static uint8_t force_region = 0;
334+void init_system_with_media(const char *path, system_type force_stype)
335+{
336+	if (game_system) {
337+		game_system->persist_save(game_system);
338+		//swap to game context arena and mark all allocated pages in it free
339+		if (current_system == menu_system) {
340+			current_system->arena = set_current_arena(game_system->arena);
341+		}
342+		mark_all_free();
343+		game_system->free_context(game_system);
344+	} else if(current_system) {
345+		//start a new arena and save old one in suspended system context
346+		current_system->arena = start_new_arena();
347+	}
348+	system_type stype = SYSTEM_UNKNOWN;
349+	if (!(cart.size = load_rom(path, &cart.buffer, &stype))) {
350+		fatal_error("Failed to open %s for reading\n", path);
351+	}
352+	free(cart.dir);
353+	free(cart.name);
354+	free(cart.extension);
355+	cart.dir = path_dirname(path);
356+	cart.name = basename_no_extension(path);
357+	cart.extension = path_extension(path);
358+	if (force_stype != SYSTEM_UNKNOWN) {
359+		stype = force_stype;
360+	}
361+	if (stype == SYSTEM_UNKNOWN) {
362+		stype = detect_system_type(&cart);
363+	}
364+	if (stype == SYSTEM_UNKNOWN) {
365+		fatal_error("Failed to detect system type for %s\n", path);
366+	}
367+	//allocate new system context
368+	game_system = alloc_config_system(stype, &cart, opts, force_region);
369+	if (!game_system) {
370+		fatal_error("Failed to configure emulated machine for %s\n", path);
371+	}
372+	if (menu_system) {
373+		menu_system->next_context = game_system;
374+	}
375+	game_system->next_context = menu_system;
376+	setup_saves(&cart, game_system);
377+	update_title(game_system->info.name);
378+}
379+
380+int main(int argc, char ** argv)
381+{
382+	set_exe_str(argv[0]);
383+	config = load_config();
384+	int width = -1;
385+	int height = -1;
386+	int loaded = 0;
387+	system_type stype = SYSTEM_UNKNOWN, force_stype = SYSTEM_UNKNOWN;
388+	char * romfname = NULL;
389+	char * statefile = NULL;
390+	debugger_type dtype = DEBUGGER_NATIVE;
391+	uint8_t start_in_debugger = 0;
392+	uint8_t debug_target = 0;
393+	for (int i = 1; i < argc; i++) {
394+		if (argv[i][0] == '-') {
395+			switch(argv[i][1]) {
396+			case 'b':
397+				i++;
398+				if (i >= argc) {
399+					fatal_error("-b must be followed by a frame count\n");
400+				}
401+				headless = 1;
402+				exit_after = atoi(argv[i]);
403+				break;
404+			case 'd':
405+				start_in_debugger = 1;
406+				//allow debugging the menu
407+				if (argv[i][2] == 'm') {
408+					debug_target = 1;
409+				}
410+				break;
411+			case 'D':
412+				gdb_remote_init();
413+				dtype = DEBUGGER_GDB;
414+				start_in_debugger = 1;
415+				break;
416+			case 'l':
417+				opts |= OPT_ADDRESS_LOG;
418+				break;
419+			case 'v':
420+				info_message("blastem %s\n", BLASTEM_VERSION);
421+				return 0;
422+				break;
423+			case 'n':
424+				z80_enabled = 0;
425+				break;
426+			case 'r':
427+				i++;
428+				if (i >= argc) {
429+					fatal_error("-r must be followed by region (J, U or E)\n");
430+				}
431+				force_region = translate_region_char(toupper(argv[i][0]));
432+				if (!force_region) {
433+					fatal_error("'%c' is not a valid region character for the -r option\n", argv[i][0]);
434+				}
435+				break;
436+			case 'm':
437+				i++;
438+				if (i >= argc) {
439+					fatal_error("-r must be followed by a machine type (sms, gen or jag)\n");
440+				}
441+				if (!strcmp("sms", argv[i])) {
442+					stype = force_stype = SYSTEM_SMS;
443+				} else if (!strcmp("gen", argv[i])) {
444+					stype = force_stype = SYSTEM_GENESIS;
445+				} else {
446+					fatal_error("Unrecognized machine type %s\n", argv[i]);
447+				}
448+				break;
449+			case 's':
450+				i++;
451+				if (i >= argc) {
452+					fatal_error("-s must be followed by a savestate filename\n");
453+				}
454+				statefile = argv[i];
455+				break;
456+			case 't':
457+				force_no_terminal();
458+				break;
459+			case 'y':
460+				opts |= YM_OPT_WAVE_LOG;
461+				break;
462+			case 'o': {
463+				i++;
464+				if (i >= argc) {
465+					fatal_error("-o must be followed by a lock on cartridge filename\n");
466+				}
467+				lock_on.size = load_rom(argv[i], &lock_on.buffer, NULL);
468+				if (!lock_on.size) {
469+					fatal_error("Failed to load lock on cartridge %s\n", argv[i]);
470+				}
471+				lock_on.name = basename_no_extension(argv[i]);
472+				lock_on.extension = path_extension(argv[i]);
473+				cart.chain = &lock_on;
474+				break;
475+			}
476+			case 'h':
477+				info_message(
478+					"Usage: blastem [OPTIONS] ROMFILE [WIDTH] [HEIGHT]\n"
479+					"Options:\n"
480+					"	-h          Print this help text\n"
481+					"	-r (J|U|E)  Force region to Japan, US or Europe respectively\n"
482+					"	-m MACHINE  Force emulated machine type to MACHINE. Valid values are:\n"
483+					"                   sms - Sega Master System/Mark III\n"
484+					"                   gen - Sega Genesis/Megadrive\n"
485+					"	-s FILE     Load a GST format savestate from FILE\n"
486+					"	-o FILE     Load FILE as a lock-on cartridge\n"
487+					"	-d          Enter debugger on startup\n"
488+					"	-n          Disable Z80\n"
489+					"	-v          Display version number and exit\n"
490+					"	-l          Log 68K code addresses (useful for assemblers)\n"
491+					"	-y          Log individual YM-2612 channels to WAVE files\n"
492+				);
493+				return 0;
494+			default:
495+				fatal_error("Unrecognized switch %s\n", argv[i]);
496+			}
497+		} else if (!loaded) {
498+			if (!(cart.size = load_rom(argv[i], &cart.buffer, stype == SYSTEM_UNKNOWN ? &stype : NULL))) {
499+				fatal_error("Failed to open %s for reading\n", argv[i]);
500+			}
501+			cart.dir = path_dirname(argv[i]);
502+			cart.name = basename_no_extension(argv[i]);
503+			cart.extension = path_extension(argv[i]);
504+			romfname = argv[i];
505+			loaded = 1;
506+		} else if (width < 0) {
507+			width = atoi(argv[i]);
508+		} else if (height < 0) {
509+			height = atoi(argv[i]);
510+		}
511+	}
512+	
513+	int def_width = 0, def_height = 0;
514+	char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval;
515+	if (config_width) {
516+		def_width = atoi(config_width);
517+	}
518+	if (!def_width) {
519+		def_width = 640;
520+	}
521+	char *config_height = tern_find_path(config, "video\0height\0", TVAL_PTR).ptrval;
522+	if (config_height) {
523+		def_height = atoi(config_height);
524+	}
525+	if (!def_height) {
526+		def_height = -1;
527+	}
528+	width = width < 1 ? def_width : width;
529+	height = height < 1 ? def_height : height;
530+
531+	if (!headless) {
532+		render_init(width, height, "BlastEm");
533+	}
534+	set_bindings();
535+	
536+	uint8_t menu = !loaded;
537+	if (!loaded) {
538+		//load menu
539+		romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval;
540+		if (!romfname) {
541+			romfname = "menu.bin";
542+		}
543+		if (is_absolute_path(romfname)) {
544+			if (!(cart.size = load_rom(romfname, &cart.buffer, &stype))) {
545+				fatal_error("Failed to open UI ROM %s for reading", romfname);
546+			}
547+		} else {
548+			cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size);
549+			if (!cart.buffer) {
550+				fatal_error("Failed to open UI ROM %s for reading", romfname);
551+			}
552+			uint32_t rom_size = nearest_pow2(cart.size);
553+			if (rom_size > cart.size) {
554+				cart.buffer = realloc(cart.buffer, rom_size);
555+				cart.size = rom_size;
556+			}
557+		}
558+		//force system detection, value on command line is only for games not the menu
559+		stype = detect_system_type(&cart);
560+		cart.dir = path_dirname(romfname);
561+		cart.name = basename_no_extension(romfname);
562+		cart.extension = path_extension(romfname);
563+		loaded = 1;
564+	}
565+	char *state_format = tern_find_path(config, "ui\0state_format\0", TVAL_PTR).ptrval;
566+	if (state_format && !strcmp(state_format, "gst")) {
567+		use_native_states = 0;
568+	} else if (state_format && strcmp(state_format, "native")) {
569+		warning("%s is not a valid value for the ui.state_format setting. Valid values are gst and native\n", state_format);
570+	}
571+
572+	if (loaded) {
573+		if (stype == SYSTEM_UNKNOWN) {
574+			stype = detect_system_type(&cart);
575+		}
576+		if (stype == SYSTEM_UNKNOWN) {
577+			fatal_error("Failed to detect system type for %s\n", romfname);
578+		}
579+		current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region);
580+		if (!current_system) {
581+			fatal_error("Failed to configure emulated machine for %s\n", romfname);
582+		}
583+	
584+		setup_saves(&cart, current_system);
585+		update_title(current_system->info.name);
586+		if (menu) {
587+			menu_system = current_system;
588+		} else {
589+			game_system = current_system;
590+		}
591+	}
592+	
593+	current_system->debugger_type = dtype;
594+	current_system->enter_debugger = start_in_debugger && menu == debug_target;
595+	current_system->start_context(current_system,  menu ? NULL : statefile);
596+	for(;;)
597+	{
598+		if (current_system->should_exit) {
599+			break;
600+		}
601+		if (current_system->next_rom) {
602+			char *next_rom = current_system->next_rom;
603+			current_system->next_rom = NULL;
604+			init_system_with_media(next_rom, force_stype);
605+			free(next_rom);
606+			menu = 0;
607+			current_system = game_system;
608+			current_system->debugger_type = dtype;
609+			current_system->enter_debugger = start_in_debugger && menu == debug_target;
610+			current_system->start_context(current_system, statefile);
611+		} else if (menu && game_system) {
612+			current_system->arena = set_current_arena(game_system->arena);
613+			current_system = game_system;
614+			menu = 0;
615+			current_system->resume_context(current_system);
616+		} else if (!menu && menu_system) {
617+			current_system->arena = set_current_arena(menu_system->arena);
618+			current_system = menu_system;
619+			menu = 1;
620+			if (!current_system->next_rom) {
621+				current_system->resume_context(current_system);
622+			}
623+		} else {
624+			break;
625+		}
626+	}
627+
628+	return 0;
629+}
+23, -0
 1@@ -0,0 +1,23 @@
 2+#ifndef BLASTEM_H_
 3+#define BLASTEM_H_
 4+
 5+#include "tern.h"
 6+#include "system.h"
 7+
 8+extern int headless;
 9+extern int exit_after;
10+extern int z80_enabled;
11+extern int frame_limit;
12+
13+extern tern_node * config;
14+extern system_header *current_system;
15+
16+extern char *save_state_path;
17+extern char *save_filename;
18+extern uint8_t use_native_states;
19+void reload_media(void);
20+void lockon_media(char *lock_on_path);
21+void init_system_with_media(const char *path, system_type force_stype);
22+void apply_updated_config(void);
23+
24+#endif //BLASTEM_H_
+97, -0
 1@@ -0,0 +1,97 @@
 2+# i know this is a ninja file, but you're allowed to edit it.
 3+# you can also pass things on the command line if you like, eg
 4+#
 5+#     CC=clang ninja
 6+
 7+cc = $${CC:-cc}
 8+cflags = $${CFLAGS:--O2 -flto -std=gnu11 -Wreturn-type -Werror=return-type -Werror=implicit-function-declaration -Wno-unused-value -m64 -pthread $$(pkg-config --cflags wayland-client)}
 9+ldflags = $${LDFLAGS:--O2 -flto -m64 -pthread}
10+libs = $${LIBS:--lm $$(pkg-config --libs wayland-client) -lasound -lz}
11+prefix = $${PREFIX:-/usr}
12+destdir = $${DESTDIR:-}
13+bindir = $${BINDIR:-$${DESTDIR:-}$${PREFIX:-/usr}/bin}
14+xdg_shell_xml = $${XDG_SHELL_XML:-/usr/share/wayland-protocols/stable/xdg-shell/xdg-shell.xml}
15+
16+rule wayland_client_header
17+  command = wayland-scanner client-header $xdg_shell_xml $out
18+  description = wl $out
19+
20+rule wayland_private_code
21+  command = wayland-scanner private-code $xdg_shell_xml $out
22+  description = wl $out
23+
24+rule cc
25+  command = $cc $cflags -MMD -MF $out.d -c -o $out $in
26+  deps = gcc
27+  depfile = $out.d
28+  description = cc $out
29+
30+rule link
31+  command = $cc $ldflags -o $out $in $libs
32+  description = link $out
33+
34+rule install
35+  command = mkdir -p $bindir && cp $in $bindir/
36+  description = install $in
37+
38+build xdg-shell-client-protocol.h: wayland_client_header
39+build xdg-shell-protocol.c: wayland_private_code
40+
41+build blastem.o: cc blastem.c
42+build system.o: cc system.c
43+build genesis.o: cc genesis.c
44+build debug.o: cc debug.c
45+build gdb_remote.o: cc gdb_remote.c
46+build vdp.o: cc vdp.c
47+build ppm.o: cc ppm.c
48+build controller_info.o: cc controller_info.c
49+build render_wayland.o: cc render_wayland.c | xdg-shell-client-protocol.h
50+build xdg-shell-protocol.o: cc xdg-shell-protocol.c | xdg-shell-client-protocol.h
51+build png.o: cc png.c
52+build io.o: cc io.c
53+build romdb.o: cc romdb.c
54+build hash.o: cc hash.c
55+build menu.o: cc menu.c
56+build xband.o: cc xband.c
57+build realtec.o: cc realtec.c
58+build i2c.o: cc i2c.c
59+build nor.o: cc nor.c
60+build sega_mapper.o: cc sega_mapper.c
61+build multi_game.o: cc multi_game.c
62+build megawifi.o: cc megawifi.c
63+build net.o: cc net.c
64+build serialize.o: cc serialize.c
65+build terminal.o: cc terminal.c
66+build config.o: cc config.c
67+build tern.o: cc tern.c
68+build util.o: cc util.c
69+build paths.o: cc paths.c
70+build gst.o: cc gst.c
71+build 68kinst.o: cc 68kinst.c
72+build m68k_core.o: cc m68k_core.c
73+build m68k_core_x86.o: cc m68k_core_x86.c
74+build gen.o: cc gen.c
75+build backend.o: cc backend.c
76+build mem.o: cc mem.c
77+build arena.o: cc arena.c
78+build gen_x86.o: cc gen_x86.c
79+build backend_x86.o: cc backend_x86.c
80+build ym2612.o: cc ym2612.c
81+build psg.o: cc psg.c
82+build wave.o: cc wave.c
83+build saves.o: cc saves.c
84+build zip.o: cc zip.c
85+build bindings.o: cc bindings.c
86+build jcart.o: cc jcart.c
87+build sms.o: cc sms.c
88+build z80inst.o: cc z80inst.c
89+build z80_to_x86.o: cc z80_to_x86.c
90+
91+build blastem: link blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o ppm.o controller_info.o render_wayland.o xdg-shell-protocol.o png.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o sega_mapper.o multi_game.o megawifi.o net.o serialize.o terminal.o config.o tern.o util.o paths.o gst.o 68kinst.o m68k_core.o m68k_core_x86.o gen.o backend.o mem.o arena.o gen_x86.o backend_x86.o ym2612.o psg.o wave.o saves.o zip.o bindings.o jcart.o sms.o z80inst.o z80_to_x86.o
92+build all: phony blastem
93+build install-blastem: install blastem
94+build install-default-config: install default.cfg
95+build install-rom-db: install rom.db
96+build install: phony install-blastem install-default-config install-rom-db
97+
98+default all
+1, -0
1@@ -0,0 +1 @@
2+button.png,4,0,raw,interlace,nopal
+0, -0
+96, -0
 1@@ -0,0 +1,96 @@
 2+#!/usr/bin/env python
 3+from glob import glob
 4+import subprocess
 5+from sys import exit,argv
 6+
 7+prefixes = []
 8+skip = set()
 9+for i in range(1, len(argv)):
10+	if '.' in argv[i]:
11+		f = open(argv[i])
12+		for line in f:
13+			parts = line.split()
14+			for part in parts:
15+				if part.endswith('.bin'):
16+					skip.add(part)
17+		f.close()
18+		print 'Skipping',len(skip),'entries from previous report.'
19+	else:
20+		prefixes.append(argv[i])
21+
22+def print_mismatch(path, b, m):
23+	blines = b.split('\n')
24+	mlines = m.split('\n')
25+	if len(blines) != len(mlines):
26+		print '-----------------------------'
27+		print 'Unknown mismatch in', path
28+		print 'blastem output:'
29+		print b
30+		print 'musashi output:'
31+		print m
32+		print '-----------------------------'
33+		return
34+	prevline = ''
35+	differences = []
36+	flagmismatch = False
37+	regmismatch = False
38+	for i in xrange(0, len(blines)):
39+		if blines[i] != mlines[i]:
40+			if prevline == 'XNZVC':
41+				differences.append((prevline, prevline))
42+				flagmismatch = True
43+			else:
44+				regmismatch = True
45+			differences.append((blines[i], mlines[i]))
46+		prevline = blines[i]
47+	if flagmismatch and regmismatch:
48+		mtype = 'General'
49+	elif flagmismatch:
50+		mtype = 'Flag'
51+	elif regmismatch:
52+		mtype = 'Register'
53+	else:
54+		mtype = 'Unknown'
55+	print '-----------------------------'
56+	print mtype, 'mismatch in', path
57+	for i in xrange(0, 2):
58+		print 'musashi' if i else 'blastem', 'output:'
59+		for diff in differences:
60+			print diff[i]
61+	print '-----------------------------'
62+
63+
64+
65+for path in glob('generated_tests/*/*.bin'):
66+	if path in skip:
67+		continue
68+	if prefixes:
69+		good = False
70+		fname = path.split('/')[-1]
71+		for prefix in prefixes:
72+			if fname.startswith(prefix):
73+				good = True
74+				break
75+		if not good:
76+			continue
77+	try:
78+		b = subprocess.check_output(['./trans', path])
79+		try:
80+			m = subprocess.check_output(['musashi/mustrans', path])
81+			#_,_,b = b.partition('\n')
82+			if b != m:
83+				print_mismatch(path, b, m)
84+
85+			else:
86+				print path, 'passed'
87+		except subprocess.CalledProcessError as e:
88+			print '-----------------------------'
89+			print 'musashi exited with code', e.returncode, 'for test', path
90+			print 'blastem output:'
91+			print b
92+			print '-----------------------------'
93+	except subprocess.CalledProcessError as e:
94+		print '-----------------------------'
95+		print 'blastem exited with code', e.returncode, 'for test', path
96+		print '-----------------------------'
97+
+295, -0
  1@@ -0,0 +1,295 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "tern.h"
  8+#include "util.h"
  9+#include "paths.h"
 10+#include <stdio.h>
 11+#include <stdlib.h>
 12+#include <string.h>
 13+
 14+static tern_node * parse_config_int(char **state, int started, int *line)
 15+{
 16+	char *config_data, *curline;
 17+	tern_node * head = NULL;
 18+	config_data = started ? NULL : *state;
 19+	while ((curline = strtok_r(config_data, "\n", state)))
 20+	{
 21+
 22+		config_data = NULL;
 23+		curline = strip_ws(curline);
 24+		int len = strlen(curline);
 25+		if (!len) {
 26+			(*line)++;
 27+			continue;
 28+		}
 29+		if (curline[0] == '#') {
 30+			(*line)++;
 31+			continue;
 32+		}
 33+		if (curline[0] == '}') {
 34+			if (started) {
 35+				return head;
 36+			}
 37+			fatal_error("unexpected } on line %d\n", *line);
 38+		}
 39+
 40+		char * end = curline + len - 1;
 41+		if (*end == '{') {
 42+			*end = 0;
 43+			curline = strip_ws(curline);
 44+			(*line)++;
 45+			head = tern_insert_node(head, curline, parse_config_int(state, 1, line));
 46+		} else {
 47+			char * val = strip_ws(split_keyval(curline));
 48+			char * key = curline;
 49+			if (*val) {
 50+				head = tern_insert_ptr(head, key, strdup(val));
 51+			} else {
 52+				fprintf(stderr, "Key %s is missing a value on line %d\n", key, *line);
 53+			}
 54+			(*line)++;
 55+		}
 56+	}
 57+	return head;
 58+}
 59+
 60+tern_node *parse_config(char * config_data)
 61+{
 62+	int line = 1;
 63+	return parse_config_int(&config_data, 0, &line);
 64+}
 65+
 66+typedef struct {
 67+	char     *buf;
 68+	uint32_t capacity;
 69+	uint32_t size;
 70+	uint32_t indent;
 71+} serialize_state;
 72+
 73+static void ensure_buf_capacity(uint32_t ensure, serialize_state *state)
 74+{
 75+	if (ensure + state->size > state->capacity) {
 76+		state->capacity = state->capacity * 2;
 77+		state->buf = realloc(state->buf, state->capacity);
 78+	}
 79+}
 80+
 81+static void indent(serialize_state *state)
 82+{
 83+	memset(state->buf + state->size, '\t', state->indent);
 84+	state->size += state->indent;
 85+}
 86+
 87+static void serialize_config_int(tern_node *config, serialize_state *state);
 88+
 89+static void serialize_iter(char *key, tern_val val, uint8_t valtype, void *data)
 90+{
 91+	serialize_state *state = data;
 92+	uint32_t keylen = strlen(key);
 93+	uint32_t vallen = 0;
 94+	if (valtype == TVAL_PTR) {
 95+		vallen = strlen(val.ptrval);
 96+	}
 97+	ensure_buf_capacity(state->indent + keylen + 2 + vallen, state);
 98+	state->buf[state->size++] = '\n';
 99+	indent(state);
100+	memcpy(state->buf + state->size, key, keylen);
101+	state->size += keylen;
102+	state->buf[state->size++] = ' ';
103+	if (valtype == TVAL_PTR) {
104+		memcpy(state->buf + state->size, val.ptrval, vallen);
105+		state->size += vallen;
106+	} else {
107+		serialize_config_int(val.ptrval, state);
108+	}
109+}
110+
111+static void serialize_config_int(tern_node *config, serialize_state *state)
112+{
113+	ensure_buf_capacity(1, state);
114+	state->buf[state->size++] = '{';
115+	state->indent++;
116+	
117+	tern_foreach(config, serialize_iter, state);
118+
119+	--state->indent;
120+	ensure_buf_capacity(2 + state->indent, state);
121+	state->buf[state->size++] = '\n';
122+	indent(state);
123+	state->buf[state->size++] = '}';
124+}
125+
126+char *serialize_config(tern_node *config, uint32_t *size_out)
127+{
128+	serialize_state state = {
129+		.size = 0,
130+		.capacity = 1024,
131+		.indent = 0
132+	};
133+	state.buf = malloc(state.capacity);
134+	tern_foreach(config, serialize_iter, &state);
135+	//serialize_config_int(config, &state);
136+	*size_out = state.size;
137+	return state.buf;
138+}
139+
140+tern_node *parse_config_file(char *config_path)
141+{
142+	tern_node * ret = NULL;
143+	FILE * config_file = fopen(config_path, "rb");
144+	if (!config_file) {
145+		goto open_fail;
146+	}
147+	long config_size = file_size(config_file);
148+	if (!config_size) {
149+		goto config_empty;
150+	}
151+	char *config_data = calloc(config_size + 1, 1);
152+	if (fread(config_data, 1, config_size, config_file) != config_size) {
153+		goto config_read_fail;
154+	}
155+
156+	ret = parse_config(config_data);
157+config_read_fail:
158+	free(config_data);
159+config_empty:
160+	fclose(config_file);
161+open_fail:
162+	return ret;
163+}
164+
165+uint8_t serialize_config_file(tern_node *config, char *path)
166+{
167+	FILE *f = fopen(path, "w");
168+	if (!f) {
169+		return 0;
170+	}
171+	uint32_t buf_size;
172+	char *buffer = serialize_config(config, &buf_size);
173+	uint8_t ret = buf_size == fwrite(buffer, 1, buf_size, f);
174+	free(buffer);
175+	fclose(f);
176+	return ret;
177+}
178+
179+tern_node *parse_bundled_config(char *config_name)
180+{
181+	tern_node *ret = NULL;
182+#ifdef CONFIG_PATH
183+	if (!strcmp("default.cfg", config_name) || !strcmp("blastem.cfg", config_name)) {
184+		char *confpath = path_append(CONFIG_PATH, config_name);
185+		ret = parse_config_file(confpath);
186+		free(confpath);
187+	} else {
188+#endif
189+	uint32_t confsize;
190+	char *confdata = read_bundled_file(config_name, &confsize);
191+	if (confdata) {
192+		confdata[confsize] = 0;
193+		ret = parse_config(confdata);
194+		free(confdata);
195+	}
196+#ifdef CONFIG_PATH
197+	}
198+#endif
199+	return ret;
200+}
201+
202+tern_node *load_overrideable_config(char *name, char *bundled_name)
203+{
204+	char const *confdir = get_config_dir();
205+	char *confpath = NULL;
206+	tern_node *ret;
207+	if (confdir) {
208+		confpath = path_append(confdir, name);
209+		ret = parse_config_file(confpath);
210+		if (ret) {
211+			free(confpath);
212+			return ret;
213+		}
214+	}
215+
216+	ret = parse_bundled_config(bundled_name);
217+	if (ret) {
218+		free(confpath);
219+		return ret;
220+	}
221+	return NULL;
222+}
223+
224+tern_node *load_config()
225+{
226+	char const *confdir = get_config_dir();
227+	char *confpath = NULL;
228+	tern_node *ret = load_overrideable_config("blastem.cfg", "default.cfg");
229+	if (confdir) {
230+		confpath = path_append(confdir, "blastem.cfg");
231+		ret = parse_config_file(confpath);
232+		if (ret) {
233+			free(confpath);
234+			return ret;
235+		}
236+	}
237+
238+	ret = parse_bundled_config("default.cfg");
239+	if (ret) {
240+		free(confpath);
241+		return ret;
242+	}
243+
244+	if (get_config_dir()) {
245+		fatal_error("Failed to find a config file at %s or in the blastem executable directory\n", get_config_dir());
246+	} else {
247+		fatal_error("Failed to find a config file in the BlastEm executable directory and the config directory path could not be determined\n");
248+	}
249+	//this will never get reached, but the compiler doesn't know that. Let's make it happy
250+	return NULL;
251+}
252+
253+void persist_config_at(tern_node *config, char *fname)
254+{
255+	char const *confdir = get_config_dir();
256+	if (!confdir) {
257+		fatal_error("Failed to locate config file directory\n");
258+	}
259+	ensure_dir_exists(confdir);
260+	char *confpath = path_append(confdir, fname);
261+	if (!serialize_config_file(config, confpath)) {
262+		fatal_error("Failed to write config to %s\n", confpath);
263+	}
264+	free(confpath);
265+}
266+
267+void persist_config(tern_node *config)
268+{
269+	persist_config_at(config, "blastem.cfg");
270+}
271+
272+char **get_extension_list(tern_node *config, uint32_t *num_exts_out)
273+{
274+	char *ext_filter = strdup(tern_find_path_default(config, "ui\0extensions\0", (tern_val){.ptrval = "bin gen md smd sms gg"}, TVAL_PTR).ptrval);
275+	uint32_t num_exts = 0, ext_storage = 5;
276+	char **ext_list = malloc(sizeof(char *) * ext_storage);
277+	char *cur_filter = ext_filter;
278+	while (*cur_filter)
279+	{
280+		if (num_exts == ext_storage) {
281+			ext_storage *= 2;
282+			ext_list = realloc(ext_list, sizeof(char *) * ext_storage);
283+		}
284+		ext_list[num_exts++] = cur_filter;
285+		cur_filter = split_keyval(cur_filter);
286+	}
287+	*num_exts_out = num_exts;
288+	return ext_list;
289+}
290+
291+#define DEFAULT_LOWPASS_CUTOFF 3390
292+uint32_t get_lowpass_cutoff(tern_node *config)
293+{
294+	char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval;
295+	return lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF;
296+}
+22, -0
 1@@ -0,0 +1,22 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef CONFIG_H_
 8+#define CONFIG_H_
 9+#include "tern.h"
10+
11+tern_node *parse_config_file(char *config_path);
12+tern_node *parse_bundled_config(char *config_name);
13+tern_node *load_overrideable_config(char *name, char *bundled_name);
14+tern_node *load_config();
15+char *serialize_config(tern_node *config, uint32_t *size_out);
16+uint8_t serialize_config_file(tern_node *config, char *path);
17+void persist_config_at(tern_node *config, char *fname);
18+void persist_config(tern_node *config);
19+char **get_extension_list(tern_node *config, uint32_t *num_exts_out);
20+uint32_t get_lowpass_cutoff(tern_node *config);
21+
22+#endif //CONFIG_H_
23+
+217, -0
  1@@ -0,0 +1,217 @@
  2+#include <string.h>
  3+#include <stdlib.h>
  4+#include "controller_info.h"
  5+#include "config.h"
  6+#include "util.h"
  7+
  8+typedef struct {
  9+	char const      *name;
 10+	controller_info info;
 11+} heuristic;
 12+
 13+static heuristic heuristics[] = {
 14+	//TODO: Add more heuristic rules
 15+	{"DualShock 4", {.type = TYPE_PSX, .subtype = SUBTYPE_PS4}},
 16+	{"PS4", {.type = TYPE_PSX, .subtype = SUBTYPE_PS4}},
 17+	{"PS3", {.type = TYPE_PSX, .subtype = SUBTYPE_PS3}},
 18+	{"X360", {.type = TYPE_XBOX, .subtype = SUBTYPE_X360}},
 19+	{"Xbox 360", {.type = TYPE_XBOX, .subtype = SUBTYPE_X360}},
 20+	{"X-box 360", {.type = TYPE_XBOX, .subtype = SUBTYPE_X360}},
 21+	{"Xbox One", {.type = TYPE_XBOX, .subtype = SUBTYPE_XBONE}},
 22+	{"X-box One", {.type = TYPE_XBOX, .subtype = SUBTYPE_XBONE}},
 23+	{"WiiU", {.type = TYPE_NINTENDO, .subtype = SUBTYPE_WIIU}},
 24+	{"Wii U", {.type = TYPE_NINTENDO, .subtype = SUBTYPE_WIIU}},
 25+	{"Nintendo Switch", {.type = TYPE_NINTENDO, .subtype = SUBTYPE_SWITCH}},
 26+	{"Saturn", {.type = TYPE_SEGA, .subtype = SUBTYPE_SATURN}}
 27+};
 28+const uint32_t num_heuristics = sizeof(heuristics)/sizeof(*heuristics);
 29+
 30+static tern_node *info_config;
 31+static uint8_t loaded;
 32+static const char *subtype_names[] = {
 33+	"unknown",
 34+	"xbox",
 35+	"xbox 360",
 36+	"xbone",
 37+	"ps2",
 38+	"ps3",
 39+	"ps4",
 40+	"wiiu",
 41+	"switch",
 42+	"genesis",
 43+	"saturn"
 44+};
 45+static const char *subtype_human_names[] = {
 46+	"unknown",
 47+	"Xbos",
 48+	"Xbox 360",
 49+	"Xbox One",
 50+	"PS2",
 51+	"PS3",
 52+	"PS4",
 53+	"Wii-U",
 54+	"Switch",
 55+	"Genesis",
 56+	"Saturn"
 57+};
 58+static const char *variant_names[] = {
 59+	"normal",
 60+	"6b bumpers",
 61+	"6b right"
 62+};
 63+
 64+static void load_ctype_config(void)
 65+{
 66+	if (!loaded) {
 67+		info_config = load_overrideable_config("controller_types.cfg", "controller_types.cfg");
 68+		loaded = 1;
 69+	}
 70+}
 71+
 72+controller_info get_controller_info(int joystick)
 73+{
 74+	const char *name = "Unknown";
 75+	return (controller_info){
 76+		.type = TYPE_GENERIC_MAPPING,
 77+		.subtype = SUBTYPE_UNKNOWN,
 78+		.variant = VARIANT_NORMAL,
 79+		.name = name
 80+	};
 81+}
 82+
 83+static void mappings_iter(char *key, tern_val val, uint8_t valtype, void *data)
 84+{
 85+}
 86+
 87+void controller_add_mappings(void)
 88+{
 89+	load_ctype_config();
 90+	if (info_config) {
 91+		tern_foreach(info_config, mappings_iter, NULL);
 92+	}
 93+}
 94+
 95+void save_controller_info(int joystick, controller_info *info)
 96+{
 97+}
 98+
 99+void save_controller_mapping(int joystick, char *mapping_string)
100+{
101+}
102+
103+char const *labels_xbox[] = {
104+	"A", "B", "X", "Y", "Back", NULL, "Start", "Click", "Click", "White", "Black", "LT", "RT"
105+};
106+char const *labels_360[] = {
107+	"A", "B", "X", "Y", "Back", "Xbox", "Start", "Click", "Click", "LB", "RB", "LT", "RT"
108+};
109+static char const *labels_xbone[] = {
110+	"A", "B", "X", "Y", "View", "Xbox", "Menu", "Click", "Click", "LB", "RB", "LT", "RT"
111+};
112+static char const *labels_ps3[] = {
113+	"cross", "circle", "square", "triangle", "Select", "PS", "Start", "L3", "R3", "L1", "R1", "L2", "R2"
114+};
115+static char const *labels_ps4[] = {
116+	"cross", "circle", "square", "triangle", "Share", "PS", "Options", "L3", "R3", "L1", "R1", "L2", "R2"
117+};
118+static char const *labels_nintendo[] = {
119+	"B", "A", "Y", "X", "-", "Home", "+", "Click", "Click", "L", "R", "ZL", "ZR"
120+};
121+static char const *labels_genesis[] = {
122+	"A", "B", "X", "Y", NULL, NULL, "Start", NULL, NULL, "Z", "C", NULL, "Mode"
123+};
124+static char const *labels_saturn[] = {
125+	"A", "B", "X", "Y", NULL, NULL, "Start", NULL, NULL, "Z", "C", "LT", "RT"
126+};
127+
128+static const char** label_source(controller_info *info)
129+{
130+	if (info->type == TYPE_UNKNOWN || info->type == TYPE_GENERIC_MAPPING || info->subtype ==SUBTYPE_X360) {
131+		return labels_360;
132+	} else if (info->type == TYPE_NINTENDO) {
133+		return labels_nintendo;
134+	} else if (info->type == TYPE_PSX) {
135+		if (info->subtype == SUBTYPE_PS4) {
136+			return labels_ps4;
137+		} else {
138+			return labels_ps3;
139+		}
140+	} else if (info->type == TYPE_XBOX) {
141+		if (info->subtype == SUBTYPE_XBONE) {
142+			return labels_xbone;
143+		} else {
144+			return labels_xbox;
145+		}
146+	} else {
147+		if (info->subtype == SUBTYPE_GENESIS) {
148+			return labels_genesis;
149+		} else {
150+			return labels_saturn;
151+		}
152+	}
153+}
154+
155+const char *get_button_label(controller_info *info, int button)
156+{
157+	return label_source(info)[button];
158+}
159+
160+static char const *axis_labels[] = {
161+	"Left X", "Left Y", "Right X", "Right Y"
162+};
163+const char *get_axis_label(controller_info *info, int axis)
164+{
165+	return NULL;
166+}
167+
168+char *make_controller_type_key(controller_info *info)
169+{
170+	const char *subtype;
171+	if (info->subtype == SUBTYPE_UNKNOWN) {
172+		switch(info->type)
173+		{
174+		case TYPE_XBOX:
175+			subtype = subtype_names[SUBTYPE_X360];
176+			break;
177+		case TYPE_PSX:
178+			subtype = subtype_names[SUBTYPE_PS4];
179+			break;
180+		case TYPE_NINTENDO:
181+			subtype = subtype_names[SUBTYPE_SWITCH];
182+			break;
183+		default:
184+			subtype = "unknown";
185+		}
186+	} else {
187+		subtype = subtype_names[info->subtype];
188+	}
189+	const char *variant = variant_names[info->variant];
190+	const char *parts[] = {subtype, "_", variant};
191+	char *ret = alloc_concat_m(3, parts);
192+	for (char *cur = ret; *cur; cur++)
193+	{
194+		if (*cur == ' ')
195+		{
196+			*cur = '_';
197+		}
198+	}
199+	return ret;
200+}
201+
202+char *make_human_readable_type_name(controller_info *info)
203+{
204+	const char *base = subtype_human_names[info->subtype];
205+	char *prefix;
206+	if (info->variant == VARIANT_NORMAL) {
207+		prefix = "Normal ";
208+	} else {
209+		static const char *parts[] = {"6 button (", NULL, "/", NULL, ") "};
210+		parts[1] = parts[3] = "??";
211+		prefix = alloc_concat_m(5, parts);
212+	}
213+	char *ret = alloc_concat(prefix, base);
214+	if (info->variant != VARIANT_NORMAL) {
215+		free(prefix);
216+	}
217+	return ret;
218+}
+52, -0
 1@@ -0,0 +1,52 @@
 2+#ifndef CONTROLLER_INFO_H_
 3+#define CONTROLLER_INFO_H_
 4+#include <stdint.h>
 5+
 6+enum {
 7+	TYPE_UNKNOWN,
 8+	TYPE_GENERIC_MAPPING,
 9+	TYPE_XBOX,
10+	TYPE_PSX,
11+	TYPE_NINTENDO,
12+	TYPE_SEGA
13+};
14+
15+enum {
16+	SUBTYPE_UNKNOWN,
17+	SUBTYPE_XBOX,
18+	SUBTYPE_X360,
19+	SUBTYPE_XBONE,
20+	SUBTYPE_PS2,
21+	SUBTYPE_PS3,
22+	SUBTYPE_PS4,
23+	SUBTYPE_WIIU,
24+	SUBTYPE_SWITCH,
25+	SUBTYPE_GENESIS,
26+	SUBTYPE_SATURN,
27+	SUBTYPE_NUM
28+};
29+
30+enum {
31+	VARIANT_NORMAL,
32+	VARIANT_6B_BUMPERS, //C and Z positions are RB and LB respectively
33+	VARIANT_6B_RIGHT, //C and Z positions are RT and RB respectively
34+	VARIANT_NUM
35+};
36+
37+typedef struct {
38+	char const *name;
39+	uint8_t    type;
40+	uint8_t    subtype;
41+	uint8_t    variant;
42+} controller_info;
43+
44+controller_info get_controller_info(int index);
45+const char *get_button_label(controller_info *info, int button);
46+const char *get_axis_label(controller_info *info, int axis);
47+void save_controller_info(int joystick, controller_info *info);
48+void save_controller_mapping(int joystick, char *mapping_string);
49+void controller_add_mappings(void);
50+char *make_controller_type_key(controller_info *info);
51+char *make_human_readable_type_name(controller_info *info);
52+
53+#endif //CONTROLLER_INFO_H_
+1697, -0
   1@@ -0,0 +1,1697 @@
   2+#!/usr/bin/env python3
   3+
   4+
   5+class Block:
   6+	def addOp(self, op):
   7+		pass
   8+	
   9+	def processLine(self, parts):
  10+		if parts[0] == 'switch':
  11+			o = Switch(self, parts[1])
  12+			self.addOp(o)
  13+			return o
  14+		elif parts[0] == 'if':
  15+			o = If(self, parts[1])
  16+			self.addOp(o)
  17+			return o
  18+		elif parts[0] == 'end':
  19+			raise Exception('end is only allowed inside a switch or if block')
  20+		else:
  21+			self.addOp(NormalOp(parts))
  22+		return self
  23+		
  24+	def processOps(self, prog, fieldVals, output, otype, oplist):
  25+		for i in range(0, len(oplist)):
  26+			if i + 1 < len(oplist) and oplist[i+1].op == 'update_flags':
  27+				flagUpdates, _ = prog.flags.parseFlagUpdate(oplist[i+1].params[0])
  28+			else:
  29+				flagUpdates = None
  30+			oplist[i].generate(prog, self, fieldVals, output, otype, flagUpdates)
  31+		
  32+	def resolveLocal(self, name):
  33+		return None
  34+			
  35+class ChildBlock(Block):
  36+	def processLine(self, parts):
  37+		if parts[0] == 'end':
  38+			return self.parent
  39+		return super().processLine(parts)
  40+
  41+#Represents an instruction of the emulated CPU
  42+class Instruction(Block):
  43+	def __init__(self, value, fields, name):
  44+		self.value = value
  45+		self.fields = fields
  46+		self.name = name
  47+		self.implementation = []
  48+		self.locals = {}
  49+		self.regValues = {}
  50+		self.varyingBits = 0
  51+		self.invalidFieldValues = {}
  52+		self.newLocals = []
  53+		for field in fields:
  54+			self.varyingBits += fields[field][1]
  55+	
  56+	def addOp(self, op):
  57+		if op.op == 'local':
  58+			name = op.params[0]
  59+			size = int(op.params[1])
  60+			self.locals[name] = size
  61+		elif op.op == 'invalid':
  62+			name = op.params[0]
  63+			value = int(op.params[1])
  64+			self.invalidFieldValues.setdefault(name, set()).add(value)
  65+		else:
  66+			self.implementation.append(op)
  67+			
  68+	def resolveLocal(self, name):
  69+		if name in self.locals:
  70+			return name
  71+		return None
  72+	
  73+	def addLocal(self, name, size):
  74+		self.locals[name] = size
  75+		self.newLocals.append(name)
  76+		
  77+	def localSize(self, name):
  78+		return self.locals.get(name)
  79+			
  80+	def __lt__(self, other):
  81+		if isinstance(other, Instruction):
  82+			if self.varyingBits != other.varyingBits:
  83+				return self.varyingBits < other.varyingBits
  84+			return self.value < other.value
  85+		else:
  86+			return NotImplemented
  87+			
  88+	def allValues(self):
  89+		values = []
  90+		for i in range(0, 1 << self.varyingBits):
  91+			iword = self.value
  92+			doIt = True
  93+			for field in self.fields:
  94+				shift,bits = self.fields[field]
  95+				val = i & ((1 << bits) - 1)
  96+				if field in self.invalidFieldValues and val in self.invalidFieldValues[field]:
  97+					doIt = False
  98+					break
  99+				i >>= bits
 100+				iword |= val << shift
 101+			if doIt:
 102+				values.append(iword)
 103+		return values
 104+		
 105+	def getFieldVals(self, value):
 106+		fieldVals = {}
 107+		fieldBits = {}
 108+		for field in self.fields:
 109+			shift,bits = self.fields[field]
 110+			val = (value >> shift) & ((1 << bits) - 1)
 111+			fieldVals[field] = val
 112+			fieldBits[field] = bits
 113+		return (fieldVals, fieldBits)
 114+	
 115+	def generateName(self, value):
 116+		fieldVals,fieldBits = self.getFieldVals(value)
 117+		names = list(fieldVals.keys())
 118+		names.sort()
 119+		funName = self.name
 120+		for name in names:
 121+			funName += '_{0}_{1:0>{2}}'.format(name, bin(fieldVals[name])[2:], fieldBits[name])
 122+		return funName
 123+		
 124+	def generateBody(self, value, prog, otype):
 125+		output = []
 126+		prog.meta = {}
 127+		prog.pushScope(self)
 128+		self.regValues = {}
 129+		for var in self.locals:
 130+			output.append('\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var))
 131+		self.newLocals = []
 132+		fieldVals,_ = self.getFieldVals(value)
 133+		self.processOps(prog, fieldVals, output, otype, self.implementation)
 134+		
 135+		if prog.dispatch == 'call':
 136+			begin = '\nvoid ' + self.generateName(value) + '(' + prog.context_type + ' *context)\n{'
 137+		elif prog.dispatch == 'goto':
 138+			begin = '\n' + self.generateName(value) + ': {'
 139+		else:
 140+			raise Exception('Unsupported dispatch type ' + prog.dispatch)
 141+		if prog.needFlagCoalesce:
 142+			begin += prog.flags.coalesceFlags(prog, otype)
 143+		if prog.needFlagDisperse:
 144+			output.append(prog.flags.disperseFlags(prog, otype))
 145+		for var in self.newLocals:
 146+			begin += '\n\tuint{sz}_t {name};'.format(sz=self.locals[var], name=var)
 147+		prog.popScope()
 148+		if prog.dispatch == 'goto':
 149+			output += prog.nextInstruction(otype)
 150+		return begin + ''.join(output) + '\n}'
 151+		
 152+	def __str__(self):
 153+		pieces = [self.name + ' ' + hex(self.value) + ' ' + str(self.fields)]
 154+		for name in self.locals:
 155+			pieces.append('\n\tlocal {0} {1}'.format(name, self.locals[name]))
 156+		for op in self.implementation:
 157+			pieces.append(str(op))
 158+		return ''.join(pieces)
 159+	
 160+#Represents the definition of a helper function
 161+class SubRoutine(Block):
 162+	def __init__(self, name):
 163+		self.name = name
 164+		self.implementation = []
 165+		self.args = []
 166+		self.arg_map = {}
 167+		self.locals = {}
 168+		self.regValues = {}
 169+		self.argValues = {}
 170+	
 171+	def addOp(self, op):
 172+		if op.op == 'arg':
 173+			name = op.params[0]
 174+			size = int(op.params[1])
 175+			self.arg_map[name] = len(self.args)
 176+			self.args.append((name, size))
 177+		elif op.op == 'local':
 178+			name = op.params[0]
 179+			size = int(op.params[1])
 180+			self.locals[name] = size
 181+		else:
 182+			self.implementation.append(op)
 183+			
 184+	def resolveLocal(self, name):
 185+		if name in self.locals:
 186+			return self.name + '_' + name
 187+		return None
 188+	
 189+	def addLocal(self, name, size):
 190+		self.locals[name] = size
 191+	
 192+	def localSize(self, name):
 193+		if name in self.locals:
 194+			return self.locals[name]
 195+		if name in self.arg_map:
 196+			argIndex = self.arg_map[name]
 197+			return self.args[argIndex][1]
 198+		return None
 199+			
 200+	def inline(self, prog, params, output, otype, parent):
 201+		if len(params) != len(self.args):
 202+			raise Exception('{0} expects {1} arguments, but was called with {2}'.format(self.name, len(self.args), len(params)))
 203+		argValues = {}
 204+		if parent:
 205+			self.regValues = parent.regValues
 206+		prog.pushScope(self)
 207+		i = 0
 208+		for name,size in self.args:
 209+			argValues[name] = params[i]
 210+			i += 1
 211+		for name in self.locals:
 212+			size = self.locals[name]
 213+			output.append('\n\tuint{size}_t {sub}_{local};'.format(size=size, sub=self.name, local=name))
 214+		self.argValues = argValues
 215+		self.processOps(prog, argValues, output, otype, self.implementation)
 216+		prog.popScope()
 217+		
 218+	def __str__(self):
 219+		pieces = [self.name]
 220+		for name,size in self.args:
 221+			pieces.append('\n\targ {0} {1}'.format(name, size))
 222+		for name in self.locals:
 223+			pieces.append('\n\tlocal {0} {1}'.format(name, self.locals[name]))
 224+		for op in self.implementation:
 225+			pieces.append(str(op))
 226+		return ''.join(pieces)
 227+	
 228+class Op:
 229+	def __init__(self, evalFun = None):
 230+		self.evalFun = evalFun
 231+		self.impls = {}
 232+		self.outOp = ()
 233+	def cBinaryOperator(self, op):
 234+		def _impl(prog, params, rawParams, flagUpdates):
 235+			if op == '-':
 236+				a = params[1]
 237+				b = params[0]
 238+			else:
 239+				a = params[0]
 240+				b = params[1]
 241+			needsCarry = needsOflow = needsHalf = False
 242+			if flagUpdates:
 243+				for flag in flagUpdates:
 244+					calc = prog.flags.flagCalc[flag]
 245+					if calc == 'carry':
 246+						needsCarry = True
 247+					elif calc == 'half-carry':
 248+						needsHalf = True
 249+					elif calc == 'overflow':
 250+						needsOflow = True
 251+			decl = ''
 252+			if needsCarry or needsOflow or needsHalf:
 253+				size = prog.paramSize(rawParams[2])
 254+				if needsCarry and op != 'lsr':
 255+					size *= 2
 256+				decl,name = prog.getTemp(size)
 257+				dst = prog.carryFlowDst = name
 258+				prog.lastA = a
 259+				prog.lastB = b
 260+				prog.lastBFlow = b if op == '-' else '(~{b})'.format(b=b)
 261+			else:
 262+				dst = params[2]
 263+			return decl + '\n\t{dst} = {a} {op} {b};'.format(
 264+				dst = dst, a = a, b = b, op = op
 265+			)
 266+		self.impls['c'] = _impl
 267+		self.outOp = (2,)
 268+		return self
 269+	def cUnaryOperator(self, op):
 270+		def _impl(prog, params, rawParams, flagUpdates):
 271+			dst = params[1]
 272+			decl = ''
 273+			if op == '-':
 274+				if flagUpdates:
 275+					for flag in flagUpdates:
 276+						calc = prog.flags.flagCalc[flag]
 277+						if calc == 'carry':
 278+							needsCarry = True
 279+						elif calc == 'half-carry':
 280+							needsHalf = True
 281+						elif calc == 'overflow':
 282+							needsOflow = True
 283+				if needsCarry or needsOflow or needsHalf:
 284+					size = prog.paramSize(rawParams[1])
 285+					if needsCarry:
 286+						size *= 2
 287+					decl,name = prog.getTemp(size)
 288+					dst = prog.carryFlowDst = name
 289+					prog.lastA = 0
 290+					prog.lastB = params[0]
 291+					prog.lastBFlow = params[0]
 292+			return decl + '\n\t{dst} = {op}{a};'.format(
 293+				dst = dst, a = params[0], op = op
 294+			)
 295+		self.impls['c'] = _impl
 296+		self.outOp = (1,)
 297+		return self
 298+	def addImplementation(self, lang, outOp, impl):
 299+		self.impls[lang] = impl
 300+		if not outOp is None:
 301+			if type(outOp) is tuple:
 302+				self.outOp = outOp
 303+			else:
 304+				self.outOp = (outOp,)
 305+		return self
 306+	def evaluate(self, params):
 307+		return self.evalFun(*params)
 308+	def canEval(self):
 309+		return not self.evalFun is None
 310+	def numArgs(self):
 311+		return self.evalFun.__code__.co_argcount
 312+	def numParams(self):
 313+		if self.outOp:
 314+			params = max(self.outOp) + 1
 315+		else:
 316+			params = 0
 317+		if self.evalFun:
 318+			params = max(params, self.numArgs())
 319+		return params
 320+	def generate(self, otype, prog, params, rawParams, flagUpdates):
 321+		if self.impls[otype].__code__.co_argcount == 2:
 322+			return self.impls[otype](prog, params)
 323+		elif self.impls[otype].__code__.co_argcount == 3:
 324+			return self.impls[otype](prog, params, rawParams)
 325+		else:
 326+			return self.impls[otype](prog, params, rawParams, flagUpdates)
 327+		
 328+		
 329+def _xchgCImpl(prog, params, rawParams):
 330+	size = prog.paramSize(rawParams[0])
 331+	decl,name = prog.getTemp(size)
 332+	return decl + '\n\t{tmp} = {a};\n\t{a} = {b};\n\t{b} = {tmp};'.format(a = params[0], b = params[1], tmp = name)
 333+
 334+def _dispatchCImpl(prog, params):
 335+	if len(params) == 1:
 336+		table = 'main'
 337+	else:
 338+		table = params[1]
 339+	if prog.dispatch == 'call':
 340+		return '\n\timpl_{tbl}[{op}](context);'.format(tbl = table, op = params[0])
 341+	elif prog.dispatch == 'goto':
 342+		return '\n\tgoto *impl_{tbl}[{op}];'.format(tbl = table, op = params[0])
 343+	else:
 344+		raise Exception('Unsupported dispatch type ' + prog.dispatch)
 345+
 346+def _updateFlagsCImpl(prog, params, rawParams):
 347+	autoUpdate, explicit = prog.flags.parseFlagUpdate(params[0])
 348+	output = []
 349+	parity = None
 350+	directFlags = {}
 351+	for flag in autoUpdate:
 352+		calc = prog.flags.flagCalc[flag]
 353+		calc,_,resultBit = calc.partition('-')
 354+		if prog.carryFlowDst:
 355+			lastDst = prog.carryFlowDst
 356+		else:
 357+			lastDst = prog.resolveParam(prog.lastDst, prog.currentScope, {})
 358+		storage = prog.flags.getStorage(flag)
 359+		if calc == 'bit' or calc == 'sign' or calc == 'carry' or calc == 'half' or calc == 'overflow':
 360+			myRes = lastDst
 361+			if calc == 'sign':
 362+				resultBit = prog.paramSize(prog.lastDst) - 1
 363+			elif calc == 'carry':
 364+				if prog.lastOp.op in ('asr', 'lsr'):
 365+					resultBit = 0
 366+					myRes = prog.lastA
 367+				else:
 368+					resultBit = prog.paramSize(prog.lastDst)
 369+					if prog.lastOp.op == 'ror':
 370+						resultBit -= 1
 371+			elif calc == 'half':
 372+				resultBit = prog.paramSize(prog.lastDst) - 4
 373+				myRes = '({a} ^ {b} ^ {res})'.format(a = prog.lastA, b = prog.lastB, res = lastDst)
 374+			elif calc == 'overflow':
 375+				resultBit = prog.paramSize(prog.lastDst) - 1
 376+				myRes = '((({a} ^ {b})) & ({a} ^ {res}))'.format(a = prog.lastA, b = prog.lastBFlow, res = lastDst)
 377+			else:
 378+				#Note: offsetting this by the operation size - 8 makes sense for the Z80
 379+				#but might not for other CPUs with this kind of fixed bit flag behavior
 380+				resultBit = int(resultBit) + prog.paramSize(prog.lastDst) - 8
 381+			if type(storage) is tuple:
 382+				reg,storageBit = storage
 383+				if storageBit == resultBit:
 384+					directFlags.setdefault((reg, myRes), []).append(resultBit)
 385+				else:
 386+					reg = prog.resolveParam(reg, None, {})
 387+					if resultBit > storageBit:
 388+						op = '>>'
 389+						shift = resultBit - storageBit
 390+					else:
 391+						op = '<<'
 392+						shift = storageBit - resultBit
 393+					output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} {op} {shift}U & {mask}U);'.format(
 394+						reg = reg, mask = 1 << storageBit, res = myRes, op = op, shift = shift
 395+					))
 396+			else:
 397+				reg = prog.resolveParam(storage, None, {})
 398+				maxBit = prog.paramSize(storage) - 1
 399+				if resultBit > maxBit:
 400+					output.append('\n\t{reg} = {res} >> {shift} & {mask}U;'.format(reg=reg, res=myRes, shift = resultBit - maxBit, mask = 1 << maxBit))
 401+				else:
 402+					output.append('\n\t{reg} = {res} & {mask}U;'.format(reg=reg, res=myRes, mask = 1 << resultBit))
 403+		elif calc == 'zero':
 404+			if prog.carryFlowDst:
 405+				realSize = prog.paramSize(prog.lastDst)
 406+				if realSize != prog.paramSize(prog.carryFlowDst):
 407+					lastDst = '({res} & {mask})'.format(res=lastDst, mask = (1 << realSize) - 1)
 408+			if type(storage) is tuple:
 409+				reg,storageBit = storage
 410+				reg = prog.resolveParam(reg, None, {})
 411+				output.append('\n\t{reg} = {res} ? ({reg} & {mask}U) : ({reg} | {bit}U);'.format(
 412+					reg = reg, mask = ~(1 << storageBit), res = lastDst, bit = 1 << storageBit
 413+				))
 414+			else:
 415+				reg = prog.resolveParam(storage, None, {})
 416+				output.append('\n\t{reg} = {res} == 0;'.format(
 417+					reg = reg, res = lastDst
 418+				))
 419+		elif calc == 'parity':
 420+			parity = storage
 421+			paritySize = prog.paramSize(prog.lastDst)
 422+			if prog.carryFlowDst:
 423+				parityDst = paritySrc = prog.carryFlowDst
 424+			else:
 425+				paritySrc = lastDst
 426+				decl,name = prog.getTemp(paritySize)
 427+				output.append(decl)
 428+				parityDst = name
 429+		else:
 430+			raise Exception('Unknown flag calc type: ' + calc)
 431+	for reg, myRes in directFlags:
 432+		bits = directFlags[(reg, myRes)]
 433+		resolved = prog.resolveParam(reg, None, {})
 434+		if len(bits) == len(prog.flags.storageToFlags[reg]):
 435+			output.append('\n\t{reg} = {res};'.format(reg = resolved, res = myRes))
 436+		else:
 437+			mask = 0
 438+			for bit in bits:
 439+				mask |= 1 << bit
 440+			output.append('\n\t{reg} = ({reg} & ~{mask}U) | ({res} & {mask}U);'.format(
 441+				reg = resolved, mask = mask, res = myRes
 442+			))
 443+	if prog.carryFlowDst:
 444+		if prog.lastOp.op != 'cmp':
 445+			output.append('\n\t{dst} = {tmpdst};'.format(dst = prog.resolveParam(prog.lastDst, prog.currentScope, {}), tmpdst = prog.carryFlowDst))
 446+		prog.carryFlowDst = None
 447+	if parity:
 448+		if paritySize > 8:
 449+			if paritySize > 16:
 450+				output.append('\n\t{dst} = {src} ^ ({src} >> 16);'.format(dst=parityDst, src=paritySrc))
 451+				paritySrc = parityDst
 452+			output.append('\n\t{dst} = {src} ^ ({src} >> 8);'.format(dst=parityDst, src=paritySrc))
 453+			paritySrc = parityDst
 454+		output.append('\n\t{dst} = ({src} ^ ({src} >> 4)) & 0xF;'.format(dst=parityDst, src=paritySrc))
 455+		if type(parity) is tuple:
 456+			reg,bit = parity
 457+			reg = prog.resolveParam(reg, None, {})
 458+			output.append('\n\t{flag} = ({flag} & ~{mask}U) | ((0x6996 >> {parity}) << {bit} & {mask}U);'.format(
 459+				flag=reg, mask = 1 << bit, bit = bit, parity = parityDst
 460+			))
 461+		else:
 462+			reg = prog.resolveParam(parity, None, {})
 463+			output.append('\n\t{flag} = 0x9669 >> {parity} & 1;'.format(flag=reg, parity=parityDst))
 464+			
 465+	#TODO: combine explicit flags targeting the same storage location
 466+	for flag in explicit:
 467+		location = prog.flags.getStorage(flag)
 468+		if type(location) is tuple:
 469+			reg,bit = location
 470+			reg = prog.resolveReg(reg, None, {})
 471+			value = str(1 << bit)
 472+			if explicit[flag]:
 473+				operator = '|='
 474+			else:
 475+				operator = '&='
 476+				value = '~' + value
 477+			output.append('\n\t{reg} {op} {val};'.format(reg=reg, op=operator, val=value))
 478+		else:
 479+			reg = prog.resolveReg(location, None, {})
 480+			output.append('\n\t{reg} = {val};'.format(reg=reg, val=explicit[flag]))
 481+	return ''.join(output)
 482+	
 483+def _cmpCImpl(prog, params, rawParams, flagUpdates):
 484+	size = prog.paramSize(rawParams[1])
 485+	needsCarry = False
 486+	if flagUpdates:
 487+		for flag in flagUpdates:
 488+			calc = prog.flags.flagCalc[flag]
 489+			if calc == 'carry':
 490+				needsCarry = True
 491+				break
 492+	if needsCarry:
 493+		size *= 2
 494+	tmpvar = 'cmp_tmp{sz}__'.format(sz=size)
 495+	if flagUpdates:
 496+		prog.carryFlowDst = tmpvar
 497+		prog.lastA = params[1]
 498+		prog.lastB = params[0]
 499+		prog.lastBFlow = params[0]
 500+	scope = prog.getRootScope()
 501+	if not scope.resolveLocal(tmpvar):
 502+		scope.addLocal(tmpvar, size)
 503+	prog.lastDst = rawParams[1]
 504+	return '\n\t{var} = {b} - {a};'.format(var = tmpvar, a = params[0], b = params[1])
 505+
 506+def _asrCImpl(prog, params, rawParams, flagUpdates):
 507+	needsCarry = False
 508+	if flagUpdates:
 509+		for flag in flagUpdates:
 510+			calc = prog.flags.flagCalc[flag]
 511+			if calc == 'carry':
 512+				needsCarry = True
 513+	decl = ''
 514+	size = prog.paramSize(rawParams[2])
 515+	if needsCarry:
 516+		decl,name = prog.getTemp(size * 2)
 517+		dst = prog.carryFlowDst = name
 518+		prog.lastA = params[0]
 519+	else:
 520+		dst = params[2]
 521+	mask = 1 << (size - 1)
 522+	return decl + '\n\t{dst} = ({a} >> {b}) | ({a} & {mask} ? 0xFFFFFFFFU << ({size} - {b}) : 0);'.format(
 523+		a = params[0], b = params[1], dst = dst, mask = mask, size=size)
 524+	
 525+def _sext(size, src):
 526+	if size == 16:
 527+		return src | 0xFF00 if src & 0x80 else src
 528+	else:
 529+		return src | 0xFFFF0000 if src & 0x8000 else src
 530+
 531+def _sextCImpl(prog, params, rawParms):
 532+	if params[0] == 16:
 533+		fmt = '\n\t{dst} = {src} & 0x80 ? {src} | 0xFF00 : {src};'
 534+	else:
 535+		fmt = '\n\t{dst} = {src} & 0x8000 ? {src} | 0xFFFF0000 : {src};'
 536+	return fmt.format(src=params[1], dst=params[2])
 537+	
 538+def _getCarryCheck(prog):
 539+	carryFlag = None
 540+	for flag in prog.flags.flagCalc:
 541+		if prog.flags.flagCalc[flag] == 'carry':
 542+			carryFlag = flag
 543+	if carryFlag is None:
 544+		raise Exception('adc requires a defined carry flag')
 545+	carryStorage = prog.flags.getStorage(carryFlag)
 546+	if type(carryStorage) is tuple:
 547+		reg,bit = carryStorage
 548+		reg = prog.resolveReg(reg, None, (), False)
 549+		return '({reg} & 1 << {bit})'.format(reg=reg, bit=bit)
 550+	else:
 551+		return prog.resolveReg(carryStorage, None, (), False)
 552+
 553+def _adcCImpl(prog, params, rawParams, flagUpdates):
 554+	needsCarry = needsOflow = needsHalf = False
 555+	if flagUpdates:
 556+		for flag in flagUpdates:
 557+			calc = prog.flags.flagCalc[flag]
 558+			if calc == 'carry':
 559+				needsCarry = True
 560+			elif calc == 'half-carry':
 561+				needsHalf = True
 562+			elif calc == 'overflow':
 563+				needsOflow = True
 564+	decl = ''
 565+	carryCheck = _getCarryCheck(prog)
 566+	if needsCarry or needsOflow or needsHalf:
 567+		size = prog.paramSize(rawParams[2])
 568+		if needsCarry:
 569+			size *= 2
 570+		decl,name = prog.getTemp(size)
 571+		dst = prog.carryFlowDst = name
 572+		prog.lastA = params[0]
 573+		prog.lastB = params[1]
 574+		prog.lastBFlow = '(~{b})'.format(b=params[1])
 575+	else:
 576+		dst = params[2]
 577+	return decl + '\n\t{dst} = {a} + {b} + ({check} ? 1 : 0);'.format(dst = dst,
 578+		a = params[0], b = params[1], check = carryCheck
 579+	)
 580+
 581+def _sbcCImpl(prog, params, rawParams, flagUpdates):
 582+	needsCarry = needsOflow = needsHalf = False
 583+	if flagUpdates:
 584+		for flag in flagUpdates:
 585+			calc = prog.flags.flagCalc[flag]
 586+			if calc == 'carry':
 587+				needsCarry = True
 588+			elif calc == 'half-carry':
 589+				needsHalf = True
 590+			elif calc == 'overflow':
 591+				needsOflow = True
 592+	decl = ''
 593+	carryCheck = _getCarryCheck(prog)
 594+	if needsCarry or needsOflow or needsHalf:
 595+		size = prog.paramSize(rawParams[2])
 596+		if needsCarry:
 597+			size *= 2
 598+		decl,name = prog.getTemp(size)
 599+		dst = prog.carryFlowDst = name
 600+		prog.lastA = params[1]
 601+		prog.lastB = params[0]
 602+		prog.lastBFlow = params[0]
 603+	else:
 604+		dst = params[2]
 605+	return decl + '\n\t{dst} = {b} - {a} - ({check} ? 1 : 0);'.format(dst = dst,
 606+		a = params[0], b = params[1], check=_getCarryCheck(prog)
 607+	)
 608+	
 609+def _rolCImpl(prog, params, rawParams, flagUpdates):
 610+	needsCarry = False
 611+	if flagUpdates:
 612+		for flag in flagUpdates:
 613+			calc = prog.flags.flagCalc[flag]
 614+			if calc == 'carry':
 615+				needsCarry = True
 616+	decl = ''
 617+	size = prog.paramSize(rawParams[2])
 618+	if needsCarry:
 619+		decl,name = prog.getTemp(size * 2)
 620+		dst = prog.carryFlowDst = name
 621+	else:
 622+		dst = params[2]
 623+	return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} - {b});'.format(dst = dst,
 624+		a = params[0], b = params[1], size=size
 625+	)
 626+	
 627+def _rlcCImpl(prog, params, rawParams, flagUpdates):
 628+	needsCarry = False
 629+	if flagUpdates:
 630+		for flag in flagUpdates:
 631+			calc = prog.flags.flagCalc[flag]
 632+			if calc == 'carry':
 633+				needsCarry = True
 634+	decl = ''
 635+	carryCheck = _getCarryCheck(prog)
 636+	size = prog.paramSize(rawParams[2])
 637+	if needsCarry:
 638+		decl,name = prog.getTemp(size * 2)
 639+		dst = prog.carryFlowDst = name
 640+	else:
 641+		dst = params[2]
 642+	return decl + '\n\t{dst} = {a} << {b} | {a} >> ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({b} - 1);'.format(dst = dst,
 643+		a = params[0], b = params[1], size=size, check=carryCheck
 644+	)
 645+	
 646+def _rorCImpl(prog, params, rawParams, flagUpdates):
 647+	size = prog.paramSize(rawParams[2])
 648+	return '\n\t{dst} = {a} >> {b} | {a} << ({size} - {b});'.format(dst = params[2],
 649+		a = params[0], b = params[1], size=size
 650+	)
 651+
 652+def _rrcCImpl(prog, params, rawParams, flagUpdates):
 653+	needsCarry = False
 654+	if flagUpdates:
 655+		for flag in flagUpdates:
 656+			calc = prog.flags.flagCalc[flag]
 657+			if calc == 'carry':
 658+				needsCarry = True
 659+	decl = ''
 660+	carryCheck = _getCarryCheck(prog)
 661+	size = prog.paramSize(rawParams[2])
 662+	if needsCarry:
 663+		decl,name = prog.getTemp(size * 2)
 664+		dst = prog.carryFlowDst = name
 665+	else:
 666+		dst = params[2]
 667+	return decl + '\n\t{dst} = {a} >> {b} | {a} << ({size} + 1 - {b}) | ({check} ? 1 : 0) << ({size}-{b});'.format(dst = dst,
 668+		a = params[0], b = params[1], size=size, check=carryCheck
 669+	)
 670+	
 671+def _updateSyncCImpl(prog, params):
 672+	return '\n\t{sync}(context, target_cycle);'.format(sync=prog.sync_cycle)
 673+
 674+_opMap = {
 675+	'mov': Op(lambda val: val).cUnaryOperator(''),
 676+	'not': Op(lambda val: ~val).cUnaryOperator('~'),
 677+	'lnot': Op(lambda val: 0 if val else 1).cUnaryOperator('!'),
 678+	'neg': Op(lambda val: -val).cUnaryOperator('-'),
 679+	'add': Op(lambda a, b: a + b).cBinaryOperator('+'),
 680+	'adc': Op().addImplementation('c', 2, _adcCImpl),
 681+	'sub': Op(lambda a, b: b - a).cBinaryOperator('-'),
 682+	'sbc': Op().addImplementation('c', 2, _sbcCImpl),
 683+	'lsl': Op(lambda a, b: a << b).cBinaryOperator('<<'),
 684+	'lsr': Op(lambda a, b: a >> b).cBinaryOperator('>>'),
 685+	'asr': Op(lambda a, b: a >> b).addImplementation('c', 2, _asrCImpl),
 686+	'rol': Op().addImplementation('c', 2, _rolCImpl),
 687+	'rlc': Op().addImplementation('c', 2, _rlcCImpl),
 688+	'ror': Op().addImplementation('c', 2, _rorCImpl),
 689+	'rrc': Op().addImplementation('c', 2, _rrcCImpl),
 690+	'and': Op(lambda a, b: a & b).cBinaryOperator('&'),
 691+	'or':  Op(lambda a, b: a | b).cBinaryOperator('|'),
 692+	'xor': Op(lambda a, b: a ^ b).cBinaryOperator('^'),
 693+	'abs': Op(lambda val: abs(val)).addImplementation(
 694+		'c', 1, lambda prog, params: '\n\t{dst} = abs({src});'.format(dst=params[1], src=params[0])
 695+	),
 696+	'cmp': Op().addImplementation('c', None, _cmpCImpl),
 697+	'sext': Op(_sext).addImplementation('c', 2, _sextCImpl),
 698+	'ocall': Op().addImplementation('c', None, lambda prog, params: '\n\t{pre}{fun}({args});'.format(
 699+		pre = prog.prefix, fun = params[0], args = ', '.join(['context'] + [str(p) for p in params[1:]])
 700+	)),
 701+	'cycles': Op().addImplementation('c', None,
 702+		lambda prog, params: '\n\tcontext->cycles += context->opts->gen.clock_divider * {0};'.format(
 703+			params[0]
 704+		)
 705+	),
 706+	'addsize': Op(
 707+		lambda a, b: b + (2 * a if a else 1)
 708+	).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} + {sz} ? {sz} * 2 : 1;'.format(
 709+		dst = params[2], sz = params[0], val = params[1]
 710+	)),
 711+	'decsize': Op(
 712+		lambda a, b: b - (2 * a if a else 1)
 713+	).addImplementation('c', 2, lambda prog, params: '\n\t{dst} = {val} - {sz} ? {sz} * 2 : 1;'.format(
 714+		dst = params[2], sz = params[0], val = params[1]
 715+	)),
 716+	'xchg': Op().addImplementation('c', (0,1), _xchgCImpl),
 717+	'dispatch': Op().addImplementation('c', None, _dispatchCImpl),
 718+	'update_flags': Op().addImplementation('c', None, _updateFlagsCImpl),
 719+	'update_sync': Op().addImplementation('c', None, _updateSyncCImpl)
 720+}
 721+
 722+#represents a simple DSL instruction
 723+class NormalOp:
 724+	def __init__(self, parts):
 725+		self.op = parts[0]
 726+		self.params = parts[1:]
 727+		
 728+	def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
 729+		procParams = []
 730+		allParamsConst = flagUpdates is None and not prog.conditional
 731+		opDef = _opMap.get(self.op)
 732+		for param in self.params:
 733+			allowConst = (self.op in prog.subroutines or len(procParams) != len(self.params) - 1) and param in parent.regValues
 734+			isDst = (not opDef is None) and len(procParams) in opDef.outOp
 735+			if isDst and self.op == 'xchg':
 736+				#xchg uses its regs as both source and destination
 737+				#we need to resolve as both so that disperse/coalesce flag stuff gets done
 738+				prog.resolveParam(param, parent, fieldVals, allowConst, False)
 739+			param = prog.resolveParam(param, parent, fieldVals, allowConst, isDst)
 740+			
 741+			if (not type(param) is int) and len(procParams) != len(self.params) - 1:
 742+				allParamsConst = False
 743+			procParams.append(param)
 744+			
 745+		if self.op == 'meta':
 746+			param,_,index = self.params[1].partition('.')
 747+			if index:
 748+				index = (parent.resolveLocal(index) or index)
 749+				if index in fieldVals:
 750+					index = str(fieldVals[index])
 751+				param = param + '.' + index
 752+			else:
 753+				param = parent.resolveLocal(param) or param
 754+				if param in fieldVals:
 755+					param = fieldVals[index]
 756+			prog.meta[self.params[0]] = param
 757+		elif self.op == 'dis':
 758+			#TODO: Disassembler
 759+			pass
 760+		elif not opDef is None:
 761+			if opDef.numParams() > len(procParams):
 762+				raise Exception('Insufficient params for ' + self.op + ' (' + ', '.join(self.params) + ')')
 763+			if opDef.canEval() and allParamsConst:
 764+				#do constant folding
 765+				if opDef.numArgs() >= len(procParams):
 766+					raise Exception('Insufficient args for ' + self.op + ' (' + ', '.join(self.params) + ')')
 767+				dst = self.params[opDef.numArgs()]
 768+				result = opDef.evaluate(procParams[:opDef.numArgs()])
 769+				while dst in prog.meta:
 770+					dst = prog.meta[dst]
 771+				maybeLocal = parent.resolveLocal(dst)
 772+				if maybeLocal:
 773+					dst = maybeLocal
 774+				parent.regValues[dst] = result
 775+				if prog.isReg(dst):
 776+					shortProc = (procParams[0], procParams[-1])
 777+					shortParams = (self.params[0], self.params[-1])
 778+					output.append(_opMap['mov'].generate(otype, prog, shortProc, shortParams, None))
 779+			else:
 780+				output.append(opDef.generate(otype, prog, procParams, self.params, flagUpdates))
 781+				for dstIdx in opDef.outOp:
 782+					dst = self.params[dstIdx]
 783+					while dst in prog.meta:
 784+						dst = prog.meta[dst]
 785+					if dst in parent.regValues:
 786+						del parent.regValues[dst]
 787+					
 788+		elif self.op in prog.subroutines:
 789+			procParams = []
 790+			for param in self.params:
 791+				begin,sep,end = param.partition('.')
 792+				if sep:
 793+					if end in fieldVals:
 794+						param = begin + '.' + str(fieldVals[end])
 795+				else:
 796+					if param in fieldVals:
 797+						param = fieldVals[param]
 798+				procParams.append(param)
 799+			prog.subroutines[self.op].inline(prog, procParams, output, otype, parent)
 800+		else:
 801+			output.append('\n\t' + self.op + '(' + ', '.join([str(p) for p in procParams]) + ');')
 802+		prog.lastOp = self
 803+	
 804+	def __str__(self):
 805+		return '\n\t' + self.op + ' ' + ' '.join(self.params)
 806+		
 807+#represents a DSL switch construct
 808+class Switch(ChildBlock):
 809+	def __init__(self, parent, param):
 810+		self.op = 'switch'
 811+		self.parent = parent
 812+		self.param = param
 813+		self.cases = {}
 814+		self.regValues = None
 815+		self.current_locals = {}
 816+		self.case_locals = {}
 817+		self.current_case = None
 818+		self.default = None
 819+		self.default_locals = None
 820+	
 821+	def addOp(self, op):
 822+		if op.op == 'case':
 823+			val = int(op.params[0], 16) if op.params[0].startswith('0x') else int(op.params[0])
 824+			self.cases[val] = self.current_case = []
 825+			self.case_locals[val] = self.current_locals = {}
 826+		elif op.op == 'default':
 827+			self.default = self.current_case = []
 828+			self.default_locals = self.current_locals = {}
 829+		elif self.current_case == None:
 830+			raise ion('Orphan instruction in switch')
 831+		elif op.op == 'local':
 832+			name = op.params[0]
 833+			size = op.params[1]
 834+			self.current_locals[name] = size
 835+		else:
 836+			self.current_case.append(op)
 837+			
 838+	def resolveLocal(self, name):
 839+		if name in self.current_locals:
 840+			return name
 841+		return self.parent.resolveLocal(name)
 842+	
 843+	def addLocal(self, name, size):
 844+		self.current_locals[name] = size
 845+		
 846+	def localSize(self, name):
 847+		if name in self.current_locals:
 848+			return self.current_locals[name]
 849+		return self.parent.localSize(name)
 850+			
 851+	def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
 852+		prog.pushScope(self)
 853+		param = prog.resolveParam(self.param, parent, fieldVals)
 854+		if type(param) is int:
 855+			self.regValues = self.parent.regValues
 856+			if param in self.cases:
 857+				self.current_locals = self.case_locals[param]
 858+				output.append('\n\t{')
 859+				for local in self.case_locals[param]:
 860+					output.append('\n\tuint{0}_t {1};'.format(self.case_locals[param][local], local))
 861+				self.processOps(prog, fieldVals, output, otype, self.cases[param])
 862+				output.append('\n\t}')
 863+			elif self.default:
 864+				self.current_locals = self.default_locals
 865+				output.append('\n\t{')
 866+				for local in self.default_locals:
 867+					output.append('\n\tuint{0}_t {1};'.format(self.default[local], local))
 868+				self.processOps(prog, fieldVals, output, otype, self.default)
 869+				output.append('\n\t}')
 870+		else:
 871+			oldCond = prog.conditional
 872+			prog.conditional = True
 873+			output.append('\n\tswitch(' + param + ')')
 874+			output.append('\n\t{')
 875+			for case in self.cases:
 876+				temp = prog.temp.copy()
 877+				self.current_locals = self.case_locals[case]
 878+				self.regValues = dict(self.parent.regValues)
 879+				output.append('\n\tcase {0}U: '.format(case) + '{')
 880+				for local in self.case_locals[case]:
 881+					output.append('\n\tuint{0}_t {1};'.format(self.case_locals[case][local], local))
 882+				self.processOps(prog, fieldVals, output, otype, self.cases[case])
 883+				output.append('\n\tbreak;')
 884+				output.append('\n\t}')
 885+				prog.temp = temp
 886+			if self.default:
 887+				temp = prog.temp.copy()
 888+				self.current_locals = self.default_locals
 889+				self.regValues = dict(self.parent.regValues)
 890+				output.append('\n\tdefault: {')
 891+				for local in self.default_locals:
 892+					output.append('\n\tuint{0}_t {1};'.format(self.default_locals[local], local))
 893+				self.processOps(prog, fieldVals, output, otype, self.default)
 894+				prog.temp = temp
 895+			output.append('\n\t}')
 896+			prog.conditional = oldCond
 897+		prog.popScope()
 898+	
 899+	def __str__(self):
 900+		keys = self.cases.keys()
 901+		keys.sort()
 902+		lines = ['\n\tswitch']
 903+		for case in keys:
 904+			lines.append('\n\tcase {0}'.format(case))
 905+			lines.append(''.join([str(op) for op in self.cases[case]]))
 906+		lines.append('\n\tend')
 907+		return ''.join(lines)
 908+
 909+		
 910+def _geuCImpl(prog, parent, fieldVals, output):
 911+	if prog.lastOp.op == 'cmp':
 912+		output.pop()
 913+		params = [prog.resolveParam(p, parent, fieldVals) for p in prog.lastOp.params]
 914+		return '\n\tif ({a} >= {b}) '.format(a=params[1], b = params[0]) + '{'
 915+	else:
 916+		raise Exception(">=U not implemented in the general case yet")
 917+
 918+def _eqCImpl(prog, parent, fieldVals, output):
 919+	return '\n\tif (!{a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
 920+
 921+def _neqCImpl(prog, parent, fieldVals, output):
 922+	return '\n\tif ({a}) {'.format(a=prog.resolveParam(prog.lastDst, None, {}))
 923+	
 924+_ifCmpImpl = {
 925+	'c': {
 926+		'>=U': _geuCImpl,
 927+		'=': _eqCImpl,
 928+		'!=': _neqCImpl
 929+	}
 930+}
 931+#represents a DSL conditional construct
 932+class If(ChildBlock):
 933+	def __init__(self, parent, cond):
 934+		self.op = 'if'
 935+		self.parent = parent
 936+		self.cond = cond
 937+		self.body = []
 938+		self.elseBody = []
 939+		self.curBody = self.body
 940+		self.locals = {}
 941+		self.elseLocals = {}
 942+		self.curLocals = self.locals
 943+		self.regValues = None
 944+		
 945+	def addOp(self, op):
 946+		if op.op in ('case', 'arg'):
 947+			raise Exception(self.op + ' is not allows inside an if block')
 948+		if op.op == 'local':
 949+			name = op.params[0]
 950+			size = op.params[1]
 951+			self.curLocals[name] = size
 952+		elif op.op == 'else':
 953+			self.curLocals = self.elseLocals
 954+			self.curBody = self.elseBody
 955+		else:
 956+			self.curBody.append(op)
 957+			
 958+	def localSize(self, name):
 959+		return self.curLocals.get(name)
 960+		
 961+	def resolveLocal(self, name):
 962+		if name in self.curLocals:
 963+			return name
 964+		return self.parent.resolveLocal(name)
 965+		
 966+	def _genTrueBody(self, prog, fieldVals, output, otype):
 967+		self.curLocals = self.locals
 968+		subOut = []
 969+		self.processOps(prog, fieldVals, subOut, otype, self.body)
 970+		for local in self.locals:
 971+			output.append('\n\tuint{sz}_t {nm};'.format(sz=self.locals[local], nm=local))
 972+		output += subOut
 973+			
 974+	def _genFalseBody(self, prog, fieldVals, output, otype):
 975+		self.curLocals = self.elseLocals
 976+		subOut = []
 977+		self.processOps(prog, fieldVals, subOut, otype, self.elseBody)
 978+		for local in self.elseLocals:
 979+			output.append('\n\tuint{sz}_t {nm};'.format(sz=self.elseLocals[local], nm=local))
 980+		output += subOut
 981+	
 982+	def _genConstParam(self, param, prog, fieldVals, output, otype):
 983+		if param:
 984+			self._genTrueBody(prog, fieldVals, output, otype)
 985+		else:
 986+			self._genFalseBody(prog, fieldVals, output, otype)
 987+			
 988+	def generate(self, prog, parent, fieldVals, output, otype, flagUpdates):
 989+		self.regValues = parent.regValues
 990+		try:
 991+			self._genConstParam(prog.checkBool(self.cond), prog, fieldVals, output, otype)
 992+		except Exception:
 993+			if self.cond in _ifCmpImpl[otype]:
 994+				oldCond = prog.conditional
 995+				prog.conditional = True
 996+				temp = prog.temp.copy()
 997+				output.append(_ifCmpImpl[otype][self.cond](prog, parent, fieldVals, output))
 998+				self._genTrueBody(prog, fieldVals, output, otype)
 999+				prog.temp = temp
1000+				if self.elseBody:
1001+					temp = prog.temp.copy()
1002+					output.append('\n\t} else {')
1003+					self._genFalseBody(prog, fieldVals, output, otype)
1004+					prog.temp = temp
1005+				output.append('\n\t}')
1006+				prog.conditional = oldCond
1007+			else:
1008+				cond = prog.resolveParam(self.cond, parent, fieldVals)
1009+				if type(cond) is int:
1010+					self._genConstParam(cond, prog, fieldVals, output, otype)
1011+				else:
1012+					temp = prog.temp.copy()
1013+					output.append('\n\tif ({cond}) '.format(cond=cond) + '{')
1014+					oldCond = prog.conditional
1015+					prog.conditional = True
1016+					self._genTrueBody(prog, fieldVals, output, otype)
1017+					prog.temp = temp
1018+					if self.elseBody:
1019+						temp = prog.temp.copy()
1020+						output.append('\n\t} else {')
1021+						self._genFalseBody(prog, fieldVals, output, otype)
1022+						prog.temp = temp
1023+					output.append('\n\t}')
1024+					prog.conditional = oldCond
1025+						
1026+	
1027+	def __str__(self):
1028+		lines = ['\n\tif']
1029+		for op in self.body:
1030+			lines.append(str(op))
1031+		lines.append('\n\tend')
1032+		return ''.join(lines)
1033+
1034+class Registers:
1035+	def __init__(self):
1036+		self.regs = {}
1037+		self.pointers = {}
1038+		self.regArrays = {}
1039+		self.regToArray = {}
1040+		self.addReg('cycles', 32)
1041+		self.addReg('sync_cycle', 32)
1042+	
1043+	def addReg(self, name, size):
1044+		self.regs[name] = size
1045+		
1046+	def addPointer(self, name, size, count):
1047+		self.pointers[name] = (size, count)
1048+	
1049+	def addRegArray(self, name, size, regs):
1050+		self.regArrays[name] = (size, regs)
1051+		idx = 0
1052+		if not type(regs) is int:
1053+			for reg in regs:
1054+				self.regs[reg] = size
1055+				self.regToArray[reg] = (name, idx)
1056+				idx += 1
1057+	
1058+	def isReg(self, name):
1059+		return name in self.regs
1060+	
1061+	def isRegArray(self, name):
1062+		return name in self.regArrays
1063+		
1064+	def isRegArrayMember(self, name):
1065+		return name in self.regToArray
1066+		
1067+	def arrayMemberParent(self, name):
1068+		return self.regToArray[name][0]
1069+	
1070+	def arrayMemberIndex(self, name):
1071+		return self.regToArray[name][1]
1072+	
1073+	def arrayMemberName(self, array, index):
1074+		if type(index) is int and not type(self.regArrays[array][1]) is int:
1075+			return self.regArrays[array][1][index]
1076+		else:
1077+			return None
1078+			
1079+	def isNamedArray(self, array):
1080+		return array in self.regArrays and type(self.regArrays[array][1]) is int
1081+	
1082+	def processLine(self, parts):
1083+		if len(parts) == 3:
1084+			if parts[1].startswith('ptr'):
1085+				self.addPointer(parts[0], parts[1][3:], int(parts[2]))
1086+			else:
1087+				self.addRegArray(parts[0], int(parts[1]), int(parts[2]))
1088+		elif len(parts) > 2:
1089+			self.addRegArray(parts[0], int(parts[1]), parts[2:])
1090+		else:
1091+			if parts[1].startswith('ptr'):
1092+				self.addPointer(parts[0], parts[1][3:], 1)
1093+			else:
1094+				self.addReg(parts[0], int(parts[1]))
1095+		return self
1096+
1097+	def writeHeader(self, otype, hFile):
1098+		fieldList = []
1099+		for pointer in self.pointers:
1100+			stars = '*'
1101+			ptype, count = self.pointers[pointer]
1102+			while ptype.startswith('ptr'):
1103+				stars += '*'
1104+				ptype = ptype[3:]
1105+			if ptype.isdigit():
1106+				ptype = 'uint{sz}_t'.format(sz=ptype)
1107+			if count > 1:
1108+				arr = '[{n}]'.format(n=count)
1109+			else:
1110+				arr = ''
1111+			hFile.write('\n\t{ptype} {stars}{nm}{arr};'.format(nm=pointer, ptype=ptype, stars=stars, arr=arr))
1112+		for reg in self.regs:
1113+			if not self.isRegArrayMember(reg):
1114+				fieldList.append((self.regs[reg], 1, reg))
1115+		for arr in self.regArrays:
1116+			size,regs = self.regArrays[arr]
1117+			if not type(regs) is int:
1118+				regs = len(regs)
1119+			fieldList.append((size, regs, arr))
1120+		fieldList.sort()
1121+		fieldList.reverse()
1122+		for size, count, name in fieldList:
1123+			if count > 1:
1124+				hFile.write('\n\tuint{sz}_t {nm}[{ct}];'.format(sz=size, nm=name, ct=count))
1125+			else:
1126+				hFile.write('\n\tuint{sz}_t {nm};'.format(sz=size, nm=name))
1127+	
1128+class Flags:
1129+	def __init__(self):
1130+		self.flagBits = {}
1131+		self.flagCalc = {}
1132+		self.flagStorage = {}
1133+		self.flagReg = None
1134+		self.storageToFlags = {}
1135+		self.maxBit = -1
1136+	
1137+	def processLine(self, parts):
1138+		if parts[0] == 'register':
1139+			self.flagReg = parts[1]
1140+		else:
1141+			flag,bit,calc,storage = parts
1142+			bit,_,top = bit.partition('-')
1143+			bit = int(bit)
1144+			if top:
1145+				top = int(bit)
1146+				if top > self.maxBit:
1147+					self.maxBit = top
1148+				self.flagBits[flag] = (bit,top)
1149+			else:
1150+				if bit > self.maxBit:
1151+					self.maxBit = bit
1152+				self.flagBits[flag] = bit
1153+			self.flagCalc[flag] = calc
1154+			self.flagStorage[flag] = storage
1155+			storage,_,storebit = storage.partition('.')
1156+			self.storageToFlags.setdefault(storage, []).append((storebit, flag))
1157+		return self
1158+	
1159+	def getStorage(self, flag):
1160+		if not flag in self.flagStorage:
1161+			raise Exception('Undefined flag ' + flag)
1162+		loc,_,bit = self.flagStorage[flag].partition('.')
1163+		if bit:
1164+			return (loc, int(bit))
1165+		else:
1166+			return loc 
1167+	
1168+	def parseFlagUpdate(self, flagString):
1169+		last = ''
1170+		autoUpdate = set()
1171+		explicit = {}
1172+		for c in flagString:
1173+			if c.isdigit():
1174+				if last.isalpha():
1175+					num = int(c)
1176+					if num > 1:
1177+						raise Exception(c + ' is not a valid digit for update_flags')
1178+					explicit[last] = num
1179+					last = c
1180+				else:
1181+					raise Exception('Digit must follow flag letter in update_flags')
1182+			else:
1183+				if last.isalpha():
1184+					autoUpdate.add(last)
1185+				last = c
1186+		if last.isalpha():
1187+			autoUpdate.add(last)
1188+		return (autoUpdate, explicit)
1189+	
1190+	def disperseFlags(self, prog, otype):
1191+		bitToFlag = [None] * (self.maxBit+1)
1192+		src = prog.resolveReg(self.flagReg, None, {})
1193+		output = []
1194+		for flag in self.flagBits:
1195+			bit = self.flagBits[flag]
1196+			if type(bit) is tuple:
1197+				bot,top = bit
1198+				mask = ((1 << (top + 1 - bot)) - 1) << bot
1199+				output.append('\n\t{dst} = {src} & mask;'.format(
1200+					dst=prog.resolveReg(self.flagStorage[flag], None, {}), src=src, mask=mask
1201+				))
1202+			else:
1203+				bitToFlag[self.flagBits[flag]] = flag		
1204+		multi = {}
1205+		for bit in range(len(bitToFlag)-1,-1,-1):
1206+			flag = bitToFlag[bit]
1207+			if not flag is None:
1208+				field,_,dstbit = self.flagStorage[flag].partition('.')
1209+				dst = prog.resolveReg(field, None, {})
1210+				if dstbit:
1211+					dstbit = int(dstbit)
1212+					multi.setdefault(dst, []).append((dstbit, bit))
1213+				else:
1214+					output.append('\n\t{dst} = {src} & {mask};'.format(dst=dst, src=src, mask=(1 << bit)))
1215+		for dst in multi:
1216+			didClear = False
1217+			direct = []
1218+			for dstbit, bit in multi[dst]:
1219+				if dstbit == bit:
1220+					direct.append(bit)
1221+				else:
1222+					if not didClear:
1223+						output.append('\n\t{dst} = 0;'.format(dst=dst))
1224+						didClear = True
1225+					if dstbit > bit:
1226+						shift = '<<'
1227+						diff = dstbit - bit
1228+					else:
1229+						shift = '>>'
1230+						diff = bit - dstbit
1231+					output.append('\n\t{dst} |= {src} {shift} {diff} & {mask};'.format(
1232+						src=src, dst=dst, shift=shift, diff=diff, mask=(1 << dstbit)
1233+					))
1234+			if direct:
1235+				if len(direct) == len(multi[dst]):
1236+					output.append('\n\t{dst} = {src};'.format(dst=dst, src=src))
1237+				else:
1238+					mask = 0
1239+					for bit in direct:
1240+						mask = mask | (1 << bit)
1241+					output.append('\n\t{dst} = {src} & {mask};'.format(dst=dst, src=src, mask=mask))
1242+		return ''.join(output)
1243+	
1244+	def coalesceFlags(self, prog, otype):
1245+		dst = prog.resolveReg(self.flagReg, None, {})
1246+		output = ['\n\t{dst} = 0;'.format(dst=dst)]
1247+		bitToFlag = [None] * (self.maxBit+1)
1248+		for flag in self.flagBits:
1249+			bit = self.flagBits[flag]
1250+			if type(bit) is tuple:
1251+				bot,_ = bit
1252+				src = prog.resolveReg(self.flagStorage[flag], None, {})
1253+				if bot:
1254+					output.append('\n\t{dst} |= {src} << {shift};'.format(
1255+						dst=dst, src = src, shift = bot
1256+					))
1257+				else:
1258+					output.append('\n\t{dst} |= {src};'.format(
1259+						dst=dst, src = src
1260+					))
1261+			else:
1262+				bitToFlag[bit] = flag
1263+		multi = {}
1264+		for bit in range(len(bitToFlag)-1,-1,-1):
1265+			flag = bitToFlag[bit]
1266+			if not flag is None:
1267+				field,_,srcbit = self.flagStorage[flag].partition('.')
1268+				src = prog.resolveReg(field, None, {})
1269+				if srcbit:
1270+					srcbit = int(srcbit)
1271+					multi.setdefault(src, []).append((srcbit,bit))
1272+				else:
1273+					output.append('\n\tif ({src}) {{\n\t\t{dst} |= 1 << {bit};\n\t}}'.format(
1274+						dst=dst, src=src, bit=bit
1275+					))
1276+		for src in multi:
1277+			direct = 0
1278+			for srcbit, dstbit in multi[src]:
1279+				if srcbit == dstbit:
1280+					direct = direct | (1 << srcbit)
1281+				else:
1282+					output.append('\n\tif ({src} & (1 << {srcbit})) {{\n\t\t{dst} |= 1 << {dstbit};\n\t}}'.format(
1283+						src=src, dst=dst, srcbit=srcbit, dstbit=dstbit
1284+					))
1285+			if direct:
1286+				output.append('\n\t{dst} |= {src} & {mask};'.format(
1287+					dst=dst, src=src, mask=direct
1288+				))
1289+		return ''.join(output)
1290+		
1291+		
1292+class Program:
1293+	def __init__(self, regs, instructions, subs, info, flags):
1294+		self.regs = regs
1295+		self.instructions = instructions
1296+		self.subroutines = subs
1297+		self.meta = {}
1298+		self.booleans = {}
1299+		self.prefix = info.get('prefix', [''])[0]
1300+		self.opsize = int(info.get('opcode_size', ['8'])[0])
1301+		self.extra_tables = info.get('extra_tables', [])
1302+		self.context_type = self.prefix + 'context'
1303+		self.body = info.get('body', [None])[0]
1304+		self.interrupt = info.get('interrupt', [None])[0]
1305+		self.sync_cycle = info.get('sync_cycle', [None])[0]
1306+		self.includes = info.get('include', [])
1307+		self.flags = flags
1308+		self.lastDst = None
1309+		self.scopes = []
1310+		self.currentScope = None
1311+		self.lastOp = None
1312+		self.carryFlowDst = None
1313+		self.lastA = None
1314+		self.lastB = None
1315+		self.lastBFlow = None
1316+		self.conditional = False
1317+		self.declares = []
1318+		
1319+	def __str__(self):
1320+		pieces = []
1321+		for reg in self.regs:
1322+			pieces.append(str(self.regs[reg]))
1323+		for name in self.subroutines:
1324+			pieces.append('\n'+str(self.subroutines[name]))
1325+		for instruction in self.instructions:
1326+			pieces.append('\n'+str(instruction))
1327+		return ''.join(pieces)
1328+		
1329+	def writeHeader(self, otype, header):
1330+		hFile = open(header, 'w')
1331+		macro = header.upper().replace('.', '_')
1332+		hFile.write('#ifndef {0}_'.format(macro))
1333+		hFile.write('\n#define {0}_'.format(macro))
1334+		hFile.write('\n#include "backend.h"')
1335+		hFile.write('\n\ntypedef struct {')
1336+		hFile.write('\n\tcpu_options gen;')
1337+		hFile.write('\n}} {0}options;'.format(self.prefix))
1338+		hFile.write('\n\ntypedef struct {')
1339+		hFile.write('\n\t{0}options *opts;'.format(self.prefix))
1340+		self.regs.writeHeader(otype, hFile)
1341+		hFile.write('\n}} {0}context;'.format(self.prefix))
1342+		hFile.write('\n')
1343+		hFile.write('\nvoid {pre}execute({type} *context, uint32_t target_cycle);'.format(pre = self.prefix, type = self.context_type))
1344+		for decl in self.declares:
1345+			hFile.write('\n' + decl)
1346+		hFile.write('\n#endif //{0}_'.format(macro))
1347+		hFile.write('\n')
1348+		hFile.close()
1349+		
1350+	def _buildTable(self, otype, table, body, lateBody):
1351+		pieces = []
1352+		opmap = [None] * (1 << self.opsize)
1353+		bodymap = {}
1354+		if table in self.instructions:
1355+			instructions = self.instructions[table]
1356+			instructions.sort()
1357+			for inst in instructions:
1358+				for val in inst.allValues():
1359+					if opmap[val] is None:
1360+						self.meta = {}
1361+						self.temp = {}
1362+						self.needFlagCoalesce = False
1363+						self.needFlagDisperse = False
1364+						self.lastOp = None
1365+						opmap[val] = inst.generateName(val)
1366+						bodymap[val] = inst.generateBody(val, self, otype)
1367+		
1368+		if self.dispatch == 'call':
1369+			pieces.append('\nstatic impl_fun impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
1370+			for inst in range(0, len(opmap)):
1371+				op = opmap[inst]
1372+				if op is None:
1373+					pieces.append('\n\tunimplemented,')
1374+				else:
1375+					pieces.append('\n\t' + op + ',')
1376+					body.append(bodymap[inst])
1377+			pieces.append('\n};')
1378+		elif self.dispatch == 'goto':
1379+			body.append('\n\tstatic void *impl_{name}[{sz}] = {{'.format(name = table, sz=len(opmap)))
1380+			for inst in range(0, len(opmap)):
1381+				op = opmap[inst]
1382+				if op is None:
1383+					body.append('\n\t\t&&unimplemented,')
1384+				else:
1385+					body.append('\n\t\t&&' + op + ',')
1386+					lateBody.append(bodymap[inst])
1387+			body.append('\n\t};')
1388+		else:
1389+			raise Exception("unimplmeneted dispatch type " + self.dispatch)
1390+		body.extend(pieces)
1391+		
1392+	def nextInstruction(self, otype):
1393+		output = []
1394+		if self.dispatch == 'goto':
1395+			if self.interrupt in self.subroutines:
1396+				output.append('\n\tif (context->cycles >= context->sync_cycle) {')
1397+			output.append('\n\tif (context->cycles >= target_cycle) { return; }')
1398+			if self.interrupt in self.subroutines:
1399+				self.meta = {}
1400+				self.temp = {}
1401+				self.subroutines[self.interrupt].inline(self, [], output, otype, None)
1402+				output.append('\n\t}')
1403+			
1404+			self.meta = {}
1405+			self.temp = {}
1406+			self.subroutines[self.body].inline(self, [], output, otype, None)
1407+		return output
1408+	
1409+	def build(self, otype):
1410+		body = []
1411+		pieces = []
1412+		for include in self.includes:
1413+			body.append('#include "{0}"\n'.format(include))
1414+		if self.dispatch == 'call':
1415+			body.append('\nstatic void unimplemented({pre}context *context)'.format(pre = self.prefix))
1416+			body.append('\n{')
1417+			body.append('\n\tfatal_error("Unimplemented instruction\\n");')
1418+			body.append('\n}\n')
1419+			body.append('\ntypedef void (*impl_fun)({pre}context *context);'.format(pre=self.prefix))
1420+			for table in self.extra_tables:
1421+				body.append('\nstatic impl_fun impl_{name}[{sz}];'.format(name = table, sz=(1 << self.opsize)))
1422+			body.append('\nstatic impl_fun impl_main[{sz}];'.format(sz=(1 << self.opsize)))
1423+		elif self.dispatch == 'goto':
1424+			body.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
1425+			body.append('\n{')
1426+			
1427+		for table in self.extra_tables:
1428+			self._buildTable(otype, table, body, pieces)
1429+		self._buildTable(otype, 'main', body, pieces)
1430+		if self.dispatch == 'call' and self.body in self.subroutines:
1431+			pieces.append('\nvoid {pre}execute({type} *context, uint32_t target_cycle)'.format(pre = self.prefix, type = self.context_type))
1432+			pieces.append('\n{')
1433+			pieces.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
1434+			pieces.append('\n\twhile (context->cycles < target_cycle)')
1435+			pieces.append('\n\t{')
1436+			#TODO: Handle interrupts in call dispatch mode
1437+			self.meta = {}
1438+			self.temp = {}
1439+			self.subroutines[self.body].inline(self, [], pieces, otype, None)
1440+			pieces.append('\n\t}')
1441+			pieces.append('\n}')
1442+		elif self.dispatch == 'goto':
1443+			body.append('\n\t{sync}(context, target_cycle);'.format(sync=self.sync_cycle))
1444+			body += self.nextInstruction(otype)
1445+			pieces.append('\nunimplemented:')
1446+			pieces.append('\n\tfatal_error("Unimplemented instruction\\n");')
1447+			pieces.append('\n}')
1448+		return ''.join(body) +  ''.join(pieces)
1449+		
1450+	def checkBool(self, name):
1451+		if not name in self.booleans:
1452+			raise Exception(name + ' is not a defined boolean flag')
1453+		return self.booleans[name]
1454+	
1455+	def getTemp(self, size):
1456+		if size in self.temp:
1457+			return ('', self.temp[size])
1458+		self.temp[size] = 'gen_tmp{sz}__'.format(sz=size);
1459+		return ('\n\tuint{sz}_t gen_tmp{sz}__;'.format(sz=size), self.temp[size])
1460+		
1461+	def resolveParam(self, param, parent, fieldVals, allowConstant=True, isdst=False):
1462+		keepGoing = True
1463+		while keepGoing:
1464+			keepGoing = False
1465+			try:
1466+				if type(param) is int:
1467+					pass
1468+				elif param.startswith('0x'):
1469+					param = int(param, 16)
1470+				else:
1471+					param = int(param)
1472+			except ValueError:
1473+				
1474+				if parent:
1475+					if param in parent.regValues and allowConstant:
1476+						return parent.regValues[param]
1477+					maybeLocal = parent.resolveLocal(param)
1478+					if maybeLocal:
1479+						if isdst:
1480+							self.lastDst = param
1481+						return maybeLocal
1482+				if param in fieldVals:
1483+					param = fieldVals[param]
1484+					fieldVals = {}
1485+					keepGoing = True
1486+				elif param in self.meta:
1487+					param = self.meta[param]
1488+					keepGoing = True
1489+				elif self.isReg(param):
1490+					return self.resolveReg(param, parent, fieldVals, isdst)
1491+		if isdst:
1492+			self.lastDst = param
1493+		return param
1494+	
1495+	def isReg(self, name):
1496+		if not type(name) is str:
1497+			return False
1498+		begin,sep,_ = name.partition('.')
1499+		if sep:
1500+			if begin in self.meta:
1501+				begin = self.meta[begin]
1502+			return self.regs.isRegArray(begin)
1503+		else:
1504+			return self.regs.isReg(name)
1505+	
1506+	def resolveReg(self, name, parent, fieldVals, isDst=False):
1507+		begin,sep,end = name.partition('.')
1508+		if sep:
1509+			if begin in self.meta:
1510+				begin = self.meta[begin]
1511+			if not self.regs.isRegArrayMember(end):
1512+				end = self.resolveParam(end, parent, fieldVals)
1513+			if not type(end) is int and self.regs.isRegArrayMember(end):
1514+				arrayName = self.regs.arrayMemberParent(end)
1515+				end = self.regs.arrayMemberIndex(end)
1516+				if arrayName != begin:
1517+					end = 'context->{0}[{1}]'.format(arrayName, end)
1518+			if self.regs.isNamedArray(begin):
1519+				regName = self.regs.arrayMemberName(begin, end)
1520+			else:
1521+				regName = '{0}.{1}'.format(begin, end)
1522+			ret = 'context->{0}[{1}]'.format(begin, end)
1523+		else:
1524+			regName = name
1525+			if self.regs.isRegArrayMember(name):
1526+				arr,idx = self.regs.regToArray[name]
1527+				ret = 'context->{0}[{1}]'.format(arr, idx)
1528+			else:
1529+				ret = 'context->' + name
1530+		if regName == self.flags.flagReg:
1531+			if isDst:
1532+				self.needFlagDisperse = True
1533+			else:
1534+				self.needFlagCoalesce = True
1535+		if isDst:
1536+			self.lastDst = regName
1537+		return ret
1538+		
1539+	
1540+	
1541+	def paramSize(self, name):
1542+		if name in self.meta:
1543+			return self.paramSize(self.meta[name])
1544+		for i in range(len(self.scopes) -1, -1, -1):
1545+			size = self.scopes[i].localSize(name)
1546+			if size:
1547+				return size
1548+		begin,sep,_ = name.partition('.')
1549+		if sep and self.regs.isRegArray(begin):
1550+			return self.regs.regArrays[begin][0]
1551+		if self.regs.isReg(name):
1552+			return self.regs.regs[name]
1553+		return 32
1554+	
1555+	def pushScope(self, scope):
1556+		self.scopes.append(scope)
1557+		self.currentScope = scope
1558+		
1559+	def popScope(self):
1560+		ret = self.scopes.pop()
1561+		self.currentScope = self.scopes[-1] if self.scopes else None
1562+		return ret
1563+		
1564+	def getRootScope(self):
1565+		return self.scopes[0]
1566+
1567+def parse(args):
1568+	f = args.source
1569+	instructions = {}
1570+	subroutines = {}
1571+	registers = None
1572+	flags = None
1573+	declares = []
1574+	errors = []
1575+	info = {}
1576+	line_num = 0
1577+	cur_object = None
1578+	for line in f:
1579+		line_num += 1
1580+		line,_,comment = line.partition('#')
1581+		if not line.strip():
1582+			continue
1583+		if line[0].isspace():
1584+			if not cur_object is None:
1585+				sep = True
1586+				parts = []
1587+				while sep:
1588+					before,sep,after = line.partition('"')
1589+					before = before.strip()
1590+					if before:
1591+						parts += [el.strip() for el in before.split(' ')]
1592+					if sep:
1593+						#TODO: deal with escaped quotes
1594+						inside,sep,after = after.partition('"')
1595+						parts.append('"' + inside + '"')
1596+					line = after
1597+				if type(cur_object) is dict:
1598+					cur_object[parts[0]] = parts[1:]
1599+				elif type(cur_object) is list:
1600+					cur_object.append(' '.join(parts))
1601+				else:
1602+					cur_object = cur_object.processLine(parts)
1603+				
1604+#				if type(cur_object) is Registers:
1605+#					if len(parts) > 2:
1606+#						cur_object.addRegArray(parts[0], int(parts[1]), parts[2:])
1607+#					else:
1608+#						cur_object.addReg(parts[0], int(parts[1]))
1609+#				elif type(cur_object) is dict:
1610+#					cur_object[parts[0]] = parts[1:]
1611+#				elif parts[0] == 'switch':
1612+#					o = Switch(cur_object, parts[1])
1613+#					cur_object.addOp(o)
1614+#					cur_object = o
1615+#				elif parts[0] == 'if':
1616+#					o = If(cur_object, parts[1])
1617+#					cur_object.addOp(o)
1618+#					cur_object = o
1619+#				elif parts[0] == 'end':
1620+#					cur_object = cur_object.parent
1621+#				else:
1622+#					cur_object.addOp(NormalOp(parts))
1623+			else:
1624+				errors.append("Orphan instruction on line {0}".format(line_num))
1625+		else:
1626+			parts = line.split(' ')
1627+			if len(parts) > 1:
1628+				if len(parts) > 2:
1629+					table,bitpattern,name = parts
1630+				else:
1631+					bitpattern,name = parts
1632+					table = 'main'
1633+				value = 0
1634+				fields = {}
1635+				curbit = len(bitpattern) - 1
1636+				for char in bitpattern:
1637+					value <<= 1
1638+					if char in ('0', '1'):
1639+						value |= int(char)
1640+					else:
1641+						if char in fields:
1642+							fields[char] = (curbit, fields[char][1] + 1)
1643+						else:
1644+							fields[char] = (curbit, 1)
1645+					curbit -= 1
1646+				cur_object = Instruction(value, fields, name.strip())
1647+				instructions.setdefault(table, []).append(cur_object)
1648+			elif line.strip() == 'regs':
1649+				if registers is None:
1650+					registers = Registers()
1651+				cur_object = registers
1652+			elif line.strip() == 'info':
1653+				cur_object = info
1654+			elif line.strip() == 'flags':
1655+				if flags is None:
1656+					flags = Flags()
1657+				cur_object = flags
1658+			elif line.strip() == 'declare':
1659+				cur_object = declares
1660+			else:
1661+				cur_object = SubRoutine(line.strip())
1662+				subroutines[cur_object.name] = cur_object
1663+	if errors:
1664+		print(errors)
1665+	else:
1666+		p = Program(registers, instructions, subroutines, info, flags)
1667+		p.dispatch = args.dispatch
1668+		p.declares = declares
1669+		p.booleans['dynarec'] = False
1670+		p.booleans['interp'] = True
1671+		if args.define:
1672+			for define in args.define:
1673+				name,sep,val = define.partition('=')
1674+				name = name.strip()
1675+				val = val.strip()
1676+				if sep:
1677+					p.booleans[name] = bool(val)
1678+				else:
1679+					p.booleans[name] = True
1680+		
1681+		if 'header' in info:
1682+			print('#include "{0}"'.format(info['header'][0]))
1683+			p.writeHeader('c', info['header'][0])
1684+		print('#include "util.h"')
1685+		print('#include <stdlib.h>')
1686+		print(p.build('c'))
1687+
1688+def main(argv):
1689+	from argparse import ArgumentParser, FileType
1690+	argParser = ArgumentParser(description='CPU emulator DSL compiler')
1691+	argParser.add_argument('source', type=FileType('r'))
1692+	argParser.add_argument('-D', '--define', action='append')
1693+	argParser.add_argument('-d', '--dispatch', choices=('call', 'switch', 'goto'), default='call')
1694+	parse(argParser.parse_args(argv[1:]))
1695+
1696+if __name__ == '__main__':
1697+	from sys import argv
1698+	main(argv)
+1, -0
1@@ -0,0 +1 @@
2+cursor.png,16,0,raw,nopal,interlace,sprite
+0, -0
+1037, -0
   1@@ -0,0 +1,1037 @@
   2+#include "debug.h"
   3+#include "genesis.h"
   4+#include "68kinst.h"
   5+#include <stdlib.h>
   6+#include <string.h>
   7+#include <sys/select.h>
   8+#include "render.h"
   9+#include "util.h"
  10+#include "terminal.h"
  11+#include "z80inst.h"
  12+
  13+#define Z80_OPTS options
  14+
  15+static bp_def * breakpoints = NULL;
  16+static bp_def * zbreakpoints = NULL;
  17+static uint32_t bp_index = 0;
  18+static uint32_t zbp_index = 0;
  19+
  20+bp_def ** find_breakpoint(bp_def ** cur, uint32_t address)
  21+{
  22+	while (*cur) {
  23+		if ((*cur)->address == address) {
  24+			break;
  25+		}
  26+		cur = &((*cur)->next);
  27+	}
  28+	return cur;
  29+}
  30+
  31+bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index)
  32+{
  33+	while (*cur) {
  34+		if ((*cur)->index == index) {
  35+			break;
  36+		}
  37+		cur = &((*cur)->next);
  38+	}
  39+	return cur;
  40+}
  41+
  42+disp_def * displays = NULL;
  43+disp_def * zdisplays = NULL;
  44+uint32_t disp_index = 0;
  45+uint32_t zdisp_index = 0;
  46+
  47+void add_display(disp_def ** head, uint32_t *index, char format_char, char * param)
  48+{
  49+	disp_def * ndisp = malloc(sizeof(*ndisp));
  50+	ndisp->format_char = format_char;
  51+	ndisp->param = strdup(param);
  52+	ndisp->next = *head;
  53+	ndisp->index = *index++;
  54+	*head = ndisp;
  55+}
  56+
  57+void remove_display(disp_def ** head, uint32_t index)
  58+{
  59+	while (*head) {
  60+		if ((*head)->index == index) {
  61+			disp_def * del_disp = *head;
  62+			*head = del_disp->next;
  63+			free(del_disp->param);
  64+			free(del_disp);
  65+		} else {
  66+			head = &(*head)->next;
  67+		}
  68+	}
  69+}
  70+
  71+char * find_param(char * buf)
  72+{
  73+	for (; *buf; buf++) {
  74+		if (*buf == ' ') {
  75+			if (*(buf+1)) {
  76+				return buf+1;
  77+			}
  78+		}
  79+	}
  80+	return NULL;
  81+}
  82+
  83+void strip_nl(char * buf)
  84+{
  85+	for(; *buf; buf++) {
  86+		if (*buf == '\n') {
  87+			*buf = 0;
  88+			return;
  89+		}
  90+	}
  91+}
  92+
  93+uint16_t m68k_read_word(uint32_t address, m68k_context *context)
  94+{
  95+	return read_word(address, (void **)context->mem_pointers, &context->options->gen, context);
  96+}
  97+
  98+uint32_t m68k_read_long(uint32_t address, m68k_context *context)
  99+{
 100+	return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context);
 101+}
 102+
 103+void debugger_print(m68k_context *context, char format_char, char *param)
 104+{
 105+	uint32_t value;
 106+	char format[8];
 107+	strcpy(format, "%s: %d\n");
 108+	switch (format_char)
 109+	{
 110+	case 'x':
 111+	case 'X':
 112+	case 'd':
 113+	case 'c':
 114+		format[5] = format_char;
 115+		break;
 116+	case '\0':
 117+		break;
 118+	default:
 119+		fprintf(stderr, "Unrecognized format character: %c\n", format_char);
 120+	}
 121+	if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') {
 122+		value = context->dregs[param[1]-'0'];
 123+		if (param[2] == '.') {
 124+			if (param[3] == 'w') {
 125+				value &= 0xFFFF;
 126+			} else if (param[3] == 'b') {
 127+				value &= 0xFF;
 128+			}
 129+		}
 130+	} else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') {
 131+		value = context->aregs[param[1]-'0'];
 132+		if (param[2] == '.') {
 133+			if (param[3] == 'w') {
 134+				value &= 0xFFFF;
 135+			} else if (param[3] == 'b') {
 136+				value &= 0xFF;
 137+			}
 138+		}
 139+	} else if (param[0] == 'S' && param[1] == 'R') {
 140+		value = (context->status << 8);
 141+		for (int flag = 0; flag < 5; flag++) {
 142+			value |= context->flags[flag] << (4-flag);
 143+		}
 144+	} else if(param[0] == 'c') {
 145+		value = context->current_cycle;
 146+	} else if(param[0] == 'f') {
 147+		genesis_context *gen = context->system;
 148+		value = gen->vdp->frame;
 149+	} else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') {
 150+		char *after;
 151+		uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16);
 152+		if (after[0] == '.' && after[1] == 'l') {
 153+			value = m68k_read_long(p_addr, context);
 154+		} else {
 155+			value = m68k_read_word(p_addr, context);
 156+		}
 157+	} else if(param[0] == '(' && (param[1] == 'a' || param[1] == 'd') && param[2] >= '0' && param[2] <= '7' && param[3] == ')') {
 158+		uint8_t reg = param[2] - '0';
 159+		uint32_t p_addr = param[1] == 'a' ? context->aregs[reg] : context->dregs[reg];
 160+		if (param[4] == '.' && param[5] == 'l') {
 161+			value = m68k_read_long(p_addr, context);
 162+		} else {
 163+			value = m68k_read_word(p_addr, context);
 164+		}
 165+	} else {
 166+		fprintf(stderr, "Unrecognized parameter to p: %s\n", param);
 167+		return;
 168+	}
 169+	printf(format, param, value);
 170+}
 171+
 172+void zdebugger_print(z80_context * context, char format_char, char * param)
 173+{
 174+	uint32_t value;
 175+	char format[8];
 176+	strcpy(format, "%s: %d\n");
 177+	genesis_context *system = context->system;
 178+	switch (format_char)
 179+	{
 180+	case 'x':
 181+	case 'X':
 182+	case 'd':
 183+	case 'c':
 184+		format[5] = format_char;
 185+		break;
 186+	case '\0':
 187+		break;
 188+	default:
 189+		fprintf(stderr, "Unrecognized format character: %c\n", format_char);
 190+	}
 191+	switch (param[0])
 192+	{
 193+	case 'a':
 194+		if (param[1] == 'f') {
 195+			if(param[2] == '\'') {
 196+				value = context->alt_regs[Z80_A] << 8;
 197+				value |= context->alt_flags[ZF_S] << 7;
 198+				value |= context->alt_flags[ZF_Z] << 6;
 199+				value |= context->alt_flags[ZF_H] << 4;
 200+				value |= context->alt_flags[ZF_PV] << 2;
 201+				value |= context->alt_flags[ZF_N] << 1;
 202+				value |= context->alt_flags[ZF_C];
 203+			} else {
 204+				value = context->regs[Z80_A] << 8;
 205+				value |= context->flags[ZF_S] << 7;
 206+				value |= context->flags[ZF_Z] << 6;
 207+				value |= context->flags[ZF_H] << 4;
 208+				value |= context->flags[ZF_PV] << 2;
 209+				value |= context->flags[ZF_N] << 1;
 210+				value |= context->flags[ZF_C];
 211+			}
 212+		} else if(param[1] == '\'') {
 213+			value = context->alt_regs[Z80_A];
 214+		} else {
 215+			value = context->regs[Z80_A];
 216+		}
 217+		break;
 218+	case 'b':
 219+		if (param[1] == 'c') {
 220+			if(param[2] == '\'') {
 221+				value = context->alt_regs[Z80_B] << 8;
 222+				value |= context->alt_regs[Z80_C];
 223+			} else {
 224+				value = context->regs[Z80_B] << 8;
 225+				value |= context->regs[Z80_C];
 226+			}
 227+		} else if(param[1] == '\'') {
 228+			value = context->alt_regs[Z80_B];
 229+		} else if(param[1] == 'a') {
 230+			value = context->bank_reg << 15;
 231+		} else {
 232+			value = context->regs[Z80_B];
 233+		}
 234+		break;
 235+	case 'c':
 236+		if(param[1] == '\'') {
 237+			value = context->alt_regs[Z80_C];
 238+		} else if(param[1] == 'y') {
 239+			value = context->current_cycle;
 240+		} else {
 241+			value = context->regs[Z80_C];
 242+		}
 243+		break;
 244+	case 'd':
 245+		if (param[1] == 'e') {
 246+			if(param[2] == '\'') {
 247+				value = context->alt_regs[Z80_D] << 8;
 248+				value |= context->alt_regs[Z80_E];
 249+			} else {
 250+				value = context->regs[Z80_D] << 8;
 251+				value |= context->regs[Z80_E];
 252+			}
 253+		} else if(param[1] == '\'') {
 254+			value = context->alt_regs[Z80_D];
 255+		} else {
 256+			value = context->regs[Z80_D];
 257+		}
 258+		break;
 259+	case 'e':
 260+		if(param[1] == '\'') {
 261+			value = context->alt_regs[Z80_E];
 262+		} else {
 263+			value = context->regs[Z80_E];
 264+		}
 265+		break;
 266+	case 'f':
 267+		if(param[2] == '\'') {
 268+			value = context->alt_flags[ZF_S] << 7;
 269+			value |= context->alt_flags[ZF_Z] << 6;
 270+			value |= context->alt_flags[ZF_H] << 4;
 271+			value |= context->alt_flags[ZF_PV] << 2;
 272+			value |= context->alt_flags[ZF_N] << 1;
 273+			value |= context->alt_flags[ZF_C];
 274+		} else {
 275+			value = context->flags[ZF_S] << 7;
 276+			value |= context->flags[ZF_Z] << 6;
 277+			value |= context->flags[ZF_H] << 4;
 278+			value |= context->flags[ZF_PV] << 2;
 279+			value |= context->flags[ZF_N] << 1;
 280+			value |= context->flags[ZF_C];
 281+		}
 282+		break;
 283+	case 'h':
 284+		if (param[1] == 'l') {
 285+			if(param[2] == '\'') {
 286+				value = context->alt_regs[Z80_H] << 8;
 287+				value |= context->alt_regs[Z80_L];
 288+			} else {
 289+				value = context->regs[Z80_H] << 8;
 290+				value |= context->regs[Z80_L];
 291+			}
 292+		} else if(param[1] == '\'') {
 293+			value = context->alt_regs[Z80_H];
 294+		} else {
 295+			value = context->regs[Z80_H];
 296+		}
 297+		break;
 298+	case 'l':
 299+		if(param[1] == '\'') {
 300+			value = context->alt_regs[Z80_L];
 301+		} else {
 302+			value = context->regs[Z80_L];
 303+		}
 304+		break;
 305+	case 'i':
 306+		if(param[1] == 'x') {
 307+			if (param[2] == 'h') {
 308+				value = context->regs[Z80_IXH];
 309+			} else if(param[2] == 'l') {
 310+				value = context->regs[Z80_IXL];
 311+			} else {
 312+				value = context->regs[Z80_IXH] << 8;
 313+				value |= context->regs[Z80_IXL];
 314+			}
 315+		} else if(param[1] == 'y') {
 316+			if (param[2] == 'h') {
 317+				value = context->regs[Z80_IYH];
 318+			} else if(param[2] == 'l') {
 319+				value = context->regs[Z80_IYL];
 320+			} else {
 321+				value = context->regs[Z80_IYH] << 8;
 322+				value |= context->regs[Z80_IYL];
 323+			}
 324+		} else if(param[1] == 'n') {
 325+			value = context->int_cycle;
 326+		} else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') {
 327+			value = context->iff1;
 328+		} else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') {
 329+			value = context->iff2;
 330+		} else {
 331+			value = context->im;
 332+		}
 333+		break;
 334+	case 's':
 335+		if (param[1] == 'p') {
 336+			value = context->sp;
 337+		}
 338+		break;
 339+	case '0':
 340+		if (param[1] == 'x') {
 341+			uint16_t p_addr = strtol(param+2, NULL, 16);
 342+			if (p_addr < 0x4000) {
 343+				value = system->zram[p_addr & 0x1FFF];
 344+			} else if(p_addr >= 0x8000) {
 345+				uint32_t v_addr = system->z80_bank_reg << 15;
 346+				v_addr += p_addr & 0x7FFF;
 347+				if (v_addr < 0x400000) {
 348+					value = system->cart[v_addr/2];
 349+				} else if(v_addr > 0xE00000) {
 350+					value = system->work_ram[(v_addr & 0xFFFF)/2];
 351+				}
 352+				if (v_addr & 1) {
 353+					value &= 0xFF;
 354+				} else {
 355+					value >>= 8;
 356+				}
 357+			}
 358+		}
 359+		break;
 360+	}
 361+	printf(format, param, value);
 362+}
 363+
 364+z80_context * zdebugger(z80_context * context, uint16_t address)
 365+{
 366+	static char last_cmd[1024];
 367+	char input_buf[1024];
 368+	static uint16_t branch_t;
 369+	static uint16_t branch_f;
 370+	z80inst inst;
 371+	genesis_context *system = context->system;
 372+	init_terminal();
 373+	//Check if this is a user set breakpoint, or just a temporary one
 374+	bp_def ** this_bp = find_breakpoint(&zbreakpoints, address);
 375+	if (*this_bp) {
 376+		printf("Z80 Breakpoint %d hit\n", (*this_bp)->index);
 377+	} else {
 378+		zremove_breakpoint(context, address);
 379+	}
 380+	uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
 381+	if (!pc) {
 382+		fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address);
 383+	}
 384+	for (disp_def * cur = zdisplays; cur; cur = cur->next) {
 385+		zdebugger_print(context, cur->format_char, cur->param);
 386+	}
 387+	uint8_t * after_pc = z80_decode(pc, &inst);
 388+	z80_disasm(&inst, input_buf, address);
 389+	printf("%X:\t%s\n", address, input_buf);
 390+	uint16_t after = address + (after_pc-pc);
 391+	int debugging = 1;
 392+	while(debugging) {
 393+		fputs(">", stdout);
 394+		if (!fgets(input_buf, sizeof(input_buf), stdin)) {
 395+			fputs("fgets failed", stderr);
 396+			break;
 397+		}
 398+		strip_nl(input_buf);
 399+		//hitting enter repeats last command
 400+		if (input_buf[0]) {
 401+			strcpy(last_cmd, input_buf);
 402+		} else {
 403+			strcpy(input_buf, last_cmd);
 404+		}
 405+		char * param;
 406+		char format[8];
 407+		uint32_t value;
 408+		bp_def * new_bp;
 409+		switch(input_buf[0])
 410+		{
 411+			case 'a':
 412+				param = find_param(input_buf);
 413+				if (!param) {
 414+					fputs("a command requires a parameter\n", stderr);
 415+					break;
 416+				}
 417+				value = strtol(param, NULL, 16);
 418+				zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
 419+				debugging = 0;
 420+				break;
 421+			case 'b':
 422+				param = find_param(input_buf);
 423+				if (!param) {
 424+					fputs("b command requires a parameter\n", stderr);
 425+					break;
 426+				}
 427+				value = strtol(param, NULL, 16);
 428+				zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
 429+				new_bp = malloc(sizeof(bp_def));
 430+				new_bp->next = zbreakpoints;
 431+				new_bp->address = value;
 432+				new_bp->index = zbp_index++;
 433+				new_bp->commands = NULL;
 434+				zbreakpoints = new_bp;
 435+				printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
 436+				break;
 437+			case 'c':
 438+				puts("Continuing");
 439+				debugging = 0;
 440+				break;
 441+			case 'd':
 442+				if (input_buf[1] == 'i') {
 443+					char format_char = 0;
 444+					for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
 445+						if (input_buf[i] == '/') {
 446+							format_char = input_buf[i+1];
 447+							break;
 448+						}
 449+					}
 450+					param = find_param(input_buf);
 451+					if (!param) {
 452+						fputs("display command requires a parameter\n", stderr);
 453+						break;
 454+					}
 455+					zdebugger_print(context, format_char, param);
 456+					add_display(&zdisplays, &zdisp_index, format_char, param);
 457+				} else if (input_buf[1] == 'e' || input_buf[1] == ' ') {
 458+					param = find_param(input_buf);
 459+					if (!param) {
 460+						fputs("delete command requires a parameter\n", stderr);
 461+						break;
 462+					}
 463+					if (param[0] >= '0' && param[0] <= '9') {
 464+						value = atoi(param);
 465+						this_bp = find_breakpoint_idx(&zbreakpoints, value);
 466+						if (!*this_bp) {
 467+							fprintf(stderr, "Breakpoint %d does not exist\n", value);
 468+							break;
 469+						}
 470+						new_bp = *this_bp;
 471+						zremove_breakpoint(context, new_bp->address);
 472+						*this_bp = new_bp->next;
 473+						free(new_bp);
 474+					} else if (param[0] == 'd') {
 475+						param = find_param(param);
 476+						if (!param) {
 477+							fputs("delete display command requires a parameter\n", stderr);
 478+							break;
 479+						}
 480+						remove_display(&zdisplays, atoi(param));
 481+					}
 482+				}
 483+				break;
 484+			case 'n':
 485+				//TODO: Handle conditional branch instructions
 486+				if (inst.op == Z80_JP) {
 487+					if (inst.addr_mode == Z80_IMMED) {
 488+						after = inst.immed;
 489+					} else if (inst.ea_reg == Z80_HL) {
 490+						after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
 491+					} else if (inst.ea_reg == Z80_IX) {
 492+						after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
 493+					} else if (inst.ea_reg == Z80_IY) {
 494+						after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
 495+					}
 496+				} else if(inst.op == Z80_JR) {
 497+					after += inst.immed;
 498+				} else if(inst.op == Z80_RET) {
 499+					uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
 500+					if (sp) {
 501+						after = *sp;
 502+						sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
 503+						if (sp) {
 504+							after |= *sp << 8;
 505+						}
 506+					}
 507+				}
 508+				zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
 509+				debugging = 0;
 510+				break;
 511+			case 'p':
 512+				param = find_param(input_buf);
 513+				if (!param) {
 514+					fputs("p command requires a parameter\n", stderr);
 515+					break;
 516+				}
 517+				zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param);
 518+				break;
 519+			case 'q':
 520+				puts("Quitting");
 521+				exit(0);
 522+				break;
 523+			case 's': {
 524+				param = find_param(input_buf);
 525+				if (!param) {
 526+					fputs("s command requires a file name\n", stderr);
 527+					break;
 528+				}
 529+				memmap_chunk const *ram_chunk = NULL;
 530+				for (int i = 0; i < context->Z80_OPTS->gen.memmap_chunks; i++)
 531+				{
 532+					memmap_chunk const *cur = context->Z80_OPTS->gen.memmap + i;
 533+					if (cur->flags & MMAP_WRITE) {
 534+						ram_chunk = cur;
 535+						break;
 536+					}
 537+				}
 538+				if (ram_chunk) {
 539+					uint32_t size = ram_chunk->end - ram_chunk->start;
 540+					if (size > ram_chunk->mask) {
 541+						size = ram_chunk->mask+1;
 542+					}
 543+					uint8_t *buf = get_native_pointer(ram_chunk->start, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
 544+					FILE * f = fopen(param, "wb");
 545+					if (f) {
 546+						if(fwrite(buf, 1, size, f) != size) {
 547+							fputs("Error writing file\n", stderr);
 548+						}
 549+						fclose(f);
 550+						printf("Wrote %d bytes to %s\n", size, param);
 551+					} else {
 552+						fprintf(stderr, "Could not open %s for writing\n", param);
 553+					}
 554+				} else {
 555+					fputs("Failed to find a RAM memory chunk\n", stderr);
 556+				}
 557+				break;
 558+			}
 559+			default:
 560+				if (
 561+					!context->Z80_OPTS->gen.debug_cmd_handler
 562+					|| !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf)
 563+				) {
 564+					fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
 565+				}
 566+				break;
 567+		}
 568+	}
 569+	return context;
 570+}
 571+
 572+static uint32_t branch_t;
 573+static uint32_t branch_f;
 574+
 575+int run_debugger_command(m68k_context *context, char *input_buf, m68kinst inst, uint32_t after)
 576+{
 577+	char * param;
 578+	char format_char;
 579+	genesis_context *system = context->system;
 580+	uint32_t value;
 581+	bp_def *new_bp, **this_bp;
 582+	switch(input_buf[0])
 583+	{
 584+		case 'c':
 585+			if (input_buf[1] == 0 || input_buf[1] == 'o' && input_buf[2] == 'n')
 586+			{
 587+				puts("Continuing");
 588+				return 0;
 589+			} else if (input_buf[1] == 'o' && input_buf[2] == 'm') {
 590+				param = find_param(input_buf);
 591+				if (!param) {
 592+					fputs("com command requires a parameter\n", stderr);
 593+					break;
 594+				}
 595+				bp_def **target = find_breakpoint_idx(&breakpoints, atoi(param));
 596+				if (!target) {
 597+					fprintf(stderr, "Breakpoint %s does not exist!\n", param);
 598+					break;
 599+				}
 600+				printf("Enter commands for breakpoing %d, type end when done\n", atoi(param));
 601+				char cmd_buf[1024];
 602+				char *commands = NULL;
 603+				for (;;)
 604+				{
 605+					fputs(">>", stdout);
 606+					fflush(stdout);
 607+					fgets(cmd_buf, sizeof(cmd_buf), stdin);
 608+					if (strcmp(cmd_buf, "end\n")) {
 609+						if (commands) {
 610+							char *tmp = commands;
 611+							commands = alloc_concat(commands, cmd_buf);
 612+							free(tmp);
 613+						} else {
 614+							commands = strdup(cmd_buf);
 615+						}
 616+					} else {
 617+						break;
 618+					}
 619+				}
 620+				(*target)->commands = commands;
 621+			} else {
 622+			}
 623+			break;
 624+		case 'b':
 625+			if (input_buf[1] == 't') {
 626+				uint32_t stack = context->aregs[7];
 627+				if (stack >= 0xE00000) {
 628+					stack &= 0xFFFF;
 629+					uint8_t non_adr_count = 0;
 630+					do {
 631+						uint32_t bt_address = system->work_ram[stack/2] << 16 | system->work_ram[stack/2+1];
 632+						bt_address = get_instruction_start(context->options, bt_address - 2);
 633+						if (bt_address) {
 634+							stack += 4;
 635+							non_adr_count = 0;
 636+							uint16_t *bt_pc = NULL;
 637+							if (bt_address < 0x400000) {
 638+								bt_pc = system->cart + bt_address/2;
 639+							} else if(bt_address > 0xE00000) {
 640+								bt_pc = system->work_ram + (bt_address & 0xFFFF)/2;
 641+							}
 642+							m68k_decode(bt_pc, &inst, bt_address);
 643+							m68k_disasm(&inst, input_buf);
 644+							printf("%X: %s\n", bt_address, input_buf);
 645+						} else {
 646+							//non-return address value on stack can be word wide
 647+							stack += 2;
 648+							non_adr_count++;
 649+						}
 650+						stack &= 0xFFFF;
 651+					} while (stack && non_adr_count < 6);
 652+				}
 653+			} else {
 654+				param = find_param(input_buf);
 655+				if (!param) {
 656+					fputs("b command requires a parameter\n", stderr);
 657+					break;
 658+				}
 659+				value = strtol(param, NULL, 16);
 660+				insert_breakpoint(context, value, debugger);
 661+				new_bp = malloc(sizeof(bp_def));
 662+				new_bp->next = breakpoints;
 663+				new_bp->address = value;
 664+				new_bp->index = bp_index++;
 665+				new_bp->commands = NULL;
 666+				breakpoints = new_bp;
 667+				printf("68K Breakpoint %d set at %X\n", new_bp->index, value);
 668+			}
 669+			break;
 670+		case 'a':
 671+			param = find_param(input_buf);
 672+			if (!param) {
 673+				fputs("a command requires a parameter\n", stderr);
 674+				break;
 675+			}
 676+			value = strtol(param, NULL, 16);
 677+			insert_breakpoint(context, value, debugger);
 678+			return 0;
 679+		case 'd':
 680+			if (input_buf[1] == 'i') {
 681+				format_char = 0;
 682+				for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
 683+					if (input_buf[i] == '/') {
 684+						format_char = input_buf[i+1];
 685+						break;
 686+					}
 687+				}
 688+				param = find_param(input_buf);
 689+				if (!param) {
 690+					fputs("display command requires a parameter\n", stderr);
 691+					break;
 692+				}
 693+				debugger_print(context, format_char, param);
 694+				add_display(&displays, &disp_index, format_char, param);
 695+			} else {
 696+				param = find_param(input_buf);
 697+				if (!param) {
 698+					fputs("d command requires a parameter\n", stderr);
 699+					break;
 700+				}
 701+				value = atoi(param);
 702+				this_bp = find_breakpoint_idx(&breakpoints, value);
 703+				if (!*this_bp) {
 704+					fprintf(stderr, "Breakpoint %d does not exist\n", value);
 705+					break;
 706+				}
 707+				new_bp = *this_bp;
 708+				*this_bp = (*this_bp)->next;
 709+				if (new_bp->commands) {
 710+					free(new_bp->commands);
 711+				}
 712+				free(new_bp);
 713+			}
 714+			break;
 715+		case 'p':
 716+			format_char = 0;
 717+			for(int i = 1; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
 718+				if (input_buf[i] == '/') {
 719+					format_char = input_buf[i+1];
 720+					break;
 721+				}
 722+			}
 723+			param = find_param(input_buf);
 724+			if (!param) {
 725+				fputs("p command requires a parameter\n", stderr);
 726+				break;
 727+			}
 728+			debugger_print(context, format_char, param);
 729+			break;
 730+		case 'n':
 731+			if (inst.op == M68K_RTS) {
 732+				after = m68k_read_long(context->aregs[7], context);
 733+			} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
 734+				after = m68k_read_long(context->aregs[7] + 2, context);
 735+			} else if(m68k_is_noncall_branch(&inst)) {
 736+				if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
 737+					branch_f = after;
 738+					branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
 739+					insert_breakpoint(context, branch_t, debugger);
 740+				} else if(inst.op == M68K_DBCC) {
 741+					if ( inst.extra.cond == COND_FALSE) {
 742+						if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
 743+							after = m68k_branch_target(&inst, context->dregs, context->aregs);
 744+						}
 745+					} else {
 746+						branch_t = after;
 747+						branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
 748+						insert_breakpoint(context, branch_f, debugger);
 749+					}
 750+				} else {
 751+					after = m68k_branch_target(&inst, context->dregs, context->aregs);
 752+				}
 753+			}
 754+			insert_breakpoint(context, after, debugger);
 755+			return 0;
 756+		case 'o':
 757+			if (inst.op == M68K_RTS) {
 758+				after = m68k_read_long(context->aregs[7], context);
 759+			} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
 760+				after = m68k_read_long(context->aregs[7] + 2, context);
 761+			} else if(m68k_is_noncall_branch(&inst)) {
 762+				if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
 763+					branch_t = m68k_branch_target(&inst, context->dregs, context->aregs)  & 0xFFFFFF;
 764+					if (branch_t < after) {
 765+							branch_t = 0;
 766+					} else {
 767+						branch_f = after;
 768+						insert_breakpoint(context, branch_t, debugger);
 769+					}
 770+				} else if(inst.op == M68K_DBCC) {
 771+					uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs)  & 0xFFFFFF;
 772+					if (target > after) {
 773+						if (inst.extra.cond == COND_FALSE) {
 774+							after = target;
 775+						} else {
 776+							branch_f = target;
 777+							branch_t = after;
 778+							insert_breakpoint(context, branch_f, debugger);
 779+						}
 780+					}
 781+				} else {
 782+					after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
 783+				}
 784+			}
 785+			insert_breakpoint(context, after, debugger);
 786+			return 0;
 787+		case 's':
 788+			if (input_buf[1] == 'e') {
 789+				param = find_param(input_buf);
 790+				if (!param) {
 791+					fputs("Missing destination parameter for set\n", stderr);
 792+				}
 793+				char *val = find_param(param);
 794+				if (!val) {
 795+					fputs("Missing value parameter for set\n", stderr);
 796+				}
 797+				long int_val;
 798+				int reg_num;
 799+				switch (val[0])
 800+				{
 801+				case 'd':
 802+				case 'a':
 803+					reg_num = val[1] - '0';
 804+					if (reg_num < 0 || reg_num > 8) {
 805+						fprintf(stderr, "Invalid register %s\n", val);
 806+						return 1;
 807+					}
 808+					int_val = (val[0] == 'd' ? context->dregs : context->aregs)[reg_num];
 809+					break;
 810+				case '$':
 811+					int_val = strtol(val+1, NULL, 16);
 812+					break;
 813+				case '0':
 814+					if (val[1] == 'x') {
 815+						int_val = strtol(val+2, NULL, 16);
 816+						break;
 817+					}
 818+				default:
 819+					int_val = strtol(val, NULL, 10);
 820+				}
 821+				switch(param[0])
 822+				{
 823+				case 'd':
 824+				case 'a':
 825+					reg_num = param[1] - '0';
 826+					if (reg_num < 0 || reg_num > 8) {
 827+						fprintf(stderr, "Invalid register %s\n", param);
 828+						return 1;
 829+					}
 830+					(param[0] == 'd' ? context->dregs : context->aregs)[reg_num] = int_val;
 831+					break;
 832+				default:
 833+					fprintf(stderr, "Invalid destinatino %s\n", param);
 834+				}
 835+				break;
 836+			} else {
 837+				if (inst.op == M68K_RTS) {
 838+					after = m68k_read_long(context->aregs[7], context);
 839+				} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
 840+					after = m68k_read_long(context->aregs[7] + 2, context);
 841+				} else if(m68k_is_branch(&inst)) {
 842+					if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
 843+						branch_f = after;
 844+						branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
 845+						insert_breakpoint(context, branch_t, debugger);
 846+					} else if(inst.op == M68K_DBCC) {
 847+						if (inst.extra.cond == COND_FALSE) {
 848+							if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
 849+								after = m68k_branch_target(&inst, context->dregs, context->aregs);
 850+							}
 851+						} else {
 852+							branch_t = after;
 853+							branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
 854+							insert_breakpoint(context, branch_f, debugger);
 855+						}
 856+					} else {
 857+						after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
 858+					}
 859+				}
 860+				insert_breakpoint(context, after, debugger);
 861+				return 0;
 862+			}
 863+		case 'v': {
 864+			genesis_context * gen = context->system;
 865+			//VDP debug commands
 866+			switch(input_buf[1])
 867+			{
 868+			case 's':
 869+				vdp_print_sprite_table(gen->vdp);
 870+				break;
 871+			case 'r':
 872+				vdp_print_reg_explain(gen->vdp);
 873+				break;
 874+			}
 875+			break;
 876+		}
 877+		case 'y': {
 878+			genesis_context * gen = context->system;
 879+			//YM-2612 debug commands
 880+			switch(input_buf[1])
 881+			{
 882+			case 'c':
 883+				if (input_buf[2] == ' ') {
 884+					int channel = atoi(input_buf+3)-1;
 885+					ym_print_channel_info(gen->ym, channel);
 886+				} else {
 887+					for (int i = 0; i < 6; i++) {
 888+						ym_print_channel_info(gen->ym, i);
 889+					}
 890+				}
 891+				break;
 892+			case 't':
 893+				ym_print_timer_info(gen->ym);
 894+				break;
 895+			}
 896+			break;
 897+		}
 898+		case 'z': {
 899+			genesis_context * gen = context->system;
 900+			//Z80 debug commands
 901+			switch(input_buf[1])
 902+			{
 903+			case 'b':
 904+				param = find_param(input_buf);
 905+				if (!param) {
 906+					fputs("zb command requires a parameter\n", stderr);
 907+					break;
 908+				}
 909+				value = strtol(param, NULL, 16);
 910+				zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
 911+				new_bp = malloc(sizeof(bp_def));
 912+				new_bp->next = zbreakpoints;
 913+				new_bp->address = value;
 914+				new_bp->index = zbp_index++;
 915+				zbreakpoints = new_bp;
 916+				printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
 917+				break;
 918+			case 'p':
 919+				param = find_param(input_buf);
 920+				if (!param) {
 921+					fputs("zp command requires a parameter\n", stderr);
 922+					break;
 923+				}
 924+				zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
 925+			}
 926+			break;
 927+		}
 928+		case 'q':
 929+			puts("Quitting");
 930+			exit(0);
 931+			break;
 932+		default:
 933+			fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
 934+			break;
 935+	}
 936+	return 1;
 937+}
 938+
 939+
 940+void debugger(m68k_context * context, uint32_t address)
 941+{
 942+	static char last_cmd[1024];
 943+	char input_buf[1024];
 944+	m68kinst inst;
 945+
 946+	init_terminal();
 947+
 948+	sync_components(context, 0);
 949+	genesis_context *gen = context->system;
 950+	vdp_force_update_framebuffer(gen->vdp);
 951+	//probably not necessary, but let's play it safe
 952+	address &= 0xFFFFFF;
 953+	if (address == branch_t) {
 954+		bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
 955+		if (!*f_bp) {
 956+			remove_breakpoint(context, branch_f);
 957+		}
 958+		branch_t = branch_f = 0;
 959+	} else if(address == branch_f) {
 960+		bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t);
 961+		if (!*t_bp) {
 962+			remove_breakpoint(context, branch_t);
 963+		}
 964+		branch_t = branch_f = 0;
 965+	}
 966+
 967+	uint16_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->options->gen);
 968+	if (!pc) {
 969+		fatal_error("Entered 68K debugger at address %X\n", address);
 970+	}
 971+	uint16_t * after_pc = m68k_decode(pc, &inst, address);
 972+	uint32_t after = address + (after_pc-pc)*2;
 973+	int debugging = 1;
 974+	//Check if this is a user set breakpoint, or just a temporary one
 975+	bp_def ** this_bp = find_breakpoint(&breakpoints, address);
 976+	if (*this_bp) {
 977+
 978+		if ((*this_bp)->commands)
 979+		{
 980+			char *commands = strdup((*this_bp)->commands);
 981+			char *copy = commands;
 982+
 983+			while (debugging && *commands)
 984+			{
 985+				char *cmd = commands;
 986+				strip_nl(cmd);
 987+				commands += strlen(cmd) + 1;
 988+				debugging = run_debugger_command(context, cmd, inst, after);
 989+			}
 990+			free(copy);
 991+		}
 992+		if (debugging) {
 993+			printf("68K Breakpoint %d hit\n", (*this_bp)->index);
 994+		} else {
 995+			return;
 996+		}
 997+	} else {
 998+		remove_breakpoint(context, address);
 999+	}
1000+	for (disp_def * cur = displays; cur; cur = cur->next) {
1001+		debugger_print(context, cur->format_char, cur->param);
1002+	}
1003+	m68k_disasm(&inst, input_buf);
1004+	printf("%X: %s\n", address, input_buf);
1005+	int prompt = 1;
1006+	fd_set read_fds;
1007+	FD_ZERO(&read_fds);
1008+	struct timeval timeout;
1009+	while (debugging) {
1010+		if (prompt) {
1011+			fputs(">", stdout);
1012+			fflush(stdout);
1013+		}
1014+		process_events();
1015+		timeout.tv_sec = 0;
1016+		timeout.tv_usec = 16667;
1017+		FD_SET(fileno(stdin), &read_fds);
1018+		if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) < 1) {
1019+			prompt = 0;
1020+			continue;
1021+		} else {
1022+			prompt = 1;
1023+		}
1024+		if (!fgets(input_buf, sizeof(input_buf), stdin)) {
1025+			fputs("fgets failed", stderr);
1026+			break;
1027+		}
1028+		strip_nl(input_buf);
1029+		//hitting enter repeats last command
1030+		if (input_buf[0]) {
1031+			strcpy(last_cmd, input_buf);
1032+		} else {
1033+			strcpy(input_buf, last_cmd);
1034+		}
1035+		debugging = run_debugger_command(context, input_buf, inst, after);
1036+	}
1037+	return;
1038+}
+29, -0
 1@@ -0,0 +1,29 @@
 2+#ifndef DEBUG_H_
 3+#define DEBUG_H_
 4+
 5+#include <stdint.h>
 6+#include "m68k_core.h"
 7+#include "z80_to_x86.h"
 8+
 9+typedef struct disp_def {
10+	struct disp_def * next;
11+	char *            param;
12+	uint32_t          index;
13+	char              format_char;
14+} disp_def;
15+
16+typedef struct bp_def {
17+	struct bp_def *next;
18+	char          *commands;
19+	uint32_t      address;
20+	uint32_t      index;
21+} bp_def;
22+
23+bp_def ** find_breakpoint(bp_def ** cur, uint32_t address);
24+bp_def ** find_breakpoint_idx(bp_def ** cur, uint32_t index);
25+void add_display(disp_def ** head, uint32_t *index, char format_char, char * param);
26+void remove_display(disp_def ** head, uint32_t index);
27+void debugger(m68k_context * context, uint32_t address);
28+z80_context * zdebugger(z80_context * context, uint16_t address);
29+
30+#endif //DEBUG_H_
+376, -0
  1@@ -0,0 +1,376 @@
  2+
  3+bindings {
  4+	keys {
  5+		up gamepads.1.up
  6+		down gamepads.1.down
  7+		left gamepads.1.left
  8+		right gamepads.1.right
  9+		a gamepads.1.a
 10+		s gamepads.1.b
 11+		d gamepads.1.c
 12+		q gamepads.1.x
 13+		w gamepads.1.y
 14+		e gamepads.1.z
 15+		f gamepads.1.mode
 16+		enter gamepads.1.start
 17+
 18+		r ui.release_mouse
 19+		[ ui.vdp_debug_mode
 20+		u ui.enter_debugger
 21+		p ui.screenshot
 22+		b ui.plane_debug
 23+		v ui.vram_debug
 24+		c ui.cram_debug
 25+		n ui.compositing_debug
 26+		esc ui.exit
 27+		` ui.save_state
 28+		0 ui.set_speed.0
 29+		1 ui.set_speed.1
 30+		2 ui.set_speed.2
 31+		3 ui.set_speed.3
 32+		4 ui.set_speed.4
 33+		5 ui.set_speed.5
 34+		6 ui.set_speed.6
 35+		7 ui.set_speed.7
 36+		= ui.next_speed
 37+		- ui.prev_speed
 38+		tab ui.soft_reset
 39+		f5 ui.reload
 40+		z ui.sms_pause
 41+		rctrl ui.toggle_keyboard_captured
 42+	}
 43+	pads {
 44+		default {
 45+			dpads {
 46+				0 {
 47+					up gamepads.n.up
 48+					down gamepads.n.down
 49+					left gamepads.n.left
 50+					right gamepads.n.right
 51+				}
 52+			}
 53+			buttons {
 54+				a gamepads.n.a
 55+				b gamepads.n.b
 56+				rightshoulder gamepads.n.c
 57+				x gamepads.n.x
 58+				y gamepads.n.y
 59+				leftshoulder gamepads.n.z
 60+				back gamepads.n.mode
 61+				start gamepads.n.start
 62+				guide ui.exit
 63+				leftstick ui.save_state
 64+			}
 65+			axes {
 66+				lefty.positive gamepads.n.down
 67+				lefty.negative gamepads.n.up
 68+				leftx.positive gamepads.n.right
 69+				leftx.negative gamepads.n.left
 70+				lefttrigger ui.prev_speed
 71+				righttrigger ui.next_speed
 72+			}
 73+		}
 74+		ps4_6b_right {
 75+			axes {
 76+				lefttrigger ui.next_speed
 77+				leftx.negative gamepads.n.up
 78+				leftx.positive gamepads.n.down
 79+				lefty.negative gamepads.n.left
 80+				lefty.positive gamepads.n.right
 81+				righttrigger gamepads.n.c
 82+			}
 83+			buttons {
 84+				a gamepads.n.a
 85+				b gamepads.n.b
 86+				back ui.sms_pause
 87+				guide ui.exit
 88+				leftshoulder gamepads.n.mode
 89+				leftstick ui.save_state
 90+				rightshoulder gamepads.n.z
 91+				rightstick ui.prev_speed
 92+				start gamepads.n.start
 93+				x gamepads.n.x
 94+				y gamepads.n.y
 95+			}
 96+			dpads {
 97+				0 {
 98+					down gamepads.n.down
 99+					left gamepads.n.left
100+					right gamepads.n.right
101+					up gamepads.n.up
102+				}
103+			}
104+		}
105+		ps3_6b_right {
106+			axes {
107+				lefttrigger ui.next_speed
108+				leftx.negative gamepads.n.up
109+				leftx.positive gamepads.n.down
110+				lefty.negative gamepads.n.left
111+				lefty.positive gamepads.n.right
112+				righttrigger gamepads.n.c
113+			}
114+			buttons {
115+				a gamepads.n.a
116+				b gamepads.n.b
117+				back ui.sms_pause
118+				guide ui.exit
119+				leftshoulder gamepads.n.mode
120+				leftstick ui.save_state
121+				rightshoulder gamepads.n.z
122+				rightstick ui.prev_speed
123+				start gamepads.n.start
124+				x gamepads.n.x
125+				y gamepads.n.y
126+			}
127+			dpads {
128+				0 {
129+					down gamepads.n.down
130+					left gamepads.n.left
131+					right gamepads.n.right
132+					up gamepads.n.up
133+				}
134+			}
135+		}
136+		xbox_360_6b_right {
137+			axes {
138+				lefttrigger ui.next_speed
139+				leftx.negative gamepads.n.up
140+				leftx.positive gamepads.n.down
141+				lefty.negative gamepads.n.left
142+				lefty.positive gamepads.n.right
143+				righttrigger gamepads.n.c
144+			}
145+			buttons {
146+				a gamepads.n.a
147+				b gamepads.n.b
148+				back ui.sms_pause
149+				guide ui.exit
150+				leftshoulder gamepads.n.mode
151+				leftstick ui.save_state
152+				rightshoulder gamepads.n.z
153+				rightstick ui.prev_speed
154+				start gamepads.n.start
155+				x gamepads.n.x
156+				y gamepads.n.y
157+			}
158+			dpads {
159+				0 {
160+					down gamepads.n.down
161+					left gamepads.n.left
162+					right gamepads.n.right
163+					up gamepads.n.up
164+				}
165+			}
166+		}
167+		xbone_6b_right {
168+			axes {
169+				lefttrigger ui.next_speed
170+				leftx.negative gamepads.n.up
171+				leftx.positive gamepads.n.down
172+				lefty.negative gamepads.n.left
173+				lefty.positive gamepads.n.right
174+				righttrigger gamepads.n.c
175+			}
176+			buttons {
177+				a gamepads.n.a
178+				b gamepads.n.b
179+				back ui.sms_pause
180+				guide ui.exit
181+				leftshoulder gamepads.n.mode
182+				leftstick ui.save_state
183+				rightshoulder gamepads.n.z
184+				rightstick ui.prev_speed
185+				start gamepads.n.start
186+				x gamepads.n.x
187+				y gamepads.n.y
188+			}
189+			dpads {
190+				0 {
191+					down gamepads.n.down
192+					left gamepads.n.left
193+					right gamepads.n.right
194+					up gamepads.n.up
195+				}
196+			}
197+		}
198+		genesis_6b_bumpers {
199+			axes {
200+				lefttrigger ui.exit
201+				righttrigger gamepads.n.mode
202+			}
203+			buttons {
204+				a gamepads.n.a
205+				b gamepads.n.b
206+				back ui.sms_pause
207+				guide ui.exit
208+				leftshoulder gamepads.n.z
209+				rightshoulder gamepads.n.c
210+				start gamepads.n.start
211+				x gamepads.n.x
212+				y gamepads.n.y
213+			}
214+			dpads {
215+				0 {
216+					down gamepads.n.down
217+					left gamepads.n.left
218+					right gamepads.n.right
219+					up gamepads.n.up
220+				}
221+			}
222+		}
223+		saturn_6b_bumpers {
224+			axes {
225+				lefttrigger ui.exit
226+				righttrigger gamepads.n.mode
227+			}
228+			buttons {
229+				a gamepads.n.a
230+				b gamepads.n.b
231+				back ui.sms_pause
232+				guide ui.exit
233+				leftshoulder gamepads.n.z
234+				rightshoulder gamepads.n.c
235+				start gamepads.n.start
236+				x gamepads.n.x
237+				y gamepads.n.y
238+			}
239+			dpads {
240+				0 {
241+					down gamepads.n.down
242+					left gamepads.n.left
243+					right gamepads.n.right
244+					up gamepads.n.up
245+				}
246+			}
247+		}
248+	}
249+	mice {
250+		0 {
251+			motion mouse.1.motion
252+			buttons {
253+				1 mouse.1.left
254+				2 mouse.1.middle
255+				3 mouse.1.right
256+				4 mouse.1.start
257+			}
258+		}
259+		#having the second host mouse also mapped to the first emulated
260+		#mouse is useful for laptop users with an external mouse
261+		1 {
262+			motion mouse.1.motion
263+			buttons {
264+				1 mouse.1.left
265+				2 mouse.1.middle
266+				3 mouse.1.right
267+				4 mouse.1.start
268+			}
269+		}
270+	}
271+}
272+
273+io {
274+	devices {
275+		1 gamepad6.1
276+		2 gamepad6.2
277+	}
278+}
279+
280+video {
281+	#special value "stretch" will cause aspect to match window aspect ratio
282+	aspect 4:3
283+	width 640
284+	#height is normally calculated automatically from width using the aspect setting
285+	#if you would like to set it explicitly, uncomment the line below
286+	#height 480
287+	ntsc {
288+		overscan {
289+			#these values will result in square pixels in H40 mode
290+			top 2
291+			bottom 1
292+			#if you want to completely hide the border instead
293+			#comment out those two lines and uncomment these
294+			#top 11
295+			#bottom 8
296+			
297+			#these values will completely hide the horizontal border
298+			left 13
299+			right 14
300+		}
301+	}
302+	pal {
303+		overscan {
304+			#these values will produce the same size border in V30 mode
305+			#as the default NTSC settings will produce in V24 mode
306+			#this results in a slightly vertically squished picture
307+			#which is probably approximately correct on a properly calibrated TV
308+			top 21
309+			bottom 17
310+			#for square pixels and zero border in V30 mode
311+			#coment out those two lines and uncomment these
312+			#top 30
313+			#bottom 24
314+			
315+			#these values will completely hide the horizontal border
316+			left 13
317+			right 14
318+		}
319+	}
320+}
321+
322+audio {
323+	rate 48000
324+	buffer 512
325+	lowpass_cutoff 3390
326+}
327+
328+clocks {
329+	m68k_divider 7
330+	max_cycles 3420
331+	speeds {
332+		0 100
333+		1 150
334+		2 200
335+		3 300
336+		4 400
337+		5 25
338+		6 50
339+		7 75
340+	}
341+}
342+
343+ui {
344+	#specifies the ROM that implements the Menu UI
345+	rom menu.bin
346+	#starting path for ROM browsing, accepts special variables $HOME, $EXEDIR
347+	#and variables defined in the OS environment
348+	initial_path $HOME
349+	#if this is set to on, then the menu will remember the last path when visited
350+	#if it's set to off, initial_path will always be used on startup
351+	remember_path on
352+	#path for storing internal screenshots, accepts the same variables as initial_path
353+	screenshot_path $HOME
354+	#see strftime for the format specifiers valid in screenshot_template
355+	screenshot_template blastem_%Y%m%d_%H%M%S.png
356+	#path template for saving SRAM, EEPROM and savestates
357+	#accepts special variables $HOME, $EXEDIR, $USERDATA, $ROMNAME
358+	save_path $USERDATA/blastem/$ROMNAME
359+	#space delimited list of file extensions to filter against in menu
360+	extensions bin gen md smd sms gg zip gz
361+	#specifies the preferred save-state format, set to gst for Genecyst compatible states
362+	state_format native
363+}
364+
365+system {
366+	#controls how the emulated system is synced to the host
367+	#video provides the smoothest experience when the host and emulated system have similar refresh rates
368+	#audio provides lower audio latency, especially when there is a refresh rate mismatch
369+	sync_source audio
370+	#set this to random to debug initialization bugs
371+	ram_init zero
372+	default_region U
373+	#controls whether MegaWiFi support is enabled or not
374+	#MegaWiFi allows ROMs to make connections to the internet
375+	#so it should only be enabled for ROMs you trust
376+	megawifi off
377+}
A dis.c
+407, -0
  1@@ -0,0 +1,407 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "68kinst.h"
  8+#include <stdio.h>
  9+#include <stdlib.h>
 10+#include <string.h>
 11+#include <stdarg.h>
 12+#include <ctype.h>
 13+#include "vos_program_module.h"
 14+#include "tern.h"
 15+#include "util.h"
 16+
 17+uint8_t visited[(16*1024*1024)/16];
 18+uint16_t label[(16*1024*1024)/8];
 19+
 20+void fatal_error(char *format, ...)
 21+{
 22+	va_list args;
 23+	va_start(args, format);
 24+	vfprintf(stderr, format, args);
 25+	va_end(args);
 26+	exit(1);
 27+}
 28+
 29+
 30+void visit(uint32_t address)
 31+{
 32+	address &= 0xFFFFFF;
 33+	visited[address/16] |= 1 << ((address / 2) % 8);
 34+}
 35+
 36+void reference(uint32_t address)
 37+{
 38+	address &= 0xFFFFFF;
 39+	//printf("referenced: %X\n", address);
 40+	label[address/16] |= 1 << (address % 16);
 41+}
 42+
 43+uint8_t is_visited(uint32_t address)
 44+{
 45+	address &= 0xFFFFFF;
 46+	return visited[address/16] & (1 << ((address / 2) % 8));
 47+}
 48+
 49+uint16_t is_label(uint32_t address)
 50+{
 51+	address &= 0xFFFFFF;
 52+	return label[address/16] & (1 << (address % 16));
 53+}
 54+
 55+typedef struct {
 56+	uint32_t num_labels;
 57+	uint32_t storage;
 58+	char     *labels[];
 59+} label_names;
 60+
 61+tern_node * add_label(tern_node * head, char * name, uint32_t address)
 62+{
 63+	char key[MAX_INT_KEY_SIZE];
 64+	address &= 0xFFFFFF;
 65+	reference(address);
 66+	tern_int_key(address, key);
 67+	label_names * names = tern_find_ptr(head, key);
 68+	if (names)
 69+	{
 70+		if (names->num_labels == names->storage)
 71+		{
 72+			names->storage = names->storage + (names->storage >> 1);
 73+			names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *));
 74+		}
 75+	} else {
 76+		names = malloc(sizeof(label_names) + 4 * sizeof(char *));
 77+		names->num_labels = 0;
 78+		names->storage = 4;
 79+		head = tern_insert_ptr(head, key, names);
 80+	}
 81+	names->labels[names->num_labels++] = strdup(name);
 82+	return head;
 83+}
 84+
 85+typedef struct deferred {
 86+	uint32_t address;
 87+	struct deferred *next;
 88+} deferred;
 89+
 90+deferred * defer(uint32_t address, deferred * next)
 91+{
 92+	if (is_visited(address) || address & 1) {
 93+		return next;
 94+	}
 95+	//printf("deferring %X\n", address);
 96+	deferred * d = malloc(sizeof(deferred));
 97+	d->address = address;
 98+	d->next = next;
 99+	return d;
100+}
101+
102+void check_reference(m68kinst * inst, m68k_op_info * op)
103+{
104+	switch(op->addr_mode)
105+	{
106+	case MODE_PC_DISPLACE:
107+		reference(inst->address + 2 + op->params.regs.displacement);
108+		break;
109+	case MODE_ABSOLUTE:
110+	case MODE_ABSOLUTE_SHORT:
111+		reference(op->params.immed);
112+		break;
113+	}
114+}
115+
116+int label_fun(char *dst, uint32_t address, void * data)
117+{
118+	tern_node * labels = data;
119+	char key[MAX_INT_KEY_SIZE];
120+	label_names * names = tern_find_ptr(labels, tern_int_key(address & 0xFFFFFF, key));
121+	if (names)
122+	{
123+		return sprintf(dst, "%s", names->labels[0]);
124+	} else {
125+		return m68k_default_label_fun(dst, address, NULL);
126+	}
127+}
128+
129+char * strip_ws(char * text)
130+{
131+	while (*text && (!isprint(*text) || isblank(*text)))
132+	{
133+		text++;
134+	}
135+	char * ret = text;
136+	text = ret + strlen(ret) - 1;
137+	while (text > ret && (!isprint(*text) || isblank(*text)))
138+	{
139+		*text = 0;
140+		text--;
141+	}
142+	return ret;
143+}
144+
145+int main(int argc, char ** argv)
146+{
147+	long filesize;
148+	unsigned short *filebuf;
149+	char disbuf[1024];
150+	m68kinst instbuf;
151+	unsigned short * cur;
152+	deferred *def = NULL, *tmpd;
153+
154+	uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0;
155+	tern_node * named_labels = NULL;
156+
157+	uint32_t address_off = 0, address_end;
158+	for(uint8_t opt = 2; opt < argc; ++opt) {
159+		if (argv[opt][0] == '-') {
160+			FILE * address_log;
161+			switch (argv[opt][1])
162+			{
163+			case 'l':
164+				labels = 1;
165+				break;
166+			case 'a':
167+				addr = 1;
168+				break;
169+			case 'o':
170+				only = 1;
171+				break;
172+			case 'v':
173+				vos = 1;
174+				break;
175+			case 'r':
176+				reset = 1;
177+				break;
178+			case 's':
179+				opt++;
180+				if (opt >= argc) {
181+					fputs("-s must be followed by an offset\n", stderr);
182+					exit(1);
183+				}
184+				address_off = strtol(argv[opt], NULL, 0);
185+				break;
186+			case 'f':
187+				opt++;
188+				if (opt >= argc) {
189+					fputs("-f must be followed by a filename\n", stderr);
190+					exit(1);
191+				}
192+				address_log = fopen(argv[opt], "r");
193+				if (!address_log) {
194+					fprintf(stderr, "Failed to open %s for reading\n", argv[opt]);
195+					exit(1);
196+				}
197+				while (fgets(disbuf, sizeof(disbuf), address_log)) {
198+				 	if (disbuf[0]) {
199+						char *end;
200+						uint32_t address = strtol(disbuf, &end, 16);
201+						if (address) {
202+							def = defer(address, def);
203+							reference(address);
204+							if (*end == '=') {
205+								named_labels = add_label(named_labels, strip_ws(end+1), address);
206+							}
207+						}
208+					}
209+				}
210+				fclose(address_log);
211+			}
212+		} else {
213+			char *end;
214+			uint32_t address = strtol(argv[opt], &end, 16);
215+			def = defer(address, def);
216+			reference(address);
217+			if (*end == '=') {
218+				named_labels = add_label(named_labels, end+1, address);
219+			}
220+		}
221+	}
222+	FILE * f = fopen(argv[1], "rb");
223+	fseek(f, 0, SEEK_END);
224+	filesize = ftell(f);
225+	fseek(f, 0, SEEK_SET);
226+
227+	char int_key[MAX_INT_KEY_SIZE];
228+	if (vos)
229+	{
230+		vos_program_module header;
231+		vos_read_header(f, &header);
232+		vos_read_alloc_module_map(f, &header);
233+		address_off = header.user_boundary;
234+		address_end = address_off + filesize - 0x1000;
235+		def = defer(header.main_entry_link.code_address, def);
236+		named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address);
237+		for (int i = 0; i < header.n_modules; i++)
238+		{
239+			if (!reset || header.module_map_entries[i].code_address != header.user_boundary)
240+			{
241+				def = defer(header.module_map_entries[i].code_address, def);
242+			}
243+			named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address);
244+		}
245+		fseek(f, 0x1000, SEEK_SET);
246+		filebuf = malloc(filesize - 0x1000);
247+		if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2)
248+		{
249+			fprintf(stderr, "Failure while reading file %s\n", argv[1]);
250+		}
251+		fclose(f);
252+		for(cur = filebuf; cur - filebuf < ((filesize - 0x1000)/2); ++cur)
253+		{
254+			*cur = (*cur >> 8) | (*cur << 8);
255+		}
256+		if (reset)
257+		{
258+			def = defer(filebuf[2] << 16 | filebuf[3], def);
259+			named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]);
260+		}
261+	} else {
262+		address_end = address_off + filesize;
263+		filebuf = malloc(filesize);
264+		if (fread(filebuf, 2, filesize/2, f) != filesize/2)
265+		{
266+			fprintf(stderr, "Failure while reading file %s\n", argv[1]);
267+		}
268+		fclose(f);
269+		for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
270+		{
271+			*cur = (*cur >> 8) | (*cur << 8);
272+		}
273+		uint32_t start = filebuf[2] << 16 | filebuf[3];
274+		uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2];
275+		uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2];
276+		uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2];
277+		named_labels = add_label(named_labels, "start", start);
278+		named_labels = add_label(named_labels, "int_2", int_2);
279+		named_labels = add_label(named_labels, "int_4", int_4);
280+		named_labels = add_label(named_labels, "int_6", int_6);
281+		if (!def || !only) {
282+			def = defer(start, def);
283+			def = defer(int_2, def);
284+			def = defer(int_4, def);
285+			def = defer(int_6, def);
286+		}
287+	}
288+	uint16_t *encoded, *next;
289+	uint32_t size, tmp_addr;
290+	uint32_t address;
291+	while(def) {
292+		do {
293+			encoded = NULL;
294+			address = def->address;
295+			if (!is_visited(address)) {
296+				encoded = filebuf + (address - address_off)/2;
297+			}
298+			tmpd = def;
299+			def = def->next;
300+			free(tmpd);
301+		} while(def && encoded == NULL);
302+		if (!encoded) {
303+			break;
304+		}
305+		for(;;) {
306+			if (address > address_end || address < address_off) {
307+				break;
308+			}
309+			visit(address);
310+			next = m68k_decode(encoded, &instbuf, address);
311+			address += (next-encoded)*2;
312+			encoded = next;
313+			//m68k_disasm(&instbuf, disbuf);
314+			//printf("%X: %s\n", instbuf.address, disbuf);
315+			check_reference(&instbuf, &(instbuf.src));
316+			check_reference(&instbuf, &(instbuf.dst));
317+			if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE || instbuf.op == M68K_INVALID) {
318+				break;
319+			}
320+			if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) {
321+				if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) {
322+					address = instbuf.address + 2 + instbuf.src.params.immed;
323+					encoded = filebuf + (address - address_off)/2;
324+					reference(address);
325+					if (is_visited(address)) {
326+						break;
327+					}
328+				} else {
329+					tmp_addr = instbuf.address + 2 + instbuf.src.params.immed;
330+					reference(tmp_addr);
331+					def = defer(tmp_addr, def);
332+				}
333+			} else if(instbuf.op == M68K_JMP) {
334+				if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) {
335+					address = instbuf.src.params.immed;
336+					encoded = filebuf + (address - address_off)/2;
337+					if (is_visited(address)) {
338+						break;
339+					}
340+				} else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) {
341+					address = instbuf.src.params.regs.displacement + instbuf.address + 2;
342+					encoded = filebuf + (address - address_off)/2;
343+					if (is_visited(address)) {
344+						break;
345+					}
346+				} else {
347+					break;
348+				}
349+			} else if(instbuf.op == M68K_JSR) {
350+				if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) {
351+					def = defer(instbuf.src.params.immed, def);
352+				} else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) {
353+					def = defer(instbuf.src.params.regs.displacement + instbuf.address + 2, def);
354+				}
355+			}
356+		}
357+	}
358+	if (labels) {
359+		for (address = 0; address < address_off; address++) {
360+			if (is_label(address)) {
361+				printf("ADR_%X equ $%X\n", address, address);
362+			}
363+		}
364+		for (address = filesize; address < (16*1024*1024); address++) {
365+			char key[MAX_INT_KEY_SIZE];
366+			tern_int_key(address, key);
367+			label_names *names = tern_find_ptr(named_labels, key);
368+			if (names) {
369+				for (int i = 0; i < names->num_labels; i++)
370+				{
371+					printf("%s equ $%X\n", names->labels[i], address);
372+				}
373+			} else if (is_label(address)) {
374+				printf("ADR_%X equ $%X\n", address, address);
375+			}
376+		}
377+		puts("");
378+	}
379+	for (address = address_off; address < address_end; address+=2) {
380+		if (is_visited(address)) {
381+			encoded = filebuf + (address-address_off)/2;
382+			m68k_decode(encoded, &instbuf, address);
383+			if (labels) {
384+				m68k_disasm_labels(&instbuf, disbuf, label_fun, named_labels);
385+				char keybuf[MAX_INT_KEY_SIZE];
386+				label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf));
387+				if (names)
388+				{
389+					for (int i = 0; i < names->num_labels; i++)
390+					{
391+						printf("%s:\n", names->labels[i]);
392+					}
393+				} else if (is_label(instbuf.address)) {
394+					printf("ADR_%X:\n", instbuf.address);
395+				}
396+				if (addr) {
397+					printf("\t%s\t;%X\n", disbuf, instbuf.address);
398+				} else {
399+					printf("\t%s\n", disbuf);
400+				}
401+			} else {
402+				m68k_disasm(&instbuf, disbuf);
403+				printf("%X: %s\n", instbuf.address, disbuf);
404+			}
405+		}
406+	}
407+	return 0;
408+}
+105, -0
  1@@ -0,0 +1,105 @@
  2+CONSOLE_PORT equ 0
  3+STATUS_PORT  equ 1
  4+EXIT_PORT    equ 2
  5+	org $E400
  6+	jp handle_call
  7+	ld a, (should_exit)
  8+	dec a
  9+	jr z, do_exit
 10+	ld a, 1
 11+	ld (should_exit), a
 12+	jp $100
 13+do_exit:
 14+no_impl
 15+	out (EXIT_PORT), a
 16+should_exit:
 17+	dc.b 0
 18+	
 19+console_in:
 20+	in a, (CONSOLE_PORT)
 21+	ld l, a
 22+	ret
 23+console_out:
 24+	ld a, e
 25+	out (CONSOLE_PORT), a
 26+	ret
 27+get_iobyte:
 28+	ld a, (3)
 29+	ld l, a
 30+	ret
 31+set_iobyte:
 32+	ld a, e
 33+	ld (3), a
 34+	ret
 35+write_string:
 36+	ld c, '$'
 37+	jp .start
 38+.continue
 39+	out (CONSOLE_PORT), a
 40+	inc de
 41+.start
 42+	ld a, (de)
 43+	cp c
 44+	jr nz, .continue
 45+	;flush output
 46+	out (STATUS_PORT),a 
 47+	ret
 48+read_string:
 49+	ld a, (de)
 50+	ld c, a
 51+	ld b, $A ;newline
 52+	inc c
 53+	inc de
 54+	push de
 55+	inc de
 56+	jp .start
 57+.continue
 58+	in a, (CONSOLE_PORT)
 59+	cp b
 60+	jr z, .end
 61+	ld (de), a
 62+	inc de
 63+.start
 64+	dec c
 65+	jr nz, .continue
 66+	;todo: consume excess characters
 67+.end
 68+	pop hl
 69+	ex de, hl
 70+	sbc hl, de
 71+	ld a, l
 72+	ld (de), a
 73+	ret
 74+
 75+console_status:
 76+	in a, (STATUS_PORT)
 77+	ld l, a
 78+	ret
 79+
 80+handle_call:
 81+	ld a, c
 82+	or a
 83+	jr z, do_exit
 84+	dec a
 85+	jr z, console_in
 86+	dec a
 87+	jr z, console_out
 88+	dec a
 89+	jr z, no_impl ;aux reader input
 90+	dec a
 91+	jr z, no_impl ;aux punch output
 92+	dec a
 93+	jr z, no_impl ;printer output
 94+	dec a
 95+	jr z, no_impl ;direct console IO
 96+	dec a
 97+	jr z, get_iobyte
 98+	dec a
 99+	jr z, set_iobyte
100+	dec a
101+	jr z, write_string
102+	dec a
103+	jr z, read_string
104+	dec a
105+	jr z, console_status
106+	jp no_impl
+22, -0
 1@@ -0,0 +1,22 @@
 2+    dc.l $0, start
 3+start:
 4+	moveq #42, d0
 5+	bsr fib
 6+	reset
 7+fib:
 8+	cmp.l #2, d0
 9+	blt base
10+	subq.l #1, d0
11+	move.l d0, -(a7)
12+	bsr fib
13+	move.l (a7), d1
14+	exg d0, d1
15+	move.l d1, (a7)
16+	subq.l #1, d0
17+	bsr fib
18+	move.l (a7)+, d1
19+	add.l d1, d0
20+	rts
21+base:
22+	moveq #1, d0
23+	rts
+1, -0
1@@ -0,0 +1 @@
2+font.png,16,0,raw,nopal
+0, -0
+1, -0
1@@ -0,0 +1 @@
2+font_interlace_variable.png,16,0,raw,nopal,interlace
+0, -0
+553, -0
  1@@ -0,0 +1,553 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#define GDB_IN_FD STDIN_FILENO
  8+#define GDB_OUT_FD STDOUT_FILENO
  9+#define GDB_READ read
 10+#define GDB_WRITE write
 11+
 12+#include "gdb_remote.h"
 13+#include "68kinst.h"
 14+#include "debug.h"
 15+#include "util.h"
 16+#include <unistd.h>
 17+#include <fcntl.h>
 18+#include <stddef.h>
 19+#include <stdlib.h>
 20+#include <stdio.h>
 21+#include <string.h>
 22+
 23+
 24+
 25+#define INITIAL_BUFFER_SIZE (16*1024)
 26+
 27+#ifdef DO_DEBUG_PRINT
 28+#define dfprintf fprintf
 29+#else
 30+#define dfprintf
 31+#endif
 32+
 33+char * buf = NULL;
 34+char * curbuf = NULL;
 35+char * end = NULL;
 36+size_t bufsize;
 37+int cont = 0;
 38+int expect_break_response=0;
 39+uint32_t resume_pc;
 40+
 41+
 42+static uint16_t branch_t;
 43+static uint16_t branch_f;
 44+
 45+static bp_def * breakpoints = NULL;
 46+static uint32_t bp_index = 0;
 47+
 48+
 49+void hex_32(uint32_t num, char * out)
 50+{
 51+	for (int32_t shift = 28; shift >= 0; shift -= 4)
 52+	{
 53+		uint8_t nibble = num >> shift & 0xF;
 54+		*(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
 55+	}
 56+}
 57+
 58+void hex_16(uint16_t num, char * out)
 59+{
 60+	for (int16_t shift = 14; shift >= 0; shift -= 4)
 61+	{
 62+		uint8_t nibble = num >> shift & 0xF;
 63+		*(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
 64+	}
 65+}
 66+
 67+void hex_8(uint8_t num, char * out)
 68+{
 69+	uint8_t nibble = num >> 4;
 70+	*(out++) = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
 71+	nibble = num & 0xF;
 72+	*out = nibble > 9 ? nibble - 0xA + 'A' : nibble + '0';
 73+}
 74+
 75+void gdb_calc_checksum(char * command, char *out)
 76+{
 77+	uint8_t checksum = 0;
 78+	while (*command)
 79+	{
 80+		checksum += *(command++);
 81+	}
 82+	hex_8(checksum, out);
 83+}
 84+
 85+void write_or_die(int fd, const void *buf, size_t count)
 86+{
 87+	if (GDB_WRITE(fd, buf, count) < count) {
 88+		fatal_error("Error writing to stdout\n");
 89+	}
 90+}
 91+
 92+void gdb_send_command(char * command)
 93+{
 94+	char end[3];
 95+	write_or_die(GDB_OUT_FD, "$", 1);
 96+	write_or_die(GDB_OUT_FD, command, strlen(command));
 97+	end[0] = '#';
 98+	gdb_calc_checksum(command, end+1);
 99+	write_or_die(GDB_OUT_FD, end, 3);
100+	dfprintf(stderr, "Sent $%s#%c%c\n", command, end[1], end[2]);
101+}
102+
103+uint32_t calc_status(m68k_context * context)
104+{
105+	uint32_t status = context->status << 3;
106+	for (int i = 0; i < 5; i++)
107+	{
108+		status <<= 1;
109+		status |= context->flags[i];
110+	}
111+	return status;
112+}
113+
114+void update_status(m68k_context * context, uint16_t value)
115+{
116+	context->status = value >> 8;
117+	for (int i = 4; i >= 0; i--)
118+	{
119+		context->flags[i] = value & 1;
120+		value >>= 1;
121+	}
122+}
123+
124+uint8_t m68k_read_byte(m68k_context * context, uint32_t address)
125+{
126+	
127+	genesis_context *gen = context->system;
128+	//TODO: Use generated read/write functions to support access to hardware that is not ROM or RAM
129+	uint16_t * word = get_native_pointer(address & 0xFFFFFFFE, (void **)context->mem_pointers, &context->options->gen);
130+	if (word) {	
131+	if (address & 1) {
132+		return *word;
133+	}
134+	return *word >> 8;
135+}
136+	if (address >= 0xA00000 && address < 0xA04000) {
137+		return gen->zram[address & 0x1FFF];
138+	}
139+	return 0;
140+}
141+
142+void m68k_write_byte(m68k_context * context, uint32_t address, uint8_t value)
143+{
144+	genesis_context *gen = context->system;
145+	//TODO: Use generated read/write functions so that memory map is properly respected
146+	uint16_t * word = get_native_pointer(address & 0xFFFFFFFE, (void **)context->mem_pointers, &context->options->gen);
147+	if (word) {
148+		if (address & 1) {
149+			*word = (*word & 0xFF00) | value;
150+		} else {
151+			*word = (*word & 0xFF) | value << 8;
152+		}
153+		//TODO: Deal with this more generally once m68k_handle_code_write can handle it
154+		if (address >= 0xE00000) {
155+			m68k_handle_code_write(address, context);
156+		}
157+		return;
158+	}
159+	if (address >= 0xA00000 && address < 0xA04000) {
160+		gen->zram[address & 0x1FFF] = value;
161+		genesis_context * gen = context->system;
162+		z80_handle_code_write(address & 0x1FFF, gen->z80);
163+		return;
164+	} else {
165+		return;
166+	}
167+}
168+
169+void gdb_run_command(m68k_context * context, uint32_t pc, char * command)
170+{
171+	char send_buf[512];
172+	dfprintf(stderr, "Received command %s\n", command);
173+	switch(*command)
174+	{
175+
176+	case 'c':
177+		if (*(command+1) != 0) {
178+			//TODO: implement resuming at an arbitrary address
179+			goto not_impl;
180+		}
181+		cont = 1;
182+		expect_break_response = 1;
183+		break;
184+	case 's': {
185+		if (*(command+1) != 0) {
186+			//TODO: implement resuming at an arbitrary address
187+			goto not_impl;
188+		}
189+		m68kinst inst;
190+		genesis_context *gen = context->system;
191+		uint16_t * pc_ptr = get_native_pointer(pc, (void **)context->mem_pointers, &context->options->gen);
192+		if (!pc_ptr) {
193+			fatal_error("Entered gdb remote debugger stub at address %X\n", pc);
194+		}
195+		uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF);
196+		uint32_t after = pc + (after_pc-pc_ptr)*2;
197+
198+		if (inst.op == M68K_RTS) {
199+			after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
200+		} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
201+			after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
202+		} else if(m68k_is_branch(&inst)) {
203+			if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
204+				branch_f = after;
205+				branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
206+				insert_breakpoint(context, branch_t, gdb_debug_enter);
207+			} else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) {
208+				branch_t = after;
209+				branch_f = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
210+				insert_breakpoint(context, branch_f, gdb_debug_enter);
211+			} else {
212+				after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
213+			}
214+		}
215+		insert_breakpoint(context, after, gdb_debug_enter);
216+
217+		cont = 1;
218+		expect_break_response = 1;
219+		break;
220+	}
221+	case 'H':
222+		if (command[1] == 'g' || command[1] == 'c') {;
223+			//no thread suport, just acknowledge
224+			gdb_send_command("OK");
225+		} else {
226+			goto not_impl;
227+		}
228+		break;
229+	case 'Z': {
230+		uint8_t type = command[1];
231+		if (type < '2') {
232+			uint32_t address = strtoul(command+3, NULL, 16);
233+			insert_breakpoint(context, address, gdb_debug_enter);
234+			bp_def *new_bp = malloc(sizeof(bp_def));
235+			new_bp->next = breakpoints;
236+			new_bp->address = address;
237+			new_bp->index = bp_index++;
238+			breakpoints = new_bp;
239+			gdb_send_command("OK");
240+		} else {
241+			//watchpoints are not currently supported
242+			gdb_send_command("");
243+		}
244+		break;
245+	}
246+	case 'z': {
247+		uint8_t type = command[1];
248+		if (type < '2') {
249+			uint32_t address = strtoul(command+3, NULL, 16);
250+			remove_breakpoint(context, address);
251+			bp_def **found = find_breakpoint(&breakpoints, address);
252+			if (*found)
253+			{
254+				bp_def * to_remove = *found;
255+				*found = to_remove->next;
256+				free(to_remove);
257+			}
258+			gdb_send_command("OK");
259+		} else {
260+			//watchpoints are not currently supported
261+			gdb_send_command("");
262+		}
263+		break;
264+	}
265+	case 'g': {
266+		char * cur = send_buf;
267+		for (int i = 0; i < 8; i++)
268+		{
269+			hex_32(context->dregs[i], cur);
270+			cur += 8;
271+		}
272+		for (int i = 0; i < 8; i++)
273+		{
274+			hex_32(context->aregs[i], cur);
275+			cur += 8;
276+		}
277+		hex_32(calc_status(context), cur);
278+		cur += 8;
279+		hex_32(pc, cur);
280+		cur += 8;
281+		*cur = 0;
282+		gdb_send_command(send_buf);
283+		break;
284+	}
285+	case 'm': {
286+		char * rest;
287+		uint32_t address = strtoul(command+1, &rest, 16);
288+		uint32_t size = strtoul(rest+1, NULL, 16);
289+		if (size > (sizeof(send_buf)-1)/2) {
290+			size = (sizeof(send_buf)-1)/2;
291+		}
292+		char *cur = send_buf;
293+		while (size)
294+		{
295+			hex_8(m68k_read_byte(context, address), cur);
296+			cur += 2;
297+			address++;
298+			size--;
299+		}
300+		*cur = 0;
301+		gdb_send_command(send_buf);
302+		break;
303+	}
304+	case 'M': {
305+		char * rest;
306+		uint32_t address = strtoul(command+1, &rest, 16);
307+		uint32_t size = strtoul(rest+1, &rest, 16);
308+
309+		char *cur = rest+1;
310+		while (size)
311+		{
312+			char tmp[3];
313+			tmp[0] = *(cur++);
314+			tmp[1] = *(cur++);
315+			tmp[2] = 0;
316+			m68k_write_byte(context, address, strtoul(tmp, NULL, 16));
317+			address++;
318+			size--;
319+		}
320+		gdb_send_command("OK");
321+		break;
322+	}
323+	case 'X':
324+		//binary transfers aren't supported currently as I don't feel like dealing with the escaping
325+		gdb_send_command("");
326+		break;
327+	case 'p': {
328+		unsigned long reg = strtoul(command+1, NULL, 16);
329+
330+		if (reg < 8) {
331+			hex_32(context->dregs[reg], send_buf);
332+		} else if (reg < 16) {
333+			hex_32(context->aregs[reg-8], send_buf);
334+		} else if (reg == 16) {
335+			hex_32(calc_status(context), send_buf);
336+		} else if (reg == 17) {
337+			hex_32(pc, send_buf);
338+		} else {
339+			send_buf[0] = 0;
340+		}
341+		send_buf[8] = 0;
342+		gdb_send_command(send_buf);
343+		break;
344+	}
345+	case 'P': {
346+		char *after = NULL;
347+		unsigned long reg = strtoul(command+1, &after, 16);
348+		uint32_t value = strtoul(after+1, NULL, 16);
349+
350+		if (reg < 8) {
351+			context->dregs[reg] = value;
352+		} else if (reg < 16) {
353+			context->aregs[reg-8] = value;
354+		} else if (reg == 16) {
355+			update_status(context, value);
356+		} else {
357+			//supporting updates to PC is going to be a pain
358+			gdb_send_command("E01");
359+			break;
360+		}
361+		gdb_send_command("OK");
362+		break;
363+	}
364+	case 'q':
365+		if (!memcmp("Supported", command+1, strlen("Supported"))) {
366+			sprintf(send_buf, "PacketSize=%X", (int)bufsize);
367+			gdb_send_command(send_buf);
368+		} else if (!memcmp("Attached", command+1, strlen("Attached"))) {
369+			//not really meaningful for us, but saying we spawned a new process
370+			//is probably closest to the truth
371+			gdb_send_command("0");
372+		} else if (!memcmp("Offsets", command+1, strlen("Offsets"))) {
373+			//no relocations, so offsets are all 0
374+			gdb_send_command("Text=0;Data=0;Bss=0");
375+		} else if (!memcmp("Symbol", command+1, strlen("Symbol"))) {
376+			gdb_send_command("");
377+		} else if (!memcmp("TStatus", command+1, strlen("TStatus"))) {
378+			//TODO: actual tracepoint support
379+			gdb_send_command("T0;tnotrun:0");
380+		} else if (!memcmp("TfV", command+1, strlen("TfV")) || !memcmp("TfP", command+1, strlen("TfP"))) {
381+			//TODO: actual tracepoint support
382+			gdb_send_command("");
383+		} else if (command[1] == 'C') {
384+			//we only support a single thread currently, so send 1
385+			gdb_send_command("QC1");
386+		} else if (!strcmp("fThreadInfo", command + 1)) {
387+			//we only support a single thread currently, so send 1
388+			gdb_send_command("m1");
389+		} else if (!strcmp("sThreadInfo", command + 1)) {
390+			gdb_send_command("l");
391+		} else {
392+			goto not_impl;
393+		}
394+		break;
395+	case 'v':
396+		if (!memcmp("Cont?", command+1, strlen("Cont?"))) {
397+			gdb_send_command("vCont;c;C;s;S");
398+		} else if (!strcmp("MustReplyEmpty", command + 1)) {
399+			gdb_send_command("");
400+		} else if (!memcmp("Cont;", command+1, strlen("Cont;"))) {
401+			switch (*(command + 1 + strlen("Cont;")))
402+			{
403+			case 'c':
404+			case 'C':
405+				//might be interesting to have continue with signal fire a
406+				//trap exception or something, but for no we'll treat it as
407+				//a normal continue
408+				cont = 1;
409+				expect_break_response = 1;
410+				break;
411+			case 's':
412+			case 'S': {
413+				m68kinst inst;
414+				genesis_context *gen = context->system;
415+				uint16_t * pc_ptr = get_native_pointer(pc, (void **)context->mem_pointers, &context->options->gen);
416+				if (!pc_ptr) {
417+					fatal_error("Entered gdb remote debugger stub at address %X\n", pc);
418+				}
419+				uint16_t * after_pc = m68k_decode(pc_ptr, &inst, pc & 0xFFFFFF);
420+				uint32_t after = pc + (after_pc-pc_ptr)*2;
421+
422+				if (inst.op == M68K_RTS) {
423+					after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1);
424+				} else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
425+					after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1);
426+				} else if(m68k_is_branch(&inst)) {
427+					if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
428+						branch_f = after;
429+						branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
430+						insert_breakpoint(context, branch_t, gdb_debug_enter);
431+					} else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) {
432+						branch_t = after;
433+						branch_f = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
434+						insert_breakpoint(context, branch_f, gdb_debug_enter);
435+					} else {
436+						after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
437+					}
438+				}
439+				insert_breakpoint(context, after, gdb_debug_enter);
440+
441+				cont = 1;
442+				expect_break_response = 1;
443+				break;
444+			}
445+			default:
446+				goto not_impl;
447+			}
448+		} else {
449+			goto not_impl;
450+		}
451+		break;
452+	case '?':
453+		gdb_send_command("S05");
454+		break;
455+	default:
456+		goto not_impl;
457+
458+	}
459+	return;
460+not_impl:
461+	fatal_error("Command %s is not implemented, exiting...\n", command);
462+}
463+
464+void  gdb_debug_enter(m68k_context * context, uint32_t pc)
465+{
466+	dfprintf(stderr, "Entered debugger at address %X\n", pc);
467+	if (expect_break_response) {
468+		gdb_send_command("S05");
469+		expect_break_response = 0;
470+	}
471+	if ((pc & 0xFFFFFF) == branch_t) {
472+		bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
473+		if (!*f_bp) {
474+			remove_breakpoint(context, branch_f);
475+		}
476+		branch_t = branch_f = 0;
477+	} else if((pc & 0xFFFFFF) == branch_f) {
478+		bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t);
479+		if (!*t_bp) {
480+			remove_breakpoint(context, branch_t);
481+		}
482+		branch_t = branch_f = 0;
483+	}
484+	//Check if this is a user set breakpoint, or just a temporary one
485+	bp_def ** this_bp = find_breakpoint(&breakpoints, pc & 0xFFFFFF);
486+	if (!*this_bp) {
487+		remove_breakpoint(context, pc & 0xFFFFFF);
488+	}
489+	resume_pc = pc;
490+	cont = 0;
491+	uint8_t partial = 0;
492+	while(!cont)
493+	{
494+		if (!curbuf) {
495+			int numread = GDB_READ(GDB_IN_FD, buf, bufsize);
496+			if (numread < 0) {
497+				fatal_error("Failed to read on GDB input file descriptor\n");
498+			}
499+			dfprintf(stderr, "read %d bytes\n", numread);
500+			curbuf = buf;
501+			end = buf + numread;
502+		} else if (partial) {
503+			if (curbuf != buf) {
504+				memmove(curbuf, buf, end-curbuf);
505+				end -= curbuf - buf;
506+			}
507+			int numread = GDB_READ(GDB_IN_FD, end, bufsize - (end-buf));
508+			end += numread;
509+			curbuf = buf;
510+		}
511+		for (; curbuf < end; curbuf++)
512+		{
513+			if (*curbuf == '$')
514+			{
515+				curbuf++;
516+				char * start = curbuf;
517+				while (curbuf < end && *curbuf != '#') {
518+					curbuf++;
519+				}
520+				if (*curbuf == '#') {
521+					//check to make sure we've received the checksum bytes
522+					if (end-curbuf >= 2) {
523+						//TODO: verify checksum
524+						//Null terminate payload
525+						*curbuf = 0;
526+						//send acknowledgement
527+						if (GDB_WRITE(GDB_OUT_FD, "+", 1) < 1) {
528+							fatal_error("Error writing to stdout\n");
529+						}
530+						gdb_run_command(context, pc, start);
531+						curbuf += 2;
532+					}
533+				} else {
534+					curbuf--;
535+					partial = 1;
536+					break;
537+				}
538+			} else {
539+				dfprintf(stderr, "Ignoring character %c\n", *curbuf);
540+			}
541+		}
542+		if (curbuf == end) {
543+			curbuf = NULL;
544+		}
545+	}
546+}
547+
548+void gdb_remote_init(void)
549+{
550+	buf = malloc(INITIAL_BUFFER_SIZE);
551+	curbuf = NULL;
552+	bufsize = INITIAL_BUFFER_SIZE;
553+	disable_stdout_messages();
554+}
+8, -0
1@@ -0,0 +1,8 @@
2+#ifndef GDB_REMOTE_H_
3+#define GDB_REMOTE_H_
4+#include "genesis.h"
5+
6+void gdb_remote_init(void);
7+void gdb_debug_enter(m68k_context * context, uint32_t pc);
8+
9+#endif //GDB_REMOTE_H_
A gen.c
+16, -0
 1@@ -0,0 +1,16 @@
 2+#include <stdio.h>
 3+#include <stdlib.h>
 4+#include "gen.h"
 5+#include "mem.h"
 6+#include "util.h"
 7+
 8+void init_code_info(code_info *code)
 9+{
10+	size_t size = CODE_ALLOC_SIZE;
11+	code->cur = alloc_code(&size);
12+	if (!code->cur) {
13+		fatal_error("Failed to allocate memory for generated code\n");
14+	}
15+	code->last = code->cur + size/sizeof(code_word) - RESERVE_WORDS;
16+	code->stack_off = 0;
17+}
A gen.h
+47, -0
 1@@ -0,0 +1,47 @@
 2+#ifndef GEN_H_
 3+#define GEN_H_
 4+#include <stdint.h>
 5+
 6+#if defined(__x86_64__)
 7+#define X86_64
 8+#elif defined(__i386__)
 9+#define X86_32
10+#else
11+#error "The Wayland build requires an x86 host"
12+#endif
13+
14+#if defined(X86_64) || defined(X86_32)
15+typedef uint8_t code_word;
16+#define RESERVE_WORDS 5 //opcode + 4-byte displacement
17+#else
18+typedef uint32_t code_word;
19+#define RESERVE_WORDS 4 //1 push + 1 ldr + 1bx + 1 constant
20+#endif
21+typedef code_word * code_ptr;
22+#define CODE_ALLOC_SIZE (1024*1024)
23+
24+typedef struct {
25+	code_ptr cur;
26+	code_ptr last;
27+	uint32_t stack_off;
28+} code_info;
29+
30+void check_alloc_code(code_info *code, uint32_t inst_size);
31+
32+void init_code_info(code_info *code);
33+void call(code_info *code, code_ptr fun);
34+void jmp(code_info *code, code_ptr dest);
35+void jmp_r(code_info *code, uint8_t dst);
36+//standard return from subroutine instruction
37+void rts(code_info *code);
38+//call a function and put the arguments in the appropriate place according to the host ABI
39+void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...);
40+//like the above, but call a function pointer stored in a register
41+void call_args_r(code_info *code, uint8_t fun_reg, uint32_t num_args, ...);
42+//like the above, but follows other aspects of the ABI like stack alignment
43+//void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...);
44+#define call_args_abi call_args
45+void save_callee_save_regs(code_info *code);
46+void restore_callee_save_regs(code_info *code);
47+
48+#endif //GEN_H_
+585, -0
  1@@ -0,0 +1,585 @@
  2+/*
  3+ Copyright 2014 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "gen_arm.h"
  8+#include "mem.h"
  9+#include <stdio.h>
 10+#include <stdlib.h>
 11+
 12+#define OP_FIELD_SHIFT 21u
 13+
 14+//Data processing format instructions
 15+#define OP_AND 0x0u
 16+#define OP_EOR (0x1u << OP_FIELD_SHIFT)
 17+#define OP_SUB (0x2u << OP_FIELD_SHIFT)
 18+#define OP_RSB (0x3u << OP_FIELD_SHIFT)
 19+#define OP_ADD (0x4u << OP_FIELD_SHIFT)
 20+#define OP_ADC (0x5u << OP_FIELD_SHIFT)
 21+#define OP_SBC (0x6u << OP_FIELD_SHIFT)
 22+#define OP_RSC (0x7u << OP_FIELD_SHIFT)
 23+#define OP_TST (0x8u << OP_FIELD_SHIFT)
 24+#define OP_TEQ (0x9u << OP_FIELD_SHIFT)
 25+#define OP_CMP (0xAu << OP_FIELD_SHIFT)
 26+#define OP_CMN (0xBu << OP_FIELD_SHIFT)
 27+#define OP_ORR (0xCu << OP_FIELD_SHIFT)
 28+#define OP_MOV (0xDu << OP_FIELD_SHIFT)
 29+#define OP_BIC (0xEu << OP_FIELD_SHIFT)
 30+#define OP_MVN (0xFu << OP_FIELD_SHIFT)
 31+
 32+//branch instructions
 33+#define OP_B  0xA000000u
 34+#define OP_BL 0xB000000u
 35+#define OP_BX 0x12FFF10u
 36+
 37+//load/store
 38+#define OP_STR   0x4000000u
 39+#define OP_LDR   0x4100000u
 40+#define OP_STM   0x8000000u
 41+#define OP_LDM   0x8100000u
 42+#define POST_IND 0u
 43+#define PRE_IND  0x1000000u
 44+#define DIR_DOWN 0u
 45+#define DIR_UP   0x0800000u
 46+#define SZ_W     0u
 47+#define SZ_B     0x0400000u
 48+#define WRITE_B  0x0200000u
 49+#define OFF_IMM  0u
 50+#define OFF_REG  0x2000000u
 51+
 52+#define PUSH     (OP_STR | PRE_IND | OFF_IMM | SZ_W | WRITE_B | DIR_DOWN | sizeof(uint32_t) | (sp << 16))
 53+#define POP      (OP_LDR | POST_IND | OFF_IMM | SZ_W | DIR_UP | sizeof(uint32_t) | (sp << 16))
 54+#define PUSHM     (OP_STM | PRE_IND | SZ_W | WRITE_B | DIR_DOWN | (sp << 16))
 55+#define POPM      (OP_LDM | POST_IND | SZ_W | WRITE_B | DIR_UP | (sp << 16))
 56+
 57+#define IMMED    0x2000000u
 58+#define REG      0u
 59+
 60+
 61+uint32_t make_immed(uint32_t val)
 62+{
 63+	uint32_t rot_amount = 0;
 64+	for (; rot_amount < 0x20; rot_amount += 2)
 65+	{
 66+		uint32_t test_mask = ~(0xFF << rot_amount | 0xFF >> (32-rot_amount));
 67+		if (!(test_mask & val)) {
 68+			return val << rot_amount | val >> (32-rot_amount) | rot_amount << 7;
 69+		}
 70+	}
 71+	return INVALID_IMMED;
 72+}
 73+
 74+void check_alloc_code(code_info *code)
 75+{
 76+	if (code->cur == code->last) {
 77+		size_t size = CODE_ALLOC_SIZE;
 78+		uint32_t *next_code = alloc_code(&size);
 79+		if (!next_code) {
 80+			fatal_error("Failed to allocate memory for generated code\n");
 81+		}
 82+		if (next_code = code->last + RESERVE_WORDS) {
 83+			//new chunk is contiguous with the current one
 84+			code->last = next_code + size/sizeof(code_word) - RESERVE_WORDS;
 85+		} else {
 86+			uint32_t * from = code->cur + 2;
 87+			if (next_code - from < 0x400000 || from - next_code <= 0x400000) {
 88+				*from = CC_AL | OP_B | ((next_code - from) & 0xFFFFFF);
 89+			} else {
 90+				//push r0 onto the stack
 91+				*(from++) = CC_AL | PUSH;
 92+				uint32_t immed = make_immed((uint32_t)next_code);
 93+				if (immed == INVALID_IMMED) {
 94+					//Load target into r0 from word after next instruction into register 0
 95+					*(from++) = CC_AL | OP_LDR | OFF_IMM | DIR_DOWN | PRE_IND | SZ_W | (pc << 16) | 4;
 96+					from[1] = (uint32_t)next_code;
 97+				} else {
 98+					//Load target into r0
 99+					*(from++) = CC_AL | OP_MOV | IMMED | NO_COND | immed;
100+				}
101+				//branch to address in r0
102+				*from = CC_AL | OP_BX;
103+				code->last = next_code + size/sizeof(code_word) - RESERVE_WORDS;
104+				//pop r0
105+				*(next_code++) = CC_AL | POP;
106+				code->cur = next_code;
107+			}
108+		}
109+	}
110+}
111+
112+uint32_t data_proc(code_info *code, uint32_t cond, uint32_t op, uint32_t set_cond, uint32_t dst, uint32_t src1, uint32_t src2)
113+{
114+	check_alloc_code(code);
115+	*(code->cur++) = cond | op | set_cond | (src1 << 16) | (dst << 12) | src2;
116+
117+	return CODE_OK;
118+}
119+
120+uint32_t data_proci(code_info *code, uint32_t cond, uint32_t op, uint32_t set_cond, uint32_t dst, uint32_t src1, uint32_t immed)
121+{
122+	immed = make_immed(immed);
123+	if (immed == INVALID_IMMED) {
124+		return immed;
125+	}
126+	return data_proc(code, cond, op | IMMED, set_cond, dst, src1, immed);
127+}
128+
129+//TODO: support shifted register for op2
130+
131+uint32_t and(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
132+{
133+	return data_proc(code, CC_AL, OP_AND, set_cond, dst, src1, src2);
134+}
135+
136+uint32_t andi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
137+{
138+	return data_proci(code, CC_AL, OP_AND, set_cond, dst, src1, immed);
139+}
140+
141+uint32_t and_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
142+{
143+	return data_proc(code, cc, OP_AND, set_cond, dst, src1, src2);
144+}
145+
146+uint32_t andi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
147+{
148+	return data_proci(code, cc, OP_AND, set_cond, dst, src1, immed);
149+}
150+
151+uint32_t eor(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
152+{
153+	return data_proc(code, CC_AL, OP_EOR, set_cond, dst, src1, src2);
154+}
155+
156+uint32_t eori(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
157+{
158+	return data_proci(code, CC_AL, OP_EOR, set_cond, dst, src1, immed);
159+}
160+
161+uint32_t eor_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
162+{
163+	return data_proc(code, cc, OP_EOR, set_cond, dst, src1, src2);
164+}
165+
166+uint32_t eori_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
167+{
168+	return data_proci(code, cc, OP_EOR, set_cond, dst, src1, immed);
169+}
170+
171+uint32_t sub(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
172+{
173+	return data_proc(code, CC_AL, OP_SUB, set_cond, dst, src1, src2);
174+}
175+
176+uint32_t subi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
177+{
178+	return data_proci(code, CC_AL, OP_SUB, set_cond, dst, src1, immed);
179+}
180+
181+uint32_t sub_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
182+{
183+	return data_proc(code, cc, OP_SUB, set_cond, dst, src1, src2);
184+}
185+
186+uint32_t subi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
187+{
188+	return data_proci(code, cc, OP_SUB, set_cond, dst, src1, immed);
189+}
190+
191+uint32_t rsb(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
192+{
193+	return data_proc(code, CC_AL, OP_RSB, set_cond, dst, src1, src2);
194+}
195+
196+uint32_t rsbi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
197+{
198+	return data_proci(code, CC_AL, OP_RSB, set_cond, dst, src1, immed);
199+}
200+
201+uint32_t rsb_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
202+{
203+	return data_proc(code, cc, OP_RSB, set_cond, dst, src1, src2);
204+}
205+
206+uint32_t rsbi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
207+{
208+	return data_proci(code, cc, OP_RSB, set_cond, dst, src1, immed);
209+}
210+
211+uint32_t add(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
212+{
213+	return data_proc(code, CC_AL, OP_ADD, set_cond, dst, src1, src2);
214+}
215+
216+uint32_t addi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
217+{
218+	return data_proci(code, CC_AL, OP_ADD, set_cond, dst, src1, immed);
219+}
220+
221+uint32_t add_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
222+{
223+	return data_proc(code, cc, OP_ADD, set_cond, dst, src1, src2);
224+}
225+
226+uint32_t addi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
227+{
228+	return data_proci(code, cc, OP_ADD, set_cond, dst, src1, immed);
229+}
230+
231+uint32_t adc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
232+{
233+	return data_proc(code, CC_AL, OP_ADC, set_cond, dst, src1, src2);
234+}
235+
236+uint32_t adci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
237+{
238+	return data_proci(code, CC_AL, OP_ADC, set_cond, dst, src1, immed);
239+}
240+
241+uint32_t adc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
242+{
243+	return data_proc(code, cc, OP_ADC, set_cond, dst, src1, src2);
244+}
245+
246+uint32_t adci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
247+{
248+	return data_proci(code, cc, OP_ADC, set_cond, dst, src1, immed);
249+}
250+
251+uint32_t sbc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
252+{
253+	return data_proc(code, CC_AL, OP_SBC, set_cond, dst, src1, src2);
254+}
255+
256+uint32_t sbci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
257+{
258+	return data_proci(code, CC_AL, OP_SBC, set_cond, dst, src1, immed);
259+}
260+
261+uint32_t sbc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
262+{
263+	return data_proc(code, cc, OP_SBC, set_cond, dst, src1, src2);
264+}
265+
266+uint32_t sbci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
267+{
268+	return data_proci(code, cc, OP_SBC, set_cond, dst, src1, immed);
269+}
270+
271+uint32_t rsc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
272+{
273+	return data_proc(code, CC_AL, OP_RSC, set_cond, dst, src1, src2);
274+}
275+
276+uint32_t rsci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
277+{
278+	return data_proci(code, CC_AL, OP_RSC, set_cond, dst, src1, immed);
279+}
280+
281+uint32_t rsc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
282+{
283+	return data_proc(code, cc, OP_RSC, set_cond, dst, src1, src2);
284+}
285+
286+uint32_t rsci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
287+{
288+	return data_proci(code, cc, OP_RSC, set_cond, dst, src1, immed);
289+}
290+
291+uint32_t tst(code_info *code, uint32_t src1, uint32_t src2)
292+{
293+	return data_proc(code, CC_AL, OP_TST, SET_COND, r0, src1, src2);
294+}
295+
296+uint32_t tsti(code_info *code, uint32_t src1, uint32_t immed)
297+{
298+	return data_proci(code, CC_AL, OP_TST, SET_COND, r0, src1, immed);
299+}
300+
301+uint32_t tst_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc)
302+{
303+	return data_proc(code, cc, OP_TST, SET_COND, r0, src1, src2);
304+}
305+
306+uint32_t tsti_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc)
307+{
308+	return data_proci(code, cc, OP_TST, SET_COND, r0, src1, immed);
309+}
310+
311+uint32_t teq(code_info *code, uint32_t src1, uint32_t src2)
312+{
313+	return data_proc(code, CC_AL, OP_TEQ, SET_COND, r0, src1, src2);
314+}
315+
316+uint32_t teqi(code_info *code, uint32_t src1, uint32_t immed)
317+{
318+	return data_proci(code, CC_AL, OP_TEQ, SET_COND, r0, src1, immed);
319+}
320+
321+uint32_t teq_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc)
322+{
323+	return data_proc(code, cc, OP_TEQ, SET_COND, r0, src1, src2);
324+}
325+
326+uint32_t teqi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc)
327+{
328+	return data_proci(code, cc, OP_TEQ, SET_COND, r0, src1, immed);
329+}
330+
331+uint32_t cmp(code_info *code, uint32_t src1, uint32_t src2)
332+{
333+	return data_proc(code, CC_AL, OP_CMP, SET_COND, r0, src1, src2);
334+}
335+
336+uint32_t cmpi(code_info *code, uint32_t src1, uint32_t immed)
337+{
338+	return data_proci(code, CC_AL, OP_CMP, SET_COND, r0, src1, immed);
339+}
340+
341+uint32_t cmp_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc)
342+{
343+	return data_proc(code, cc, OP_CMP, SET_COND, r0, src1, src2);
344+}
345+
346+uint32_t cmpi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc)
347+{
348+	return data_proci(code, cc, OP_CMP, SET_COND, r0, src1, immed);
349+}
350+
351+uint32_t cmn(code_info *code, uint32_t src1, uint32_t src2)
352+{
353+	return data_proc(code, CC_AL, OP_CMN, SET_COND, r0, src1, src2);
354+}
355+
356+uint32_t cmni(code_info *code, uint32_t src1, uint32_t immed)
357+{
358+	return data_proci(code, CC_AL, OP_CMN, SET_COND, r0, src1, immed);
359+}
360+
361+uint32_t cmn_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc)
362+{
363+	return data_proc(code, cc, OP_CMN, SET_COND, r0, src1, src2);
364+}
365+
366+uint32_t cmni_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc)
367+{
368+	return data_proci(code, cc, OP_CMN, SET_COND, r0, src1, immed);
369+}
370+
371+uint32_t orr(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
372+{
373+	return data_proc(code, CC_AL, OP_ORR, set_cond, dst, src1, src2);
374+}
375+
376+uint32_t orri(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
377+{
378+	return data_proci(code, CC_AL, OP_ORR, set_cond, dst, src1, immed);
379+}
380+
381+uint32_t orr_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
382+{
383+	return data_proc(code, cc, OP_ORR, set_cond, dst, src1, src2);
384+}
385+
386+uint32_t orri_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
387+{
388+	return data_proci(code, cc, OP_ORR, set_cond, dst, src1, immed);
389+}
390+
391+uint32_t mov(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond)
392+{
393+	return data_proc(code, CC_AL, OP_MOV, set_cond, dst, 0, src2);
394+}
395+
396+uint32_t movi(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond)
397+{
398+	return data_proci(code, CC_AL, OP_MOV, set_cond, dst, 0, immed);
399+}
400+
401+uint32_t mov_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond)
402+{
403+	return data_proc(code, cc, OP_MOV, set_cond, dst, 0, src2);
404+}
405+
406+uint32_t movi_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond)
407+{
408+	return data_proci(code, cc, OP_MOV, set_cond, dst, 0, immed);
409+}
410+
411+uint32_t bic(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond)
412+{
413+	return data_proc(code, CC_AL, OP_BIC, set_cond, dst, src1, src2);
414+}
415+
416+uint32_t bici(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond)
417+{
418+	return data_proci(code, CC_AL, OP_BIC, set_cond, dst, src1, immed);
419+}
420+
421+uint32_t bic_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond)
422+{
423+	return data_proc(code, cc, OP_BIC, set_cond, dst, src1, src2);
424+}
425+
426+uint32_t bici_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond)
427+{
428+	return data_proci(code, cc, OP_BIC, set_cond, dst, src1, immed);
429+}
430+
431+uint32_t mvn(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond)
432+{
433+	return data_proc(code, CC_AL, OP_MVN, set_cond, dst, 0, src2);
434+}
435+
436+uint32_t mvni(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond)
437+{
438+	return data_proci(code, CC_AL, OP_MVN, set_cond, dst, 0, immed);
439+}
440+
441+uint32_t mvn_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond)
442+{
443+	return data_proc(code, cc, OP_MVN, set_cond, dst, 0, src2);
444+}
445+
446+uint32_t mvni_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond)
447+{
448+	return data_proci(code, cc, OP_MVN, set_cond, dst, 0, immed);
449+}
450+
451+uint32_t branchi(code_info *code, uint32_t cc, uint32_t op, uint32_t *dst)
452+{
453+	uint32_t * from = code->cur + 2;
454+	if (dst - from >= 0x400000 && from - dst > 0x400000) {
455+		return INVALID_IMMED;
456+	}
457+	check_alloc_code(code);
458+	*(code->cur++) = cc | op | ((dst - from) & 0xFFFFFF);
459+	return CODE_OK;
460+}
461+
462+uint32_t b(code_info *code, uint32_t *dst)
463+{
464+	return branchi(code, CC_AL, OP_B, dst);
465+}
466+
467+uint32_t b_cc(code_info *code, uint32_t *dst, uint32_t cc)
468+{
469+	return branchi(code, cc, OP_B, dst);
470+}
471+
472+uint32_t bl(code_info *code, uint32_t *dst)
473+{
474+	return branchi(code, CC_AL, OP_BL, dst);
475+}
476+
477+uint32_t bl_cc(code_info *code, uint32_t *dst, uint32_t cc)
478+{
479+	return branchi(code, cc, OP_BL, dst);
480+}
481+
482+uint32_t bx(code_info *code, uint32_t dst)
483+{
484+	check_alloc_code(code);
485+	*(code->cur++) = CC_AL | OP_BX | dst;
486+	return CODE_OK;
487+}
488+
489+uint32_t bx_cc(code_info *code, uint32_t dst, uint32_t cc)
490+{
491+	check_alloc_code(code);
492+	*(code->cur++) = cc | OP_BX | dst;
493+	return CODE_OK;
494+}
495+
496+uint32_t push(code_info *code, uint32_t reg)
497+{
498+	check_alloc_code(code);
499+	*(code->cur++) = CC_AL | PUSH | reg << 12;
500+	return CODE_OK;
501+}
502+
503+uint32_t push_cc(code_info *code, uint32_t reg, uint32_t cc)
504+{
505+	check_alloc_code(code);
506+	*(code->cur++) = cc | PUSH | reg << 12;
507+	return CODE_OK;
508+}
509+
510+uint32_t pushm(code_info *code, uint32_t reglist)
511+{
512+	check_alloc_code(code);
513+	*(code->cur++) = CC_AL | PUSHM | reglist;
514+	return CODE_OK;
515+}
516+
517+uint32_t pushm_cc(code_info *code, uint32_t reglist, uint32_t cc)
518+{
519+	check_alloc_code(code);
520+	*(code->cur++) = cc | PUSHM | reglist;
521+	return CODE_OK;
522+}
523+
524+uint32_t pop(code_info *code, uint32_t reg)
525+{
526+	check_alloc_code(code);
527+	*(code->cur++) = CC_AL | POP | reg << 12;
528+	return CODE_OK;
529+}
530+
531+uint32_t pop_cc(code_info *code, uint32_t reg, uint32_t cc)
532+{
533+	check_alloc_code(code);
534+	*(code->cur++) = cc | POP | reg << 12;
535+	return CODE_OK;
536+}
537+
538+uint32_t popm(code_info *code, uint32_t reglist)
539+{
540+	check_alloc_code(code);
541+	*(code->cur++) = CC_AL | POPM | reglist;
542+	return CODE_OK;
543+}
544+
545+uint32_t popm_cc(code_info *code, uint32_t reglist, uint32_t cc)
546+{
547+	check_alloc_code(code);
548+	*(code->cur++) = cc | POPM | reglist;
549+	return CODE_OK;
550+}
551+
552+uint32_t load_store_immoff(code_info *code, uint32_t op, uint32_t dst, uint32_t base, int32_t offset, uint32_t cc)
553+{
554+	if (offset >= 0x1000 || offset <= -0x1000) {
555+		return INVALID_IMMED;
556+	}
557+	check_alloc_code(code);
558+	uint32_t instruction = cc | op | POST_IND | OFF_IMM | SZ_W | base << 16 | dst << 12;
559+	if (offset >= 0) {
560+		instruction |= offset | DIR_UP;
561+	} else {
562+		instruction |= (-offset) | DIR_DOWN;
563+	}
564+	*(code->cur++) = instruction;
565+	return CODE_OK;
566+}
567+
568+uint32_t ldr_cc(code_info *code, uint32_t dst, uint32_t base, int32_t offset, uint32_t cc)
569+{
570+	return load_store_immoff(code, OP_LDR, dst, base, offset, cc);
571+}
572+
573+uint32_t ldr(code_info *code, uint32_t dst, uint32_t base, int32_t offset)
574+{
575+	return ldr_cc(code, dst, base, offset, CC_AL);
576+}
577+
578+uint32_t str_cc(code_info *code, uint32_t src, uint32_t base, int32_t offset, uint32_t cc)
579+{
580+	return load_store_immoff(code, OP_STR, src, base, offset, cc);
581+}
582+
583+uint32_t str(code_info *code, uint32_t src, uint32_t base, int32_t offset)
584+{
585+	return str_cc(code, src, base, offset, CC_AL);
586+}
+157, -0
  1@@ -0,0 +1,157 @@
  2+/*
  3+ Copyright 2014 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef GEN_ARM_H_
  8+#define GEN_ARM_H_
  9+
 10+#include <stdint.h>
 11+#include "gen.h"
 12+
 13+#define SET_COND 0x100000u
 14+#define NO_COND  0u
 15+
 16+#define CC_FIELD_SHIFT 28
 17+
 18+#define CC_EQ 0x0u
 19+#define CC_NE (0x1u << CC_FIELD_SHIFT)
 20+#define CC_CS (0x2u << CC_FIELD_SHIFT)
 21+#define CC_CC (0x3u << CC_FIELD_SHIFT)
 22+#define CC_MI (0x4u << CC_FIELD_SHIFT)
 23+#define CC_PL (0x5u << CC_FIELD_SHIFT)
 24+#define CC_VS (0x6u << CC_FIELD_SHIFT)
 25+#define CC_VC (0x7u << CC_FIELD_SHIFT)
 26+#define CC_HI (0x8u << CC_FIELD_SHIFT)
 27+#define CC_LS (0x9u << CC_FIELD_SHIFT)
 28+#define CC_GE (0xAu << CC_FIELD_SHIFT)
 29+#define CC_LT (0xBu << CC_FIELD_SHIFT)
 30+#define CC_GT (0xCu << CC_FIELD_SHIFT)
 31+#define CC_LE (0xDu << CC_FIELD_SHIFT)
 32+#define CC_AL (0xEu << CC_FIELD_SHIFT)
 33+
 34+#define INVALID_IMMED 0xFFFFFFFFu
 35+#define CODE_OK 0u
 36+
 37+enum {
 38+	r0,
 39+	r1,
 40+	r2,
 41+	r3,
 42+	r4,
 43+	r5,
 44+	r6,
 45+	r7,
 46+	r8,
 47+	r9,
 48+	r10,
 49+	r11,
 50+	r12,
 51+	sp,
 52+	lr,
 53+	pc
 54+};
 55+
 56+#define R0  0x1
 57+#define R1  0x2
 58+#define R2  0x4
 59+#define R3  0x8
 60+#define R4  0x10
 61+#define R5  0x20
 62+#define R6  0x40
 63+#define R7  0x80
 64+#define R8  0x100
 65+#define R9  0x200
 66+#define R10 0x400
 67+#define R11 0x800
 68+#define R12 0x1000
 69+#define SP  0x2000
 70+#define LR  0x4000
 71+#define PC  0x8000
 72+
 73+uint32_t and(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 74+uint32_t andi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 75+uint32_t and_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 76+uint32_t andi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 77+uint32_t eor(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 78+uint32_t eori(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 79+uint32_t eor_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 80+uint32_t eori_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 81+uint32_t sub(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 82+uint32_t subi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 83+uint32_t sub_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 84+uint32_t subi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 85+uint32_t rsb(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 86+uint32_t rsbi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 87+uint32_t rsb_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 88+uint32_t rsbi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 89+uint32_t add(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 90+uint32_t addi(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 91+uint32_t add_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 92+uint32_t addi_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 93+uint32_t adc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 94+uint32_t adci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 95+uint32_t adc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
 96+uint32_t adci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
 97+uint32_t sbc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
 98+uint32_t sbci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
 99+uint32_t sbc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
100+uint32_t sbci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
101+uint32_t rsc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
102+uint32_t rsci(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
103+uint32_t rsc_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
104+uint32_t rsci_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
105+uint32_t tst(code_info *code, uint32_t src1, uint32_t src2);
106+uint32_t tsti(code_info *code, uint32_t src1, uint32_t immed);
107+uint32_t tst_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc);
108+uint32_t tsti_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc);
109+uint32_t teq(code_info *code, uint32_t src1, uint32_t src2);
110+uint32_t teqi(code_info *code, uint32_t src1, uint32_t immed);
111+uint32_t teq_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc);
112+uint32_t teqi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc);
113+uint32_t cmp(code_info *code, uint32_t src1, uint32_t src2);
114+uint32_t cmpi(code_info *code, uint32_t src1, uint32_t immed);
115+uint32_t cmp_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc);
116+uint32_t cmpi_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc);
117+uint32_t cmn(code_info *code, uint32_t src1, uint32_t src2);
118+uint32_t cmni(code_info *code, uint32_t src1, uint32_t immed);
119+uint32_t cmn_cc(code_info *code, uint32_t src1, uint32_t src2, uint32_t cc);
120+uint32_t cmni_cc(code_info *code, uint32_t src1, uint32_t immed, uint32_t cc);
121+uint32_t orr(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
122+uint32_t orri(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
123+uint32_t orr_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
124+uint32_t orri_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
125+uint32_t mov(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond);
126+uint32_t movi(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond);
127+uint32_t mov_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond);
128+uint32_t movi_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond);
129+uint32_t bic(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t set_cond);
130+uint32_t bici(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t set_cond);
131+uint32_t bic_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t src2, uint32_t cc, uint32_t set_cond);
132+uint32_t bici_cc(code_info *code, uint32_t dst, uint32_t src1, uint32_t immed, uint32_t cc, uint32_t set_cond);
133+uint32_t mvn(code_info *code, uint32_t dst, uint32_t src2, uint32_t set_cond);
134+uint32_t mvni(code_info *code, uint32_t dst, uint32_t immed, uint32_t set_cond);
135+uint32_t mvn_cc(code_info *code, uint32_t dst, uint32_t src2, uint32_t cc, uint32_t set_cond);
136+uint32_t mvni_cc(code_info *code, uint32_t dst, uint32_t immed, uint32_t cc, uint32_t set_cond);
137+
138+uint32_t b(code_info *code, uint32_t *dst);
139+uint32_t b_cc(code_info *code, uint32_t *dst, uint32_t cc);
140+uint32_t bl(code_info *code, uint32_t *dst);
141+uint32_t bl_cc(code_info *code, uint32_t *dst, uint32_t cc);
142+uint32_t bx(code_info *code, uint32_t dst);
143+uint32_t bx_cc(code_info *code, uint32_t dst, uint32_t cc);
144+
145+uint32_t push(code_info *code, uint32_t reg);
146+uint32_t push_cc(code_info *code, uint32_t reg, uint32_t cc);
147+uint32_t pushm(code_info *code, uint32_t reglist);
148+uint32_t pushm_cc(code_info *code, uint32_t reglist, uint32_t cc);
149+uint32_t pop(code_info *code, uint32_t reg);
150+uint32_t pop_cc(code_info *code, uint32_t reg, uint32_t cc);
151+uint32_t popm(code_info *code, uint32_t reglist);
152+uint32_t popm_cc(code_info *code, uint32_t reglist, uint32_t cc);
153+uint32_t ldr_cc(code_info *code, uint32_t dst, uint32_t base, int32_t offset, uint32_t cc);
154+uint32_t ldr(code_info *code, uint32_t rst, uint32_t base, int32_t offset);
155+uint32_t str_cc(code_info *code, uint32_t src, uint32_t base, int32_t offset, uint32_t cc);
156+uint32_t str(code_info *code, uint32_t src, uint32_t base, int32_t offset);
157+
158+#endif //GEN_ARM_H_
+631, -0
  1@@ -0,0 +1,631 @@
  2+	dc.l $0, start
  3+	dc.l empty_handler
  4+	dc.l empty_handler
  5+	;$10
  6+	dc.l empty_handler
  7+	dc.l empty_handler
  8+	dc.l empty_handler
  9+	dc.l empty_handler
 10+	;$20
 11+	dc.l empty_handler
 12+	dc.l empty_handler
 13+	dc.l empty_handler
 14+	dc.l empty_handler
 15+	;$30
 16+	dc.l empty_handler
 17+	dc.l empty_handler
 18+	dc.l empty_handler
 19+	dc.l empty_handler
 20+	;$40
 21+	dc.l empty_handler
 22+	dc.l empty_handler
 23+	dc.l empty_handler
 24+	dc.l empty_handler
 25+	;$50
 26+	dc.l empty_handler
 27+	dc.l empty_handler
 28+	dc.l empty_handler
 29+	dc.l empty_handler
 30+	;$60
 31+	dc.l empty_handler
 32+	dc.l empty_handler
 33+	dc.l empty_handler
 34+	dc.l empty_handler
 35+	;$70
 36+	dc.l int_4
 37+	dc.l empty_handler
 38+	dc.l int_6
 39+	dc.l empty_handler
 40+	;$80
 41+	dc.l empty_handler
 42+	dc.l empty_handler
 43+	dc.l empty_handler
 44+	dc.l empty_handler
 45+	;$90
 46+	dc.l empty_handler
 47+	dc.l empty_handler
 48+	dc.l empty_handler
 49+	dc.l empty_handler
 50+	;$A0
 51+	dc.l empty_handler
 52+	dc.l empty_handler
 53+	dc.l empty_handler
 54+	dc.l empty_handler
 55+	;$B0
 56+	dc.l empty_handler
 57+	dc.l empty_handler
 58+	dc.l empty_handler
 59+	dc.l empty_handler
 60+	;$C0
 61+	dc.l empty_handler
 62+	dc.l empty_handler
 63+	dc.l empty_handler
 64+	dc.l empty_handler
 65+	;$D0
 66+	dc.l empty_handler
 67+	dc.l empty_handler
 68+	dc.l empty_handler
 69+	dc.l empty_handler
 70+	;$E0
 71+	dc.l empty_handler
 72+	dc.l empty_handler
 73+	dc.l empty_handler
 74+	dc.l empty_handler
 75+	;$F0
 76+	dc.l empty_handler
 77+	dc.l empty_handler
 78+	dc.l empty_handler
 79+	dc.l empty_handler
 80+	dc.b "SEGA"
 81+empty_handler:
 82+int_6:
 83+	rte
 84+int_4:
 85+	move.w (a2), d0
 86+	ori.w #$8000, d0
 87+	move.w d0, (a4)+
 88+	rte
 89+
 90+start:
 91+	lea $C00000, a0
 92+	lea $C00004, a1
 93+	move.w #$8104, (a1) ;Mode 5, everything turned off
 94+	move.w #$8004, (a1)
 95+	move.w #$8220, (a1) ;Scroll a table $8000
 96+	move.w #$8404, (a1) ;Scroll b table $8000
 97+	move.w #$8560, (a1) ;SAT table $C000
 98+	move.w #$8700, (a1) ;backdrop color 0
 99+	move.w #$8B00, (a1) ;full screen scroll
100+	move.w #$8C81, (a1) ;40 cell mode, no interlace
101+	move.w #$8C81, (mode).w
102+	move.w #$8D00, (a1) ;hscroll table at 0
103+	move.w #$8F02, (a1) ;autoinc 2
104+	move.w #$9011, (a1) ;64x64 scroll size
105+	move.l #$C0000000, (a1)
106+	move.w #$000, (a0)
107+	move.w #$EEE, (a0)
108+
109+	;clear scroll table
110+	move.l #$40000000, (a1)
111+	move.l #0, (a0)
112+
113+	;load tiles
114+	move.l #$44000000, (a1)
115+	lea font(pc), a2
116+	move.w #((fontend-font)/4 - 1), d0
117+tloop:
118+	move.l (a2)+, (a0)
119+	dbra d0, tloop
120+
121+
122+
123+	;clear name table
124+	move.l #$40000002, (a1)
125+	moveq #32, d0
126+	move.w #(64*64-1), d1
127+ploop:
128+	move.w d0, (a0)
129+	dbra d1, ploop
130+
131+
132+	lea $FF0000, a4
133+	move.b #$40, (a4, 6)
134+	move.w #$8144, (a1) ;enable display
135+	move #$2300, sr
136+
137+	lea (4, a1), a2 ;hv counter line address
138+	lea (2, a1), a3 ;second contro/status address
139+
140+	move.b #254, d0
141+init_wait:
142+	cmp.b (a2), d0
143+	beq init_wait
144+
145+top:
146+	move.b #254, d0
147+	lea $FF0000, a4
148+	move.w #$8F00, (a1)     ;autoinc of 0
149+	move.l #$40040000, (a1) ;unused VRAM address
150+wait_active:
151+	cmp.b (a2), d0
152+	bne.s wait_active
153+
154+	move.l #$8A718014, (a1) ;enable Hints
155+
156+	;sync to VDP by attempting to fill FIFO
157+	;being in vblank makes this a bit difficult
158+
159+	rept 8
160+	move.l d0, (a0)
161+	endr
162+
163+	;sample data for vblank flag off
164+	rept 82 ;two lines worth of move.l
165+	move.l (a3), (a4)+
166+	endr
167+
168+	move.l a4, a5 ;save end of first buffer
169+
170+	move.b (a2), d0
171+wait_new_line:
172+	cmp.b (a2), d0
173+	beq.s wait_new_line
174+
175+	;sync to VDP by filling FIFO
176+	move.l d0, (a0)
177+	move.l d0, (a0)
178+	move.w d0, (a0)
179+
180+	;sample data for line change HV value
181+	rept 45 ;one line worth of move.l
182+	move.l (a2), (a4)+
183+	endr
184+
185+	move.l a4, usp ;save end of second buffer
186+
187+	moveq #$70, d0
188+wait_hint_line:
189+	cmp.b (a2), d0
190+	bne.s wait_hint_line
191+
192+	;sample data for line change HV value
193+	rept 45 ;one line worth of move.l
194+	move.l (a2), (a4)+
195+	endr
196+
197+	move.l a4, a6
198+
199+	move.b #223, d0
200+wait_inactive:
201+	cmp.b (a2), d0
202+	bne.s wait_inactive
203+
204+	;sync to VDP by filling FIFO
205+	move.l d0, (a0)
206+	move.l d0, (a0)
207+	move.w d0, (a0)
208+
209+	;sample data for vblank on
210+	rept 82 ;two lines worth of move.l
211+	move.l (a3), (a4)+
212+	endr
213+
214+	move.l #$8AFF8004, (a1) ;disable Hints
215+
216+	rsset $FFFF8000
217+vblank_start_min rs.w 1
218+vblank_start_max rs.w 1
219+vblank_end_min   rs.w 1
220+vblank_end_max   rs.w 1
221+hblank_start_min rs.w 1
222+hblank_start_max rs.w 1
223+hblank_end_min   rs.w 1
224+hblank_end_max   rs.w 1
225+line_change_min  rs.w 1
226+line_change_max  rs.w 1
227+hint_min         rs.w 1
228+hint_max         rs.w 1
229+mode             rs.w 1
230+printed_hv_dump  rs.b 1
231+button_state     rs.b 1
232+
233+	lea $FF0001, a4
234+.loop:
235+	btst.b #3, (a4)
236+	beq.s found_vblank_off
237+	move.w 1(a4), d6
238+	addq #4, a4
239+	bra.s .loop
240+found_vblank_off:
241+
242+	move.w (vblank_end_max).w, d0
243+	beq .new_max
244+	cmp.w d0, d6
245+	blo .no_new_max
246+.new_max
247+	move.w d6, (vblank_end_max).w
248+.no_new_max:
249+
250+
251+	move.w 1(a4), d6
252+
253+	move.w (vblank_end_min).w, d0
254+	beq .new_min
255+	cmp.w d0, d6
256+	bhi .no_new_min
257+.new_min
258+	move.w d6, (vblank_end_min).w
259+.no_new_min:
260+
261+	lea $FF0001, a4
262+;first find a point where HBLANK is not set
263+	bra.s .start
264+.loop:
265+	addq #4, a4
266+.start
267+	btst.b #2, (a4)
268+	bne.s .loop
269+
270+;then find a point after that where it switches to on
271+.loop2:
272+	btst.b #2, (a4)
273+	bne.s found_hblank_on
274+	move.w 1(a4), d5
275+	addq #4, a4
276+	bra.s .loop2
277+found_hblank_on:
278+
279+	move.w (hblank_start_max).w, d0
280+	beq .new_max
281+	cmp.w d0, d5
282+	blo .no_new_max
283+.new_max
284+	move.w d5, (hblank_start_max).w
285+.no_new_max:
286+
287+
288+	move.w 1(a4), d5
289+
290+	move.w (hblank_start_min).w, d0
291+	beq .new_min
292+	cmp.w d0, d5
293+	bhi .no_new_min
294+.new_min
295+	move.w d5, (hblank_start_min).w
296+.no_new_min:
297+
298+;finally find a point after that where it switches back off
299+.loop2:
300+	btst.b #2, (a4)
301+	beq.s found_hblank_off
302+	move.w 1(a4), d5
303+	addq #4, a4
304+	bra.s .loop2
305+found_hblank_off:
306+
307+	move.w (hblank_end_max).w, d0
308+	beq .new_max
309+	cmp.w d0, d5
310+	blo .no_new_max
311+.new_max
312+	move.w d5, (hblank_end_max).w
313+.no_new_max:
314+
315+
316+	move.w 1(a4), d5
317+
318+	move.w (hblank_end_min).w, d0
319+	beq .new_min
320+	cmp.w d0, d5
321+	bhi .no_new_min
322+.new_min
323+	move.w d5, (hblank_end_min).w
324+.no_new_min:
325+
326+	move.l a5, a4 ;save line change buffer for later
327+	move.b (a5), d0
328+.loop
329+	move.w (a5), d7
330+	addq #2, a5
331+	cmp.b (a5), d0
332+	beq .loop
333+found_line_change:
334+
335+	move.w (line_change_max).w, d0
336+	beq .new_max
337+	cmp.w d0, d7
338+	blo .no_new_max
339+.new_max
340+	move.w d7, (line_change_max).w
341+.no_new_max:
342+
343+	move.w (a5), d7
344+
345+	move.w (line_change_min).w, d0
346+	beq .new_min
347+	cmp.w d0, d7
348+	bhi .no_new_min
349+.new_min
350+	move.w d7, (line_change_min).w
351+.no_new_min:
352+
353+	addq #1, a6
354+.loop:
355+	btst.b #3, (a6)
356+	bne.s found_vblank_on
357+	move.w 1(a6), d5
358+	addq #4, a6
359+	bra.s .loop
360+found_vblank_on:
361+
362+	move.w (vblank_start_max).w, d0
363+	beq .new_max
364+	cmp.w d0, d5
365+	blo .no_new_max
366+.new_max
367+	move.w d5, (vblank_start_max).w
368+.no_new_max:
369+
370+	move.w 1(a6), d5
371+
372+	move.w (vblank_start_min).w, d0
373+	beq .new_min
374+	cmp.b d0, d5
375+	bhi .no_new_min
376+.new_min
377+	move.w d5, (vblank_start_min).w
378+.no_new_min:
379+
380+	move usp, a5
381+.loop:
382+	btst.b #7, (a5)
383+	bne.s found_hint
384+	move.w (a5), d1
385+	addq #2, a5
386+	bra.s .loop
387+found_hint:
388+
389+	move.w (hint_max).w, d0
390+	beq .new_max
391+	cmp.w d0, d1
392+	blo .no_new_max
393+.new_max
394+	move.w d1, (hint_max).w
395+.no_new_max:
396+
397+	move.w (a5), d1
398+	and.w #$7FFF, d1
399+
400+	move.w (hint_min).w, d0
401+	beq .new_min
402+	cmp.b d0, d1
403+	bhi .no_new_min
404+.new_min
405+	move.w d1, (hint_min).w
406+.no_new_min:
407+
408+draw_info:
409+	;draw data
410+	move.w #$8F02, (a1)     ;autoinc of 2
411+	move.l #$40840002, (a1)
412+
413+	moveq #0, d0
414+	lea VBlankStart(pc), a6
415+	bsr print_string
416+
417+
418+	move.w (vblank_start_max), d0
419+	moveq #0, d1
420+	bsr print_hexw
421+
422+	move.w #32, (a0)
423+	move.w d5, d0
424+	bsr print_hexw
425+
426+	move.w #32, (a0)
427+	move.w (vblank_start_min), d0
428+	bsr print_hexw
429+
430+	moveq #0, d0
431+	move.l #$41040002, (a1)
432+	lea VBlankEnd(pc), a6
433+	bsr print_string
434+
435+	;max value before vblank end
436+	moveq #0, d1
437+	move.w (vblank_end_max), d0
438+	bsr print_hexw
439+
440+	move.w #32, (a0)
441+	move.w d6, d0
442+	bsr print_hexw
443+
444+	;min value after vblank end
445+	move.w (vblank_end_min), d0
446+	move.w #32, (a0)
447+	bsr print_hexw
448+
449+	moveq #0, d0
450+	move.l #$41840002, (a1)
451+	lea LineChange(pc), a6
452+	bsr print_string
453+
454+	move.w (line_change_max), d0
455+	moveq #0, d1
456+	bsr print_hexw
457+
458+	move.w #32, (a0)
459+	move.w d7, d0
460+	bsr print_hexw
461+
462+	move.w (line_change_min), d0
463+	move.w #32, (a0)
464+	bsr print_hexw
465+
466+	moveq #0, d0
467+	move.l #$42040002, (a1)
468+	lea HBlankStart(pc), a6
469+	bsr print_string
470+
471+	move.w (hblank_start_max), d0
472+	moveq #0, d1
473+	bsr print_hexw
474+
475+	move.w (hblank_start_min), d0
476+	move.w #32, (a0)
477+	bsr print_hexw
478+
479+	moveq #0, d0
480+	move.l #$42840002, (a1)
481+	lea HBlankEnd(pc), a6
482+	bsr print_string
483+
484+	move.w (hblank_end_max), d0
485+	moveq #0, d1
486+	bsr print_hexw
487+
488+	move.w (hblank_end_min), d0
489+	move.w #32, (a0)
490+	bsr print_hexw
491+
492+	moveq #0, d0
493+	move.l #$43040002, (a1)
494+	lea HInterrupt(pc), a6
495+	bsr print_string
496+
497+	move.w (hint_max), d0
498+	moveq #0, d1
499+	bsr print_hexw
500+
501+	move.w (hint_min), d0
502+	move.w #32, (a0)
503+	bsr print_hexw
504+
505+	;read pad
506+	move.b #$40, $A10003
507+	move.b $A10003, d0
508+	move.b #$00, $A10003
509+	and.b #$3f, d0
510+	move.b $A10003, d1
511+	and.b #$30, d1
512+	lsl.b #2, d1
513+	or.b d1, d0
514+	not.b d0
515+	move.b (button_state).w, d2
516+	eor.b d0, d2
517+	and.b d0, d2
518+	move.b d2, d3 ;d3 contains newly pressed buttons, SACBRLDU
519+	move.b d0, (button_state).w
520+
521+	btst.l #7, d3
522+	beq not_pressed
523+
524+	moveq #0, d0
525+	move.l d0, (vblank_start_min).w
526+	move.l d0, (vblank_end_min).w
527+	move.l d0, (hblank_start_min).w
528+	move.l d0, (hblank_end_min).w
529+	move.l d0, (line_change_min).w
530+	move.l d0, (hint_min).w
531+	move.b d0, (printed_hv_dump).w
532+	move.w (mode).w, d0
533+	eor.w  #$81, d0
534+	move.w d0, (mode).w
535+	move.w d0, (a1)
536+	bra top
537+
538+not_pressed
539+
540+	move.b (printed_hv_dump).w, d0
541+	bne top
542+	move.b #1, (printed_hv_dump).w
543+
544+	moveq #0, d1
545+	moveq #89, d4
546+	moveq #6, d5
547+	move.l #$45820002, d6
548+	move.l d6, (a1)
549+
550+print_loop:
551+	dbra d5, .no_line_change
552+		 ;#$45820002
553+	add.l #$00800000, d6
554+	move.l d6, (a1)
555+	moveq #5, d5
556+.no_line_change
557+	move.w #32, (a0)
558+	move.w (a4)+, d0
559+	bsr print_hexw
560+	dbra d4, print_loop
561+
562+	add.l #$01020000, d6
563+	move.l d6, (a1)
564+	moveq #0, d0
565+	lea Instructions(pc), a6
566+	bsr print_string
567+
568+	bra top
569+
570+VBlankStart:
571+	dc.b "VBlank Start: ", 0
572+VBlankEnd:
573+	dc.b "VBlank End:   ", 0
574+LineChange:
575+	dc.b "Line Change:  ", 0
576+HBlankStart:
577+	dc.b "HBlank Start: ", 0
578+HBlankEnd:
579+	dc.b "HBlank End:   ", 0
580+HInterrupt:
581+	dc.b "HInterrupt:   ", 0
582+Instructions:
583+	dc.b "Press Start to switch modes", 0
584+
585+	align 1
586+;Prints a number in hex format
587+;d0.w - number to print
588+;d1.w - base tile attribute
589+;a0 - VDP data port
590+;
591+;Clobbers: d2.l, d3.l
592+;
593+print_hexw:
594+	moveq #3, d3
595+.digitloop
596+	rol.w #4, d0
597+	moveq #$F, d2
598+	and.b d0, d2
599+	cmp.b #$A, d2
600+	bge .hex
601+	add.w #$30, d2
602+	bra .makeattrib
603+.hex
604+	add.w #($41-$A), d2
605+.makeattrib
606+	add.w d1, d2
607+	move.w d2, (a0)
608+	dbra d3, .digitloop
609+	rts
610+
611+;Prints a null terminated string
612+;a6 - pointer to string
613+;a0 - VDP data port
614+;d0 - base tile attribute
615+;
616+;Clobbers: d1.w
617+print_string:
618+.loop
619+	moveq #0, d1
620+	move.b (a6)+, d1
621+	beq .end
622+	add.w d0, d1
623+	move.w d1, (a0)
624+	bra .loop
625+.end
626+	rts
627+
628+	align 1
629+font:
630+	incbin font.tiles
631+fontend
632+
+2321, -0
   1@@ -0,0 +1,2321 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "gen_x86.h"
   8+#include "mem.h"
   9+#include "util.h"
  10+#include <stddef.h>
  11+#include <stdio.h>
  12+#include <stdlib.h>
  13+#include <stdarg.h>
  14+#include <string.h>
  15+
  16+#define REX_RM_FIELD 0x1
  17+#define REX_SIB_FIELD 0x2
  18+#define REX_REG_FIELD 0x4
  19+#define REX_QUAD 0x8
  20+
  21+#define OP_ADD 0x00
  22+#define OP_OR  0x08
  23+#define PRE_2BYTE 0x0F
  24+#define OP_ADC 0x10
  25+#define OP_SBB 0x18
  26+#define OP_AND 0x20
  27+#define OP_SUB 0x28
  28+#define OP_XOR 0x30
  29+#define OP_CMP 0x38
  30+#define PRE_REX 0x40
  31+#define OP_PUSH 0x50
  32+#define OP_POP 0x58
  33+#define OP_MOVSXD 0x63
  34+#define PRE_SIZE 0x66
  35+#define OP_IMUL 0x69
  36+#define OP_JCC 0x70
  37+#define OP_IMMED_ARITH 0x80
  38+#define OP_TEST 0x84
  39+#define OP_XCHG 0x86
  40+#define OP_MOV 0x88
  41+#define PRE_XOP 0x8F
  42+#define OP_XCHG_AX 0x90
  43+#define OP_CDQ 0x99
  44+#define OP_PUSHF 0x9C
  45+#define OP_POPF 0x9D
  46+#define OP_MOV_I8R 0xB0
  47+#define OP_MOV_IR 0xB8
  48+#define OP_SHIFTROT_IR 0xC0
  49+#define OP_RETN 0xC3
  50+#define OP_MOV_IEA 0xC6
  51+#define OP_SHIFTROT_1 0xD0
  52+#define OP_SHIFTROT_CL 0xD2
  53+#define OP_LOOP 0xE2
  54+#define OP_CALL 0xE8
  55+#define OP_JMP 0xE9
  56+#define OP_JMP_BYTE 0xEB
  57+#define OP_NOT_NEG 0xF6
  58+#define OP_SINGLE_EA 0xFF
  59+
  60+#define OP2_JCC 0x80
  61+#define OP2_SETCC 0x90
  62+#define OP2_BT 0xA3
  63+#define OP2_BTS 0xAB
  64+#define OP2_IMUL 0xAF
  65+#define OP2_BTR 0xB3
  66+#define OP2_BTX_I 0xBA
  67+#define OP2_BTC 0xBB
  68+#define OP2_MOVSX 0xBE
  69+#define OP2_MOVZX 0xB6
  70+
  71+#define OP_EX_ADDI 0x0
  72+#define OP_EX_ORI  0x1
  73+#define OP_EX_ADCI 0x2
  74+#define OP_EX_SBBI 0x3
  75+#define OP_EX_ANDI 0x4
  76+#define OP_EX_SUBI 0x5
  77+#define OP_EX_XORI 0x6
  78+#define OP_EX_CMPI 0x7
  79+
  80+#define OP_EX_ROL 0x0
  81+#define OP_EX_ROR 0x1
  82+#define OP_EX_RCL 0x2
  83+#define OP_EX_RCR 0x3
  84+#define OP_EX_SHL 0x4
  85+#define OP_EX_SHR 0x5
  86+#define OP_EX_SAL 0x6 //identical to SHL
  87+#define OP_EX_SAR 0x7
  88+
  89+#define OP_EX_BT  0x4
  90+#define OP_EX_BTS 0x5
  91+#define OP_EX_BTR 0x6
  92+#define OP_EX_BTC 0x7
  93+
  94+#define OP_EX_TEST_I 0x0
  95+#define OP_EX_NOT    0x2
  96+#define OP_EX_NEG    0x3
  97+#define OP_EX_MUL    0x4
  98+#define OP_EX_IMUL   0x5
  99+#define OP_EX_DIV    0x6
 100+#define OP_EX_IDIV   0x7
 101+
 102+#define OP_EX_INC     0x0
 103+#define OP_EX_DEC     0x1
 104+#define OP_EX_CALL_EA 0x2
 105+#define OP_EX_JMP_EA  0x4
 106+#define OP_EX_PUSH_EA 0x6
 107+
 108+#define BIT_IMMED_RAX 0x4
 109+#define BIT_DIR 0x2
 110+#define BIT_SIZE 0x1
 111+
 112+
 113+enum {
 114+	X86_RAX = 0,
 115+	X86_RCX,
 116+	X86_RDX,
 117+	X86_RBX,
 118+	X86_RSP,
 119+	X86_RBP,
 120+	X86_RSI,
 121+	X86_RDI,
 122+	X86_AH=4,
 123+	X86_CH,
 124+	X86_DH,
 125+	X86_BH,
 126+	X86_R8=0,
 127+	X86_R9,
 128+	X86_R10,
 129+	X86_R11,
 130+	X86_R12,
 131+	X86_R13,
 132+	X86_R14,
 133+	X86_R15
 134+} x86_regs_enc;
 135+
 136+char * x86_reg_names[] = {
 137+#ifdef X86_64
 138+	"rax",
 139+	"rcx",
 140+	"rdx",
 141+	"rbx",
 142+	"rsp",
 143+	"rbp",
 144+	"rsi",
 145+	"rdi",
 146+#else
 147+	"eax",
 148+	"ecx",
 149+	"edx",
 150+	"ebx",
 151+	"esp",
 152+	"ebp",
 153+	"esi",
 154+	"edi",
 155+#endif
 156+	"ah",
 157+	"ch",
 158+	"dh",
 159+	"bh",
 160+	"r8",
 161+	"r9",
 162+	"r10",
 163+	"r11",
 164+	"r12",
 165+	"r13",
 166+	"r14",
 167+	"r15",
 168+};
 169+
 170+char * x86_sizes[] = {
 171+	"b", "w", "d", "q"
 172+};
 173+
 174+#ifdef X86_64
 175+#define CHECK_DISP(disp) (disp <= 0x7FFFFFFF && disp >= -2147483648)
 176+#else
 177+#define CHECK_DISP(disp) 1
 178+#endif
 179+
 180+void jmp_nocheck(code_info *code, code_ptr dest)
 181+{
 182+	code_ptr out = code->cur;
 183+	ptrdiff_t disp = dest-(out+2);
 184+	if (disp <= 0x7F && disp >= -0x80) {
 185+		*(out++) = OP_JMP_BYTE;
 186+		*(out++) = disp;
 187+	} else {
 188+		disp = dest-(out+5);
 189+		if (CHECK_DISP(disp)) {
 190+			*(out++) = OP_JMP;
 191+			*(out++) = disp;
 192+			disp >>= 8;
 193+			*(out++) = disp;
 194+			disp >>= 8;
 195+			*(out++) = disp;
 196+			disp >>= 8;
 197+			*(out++) = disp;
 198+		} else {
 199+			fatal_error("jmp: %p - %p = %l which is out of range of a 32-bit displacementX\n", dest, out + 6, (long)disp);
 200+		}
 201+	}
 202+	code->cur = out;
 203+}
 204+
 205+void check_alloc_code(code_info *code, uint32_t inst_size)
 206+{
 207+	if (code->cur + inst_size > code->last) {
 208+		size_t size = CODE_ALLOC_SIZE;
 209+		code_ptr next_code = alloc_code(&size);
 210+		if (!next_code) {
 211+			fatal_error("Failed to allocate memory for generated code\n");
 212+		}
 213+		if (next_code != code->last + RESERVE_WORDS) {
 214+			//new chunk is not contiguous with the current one
 215+			jmp_nocheck(code, next_code);
 216+			code->cur = next_code;
 217+		}
 218+		code->last = next_code + size/sizeof(code_word) - RESERVE_WORDS;
 219+	}
 220+}
 221+
 222+void x86_rr_sizedir(code_info *code, uint16_t opcode, uint8_t src, uint8_t dst, uint8_t size)
 223+{
 224+	check_alloc_code(code, 5);
 225+	code_ptr out = code->cur;
 226+	uint8_t tmp;
 227+	if (size == SZ_W) {
 228+		*(out++) = PRE_SIZE;
 229+	}
 230+	if (size == SZ_B && dst >= RSP && dst <= RDI) {
 231+		opcode |= BIT_DIR;
 232+		tmp = dst;
 233+		dst = src;
 234+		src = tmp;
 235+	}
 236+	if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) {
 237+#ifdef X86_64
 238+		*out = PRE_REX;
 239+		if (src >= AH && src <= BH || dst >= AH && dst <= BH) {
 240+			fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
 241+		}
 242+		if (size == SZ_Q) {
 243+			*out |= REX_QUAD;
 244+		}
 245+		if (src >= R8) {
 246+			*out |= REX_REG_FIELD;
 247+			src -= (R8 - X86_R8);
 248+		}
 249+		if (dst >= R8) {
 250+			*out |= REX_RM_FIELD;
 251+			dst -= (R8 - X86_R8);
 252+		}
 253+		out++;
 254+#else
 255+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, src: %s, dst: %s, size: %s\n", opcode, x86_reg_names[src], x86_reg_names[dst], x86_sizes[size]);
 256+#endif
 257+	}
 258+	if (size == SZ_B) {
 259+		if (src >= AH && src <= BH) {
 260+			src -= (AH-X86_AH);
 261+		}
 262+		if (dst >= AH && dst <= BH) {
 263+			dst -= (AH-X86_AH);
 264+		}
 265+	} else {
 266+		opcode |= BIT_SIZE;
 267+	}
 268+	if (opcode >= 0x100) {
 269+		*(out++) = opcode >> 8;
 270+		*(out++) = opcode;
 271+	} else {
 272+		*(out++) = opcode;
 273+	}
 274+	*(out++) = MODE_REG_DIRECT | dst | (src << 3);
 275+	code->cur = out;
 276+}
 277+
 278+void x86_rrdisp_sizedir(code_info *code, uint16_t opcode, uint8_t reg, uint8_t base, int32_t disp, uint8_t size, uint8_t dir)
 279+{
 280+	check_alloc_code(code, 10);
 281+	code_ptr out = code->cur;
 282+	//TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix
 283+	uint8_t tmp;
 284+	if (size == SZ_W) {
 285+		*(out++) = PRE_SIZE;
 286+	}
 287+	if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
 288+#ifdef X86_64
 289+		*out = PRE_REX;
 290+		if (reg >= AH && reg <= BH) {
 291+			fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
 292+		}
 293+		if (size == SZ_Q) {
 294+			*out |= REX_QUAD;
 295+		}
 296+		if (reg >= R8) {
 297+			*out |= REX_REG_FIELD;
 298+			reg -= (R8 - X86_R8);
 299+		}
 300+		if (base >= R8) {
 301+			*out |= REX_RM_FIELD;
 302+			base -= (R8 - X86_R8);
 303+		}
 304+		out++;
 305+#else
 306+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
 307+#endif
 308+	}
 309+	if (size == SZ_B) {
 310+		if (reg >= AH && reg <= BH) {
 311+			reg -= (AH-X86_AH);
 312+		}
 313+	} else {
 314+		opcode |= BIT_SIZE;
 315+	}
 316+	opcode |= dir;
 317+	if (opcode >= 0x100) {
 318+		*(out++) = opcode >> 8;
 319+		*(out++) = opcode;
 320+	} else {
 321+		*(out++) = opcode;
 322+	}
 323+	if (disp < 128 && disp >= -128) {
 324+	*(out++) = MODE_REG_DISPLACE8 | base | (reg << 3);
 325+	} else {
 326+		*(out++) = MODE_REG_DISPLACE32 | base | (reg << 3);
 327+	}
 328+	if (base == RSP) {
 329+		//add SIB byte, with no index and RSP as base
 330+		*(out++) = (RSP << 3) | RSP;
 331+	}
 332+	*(out++) = disp;
 333+	if (disp >= 128 || disp < -128) {
 334+	*(out++) = disp >> 8;
 335+	*(out++) = disp >> 16;
 336+	*(out++) = disp >> 24;
 337+	}
 338+	code->cur = out;
 339+}
 340+
 341+void x86_rrind_sizedir(code_info *code, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t size, uint8_t dir)
 342+{
 343+	check_alloc_code(code, 5);
 344+	code_ptr out = code->cur;
 345+	//TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix
 346+	uint8_t tmp;
 347+	if (size == SZ_W) {
 348+		*(out++) = PRE_SIZE;
 349+	}
 350+	if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
 351+#ifdef X86_64
 352+		*out = PRE_REX;
 353+		if (reg >= AH && reg <= BH) {
 354+			fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
 355+		}
 356+		if (size == SZ_Q) {
 357+			*out |= REX_QUAD;
 358+		}
 359+		if (reg >= R8) {
 360+			*out |= REX_REG_FIELD;
 361+			reg -= (R8 - X86_R8);
 362+		}
 363+		if (base >= R8) {
 364+			*out |= REX_RM_FIELD;
 365+			base -= (R8 - X86_R8);
 366+		}
 367+		out++;
 368+#else
 369+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
 370+#endif
 371+	}
 372+	if (size == SZ_B) {
 373+		if (reg >= AH && reg <= BH) {
 374+			reg -= (AH-X86_AH);
 375+		}
 376+	} else {
 377+		opcode |= BIT_SIZE;
 378+	}
 379+	*(out++) = opcode | dir;
 380+	if (base == RBP) {
 381+		//add a dummy 8-bit displacement since MODE_REG_INDIRECT with
 382+		//an R/M field of RBP selects RIP, relative addressing
 383+		*(out++) = MODE_REG_DISPLACE8 | base | (reg << 3);
 384+		*(out++) = 0;
 385+	} else {
 386+	*(out++) = MODE_REG_INDIRECT | base | (reg << 3);
 387+	if (base == RSP) {
 388+		//add SIB byte, with no index and RSP as base
 389+		*(out++) = (RSP << 3) | RSP;
 390+	}
 391+	}
 392+	code->cur = out;
 393+}
 394+
 395+void x86_rrindex_sizedir(code_info *code, uint8_t opcode, uint8_t reg, uint8_t base, uint8_t index, uint8_t scale, uint8_t size, uint8_t dir)
 396+{
 397+	check_alloc_code(code, 5);
 398+	code_ptr out = code->cur;
 399+	//TODO: Deal with the fact that AH, BH, CH and DH can only be in the R/M param when there's a REX prefix
 400+	uint8_t tmp;
 401+	if (size == SZ_W) {
 402+		*(out++) = PRE_SIZE;
 403+	}
 404+	if (size == SZ_Q || reg >= R8 || base >= R8 || (size == SZ_B && reg >= RSP && reg <= RDI)) {
 405+#ifdef X86_64
 406+		*out = PRE_REX;
 407+		if (reg >= AH && reg <= BH) {
 408+			fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
 409+		}
 410+		if (size == SZ_Q) {
 411+			*out |= REX_QUAD;
 412+		}
 413+		if (reg >= R8) {
 414+			*out |= REX_REG_FIELD;
 415+			reg -= (R8 - X86_R8);
 416+		}
 417+		if (base >= R8) {
 418+			*out |= REX_RM_FIELD;
 419+			base -= (R8 - X86_R8);
 420+		}
 421+		if (index >= R8) {
 422+			*out |= REX_SIB_FIELD;
 423+			index -= (R8 - X86_R8);
 424+		}
 425+		out++;
 426+#else
 427+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, base: %s, size: %s\n", opcode, x86_reg_names[reg], x86_reg_names[base], x86_sizes[size]);
 428+#endif
 429+	}
 430+	if (size == SZ_B) {
 431+		if (reg >= AH && reg <= BH) {
 432+			reg -= (AH-X86_AH);
 433+		}
 434+	} else {
 435+		opcode |= BIT_SIZE;
 436+	}
 437+	*(out++) = opcode | dir;
 438+	*(out++) = MODE_REG_INDIRECT | RSP | (reg << 3);
 439+	if (scale == 4) {
 440+		scale = 2;
 441+	} else if(scale == 8) {
 442+			scale = 3;
 443+	} else {
 444+		scale--;
 445+	}
 446+	*(out++) = scale << 6 | (index << 3) | base;
 447+	code->cur = out;
 448+}
 449+
 450+void x86_r_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, uint8_t size)
 451+{
 452+	check_alloc_code(code, 4);
 453+	code_ptr out = code->cur;
 454+	uint8_t tmp;
 455+	if (size == SZ_W) {
 456+		*(out++) = PRE_SIZE;
 457+	}
 458+	if (size == SZ_Q || dst >= R8) {
 459+#ifdef X86_64
 460+		*out = PRE_REX;
 461+		if (dst >= AH && dst <= BH) {
 462+			fatal_error("attempt to use *H reg in an instruction requiring REX prefix. opcode = %X\n", opcode);
 463+		}
 464+		if (size == SZ_Q) {
 465+			*out |= REX_QUAD;
 466+		}
 467+		if (dst >= R8) {
 468+			*out |= REX_RM_FIELD;
 469+			dst -= (R8 - X86_R8);
 470+		}
 471+		out++;
 472+#else
 473+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]);
 474+#endif
 475+	}
 476+	if (size == SZ_B) {
 477+		if (dst >= AH && dst <= BH) {
 478+			dst -= (AH-X86_AH);
 479+		}
 480+	} else {
 481+		opcode |= BIT_SIZE;
 482+	}
 483+	*(out++) = opcode;
 484+	*(out++) = MODE_REG_DIRECT | dst | (opex << 3);
 485+	code->cur = out;
 486+}
 487+
 488+void x86_rdisp_size(code_info *code, uint8_t opcode, uint8_t opex, uint8_t dst, int32_t disp, uint8_t size)
 489+{
 490+	check_alloc_code(code, 7);
 491+	code_ptr out = code->cur;
 492+	uint8_t tmp;
 493+	if (size == SZ_W) {
 494+		*(out++) = PRE_SIZE;
 495+	}
 496+	if (size == SZ_Q || dst >= R8) {
 497+#ifdef X86_64
 498+		*out = PRE_REX;
 499+		if (size == SZ_Q) {
 500+			*out |= REX_QUAD;
 501+		}
 502+		if (dst >= R8) {
 503+			*out |= REX_RM_FIELD;
 504+			dst -= (R8 - X86_R8);
 505+		}
 506+		out++;
 507+#else
 508+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, opex, x86_reg_names[dst], x86_sizes[size]);
 509+#endif
 510+	}
 511+	if (size != SZ_B) {
 512+		opcode |= BIT_SIZE;
 513+	}
 514+	*(out++) = opcode;
 515+	if (disp < 128 && disp >= -128) {
 516+	*(out++) = MODE_REG_DISPLACE8 | dst | (opex << 3);
 517+	*(out++) = disp;
 518+	} else {
 519+		*(out++) = MODE_REG_DISPLACE32 | dst | (opex << 3);
 520+		*(out++) = disp;
 521+		*(out++) = disp >> 8;
 522+		*(out++) = disp >> 16;
 523+		*(out++) = disp >> 24;
 524+	}
 525+	code->cur = out;
 526+}
 527+
 528+void x86_ir(code_info *code, uint8_t opcode, uint8_t op_ex, uint8_t al_opcode, int32_t val, uint8_t dst, uint8_t size)
 529+{
 530+	check_alloc_code(code, 8);
 531+	code_ptr out = code->cur;
 532+	uint8_t sign_extend = 0;
 533+	if (opcode != OP_NOT_NEG && (size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
 534+		sign_extend = 1;
 535+		opcode |= BIT_DIR;
 536+	}
 537+	if (size == SZ_W) {
 538+		*(out++) = PRE_SIZE;
 539+	}
 540+	if (dst == RAX && !sign_extend && al_opcode) {
 541+		if (size != SZ_B) {
 542+			al_opcode |= BIT_SIZE;
 543+			if (size == SZ_Q) {
 544+#ifdef X86_64
 545+				*out = PRE_REX | REX_QUAD;
 546+#else
 547+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X, reg: %s, size: %s\n", al_opcode, x86_reg_names[dst], x86_sizes[size]);
 548+#endif
 549+			}
 550+		}
 551+		*(out++) = al_opcode | BIT_IMMED_RAX;
 552+	} else {
 553+		if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
 554+#ifdef X86_64
 555+			*out = PRE_REX;
 556+			if (size == SZ_Q) {
 557+				*out |= REX_QUAD;
 558+			}
 559+			if (dst >= R8) {
 560+				*out |= REX_RM_FIELD;
 561+				dst -= (R8 - X86_R8);
 562+			}
 563+			out++;
 564+#else
 565+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]);
 566+#endif
 567+		}
 568+		if (dst >= AH && dst <= BH) {
 569+			dst -= (AH-X86_AH);
 570+		}
 571+		if (size != SZ_B) {
 572+			opcode |= BIT_SIZE;
 573+		}
 574+		*(out++) = opcode;
 575+		*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
 576+	}
 577+	*(out++) = val;
 578+	if (size != SZ_B && !sign_extend) {
 579+		val >>= 8;
 580+		*(out++) = val;
 581+		if (size != SZ_W) {
 582+			val >>= 8;
 583+			*(out++) = val;
 584+			val >>= 8;
 585+			*(out++) = val;
 586+		}
 587+	}
 588+	code->cur = out;
 589+}
 590+
 591+void x86_irdisp(code_info *code, uint8_t opcode, uint8_t op_ex, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
 592+{
 593+	check_alloc_code(code, 12);
 594+	code_ptr out = code->cur;
 595+	uint8_t sign_extend = 0;
 596+	if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
 597+		sign_extend = 1;
 598+		opcode |= BIT_DIR;
 599+	}
 600+	if (size == SZ_W) {
 601+		*(out++) = PRE_SIZE;
 602+	}
 603+
 604+	if (size == SZ_Q || dst >= R8) {
 605+#ifdef X86_64
 606+		*out = PRE_REX;
 607+		if (size == SZ_Q) {
 608+			*out |= REX_QUAD;
 609+		}
 610+		if (dst >= R8) {
 611+			*out |= REX_RM_FIELD;
 612+			dst -= (R8 - X86_R8);
 613+		}
 614+		out++;
 615+#else
 616+		fatal_error("Instruction requires REX prefix but this is a 32-bit build | opcode: %X:%X, reg: %s, size: %s\n", opcode, op_ex, x86_reg_names[dst], x86_sizes[size]);
 617+#endif
 618+	}
 619+	if (size != SZ_B) {
 620+		opcode |= BIT_SIZE;
 621+	}
 622+	*(out++) = opcode;
 623+	if (disp < 128 && disp >= -128) {
 624+	*(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
 625+	*(out++) = disp;
 626+	} else {
 627+	*(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
 628+	*(out++) = disp;
 629+	disp >>= 8;
 630+	*(out++) = disp;
 631+	disp >>= 8;
 632+	*(out++) = disp;
 633+	disp >>= 8;
 634+	*(out++) = disp;
 635+	}
 636+	*(out++) = val;
 637+	if (size != SZ_B && !sign_extend) {
 638+		val >>= 8;
 639+		*(out++) = val;
 640+		if (size != SZ_W) {
 641+			val >>= 8;
 642+			*(out++) = val;
 643+			val >>= 8;
 644+			*(out++) = val;
 645+		}
 646+	}
 647+	code->cur = out;
 648+}
 649+
 650+void x86_shiftrot_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
 651+{
 652+	check_alloc_code(code, 5);
 653+	code_ptr out = code->cur;
 654+	if (size == SZ_W) {
 655+		*(out++) = PRE_SIZE;
 656+	}
 657+	if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
 658+		*out = PRE_REX;
 659+		if (size == SZ_Q) {
 660+			*out |= REX_QUAD;
 661+		}
 662+		if (dst >= R8) {
 663+			*out |= REX_RM_FIELD;
 664+			dst -= (R8 - X86_R8);
 665+		}
 666+		out++;
 667+	}
 668+	if (dst >= AH && dst <= BH) {
 669+		dst -= (AH-X86_AH);
 670+	}
 671+
 672+	*(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE);
 673+	*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
 674+	if (val != 1) {
 675+		*(out++) = val;
 676+	}
 677+	code->cur = out;
 678+}
 679+
 680+void x86_shiftrot_irdisp(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, int32_t disp, uint8_t size)
 681+{
 682+	check_alloc_code(code, 9);
 683+	code_ptr out = code->cur;
 684+	if (size == SZ_W) {
 685+		*(out++) = PRE_SIZE;
 686+	}
 687+	if (size == SZ_Q || dst >= R8) {
 688+		*out = PRE_REX;
 689+		if (size == SZ_Q) {
 690+			*out |= REX_QUAD;
 691+		}
 692+		if (dst >= R8) {
 693+			*out |= REX_RM_FIELD;
 694+			dst -= (R8 - X86_R8);
 695+		}
 696+		out++;
 697+	}
 698+	if (dst >= AH && dst <= BH) {
 699+		dst -= (AH-X86_AH);
 700+	}
 701+
 702+	*(out++) = (val == 1 ? OP_SHIFTROT_1: OP_SHIFTROT_IR) | (size == SZ_B ? 0 : BIT_SIZE);
 703+	if (disp < 128 && disp >= -128) {
 704+	*(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
 705+	*(out++) = disp;
 706+	} else {
 707+		*(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
 708+		*(out++) = disp;
 709+		*(out++) = disp >> 8;
 710+		*(out++) = disp >> 16;
 711+		*(out++) = disp >> 24;
 712+	}
 713+	if (val != 1) {
 714+		*(out++) = val;
 715+	}
 716+	code->cur = out;
 717+}
 718+
 719+void x86_shiftrot_clr(code_info *code, uint8_t op_ex, uint8_t dst, uint8_t size)
 720+{
 721+	check_alloc_code(code, 4);
 722+	code_ptr out = code->cur;
 723+	if (size == SZ_W) {
 724+		*(out++) = PRE_SIZE;
 725+	}
 726+	if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
 727+		*out = PRE_REX;
 728+		if (size == SZ_Q) {
 729+			*out |= REX_QUAD;
 730+		}
 731+		if (dst >= R8) {
 732+			*out |= REX_RM_FIELD;
 733+			dst -= (R8 - X86_R8);
 734+		}
 735+		out++;
 736+	}
 737+	if (dst >= AH && dst <= BH) {
 738+		dst -= (AH-X86_AH);
 739+	}
 740+
 741+	*(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE);
 742+	*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
 743+	code->cur = out;
 744+}
 745+
 746+void x86_shiftrot_clrdisp(code_info *code, uint8_t op_ex, uint8_t dst, int32_t disp, uint8_t size)
 747+{
 748+	check_alloc_code(code, 8);
 749+	code_ptr out = code->cur;
 750+	if (size == SZ_W) {
 751+		*(out++) = PRE_SIZE;
 752+	}
 753+	if (size == SZ_Q || dst >= R8) {
 754+		*out = PRE_REX;
 755+		if (size == SZ_Q) {
 756+			*out |= REX_QUAD;
 757+		}
 758+		if (dst >= R8) {
 759+			*out |= REX_RM_FIELD;
 760+			dst -= (R8 - X86_R8);
 761+		}
 762+		out++;
 763+	}
 764+	if (dst >= AH && dst <= BH) {
 765+		dst -= (AH-X86_AH);
 766+	}
 767+
 768+	*(out++) = OP_SHIFTROT_CL | (size == SZ_B ? 0 : BIT_SIZE);
 769+	if (disp < 128 && disp >= -128) {
 770+	*(out++) = MODE_REG_DISPLACE8 | dst | (op_ex << 3);
 771+	*(out++) = disp;
 772+	} else {
 773+		*(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
 774+		*(out++) = disp;
 775+		*(out++) = disp >> 8;
 776+		*(out++) = disp >> 16;
 777+		*(out++) = disp >> 24;
 778+}
 779+	code->cur = out;
 780+}
 781+
 782+void rol_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 783+{
 784+	x86_shiftrot_ir(code, OP_EX_ROL, val, dst, size);
 785+}
 786+
 787+void ror_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 788+{
 789+	x86_shiftrot_ir(code, OP_EX_ROR, val, dst, size);
 790+}
 791+
 792+void rcl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 793+{
 794+	x86_shiftrot_ir(code, OP_EX_RCL, val, dst, size);
 795+}
 796+
 797+void rcr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 798+{
 799+	x86_shiftrot_ir(code, OP_EX_RCR, val, dst, size);
 800+}
 801+
 802+void shl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 803+{
 804+	x86_shiftrot_ir(code, OP_EX_SHL, val, dst, size);
 805+}
 806+
 807+void shr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 808+{
 809+	x86_shiftrot_ir(code, OP_EX_SHR, val, dst, size);
 810+}
 811+
 812+void sar_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
 813+{
 814+	x86_shiftrot_ir(code, OP_EX_SAR, val, dst, size);
 815+}
 816+
 817+void rol_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 818+{
 819+	x86_shiftrot_irdisp(code, OP_EX_ROL, val, dst_base, disp, size);
 820+}
 821+
 822+void ror_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 823+{
 824+	x86_shiftrot_irdisp(code, OP_EX_ROR, val, dst_base, disp, size);
 825+}
 826+
 827+void rcl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 828+{
 829+	x86_shiftrot_irdisp(code, OP_EX_RCL, val, dst_base, disp, size);
 830+}
 831+
 832+void rcr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 833+{
 834+	x86_shiftrot_irdisp(code, OP_EX_RCR, val, dst_base, disp, size);
 835+}
 836+
 837+void shl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 838+{
 839+	x86_shiftrot_irdisp(code, OP_EX_SHL, val, dst_base, disp, size);
 840+}
 841+
 842+void shr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 843+{
 844+	x86_shiftrot_irdisp(code, OP_EX_SHR, val, dst_base, disp, size);
 845+}
 846+
 847+void sar_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 848+{
 849+	x86_shiftrot_irdisp(code, OP_EX_SAR, val, dst_base, disp, size);
 850+}
 851+
 852+void rol_clr(code_info *code, uint8_t dst, uint8_t size)
 853+{
 854+	x86_shiftrot_clr(code, OP_EX_ROL, dst, size);
 855+}
 856+
 857+void ror_clr(code_info *code, uint8_t dst, uint8_t size)
 858+{
 859+	x86_shiftrot_clr(code, OP_EX_ROR, dst, size);
 860+}
 861+
 862+void rcl_clr(code_info *code, uint8_t dst, uint8_t size)
 863+{
 864+	x86_shiftrot_clr(code, OP_EX_RCL, dst, size);
 865+}
 866+
 867+void rcr_clr(code_info *code, uint8_t dst, uint8_t size)
 868+{
 869+	x86_shiftrot_clr(code, OP_EX_RCR, dst, size);
 870+}
 871+
 872+void shl_clr(code_info *code, uint8_t dst, uint8_t size)
 873+{
 874+	x86_shiftrot_clr(code, OP_EX_SHL, dst, size);
 875+}
 876+
 877+void shr_clr(code_info *code, uint8_t dst, uint8_t size)
 878+{
 879+	x86_shiftrot_clr(code, OP_EX_SHR, dst, size);
 880+}
 881+
 882+void sar_clr(code_info *code, uint8_t dst, uint8_t size)
 883+{
 884+	x86_shiftrot_clr(code, OP_EX_SAR, dst, size);
 885+}
 886+
 887+void rol_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 888+{
 889+	x86_shiftrot_clrdisp(code, OP_EX_ROL, dst_base, disp, size);
 890+}
 891+
 892+void ror_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 893+{
 894+	x86_shiftrot_clrdisp(code, OP_EX_ROR, dst_base, disp, size);
 895+}
 896+
 897+void rcl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 898+{
 899+	x86_shiftrot_clrdisp(code, OP_EX_RCL, dst_base, disp, size);
 900+}
 901+
 902+void rcr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 903+{
 904+	x86_shiftrot_clrdisp(code, OP_EX_RCR, dst_base, disp, size);
 905+}
 906+
 907+void shl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 908+{
 909+	x86_shiftrot_clrdisp(code, OP_EX_SHL, dst_base, disp, size);
 910+}
 911+
 912+void shr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 913+{
 914+	x86_shiftrot_clrdisp(code, OP_EX_SHR, dst_base, disp, size);
 915+}
 916+
 917+void sar_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
 918+{
 919+	x86_shiftrot_clrdisp(code, OP_EX_SAR, dst_base, disp, size);
 920+}
 921+
 922+void add_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
 923+{
 924+	x86_rr_sizedir(code, OP_ADD, src, dst, size);
 925+}
 926+
 927+void add_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
 928+{
 929+	x86_ir(code, OP_IMMED_ARITH, OP_EX_ADDI, OP_ADD, val, dst, size);
 930+}
 931+
 932+void add_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 933+{
 934+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADDI, val, dst_base, disp, size);
 935+}
 936+
 937+void add_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
 938+{
 939+	x86_rrdisp_sizedir(code, OP_ADD, src, dst_base, disp, size, 0);
 940+}
 941+
 942+void add_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
 943+{
 944+	x86_rrdisp_sizedir(code, OP_ADD, dst, src_base, disp, size, BIT_DIR);
 945+}
 946+
 947+void adc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
 948+{
 949+	x86_rr_sizedir(code, OP_ADC, src, dst, size);
 950+}
 951+
 952+void adc_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
 953+{
 954+	x86_ir(code, OP_IMMED_ARITH, OP_EX_ADCI, OP_ADC, val, dst, size);
 955+}
 956+
 957+void adc_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 958+{
 959+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ADCI, val, dst_base, disp, size);
 960+}
 961+
 962+void adc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
 963+{
 964+	x86_rrdisp_sizedir(code, OP_ADC, src, dst_base, disp, size, 0);
 965+}
 966+
 967+void adc_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
 968+{
 969+	x86_rrdisp_sizedir(code, OP_ADC, dst, src_base, disp, size, BIT_DIR);
 970+}
 971+
 972+void or_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
 973+{
 974+	x86_rr_sizedir(code, OP_OR, src, dst, size);
 975+}
 976+void or_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
 977+{
 978+	x86_ir(code, OP_IMMED_ARITH, OP_EX_ORI, OP_OR, val, dst, size);
 979+}
 980+
 981+void or_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
 982+{
 983+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ORI, val, dst_base, disp, size);
 984+}
 985+
 986+void or_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
 987+{
 988+	x86_rrdisp_sizedir(code, OP_OR, src, dst_base, disp, size, 0);
 989+}
 990+
 991+void or_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
 992+{
 993+	x86_rrdisp_sizedir(code, OP_OR, dst, src_base, disp, size, BIT_DIR);
 994+}
 995+
 996+void and_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
 997+{
 998+	x86_rr_sizedir(code, OP_AND, src, dst, size);
 999+}
1000+
1001+void and_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1002+{
1003+	x86_ir(code, OP_IMMED_ARITH, OP_EX_ANDI, OP_AND, val, dst, size);
1004+}
1005+
1006+void and_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1007+{
1008+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_ANDI, val, dst_base, disp, size);
1009+}
1010+
1011+void and_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1012+{
1013+	x86_rrdisp_sizedir(code, OP_AND, src, dst_base, disp, size, 0);
1014+}
1015+
1016+void and_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1017+{
1018+	x86_rrdisp_sizedir(code, OP_AND, dst, src_base, disp, size, BIT_DIR);
1019+}
1020+
1021+void xor_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1022+{
1023+	x86_rr_sizedir(code, OP_XOR, src, dst, size);
1024+}
1025+
1026+void xor_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1027+{
1028+	x86_ir(code, OP_IMMED_ARITH, OP_EX_XORI, OP_XOR, val, dst, size);
1029+}
1030+
1031+void xor_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1032+{
1033+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_XORI, val, dst_base, disp, size);
1034+}
1035+
1036+void xor_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1037+{
1038+	x86_rrdisp_sizedir(code, OP_XOR, src, dst_base, disp, size, 0);
1039+}
1040+
1041+void xor_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1042+{
1043+	x86_rrdisp_sizedir(code, OP_XOR, dst, src_base, disp, size, BIT_DIR);
1044+}
1045+
1046+void sub_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1047+{
1048+	x86_rr_sizedir(code, OP_SUB, src, dst, size);
1049+}
1050+
1051+void sub_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1052+{
1053+	x86_ir(code, OP_IMMED_ARITH, OP_EX_SUBI, OP_SUB, val, dst, size);
1054+}
1055+
1056+void sub_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1057+{
1058+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SUBI, val, dst_base, disp, size);
1059+}
1060+
1061+void sub_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1062+{
1063+	x86_rrdisp_sizedir(code, OP_SUB, src, dst_base, disp, size, 0);
1064+}
1065+
1066+void sub_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1067+{
1068+	x86_rrdisp_sizedir(code, OP_SUB, dst, src_base, disp, size, BIT_DIR);
1069+}
1070+
1071+void sbb_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1072+{
1073+	x86_rr_sizedir(code, OP_SBB, src, dst, size);
1074+}
1075+
1076+void sbb_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1077+{
1078+	x86_ir(code, OP_IMMED_ARITH, OP_EX_SBBI, OP_SBB, val, dst, size);
1079+}
1080+
1081+void sbb_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1082+{
1083+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_SBBI, val, dst_base, disp, size);
1084+}
1085+
1086+void sbb_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1087+{
1088+	x86_rrdisp_sizedir(code, OP_SBB, src, dst_base, disp, size, 0);
1089+}
1090+
1091+void sbb_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1092+{
1093+	x86_rrdisp_sizedir(code, OP_SBB, dst, src_base, disp, size, BIT_DIR);
1094+}
1095+
1096+void cmp_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1097+{
1098+	x86_rr_sizedir(code, OP_CMP, src, dst, size);
1099+}
1100+
1101+void cmp_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1102+{
1103+	x86_ir(code, OP_IMMED_ARITH, OP_EX_CMPI, OP_CMP, val, dst, size);
1104+}
1105+
1106+void cmp_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1107+{
1108+	x86_irdisp(code, OP_IMMED_ARITH, OP_EX_CMPI, val, dst_base, disp, size);
1109+}
1110+
1111+void cmp_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1112+{
1113+	x86_rrdisp_sizedir(code, OP_CMP, src, dst_base, disp, size, 0);
1114+}
1115+
1116+void cmp_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1117+{
1118+	x86_rrdisp_sizedir(code, OP_CMP, dst, src_base, disp, size, BIT_DIR);
1119+}
1120+
1121+void test_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1122+{
1123+	x86_rr_sizedir(code, OP_TEST, src, dst, size);
1124+}
1125+
1126+void test_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1127+{
1128+	x86_ir(code, OP_NOT_NEG, OP_EX_TEST_I, OP_TEST, val, dst, size);
1129+}
1130+
1131+void test_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
1132+{
1133+	x86_irdisp(code, OP_NOT_NEG, OP_EX_TEST_I, val, dst_base, disp, size);
1134+}
1135+
1136+void test_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1137+{
1138+	x86_rrdisp_sizedir(code, OP_TEST, src, dst_base, disp, size, 0);
1139+}
1140+
1141+void test_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1142+{
1143+	x86_rrdisp_sizedir(code, OP_TEST, dst, src_base, disp, size, BIT_DIR);
1144+}
1145+
1146+void imul_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1147+{
1148+	x86_rr_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src, size);
1149+}
1150+
1151+void imul_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1152+{
1153+	x86_rrdisp_sizedir(code, OP2_IMUL | (PRE_2BYTE << 8), dst, src_base, disp, size, 0);
1154+}
1155+
1156+void imul_irr(code_info *code, int32_t val, uint8_t src, uint8_t dst, uint8_t size)
1157+{
1158+	if (size == SZ_B) {
1159+		fatal_error("imul immediate only supports 16-bit sizes and up");
1160+	}
1161+	
1162+	x86_ir(code, OP_IMUL, dst, 0, val, src, size);
1163+}
1164+
1165+void not_r(code_info *code, uint8_t dst, uint8_t size)
1166+{
1167+	x86_r_size(code, OP_NOT_NEG, OP_EX_NOT, dst, size);
1168+}
1169+
1170+void neg_r(code_info *code, uint8_t dst, uint8_t size)
1171+{
1172+	x86_r_size(code, OP_NOT_NEG, OP_EX_NEG, dst, size);
1173+}
1174+
1175+void not_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1176+{
1177+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NOT, dst_base, disp, size);
1178+}
1179+
1180+void neg_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1181+{
1182+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_NEG, dst_base, disp, size);
1183+}
1184+
1185+void mul_r(code_info *code, uint8_t dst, uint8_t size)
1186+{
1187+	x86_r_size(code, OP_NOT_NEG, OP_EX_MUL, dst, size);
1188+}
1189+
1190+void imul_r(code_info *code, uint8_t dst, uint8_t size)
1191+{
1192+	x86_r_size(code, OP_NOT_NEG, OP_EX_IMUL, dst, size);
1193+}
1194+
1195+void div_r(code_info *code, uint8_t dst, uint8_t size)
1196+{
1197+	x86_r_size(code, OP_NOT_NEG, OP_EX_DIV, dst, size);
1198+}
1199+
1200+void idiv_r(code_info *code, uint8_t dst, uint8_t size)
1201+{
1202+	x86_r_size(code, OP_NOT_NEG, OP_EX_IDIV, dst, size);
1203+}
1204+
1205+void mul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1206+{
1207+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_MUL, dst_base, disp, size);
1208+}
1209+
1210+void imul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1211+{
1212+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IMUL, dst_base, disp, size);
1213+}
1214+
1215+void div_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1216+{
1217+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_DIV, dst_base, disp, size);
1218+}
1219+
1220+void idiv_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size)
1221+{
1222+	x86_rdisp_size(code, OP_NOT_NEG, OP_EX_IDIV, dst_base, disp, size);
1223+}
1224+
1225+void mov_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1226+{
1227+	x86_rr_sizedir(code, OP_MOV, src, dst, size);
1228+}
1229+
1230+void mov_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size)
1231+{
1232+	x86_rrdisp_sizedir(code, OP_MOV, src, dst_base, disp, size, 0);
1233+}
1234+
1235+void mov_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size)
1236+{
1237+	x86_rrdisp_sizedir(code, OP_MOV, dst, src_base, disp, size, BIT_DIR);
1238+}
1239+
1240+void mov_rrind(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1241+{
1242+	x86_rrind_sizedir(code, OP_MOV, src, dst, size, 0);
1243+}
1244+
1245+void mov_rindr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1246+{
1247+	x86_rrind_sizedir(code, OP_MOV, dst, src, size, BIT_DIR);
1248+}
1249+
1250+void mov_rrindex(code_info *code, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size)
1251+{
1252+	x86_rrindex_sizedir(code, OP_MOV, src, dst_base, dst_index, scale, size, 0);
1253+}
1254+
1255+void mov_rindexr(code_info *code, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size)
1256+{
1257+	x86_rrindex_sizedir(code, OP_MOV, dst, src_base, src_index, scale, size, BIT_DIR);
1258+}
1259+
1260+void mov_ir(code_info *code, int64_t val, uint8_t dst, uint8_t size)
1261+{
1262+	check_alloc_code(code, 14);
1263+	code_ptr out = code->cur;
1264+	uint8_t sign_extend = 0;
1265+	if (size == SZ_Q && val <= 0x7FFFFFFF && val >= -2147483648) {
1266+		sign_extend = 1;
1267+	}
1268+	if (size == SZ_W) {
1269+		*(out++) = PRE_SIZE;
1270+	}
1271+	if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
1272+		*out = PRE_REX;
1273+		if (size == SZ_Q) {
1274+			*out |= REX_QUAD;
1275+		}
1276+		if (dst >= R8) {
1277+			*out |= REX_RM_FIELD;
1278+			dst -= (R8 - X86_R8);
1279+		}
1280+		out++;
1281+	}
1282+	if (dst >= AH && dst <= BH) {
1283+		dst -= (AH-X86_AH);
1284+	}
1285+	if (size == SZ_B) {
1286+		*(out++) = OP_MOV_I8R | dst;
1287+	} else if (size == SZ_Q && sign_extend) {
1288+		*(out++) = OP_MOV_IEA | BIT_SIZE;
1289+		*(out++) = MODE_REG_DIRECT | dst;
1290+	} else {
1291+		*(out++) = OP_MOV_IR | dst;
1292+	}
1293+	*(out++) = val;
1294+	if (size != SZ_B) {
1295+		val >>= 8;
1296+		*(out++) = val;
1297+		if (size != SZ_W) {
1298+			val >>= 8;
1299+			*(out++) = val;
1300+			val >>= 8;
1301+			*(out++) = val;
1302+			if (size == SZ_Q && !sign_extend) {
1303+				val >>= 8;
1304+				*(out++) = val;
1305+				val >>= 8;
1306+				*(out++) = val;
1307+				val >>= 8;
1308+				*(out++) = val;
1309+				val >>= 8;
1310+				*(out++) = val;
1311+			}
1312+		}
1313+	}
1314+	code->cur = out;
1315+}
1316+
1317+uint8_t is_mov_ir(code_ptr inst)
1318+{
1319+	while (*inst == PRE_SIZE || *inst == PRE_REX)
1320+	{
1321+		inst++;
1322+	}
1323+	return (*inst & 0xF8) == OP_MOV_I8R || (*inst & 0xF8) == OP_MOV_IR || (*inst & 0xFE) == OP_MOV_IEA;
1324+}
1325+
1326+void mov_irdisp(code_info *code, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
1327+{
1328+	check_alloc_code(code, 12);
1329+	code_ptr out = code->cur;
1330+	if (size == SZ_W) {
1331+		*(out++) = PRE_SIZE;
1332+	}
1333+	if (size == SZ_Q || dst >= R8) {
1334+		*out = PRE_REX;
1335+		if (size == SZ_Q) {
1336+			*out |= REX_QUAD;
1337+		}
1338+		if (dst >= R8) {
1339+			*out |= REX_RM_FIELD;
1340+			dst -= (R8 - X86_R8);
1341+		}
1342+		out++;
1343+	}
1344+	if (dst >= AH && dst <= BH) {
1345+		dst -= (AH-X86_AH);
1346+	}
1347+	*(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE);
1348+	if (disp < 128 && disp >= -128) {
1349+	*(out++) = MODE_REG_DISPLACE8 | dst;
1350+	*(out++) = disp;
1351+	} else {
1352+		*(out++) = MODE_REG_DISPLACE32 | dst;
1353+		*(out++) = disp;
1354+		*(out++) = disp >> 8;
1355+		*(out++) = disp >> 16;
1356+		*(out++) = disp >> 24;
1357+	}
1358+
1359+	*(out++) = val;
1360+	if (size != SZ_B) {
1361+		val >>= 8;
1362+		*(out++) = val;
1363+		if (size != SZ_W) {
1364+			val >>= 8;
1365+			*(out++) = val;
1366+			val >>= 8;
1367+			*(out++) = val;
1368+		}
1369+	}
1370+	code->cur = out;
1371+}
1372+
1373+void mov_irind(code_info *code, int32_t val, uint8_t dst, uint8_t size)
1374+{
1375+	check_alloc_code(code, 8);
1376+	code_ptr out = code->cur;
1377+	if (size == SZ_W) {
1378+		*(out++) = PRE_SIZE;
1379+	}
1380+	if (size == SZ_Q || dst >= R8 || (size == SZ_B && dst >= RSP && dst <= RDI)) {
1381+		*out = PRE_REX;
1382+		if (size == SZ_Q) {
1383+			*out |= REX_QUAD;
1384+		}
1385+		if (dst >= R8) {
1386+			*out |= REX_RM_FIELD;
1387+			dst -= (R8 - X86_R8);
1388+		}
1389+		out++;
1390+	}
1391+	if (dst >= AH && dst <= BH) {
1392+		dst -= (AH-X86_AH);
1393+	}
1394+	*(out++) = OP_MOV_IEA | (size == SZ_B ? 0 : BIT_SIZE);
1395+	*(out++) = MODE_REG_INDIRECT | dst;
1396+
1397+	*(out++) = val;
1398+	if (size != SZ_B) {
1399+		val >>= 8;
1400+		*(out++) = val;
1401+		if (size != SZ_W) {
1402+			val >>= 8;
1403+			*(out++) = val;
1404+			val >>= 8;
1405+			*(out++) = val;
1406+		}
1407+	}
1408+	code->cur = out;
1409+}
1410+
1411+void movsx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size)
1412+{
1413+	check_alloc_code(code, 5);
1414+	code_ptr out = code->cur;
1415+	if (size == SZ_W) {
1416+		*(out++) = PRE_SIZE;
1417+	}
1418+	if (size == SZ_Q || dst >= R8 || src >= R8) {
1419+		*out = PRE_REX;
1420+		if (size == SZ_Q) {
1421+			*out |= REX_QUAD;
1422+		}
1423+		if (src >= R8) {
1424+			*out |= REX_RM_FIELD;
1425+			src -= (R8 - X86_R8);
1426+		}
1427+		if (dst >= R8) {
1428+			*out |= REX_REG_FIELD;
1429+			dst -= (R8 - X86_R8);
1430+		}
1431+		out++;
1432+	}
1433+	if (src_size == SZ_D) {
1434+		*(out++) = OP_MOVSXD;
1435+	} else {
1436+		*(out++) = PRE_2BYTE;
1437+		*(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
1438+	}
1439+	*(out++) = MODE_REG_DIRECT | src | (dst << 3);
1440+	code->cur = out;
1441+}
1442+
1443+void movsx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size)
1444+{
1445+	check_alloc_code(code, 12);
1446+	code_ptr out = code->cur;
1447+	if (size == SZ_W) {
1448+		*(out++) = PRE_SIZE;
1449+	}
1450+	if (size == SZ_Q || dst >= R8 || src >= R8) {
1451+		*out = PRE_REX;
1452+		if (size == SZ_Q) {
1453+			*out |= REX_QUAD;
1454+		}
1455+		if (src >= R8) {
1456+			*out |= REX_RM_FIELD;
1457+			src -= (R8 - X86_R8);
1458+		}
1459+		if (dst >= R8) {
1460+			*out |= REX_REG_FIELD;
1461+			dst -= (R8 - X86_R8);
1462+		}
1463+		out++;
1464+	}
1465+	if (src_size == SZ_D) {
1466+		*(out++) = OP_MOVSXD;
1467+	} else {
1468+		*(out++) = PRE_2BYTE;
1469+		*(out++) = OP2_MOVSX | (src_size == SZ_B ? 0 : BIT_SIZE);
1470+	}
1471+	if (disp < 128 && disp >= -128) {
1472+	*(out++) = MODE_REG_DISPLACE8 | src | (dst << 3);
1473+	*(out++) = disp;
1474+	} else {
1475+		*(out++) = MODE_REG_DISPLACE32 | src | (dst << 3);
1476+		*(out++) = disp;
1477+		*(out++) = disp >> 8;
1478+		*(out++) = disp >> 16;
1479+		*(out++) = disp >> 24;
1480+	}
1481+	code->cur = out;
1482+}
1483+
1484+void movzx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size)
1485+{
1486+	check_alloc_code(code, 5);
1487+	code_ptr out = code->cur;
1488+	if (size == SZ_W) {
1489+		*(out++) = PRE_SIZE;
1490+	}
1491+	if (size == SZ_Q || dst >= R8 || src >= R8) {
1492+		*out = PRE_REX;
1493+		if (size == SZ_Q) {
1494+			*out |= REX_QUAD;
1495+		}
1496+		if (src >= R8) {
1497+			*out |= REX_RM_FIELD;
1498+			src -= (R8 - X86_R8);
1499+		}
1500+		if (dst >= R8) {
1501+			*out |= REX_REG_FIELD;
1502+			dst -= (R8 - X86_R8);
1503+		}
1504+		out++;
1505+	}
1506+	*(out++) = PRE_2BYTE;
1507+	*(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE);
1508+	*(out++) = MODE_REG_DIRECT | src | (dst << 3);
1509+	code->cur = out;
1510+}
1511+
1512+void movzx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size)
1513+{
1514+	check_alloc_code(code, 9);
1515+	code_ptr out = code->cur;
1516+	if (size == SZ_W) {
1517+		*(out++) = PRE_SIZE;
1518+	}
1519+	if (size == SZ_Q || dst >= R8 || src >= R8) {
1520+		*out = PRE_REX;
1521+		if (size == SZ_Q) {
1522+			*out |= REX_QUAD;
1523+		}
1524+		if (src >= R8) {
1525+			*out |= REX_RM_FIELD;
1526+			src -= (R8 - X86_R8);
1527+		}
1528+		if (dst >= R8) {
1529+			*out |= REX_REG_FIELD;
1530+			dst -= (R8 - X86_R8);
1531+		}
1532+		out++;
1533+	}
1534+	*(out++) = PRE_2BYTE;
1535+	*(out++) = OP2_MOVZX | (src_size == SZ_B ? 0 : BIT_SIZE);
1536+	if (disp < 128 && disp >= -128) {
1537+	*(out++) = MODE_REG_DISPLACE8 | src | (dst << 3);
1538+	*(out++) = disp;
1539+	} else {
1540+		*(out++) = MODE_REG_DISPLACE32 | src | (dst << 3);
1541+		*(out++) = disp;
1542+		*(out++) = disp >> 8;
1543+		*(out++) = disp >> 16;
1544+		*(out++) = disp >> 24;
1545+	}
1546+	code->cur = out;
1547+}
1548+
1549+void xchg_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1550+{
1551+	check_alloc_code(code, 4);
1552+	code_ptr out = code->cur;
1553+	//TODO: Use OP_XCHG_AX when one of the registers is AX, EAX or RAX
1554+	uint8_t tmp;
1555+	if (size == SZ_W) {
1556+		*(out++) = PRE_SIZE;
1557+	}
1558+	if (size == SZ_B && dst >= RSP && dst <= RDI) {
1559+		tmp = dst;
1560+		dst = src;
1561+		src = tmp;
1562+	}
1563+	if (size == SZ_Q || src >= R8 || dst >= R8 || (size == SZ_B && src >= RSP && src <= RDI)) {
1564+		*out = PRE_REX;
1565+		if (size == SZ_Q) {
1566+			*out |= REX_QUAD;
1567+		}
1568+		if (src >= R8) {
1569+			*out |= REX_REG_FIELD;
1570+			src -= (R8 - X86_R8);
1571+		}
1572+		if (dst >= R8) {
1573+			*out |= REX_RM_FIELD;
1574+			dst -= (R8 - X86_R8);
1575+		}
1576+		out++;
1577+	}
1578+	uint8_t opcode = OP_XCHG;
1579+	if (size == SZ_B) {
1580+		if (src >= AH && src <= BH) {
1581+			src -= (AH-X86_AH);
1582+		}
1583+		if (dst >= AH && dst <= BH) {
1584+			dst -= (AH-X86_AH);
1585+		}
1586+	} else {
1587+		opcode |= BIT_SIZE;
1588+	}
1589+	*(out++) = opcode;
1590+	*(out++) = MODE_REG_DIRECT | dst | (src << 3);
1591+	code->cur = out;
1592+}
1593+
1594+void pushf(code_info *code)
1595+{
1596+	check_alloc_code(code, 1);
1597+	code_ptr out = code->cur;
1598+	*(out++) = OP_PUSHF;
1599+	code->cur = out;
1600+}
1601+
1602+void popf(code_info *code)
1603+{
1604+	check_alloc_code(code, 1);
1605+	code_ptr out = code->cur;
1606+	*(out++) = OP_POPF;
1607+	code->cur = out;
1608+}
1609+
1610+void push_r(code_info *code, uint8_t reg)
1611+{
1612+	check_alloc_code(code, 2);
1613+	code_ptr out = code->cur;
1614+	if (reg >= R8) {
1615+		*(out++) = PRE_REX | REX_RM_FIELD;
1616+		reg -= R8 - X86_R8;
1617+	}
1618+	*(out++) = OP_PUSH | reg;
1619+	code->cur = out;
1620+	code->stack_off += sizeof(void *);
1621+}
1622+
1623+void push_rdisp(code_info *code, uint8_t base, int32_t disp)
1624+{
1625+	//This instruction has no explicit size, so we pass SZ_B
1626+	//to avoid any prefixes or bits being set
1627+	x86_rdisp_size(code, OP_SINGLE_EA, OP_EX_PUSH_EA, base, disp, SZ_B);
1628+	code->stack_off += sizeof(void *);
1629+}
1630+
1631+void pop_r(code_info *code, uint8_t reg)
1632+{
1633+	check_alloc_code(code, 2);
1634+	code_ptr out = code->cur;
1635+	if (reg >= R8) {
1636+		*(out++) = PRE_REX | REX_RM_FIELD;
1637+		reg -= R8 - X86_R8;
1638+	}
1639+	*(out++) = OP_POP | reg;
1640+	code->cur = out;
1641+	code->stack_off -= sizeof(void *);
1642+}
1643+
1644+void pop_rind(code_info *code, uint8_t reg)
1645+{
1646+	check_alloc_code(code, 3);
1647+	code_ptr out = code->cur;
1648+	if (reg >= R8) {
1649+		*(out++) = PRE_REX | REX_RM_FIELD;
1650+		reg -= R8 - X86_R8;
1651+	}
1652+	*(out++) = PRE_XOP;
1653+	*(out++) = MODE_REG_INDIRECT | reg;
1654+	code->cur = out;
1655+	code->stack_off -=  sizeof(void *);
1656+}
1657+
1658+void setcc_r(code_info *code, uint8_t cc, uint8_t dst)
1659+{
1660+	check_alloc_code(code, 4);
1661+	code_ptr out = code->cur;
1662+	if (dst >= R8) {
1663+		*(out++) = PRE_REX | REX_RM_FIELD;
1664+		dst -= R8 - X86_R8;
1665+	} else if (dst >= RSP && dst <= RDI) {
1666+		*(out++) = PRE_REX;
1667+	} else if (dst >= AH && dst <= BH) {
1668+		dst -= AH - X86_AH;
1669+	}
1670+	*(out++) = PRE_2BYTE;
1671+	*(out++) = OP2_SETCC | cc;
1672+	*(out++) = MODE_REG_DIRECT | dst;
1673+	code->cur = out;
1674+}
1675+
1676+void setcc_rind(code_info *code, uint8_t cc, uint8_t dst)
1677+{
1678+	check_alloc_code(code, 4);
1679+	code_ptr out = code->cur;
1680+	if (dst >= R8) {
1681+		*(out++) = PRE_REX | REX_RM_FIELD;
1682+		dst -= R8 - X86_R8;
1683+	}
1684+	*(out++) = PRE_2BYTE;
1685+	*(out++) = OP2_SETCC | cc;
1686+	*(out++) = MODE_REG_INDIRECT | dst;
1687+	code->cur = out;
1688+}
1689+
1690+void setcc_rdisp(code_info *code, uint8_t cc, uint8_t dst, int32_t disp)
1691+{
1692+	check_alloc_code(code, 8);
1693+	code_ptr out = code->cur;
1694+	if (dst >= R8) {
1695+		*(out++) = PRE_REX | REX_RM_FIELD;
1696+		dst -= R8 - X86_R8;
1697+	}
1698+	*(out++) = PRE_2BYTE;
1699+	*(out++) = OP2_SETCC | cc;
1700+	if (disp < 128 && disp >= -128) {
1701+	*(out++) = MODE_REG_DISPLACE8 | dst;
1702+	*(out++) = disp;
1703+	} else {
1704+		*(out++) = MODE_REG_DISPLACE32 | dst;
1705+		*(out++) = disp;
1706+		*(out++) = disp >> 8;
1707+		*(out++) = disp >> 16;
1708+		*(out++) = disp >> 24;
1709+	}
1710+	code->cur = out;
1711+}
1712+
1713+void bit_rr(code_info *code, uint8_t op2, uint8_t src, uint8_t dst, uint8_t size)
1714+{
1715+	check_alloc_code(code, 5);
1716+	code_ptr out = code->cur;
1717+	if (size == SZ_W) {
1718+		*(out++) = PRE_SIZE;
1719+	}
1720+	if (size == SZ_Q || src >= R8 || dst >= R8) {
1721+		*out = PRE_REX;
1722+		if (size == SZ_Q) {
1723+			*out |= REX_QUAD;
1724+		}
1725+		if (src >= R8) {
1726+			*out |= REX_REG_FIELD;
1727+			src -= (R8 - X86_R8);
1728+		}
1729+		if (dst >= R8) {
1730+			*out |= REX_RM_FIELD;
1731+			dst -= (R8 - X86_R8);
1732+		}
1733+		out++;
1734+	}
1735+	*(out++) = PRE_2BYTE;
1736+	*(out++) = op2;
1737+	*(out++) = MODE_REG_DIRECT | dst | (src << 3);
1738+	code->cur = out;
1739+}
1740+
1741+void bit_rrdisp(code_info *code, uint8_t op2, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1742+{
1743+	check_alloc_code(code, 9);
1744+	code_ptr out = code->cur;
1745+	if (size == SZ_W) {
1746+		*(out++) = PRE_SIZE;
1747+	}
1748+	if (size == SZ_Q || src >= R8 || dst_base >= R8) {
1749+		*out = PRE_REX;
1750+		if (size == SZ_Q) {
1751+			*out |= REX_QUAD;
1752+		}
1753+		if (src >= R8) {
1754+			*out |= REX_REG_FIELD;
1755+			src -= (R8 - X86_R8);
1756+		}
1757+		if (dst_base >= R8) {
1758+			*out |= REX_RM_FIELD;
1759+			dst_base -= (R8 - X86_R8);
1760+		}
1761+		out++;
1762+	}
1763+	*(out++) = PRE_2BYTE;
1764+	*(out++) = op2;
1765+	if (dst_disp < 128 && dst_disp >= -128) {
1766+	*(out++) = MODE_REG_DISPLACE8 | dst_base | (src << 3);
1767+	*(out++) = dst_disp;
1768+	} else {
1769+	*(out++) = MODE_REG_DISPLACE32 | dst_base | (src << 3);
1770+	*(out++) = dst_disp;
1771+	*(out++) = dst_disp >> 8;
1772+	*(out++) = dst_disp >> 16;
1773+	*(out++) = dst_disp >> 24;
1774+	}
1775+	code->cur = out;
1776+}
1777+
1778+void bit_ir(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
1779+{
1780+	check_alloc_code(code, 6);
1781+	code_ptr out = code->cur;
1782+	if (size == SZ_W) {
1783+		*(out++) = PRE_SIZE;
1784+	}
1785+	if (size == SZ_Q || dst >= R8) {
1786+		*out = PRE_REX;
1787+		if (size == SZ_Q) {
1788+			*out |= REX_QUAD;
1789+		}
1790+		if (dst >= R8) {
1791+			*out |= REX_RM_FIELD;
1792+			dst -= (R8 - X86_R8);
1793+		}
1794+		out++;
1795+	}
1796+	*(out++) = PRE_2BYTE;
1797+	*(out++) = OP2_BTX_I;
1798+	*(out++) = MODE_REG_DIRECT | dst | (op_ex << 3);
1799+	*(out++) = val;
1800+	code->cur = out;
1801+}
1802+
1803+void bit_irdisp(code_info *code, uint8_t op_ex, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1804+{
1805+	check_alloc_code(code, 10);
1806+	code_ptr out = code->cur;
1807+	if (size == SZ_W) {
1808+		*(out++) = PRE_SIZE;
1809+	}
1810+	if (size == SZ_Q || dst_base >= R8) {
1811+		*out = PRE_REX;
1812+		if (size == SZ_Q) {
1813+			*out |= REX_QUAD;
1814+		}
1815+		if (dst_base >= R8) {
1816+			*out |= REX_RM_FIELD;
1817+			dst_base -= (R8 - X86_R8);
1818+		}
1819+		out++;
1820+	}
1821+	*(out++) = PRE_2BYTE;
1822+	*(out++) = OP2_BTX_I;
1823+	if (dst_disp < 128 && dst_disp >= -128) {
1824+	*(out++) = MODE_REG_DISPLACE8 | dst_base | (op_ex << 3);
1825+	*(out++) = dst_disp;
1826+	} else {
1827+		*(out++) = MODE_REG_DISPLACE32 | dst_base | (op_ex << 3);
1828+		*(out++) = dst_disp;
1829+		*(out++) = dst_disp >> 8;
1830+		*(out++) = dst_disp >> 16;
1831+		*(out++) = dst_disp >> 24;
1832+	}
1833+	*(out++) = val;
1834+	code->cur = out;
1835+}
1836+
1837+void bt_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1838+{
1839+	return bit_rr(code, OP2_BT, src, dst, size);
1840+}
1841+
1842+void bt_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1843+{
1844+	return bit_rrdisp(code, OP2_BT, src, dst_base, dst_disp, size);
1845+}
1846+
1847+void bt_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
1848+{
1849+	return bit_ir(code, OP_EX_BT, val, dst, size);
1850+}
1851+
1852+void bt_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1853+{
1854+	return bit_irdisp(code, OP_EX_BT, val, dst_base, dst_disp, size);
1855+}
1856+
1857+void bts_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1858+{
1859+	return bit_rr(code, OP2_BTS, src, dst, size);
1860+}
1861+
1862+void bts_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1863+{
1864+	return bit_rrdisp(code, OP2_BTS, src, dst_base, dst_disp, size);
1865+}
1866+
1867+void bts_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
1868+{
1869+	return bit_ir(code, OP_EX_BTS, val, dst, size);
1870+}
1871+
1872+void bts_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1873+{
1874+	return bit_irdisp(code, OP_EX_BTS, val, dst_base, dst_disp, size);
1875+}
1876+
1877+void btr_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1878+{
1879+	return bit_rr(code, OP2_BTR, src, dst, size);
1880+}
1881+
1882+void btr_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1883+{
1884+	return bit_rrdisp(code, OP2_BTR, src, dst_base, dst_disp, size);
1885+}
1886+
1887+void btr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
1888+{
1889+	return bit_ir(code, OP_EX_BTR, val, dst, size);
1890+}
1891+
1892+void btr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1893+{
1894+	return bit_irdisp(code, OP_EX_BTR, val, dst_base, dst_disp, size);
1895+}
1896+
1897+void btc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size)
1898+{
1899+	return bit_rr(code, OP2_BTC, src, dst, size);
1900+}
1901+
1902+void btc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1903+{
1904+	return bit_rrdisp(code, OP2_BTC, src, dst_base, dst_disp, size);
1905+}
1906+
1907+void btc_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size)
1908+{
1909+	return bit_ir(code, OP_EX_BTC, val, dst, size);
1910+}
1911+
1912+void btc_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size)
1913+{
1914+	return bit_irdisp(code, OP_EX_BTC, val, dst_base, dst_disp, size);
1915+}
1916+
1917+void jcc(code_info *code, uint8_t cc, code_ptr dest)
1918+{
1919+	check_alloc_code(code, 6);
1920+	code_ptr out = code->cur;
1921+	ptrdiff_t disp = dest-(out+2);
1922+	if (disp <= 0x7F && disp >= -0x80) {
1923+		*(out++) = OP_JCC | cc;
1924+		*(out++) = disp;
1925+	} else {
1926+		disp = dest-(out+6);
1927+		if (CHECK_DISP(disp)) {
1928+			*(out++) = PRE_2BYTE;
1929+			*(out++) = OP2_JCC | cc;
1930+			*(out++) = disp;
1931+			disp >>= 8;
1932+			*(out++) = disp;
1933+			disp >>= 8;
1934+			*(out++) = disp;
1935+			disp >>= 8;
1936+			*(out++) = disp;
1937+		} else {
1938+			fatal_error("jcc: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp);
1939+		}
1940+	}
1941+	code->cur = out;
1942+}
1943+
1944+void jmp(code_info *code, code_ptr dest)
1945+{
1946+	check_alloc_code(code, 5);
1947+	code_ptr out = code->cur;
1948+	ptrdiff_t disp = dest-(out+2);
1949+	if (disp <= 0x7F && disp >= -0x80) {
1950+		*(out++) = OP_JMP_BYTE;
1951+		*(out++) = disp;
1952+	} else {
1953+		disp = dest-(out+5);
1954+		if (CHECK_DISP(disp)) {
1955+			*(out++) = OP_JMP;
1956+			*(out++) = disp;
1957+			disp >>= 8;
1958+			*(out++) = disp;
1959+			disp >>= 8;
1960+			*(out++) = disp;
1961+			disp >>= 8;
1962+			*(out++) = disp;
1963+		} else {
1964+			fatal_error("jmp: %p - %p = %lX which is out of range for a 32-bit displacement\n", dest, out + 6, (long)disp);
1965+		}
1966+	}
1967+	code->cur = out;
1968+}
1969+
1970+void jmp_r(code_info *code, uint8_t dst)
1971+{
1972+	check_alloc_code(code, 3);
1973+	code_ptr out = code->cur;
1974+	if (dst >= R8) {
1975+		dst -= R8 - X86_R8;
1976+		*(out++) = PRE_REX | REX_RM_FIELD;
1977+	}
1978+	*(out++) = OP_SINGLE_EA;
1979+	*(out++) = MODE_REG_DIRECT | dst | (OP_EX_JMP_EA << 3);
1980+	code->cur = out;
1981+}
1982+
1983+void jmp_rind(code_info *code, uint8_t dst)
1984+{
1985+	check_alloc_code(code, 3);
1986+	code_ptr out = code->cur;
1987+	if (dst >= R8) {
1988+		dst -= R8 - X86_R8;
1989+		*(out++) = PRE_REX | REX_RM_FIELD;
1990+	}
1991+	*(out++) = OP_SINGLE_EA;
1992+	*(out++) = MODE_REG_INDIRECT | dst | (OP_EX_JMP_EA << 3);
1993+	code->cur = out;
1994+}
1995+
1996+void call_noalign(code_info *code, code_ptr fun)
1997+{
1998+	check_alloc_code(code, 5);
1999+	code_ptr out = code->cur;
2000+	ptrdiff_t disp = fun-(out+5);
2001+	if (CHECK_DISP(disp)) {
2002+		*(out++) = OP_CALL;
2003+		*(out++) = disp;
2004+		disp >>= 8;
2005+		*(out++) = disp;
2006+		disp >>= 8;
2007+		*(out++) = disp;
2008+		disp >>= 8;
2009+		*(out++) = disp;
2010+	} else {
2011+		//TODO: Implement far call???
2012+		fatal_error("call: %p - %p = %lX which is out of range for a 32-bit displacement\n", fun, out + 5, (long)disp);
2013+	}
2014+	code->cur = out;
2015+}
2016+
2017+volatile int foo;
2018+void call(code_info *code, code_ptr fun)
2019+{
2020+	foo = *fun;
2021+	code->stack_off += sizeof(void *);
2022+	int32_t adjust = 0;
2023+	if (code->stack_off & 0xF) {
2024+		adjust = 16 - (code->stack_off & 0xF);
2025+		code->stack_off += adjust;
2026+		sub_ir(code, adjust, RSP, SZ_PTR);
2027+	}
2028+	call_noalign(code, fun);
2029+	if (adjust) {
2030+		add_ir(code, adjust, RSP, SZ_PTR);
2031+	}
2032+	code->stack_off -= sizeof(void *) + adjust;
2033+}
2034+void call_raxfallback(code_info *code, code_ptr fun)
2035+{
2036+	check_alloc_code(code, 5);
2037+	code_ptr out = code->cur;
2038+	ptrdiff_t disp = fun-(out+5);
2039+	if (CHECK_DISP(disp)) {
2040+		*(out++) = OP_CALL;
2041+		*(out++) = disp;
2042+		disp >>= 8;
2043+		*(out++) = disp;
2044+		disp >>= 8;
2045+		*(out++) = disp;
2046+		disp >>= 8;
2047+		*(out++) = disp;
2048+		code->cur = out;
2049+	} else {
2050+		mov_ir(code, (int64_t)fun, RAX, SZ_PTR);
2051+		call_r(code, RAX);
2052+	}
2053+}
2054+
2055+void call_r(code_info *code, uint8_t dst)
2056+{
2057+	code->stack_off += sizeof(void *);
2058+	int32_t adjust = 0;
2059+	if (code->stack_off & 0xF) {
2060+		adjust = 16 - (code->stack_off & 0xF);
2061+		code->stack_off += adjust;
2062+		sub_ir(code, adjust, RSP, SZ_PTR);
2063+	}
2064+	check_alloc_code(code, 2);
2065+	code_ptr out = code->cur;
2066+	*(out++) = OP_SINGLE_EA;
2067+	*(out++) = MODE_REG_DIRECT | dst | (OP_EX_CALL_EA << 3);
2068+	code->cur = out;
2069+	if (adjust) {
2070+		add_ir(code, adjust, RSP, SZ_PTR);
2071+	}
2072+	code->stack_off -= sizeof(void *) + adjust;
2073+}
2074+
2075+void retn(code_info *code)
2076+{
2077+	check_alloc_code(code, 1);
2078+	code_ptr out = code->cur;
2079+	*(out++) = OP_RETN;
2080+	code->cur = out;
2081+}
2082+
2083+void rts(code_info *code)
2084+{
2085+	retn(code);
2086+}
2087+
2088+void cdq(code_info *code)
2089+{
2090+	check_alloc_code(code, 1);
2091+	code_ptr out = code->cur;
2092+	*(out++) = OP_CDQ;
2093+	code->cur = out;
2094+}
2095+
2096+void loop(code_info *code, code_ptr dst)
2097+{
2098+	check_alloc_code(code, 2);
2099+	code_ptr out = code->cur;
2100+	ptrdiff_t disp = dst-(out+2);
2101+	*(out++) = OP_LOOP;
2102+	*(out++) = disp;
2103+	code->cur = out;
2104+}
2105+
2106+uint32_t prep_args(code_info *code, uint32_t num_args, va_list args)
2107+{
2108+	uint8_t *arg_arr = malloc(num_args);
2109+	for (int i = 0; i < num_args; i ++)
2110+	{
2111+		arg_arr[i] = va_arg(args, int);
2112+	}
2113+#ifdef X86_64
2114+	uint32_t stack_args = 0;
2115+	uint8_t abi_regs[] = {RDI, RSI, RDX, RCX, R8, R9};
2116+	int8_t reg_swap[R15+1];
2117+	uint32_t usage = 0;
2118+	memset(reg_swap, -1, sizeof(reg_swap));
2119+	for (int i = 0; i < num_args; i ++)
2120+	{
2121+		usage |= 1 << arg_arr[i];
2122+	}
2123+	for (int i = 0; i < num_args; i ++)
2124+	{
2125+		uint8_t reg_arg = arg_arr[i];
2126+		if (i < sizeof(abi_regs)) {
2127+			if (reg_swap[reg_arg] >= 0) {
2128+				reg_arg = reg_swap[reg_arg];
2129+			}
2130+			if (reg_arg != abi_regs[i]) {
2131+				if (usage & (1 << abi_regs[i])) {
2132+					xchg_rr(code, reg_arg, abi_regs[i], SZ_PTR);
2133+					reg_swap[abi_regs[i]] = reg_arg;
2134+				} else {
2135+					mov_rr(code, reg_arg, abi_regs[i], SZ_PTR);
2136+				}
2137+			}
2138+		} else {
2139+			arg_arr[stack_args++] = reg_arg;
2140+		}
2141+	}
2142+#else
2143+#define stack_args num_args
2144+#endif
2145+	uint32_t stack_off_call = code->stack_off + sizeof(void *) * (stack_args + 1);
2146+	uint32_t adjust = 0;
2147+	if (stack_off_call & 0xF) {
2148+		adjust = 16 - (stack_off_call & 0xF);
2149+		sub_ir(code, adjust, RSP, SZ_PTR);
2150+		code->stack_off += adjust;
2151+	}
2152+	for (int i = stack_args -1; i >= 0; i--)
2153+	{
2154+		push_r(code, arg_arr[i]);
2155+	}
2156+	free(arg_arr);
2157+	
2158+	return stack_args * sizeof(void *) + adjust;
2159+}
2160+
2161+void call_args(code_info *code, code_ptr fun, uint32_t num_args, ...)
2162+{
2163+	va_list args;
2164+	va_start(args, num_args);
2165+	uint32_t adjust = prep_args(code, num_args, args);
2166+	va_end(args);
2167+	call_raxfallback(code, fun);
2168+	if (adjust) {
2169+		add_ir(code, adjust, RSP, SZ_PTR);
2170+		code->stack_off -= adjust;
2171+	}
2172+}
2173+
2174+void call_args_r(code_info *code, uint8_t fun_reg, uint32_t num_args, ...)
2175+{
2176+	va_list args;
2177+	va_start(args, num_args);
2178+	uint32_t adjust = prep_args(code, num_args, args);
2179+	va_end(args);
2180+	call_r(code, fun_reg);
2181+	if (adjust) {
2182+		add_ir(code, adjust, RSP, SZ_PTR);
2183+		code->stack_off -= adjust;
2184+	}
2185+}
2186+/*
2187+void call_args_abi(code_info *code, code_ptr fun, uint32_t num_args, ...)
2188+{
2189+	va_list args;
2190+	va_start(args, num_args);
2191+	uint32_t adjust = prep_args(code, num_args, args);
2192+	va_end(args);
2193+#ifdef X86_64
2194+	test_ir(code, 8, RSP, SZ_PTR); //check stack alignment
2195+	code_ptr do_adjust_rsp = code->cur + 1;
2196+	jcc(code, CC_NZ, code->cur + 2);
2197+#endif
2198+	call_raxfallback(code, fun);
2199+	if (adjust) {
2200+		add_ir(code, adjust, RSP, SZ_PTR);
2201+	}
2202+#ifdef X86_64
2203+	code_ptr no_adjust_rsp = code->cur + 1;
2204+	jmp(code, code->cur + 2);
2205+	*do_adjust_rsp = code->cur - (do_adjust_rsp+1);
2206+	sub_ir(code, 8, RSP, SZ_PTR);
2207+	call_raxfallback(code, fun);
2208+	add_ir(code, adjust + 8 , RSP, SZ_PTR);
2209+	*no_adjust_rsp = code->cur - (no_adjust_rsp+1);
2210+#endif
2211+}
2212+*/
2213+void save_callee_save_regs(code_info *code)
2214+{
2215+	push_r(code, RBX);
2216+	push_r(code, RBP);
2217+#ifdef X86_64
2218+	push_r(code, R12);
2219+	push_r(code, R13);
2220+	push_r(code, R14);
2221+	push_r(code, R15);
2222+#else
2223+	push_r(code, RDI);
2224+	push_r(code, RSI);
2225+#endif
2226+}
2227+
2228+void restore_callee_save_regs(code_info *code)
2229+{
2230+#ifdef X86_64
2231+	pop_r(code, R15);
2232+	pop_r(code, R14);
2233+	pop_r(code, R13);
2234+	pop_r(code, R12);
2235+#else
2236+	pop_r(code, RSI);
2237+	pop_r(code, RDI);
2238+#endif
2239+	pop_r(code, RBP);
2240+	pop_r(code, RBX);
2241+}
2242+
2243+uint8_t has_modrm(uint8_t prefix, uint8_t opcode)
2244+{
2245+	if (!prefix) {
2246+		switch (opcode)
2247+		{
2248+		case OP_JMP:
2249+		case OP_JMP_BYTE:
2250+		case OP_JCC:
2251+		case OP_CALL:
2252+		case OP_RETN:
2253+		case OP_LOOP:
2254+		case OP_MOV_I8R:
2255+		case OP_MOV_IR:
2256+		case OP_PUSHF:
2257+		case OP_POPF:
2258+		case OP_PUSH:
2259+		case OP_POP:
2260+		case OP_CDQ:
2261+			return 0;
2262+		}
2263+	} else if (prefix == PRE_2BYTE) {
2264+		switch (opcode)
2265+		{
2266+		case OP2_JCC:
2267+			return 0;
2268+		}
2269+	}
2270+	return 1;
2271+}
2272+
2273+uint8_t has_sib(uint8_t mod_rm)
2274+{
2275+	uint8_t mode = mod_rm & 0xC0;
2276+	uint8_t rm = mod_rm & 3;
2277+
2278+	return mode != MODE_REG_DIRECT && rm == RSP;
2279+}
2280+
2281+uint32_t x86_inst_size(code_ptr start)
2282+{
2283+	code_ptr code = start;
2284+	uint8_t cont = 1;
2285+	uint8_t prefix = 0;
2286+	uint8_t op_size = SZ_B;
2287+	uint8_t main_op;
2288+
2289+	while (cont)
2290+	{
2291+		if (*code == PRE_SIZE) {
2292+			op_size = SZ_W;
2293+		} else if (*code == PRE_REX) {
2294+			if (*code & REX_QUAD) {
2295+				op_size = SZ_Q;
2296+			}
2297+		} else if(*code == PRE_2BYTE || *code == PRE_XOP) {
2298+			prefix = *code;
2299+		} else {
2300+			main_op = *code;
2301+			cont = 0;
2302+		}
2303+		code++;
2304+	}
2305+	if (has_modrm(prefix, main_op)) {
2306+		uint8_t mod_rm = *(code++);
2307+		if (has_sib(mod_rm)) {
2308+			//sib takes up a byte, but can't add any additional ones beyond that
2309+			code++;
2310+		}
2311+		uint8_t mode = mod_rm & 0xC0;
2312+		uint8_t rm = mod_rm & 3;
2313+		if (mode == MODE_REG_DISPLACE8) {
2314+			code++;
2315+		} else if (mode == MODE_REG_DISPLACE32 || (mode == MODE_REG_INDIRECT && rm == RBP)) {
2316+			code += 4;
2317+		}
2318+	} else {
2319+	}
2320+
2321+	return code-start;
2322+}
+221, -0
  1@@ -0,0 +1,221 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef GEN_X86_H_
  8+#define GEN_X86_H_
  9+
 10+#include <stdint.h>
 11+#include "gen.h"
 12+
 13+enum {
 14+	RAX = 0,
 15+	RCX,
 16+	RDX,
 17+	RBX,
 18+	RSP,
 19+	RBP,
 20+	RSI,
 21+	RDI,
 22+	AH,
 23+	CH,
 24+	DH,
 25+	BH,
 26+	R8,
 27+	R9,
 28+	R10,
 29+	R11,
 30+	R12,
 31+	R13,
 32+	R14,
 33+	R15
 34+};
 35+
 36+enum {
 37+	CC_O = 0,
 38+	CC_NO,
 39+	CC_C,
 40+	CC_B = CC_C,
 41+	CC_NC,
 42+	CC_NB = CC_NC,
 43+	CC_Z,
 44+	CC_NZ,
 45+	CC_BE,
 46+	CC_A,
 47+	CC_S,
 48+	CC_NS,
 49+	CC_P,
 50+	CC_NP,
 51+	CC_L,
 52+	CC_GE,
 53+	CC_LE,
 54+	CC_G
 55+};
 56+
 57+enum {
 58+	SZ_B = 0,
 59+	SZ_W,
 60+	SZ_D,
 61+	SZ_Q
 62+};
 63+
 64+#ifdef X86_64
 65+#define SZ_PTR SZ_Q
 66+#define MAX_INST_LEN 14
 67+#else
 68+#define SZ_PTR SZ_D
 69+#define MAX_INST_LEN 11
 70+#endif
 71+
 72+enum {
 73+	MODE_REG_INDIRECT = 0,
 74+	MODE_REG_INDEXED = 4,
 75+	MODE_REG_DISPLACE8 = 0x40,
 76+	MODE_REG_INDEXED_DISPLACE8 = 0x44,
 77+	MODE_REG_DISPLACE32 = 0x80,
 78+	MODE_REG_INDEXED_DIPSLACE32 = 0x84,
 79+	MODE_REG_DIRECT = 0xC0,
 80+//"phony" mode
 81+	MODE_IMMED = 0xFF
 82+};
 83+
 84+void rol_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 85+void ror_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 86+void rcl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 87+void rcr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 88+void shl_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 89+void shr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 90+void sar_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
 91+void rol_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 92+void ror_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 93+void rcl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 94+void rcr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 95+void shl_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 96+void shr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 97+void sar_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
 98+void rol_clr(code_info *code, uint8_t dst, uint8_t size);
 99+void ror_clr(code_info *code, uint8_t dst, uint8_t size);
100+void rcl_clr(code_info *code, uint8_t dst, uint8_t size);
101+void rcr_clr(code_info *code, uint8_t dst, uint8_t size);
102+void shl_clr(code_info *code, uint8_t dst, uint8_t size);
103+void shr_clr(code_info *code, uint8_t dst, uint8_t size);
104+void sar_clr(code_info *code, uint8_t dst, uint8_t size);
105+void rol_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
106+void ror_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
107+void rcl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
108+void rcr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
109+void shl_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
110+void shr_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
111+void sar_clrdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
112+void add_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
113+void adc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
114+void or_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
115+void xor_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
116+void and_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
117+void sub_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
118+void sbb_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
119+void cmp_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
120+void add_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
121+void adc_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
122+void or_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
123+void xor_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
124+void and_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
125+void sub_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
126+void sbb_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
127+void cmp_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
128+void add_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
129+void adc_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
130+void or_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
131+void xor_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
132+void and_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
133+void sub_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
134+void sbb_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
135+void cmp_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
136+void add_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
137+void adc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
138+void add_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
139+void adc_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
140+void or_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
141+void or_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
142+void xor_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
143+void xor_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
144+void and_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
145+void and_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
146+void sub_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
147+void sub_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
148+void sbb_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
149+void sbb_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
150+void cmp_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
151+void cmp_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
152+void imul_irr(code_info *code, int32_t val, uint8_t src, uint8_t dst, uint8_t size);
153+void imul_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
154+void imul_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
155+void imul_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
156+void not_r(code_info *code, uint8_t dst, uint8_t size);
157+void neg_r(code_info *code, uint8_t dst, uint8_t size);
158+void not_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
159+void neg_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
160+void mul_r(code_info *code, uint8_t dst, uint8_t size);
161+void imul_r(code_info *code, uint8_t dst, uint8_t size);
162+void div_r(code_info *code, uint8_t dst, uint8_t size);
163+void idiv_r(code_info *code, uint8_t dst, uint8_t size);
164+void mul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
165+void imul_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
166+void div_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
167+void idiv_rdisp(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
168+void test_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
169+void test_ir(code_info *code, int32_t val, uint8_t dst, uint8_t size);
170+void test_irdisp(code_info *code, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size);
171+void test_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
172+void test_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
173+void mov_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
174+void mov_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t disp, uint8_t size);
175+void mov_rdispr(code_info *code, uint8_t src_base, int32_t disp, uint8_t dst, uint8_t size);
176+void mov_rrindex(code_info *code, uint8_t src, uint8_t dst_base, uint8_t dst_index, uint8_t scale, uint8_t size);
177+void mov_rindexr(code_info *code, uint8_t src_base, uint8_t src_index, uint8_t scale, uint8_t dst, uint8_t size);
178+void mov_rrind(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
179+void mov_rindr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
180+void mov_ir(code_info *code, int64_t val, uint8_t dst, uint8_t size);
181+void mov_irdisp(code_info *code, int32_t val, uint8_t dst, int32_t disp, uint8_t size);
182+void mov_irind(code_info *code, int32_t val, uint8_t dst, uint8_t size);
183+void movsx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size);
184+void movsx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size);
185+void movzx_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t src_size, uint8_t size);
186+void movzx_rdispr(code_info *code, uint8_t src, int32_t disp, uint8_t dst, uint8_t src_size, uint8_t size);
187+void xchg_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
188+void pushf(code_info *code);
189+void popf(code_info *code);
190+void push_r(code_info *code, uint8_t reg);
191+void push_rdisp(code_info *code, uint8_t base, int32_t disp);
192+void pop_r(code_info *code, uint8_t reg);
193+void pop_rind(code_info *code, uint8_t reg);
194+void setcc_r(code_info *code, uint8_t cc, uint8_t dst);
195+void setcc_rind(code_info *code, uint8_t cc, uint8_t dst);
196+void setcc_rdisp(code_info *code, uint8_t cc, uint8_t dst, int32_t disp);
197+void bt_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
198+void bt_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size);
199+void bt_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
200+void bt_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size);
201+void bts_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
202+void bts_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size);
203+void bts_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
204+void bts_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size);
205+void btr_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
206+void btr_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size);
207+void btr_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
208+void btr_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size);
209+void btc_rr(code_info *code, uint8_t src, uint8_t dst, uint8_t size);
210+void btc_rrdisp(code_info *code, uint8_t src, uint8_t dst_base, int32_t dst_disp, uint8_t size);
211+void btc_ir(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
212+void btc_irdisp(code_info *code, uint8_t val, uint8_t dst_base, int32_t dst_disp, uint8_t size);
213+void jcc(code_info *code, uint8_t cc, code_ptr dest);
214+void jmp_rind(code_info *code, uint8_t dst);
215+void call_noalign(code_info *code, code_ptr fun);
216+void call_r(code_info *code, uint8_t dst);
217+void retn(code_info *code);
218+void cdq(code_info *code);
219+void loop(code_info *code, code_ptr dst);
220+uint8_t is_mov_ir(code_ptr inst);
221+
222+#endif //GEN_X86_H_
+1507, -0
   1@@ -0,0 +1,1507 @@
   2+/*
   3+ Copyright 2013-2016 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "genesis.h"
   8+#include "blastem.h"
   9+#include "nor.h"
  10+#include <stdlib.h>
  11+#include <ctype.h>
  12+#include <time.h>
  13+#include <string.h>
  14+#include "render.h"
  15+#include "gst.h"
  16+#include "util.h"
  17+#include "debug.h"
  18+#include "gdb_remote.h"
  19+#include "saves.h"
  20+#include "bindings.h"
  21+#include "jcart.h"
  22+#define MCLKS_NTSC 53693175
  23+#define MCLKS_PAL  53203395
  24+
  25+uint32_t MCLKS_PER_68K;
  26+#define MCLKS_PER_YM  7
  27+#define MCLKS_PER_Z80 15
  28+#define MCLKS_PER_PSG (MCLKS_PER_Z80*16)
  29+#define Z80_INT_PULSE_MCLKS 2573 //measured value is ~171.5 Z80 clocks
  30+#define DEFAULT_SYNC_INTERVAL MCLKS_LINE
  31+#define DEFAULT_LOWPASS_CUTOFF 3390
  32+
  33+//TODO: Figure out the exact value for this
  34+#define LINES_NTSC 262
  35+#define LINES_PAL 313
  36+
  37+#define MAX_SOUND_CYCLES 100000	
  38+
  39+#define Z80_CYCLE current_cycle
  40+#define Z80_OPTS options
  41+
  42+void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc)
  43+{
  44+	start_section(buf, SECTION_68000);
  45+	m68k_serialize(gen->m68k, m68k_pc, buf);
  46+	end_section(buf);
  47+	
  48+	start_section(buf, SECTION_Z80);
  49+	z80_serialize(gen->z80, buf);
  50+	end_section(buf);
  51+	
  52+	start_section(buf, SECTION_VDP);
  53+	vdp_serialize(gen->vdp, buf);
  54+	end_section(buf);
  55+	
  56+	start_section(buf, SECTION_YM2612);
  57+	ym_serialize(gen->ym, buf);
  58+	end_section(buf);
  59+	
  60+	start_section(buf, SECTION_PSG);
  61+	psg_serialize(gen->psg, buf);
  62+	end_section(buf);
  63+	
  64+	start_section(buf, SECTION_GEN_BUS_ARBITER);
  65+	save_int8(buf, gen->z80->reset);
  66+	save_int8(buf, gen->z80->busreq);
  67+	save_int16(buf, gen->z80_bank_reg);
  68+	end_section(buf);
  69+	
  70+	start_section(buf, SECTION_SEGA_IO_1);
  71+	io_serialize(gen->io.ports, buf);
  72+	end_section(buf);
  73+	
  74+	start_section(buf, SECTION_SEGA_IO_2);
  75+	io_serialize(gen->io.ports + 1, buf);
  76+	end_section(buf);
  77+	
  78+	start_section(buf, SECTION_SEGA_IO_EXT);
  79+	io_serialize(gen->io.ports + 2, buf);
  80+	end_section(buf);
  81+	
  82+	start_section(buf, SECTION_MAIN_RAM);
  83+	save_int8(buf, RAM_WORDS * 2 / 1024);
  84+	save_buffer16(buf, gen->work_ram, RAM_WORDS);
  85+	end_section(buf);
  86+	
  87+	start_section(buf, SECTION_SOUND_RAM);
  88+	save_int8(buf, Z80_RAM_BYTES / 1024);
  89+	save_buffer8(buf, gen->zram, Z80_RAM_BYTES);
  90+	end_section(buf);
  91+	
  92+	cart_serialize(&gen->header, buf);
  93+}
  94+
  95+static uint8_t *serialize(system_header *sys, size_t *size_out)
  96+{
  97+	genesis_context *gen = (genesis_context *)sys;
  98+	uint32_t address;
  99+	if (gen->m68k->resume_pc) {
 100+		gen->m68k->target_cycle = gen->m68k->current_cycle;
 101+		gen->header.save_state = SERIALIZE_SLOT+1;
 102+		resume_68k(gen->m68k);
 103+		if (size_out) {
 104+			*size_out = gen->serialize_size;
 105+		}
 106+		return gen->serialize_tmp;
 107+	} else {
 108+		serialize_buffer state;
 109+		init_serialize(&state);
 110+		uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16;
 111+		address |= read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k);
 112+		genesis_serialize(gen, &state, address);
 113+		if (size_out) {
 114+			*size_out = state.size;
 115+		}
 116+		return state.data;
 117+	}
 118+}
 119+
 120+static void ram_deserialize(deserialize_buffer *buf, void *vgen)
 121+{
 122+	genesis_context *gen = vgen;
 123+	uint32_t ram_size = load_int8(buf) * 1024 / 2;
 124+	if (ram_size > RAM_WORDS) {
 125+		fatal_error("State has a RAM size of %d bytes", ram_size * 2);
 126+	}
 127+	load_buffer16(buf, gen->work_ram, ram_size);
 128+	m68k_invalidate_code_range(gen->m68k, 0xE00000, 0x1000000);
 129+}
 130+
 131+static void zram_deserialize(deserialize_buffer *buf, void *vgen)
 132+{
 133+	genesis_context *gen = vgen;
 134+	uint32_t ram_size = load_int8(buf) * 1024;
 135+	if (ram_size > Z80_RAM_BYTES) {
 136+		fatal_error("State has a Z80 RAM size of %d bytes", ram_size);
 137+	}
 138+	load_buffer8(buf, gen->zram, ram_size);
 139+	z80_invalidate_code_range(gen->z80, 0, 0x4000);
 140+}
 141+
 142+static void update_z80_bank_pointer(genesis_context *gen)
 143+{
 144+	if (gen->z80_bank_reg < 0x140) {
 145+		gen->z80->mem_pointers[1] = get_native_pointer(gen->z80_bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen);
 146+	} else {
 147+		gen->z80->mem_pointers[1] = NULL;
 148+	}
 149+	z80_invalidate_code_range(gen->z80, 0x8000, 0xFFFF);
 150+}
 151+
 152+static void bus_arbiter_deserialize(deserialize_buffer *buf, void *vgen)
 153+{
 154+	genesis_context *gen = vgen;
 155+	gen->z80->reset = load_int8(buf);
 156+	gen->z80->busreq = load_int8(buf);
 157+	gen->z80_bank_reg = load_int16(buf) & 0x1FF;
 158+}
 159+
 160+static void adjust_int_cycle(m68k_context * context, vdp_context * v_context);
 161+void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen)
 162+{
 163+	register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000);
 164+	register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80);
 165+	register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP);
 166+	register_section_handler(buf, (section_handler){.fun = ym_deserialize, .data = gen->ym}, SECTION_YM2612);
 167+	register_section_handler(buf, (section_handler){.fun = psg_deserialize, .data = gen->psg}, SECTION_PSG);
 168+	register_section_handler(buf, (section_handler){.fun = bus_arbiter_deserialize, .data = gen}, SECTION_GEN_BUS_ARBITER);
 169+	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports}, SECTION_SEGA_IO_1);
 170+	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 1}, SECTION_SEGA_IO_2);
 171+	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 2}, SECTION_SEGA_IO_EXT);
 172+	register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = gen}, SECTION_MAIN_RAM);
 173+	register_section_handler(buf, (section_handler){.fun = zram_deserialize, .data = gen}, SECTION_SOUND_RAM);
 174+	register_section_handler(buf, (section_handler){.fun = cart_deserialize, .data = gen}, SECTION_MAPPER);
 175+	while (buf->cur_pos < buf->size)
 176+	{
 177+		load_section(buf);
 178+	}
 179+	update_z80_bank_pointer(gen);
 180+	adjust_int_cycle(gen->m68k, gen->vdp);
 181+	free(buf->handlers);
 182+	buf->handlers = NULL;
 183+}
 184+
 185+#include "m68k_internal.h" //needed for get_native_address_trans, should be eliminated once handling of PC is cleaned up
 186+static void deserialize(system_header *sys, uint8_t *data, size_t size)
 187+{
 188+	genesis_context *gen = (genesis_context *)sys;
 189+	deserialize_buffer buffer;
 190+	init_deserialize(&buffer, data, size);
 191+	genesis_deserialize(&buffer, gen);
 192+	//HACK: Fix this once PC/IR is represented in a better way in 68K core
 193+	gen->m68k->resume_pc = get_native_address_trans(gen->m68k, gen->m68k->last_prefetch_address);
 194+}
 195+
 196+uint16_t read_dma_value(uint32_t address)
 197+{
 198+	genesis_context *genesis = (genesis_context *)current_system;
 199+	//TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area
 200+	if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) {
 201+		return 0;
 202+	}
 203+	
 204+	//addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2
 205+	return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k);
 206+}
 207+
 208+static uint16_t get_open_bus_value(system_header *system)
 209+{
 210+	genesis_context *genesis = (genesis_context *)system;
 211+	return read_dma_value(genesis->m68k->last_prefetch_address/2);
 212+}
 213+
 214+static void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
 215+{
 216+	//static int old_int_cycle = CYCLE_NEVER;
 217+	genesis_context *gen = context->system;
 218+	if (context->sync_cycle - context->current_cycle > gen->max_cycles) {
 219+		context->sync_cycle = context->current_cycle + gen->max_cycles;
 220+	}
 221+	context->int_cycle = CYCLE_NEVER;
 222+	if ((context->status & 0x7) < 6) {
 223+		uint32_t next_vint = vdp_next_vint(v_context);
 224+		if (next_vint != CYCLE_NEVER) {
 225+			context->int_cycle = next_vint;
 226+			context->int_num = 6;
 227+		}
 228+		if ((context->status & 0x7) < 4) {
 229+			uint32_t next_hint = vdp_next_hint(v_context);
 230+			if (next_hint != CYCLE_NEVER) {
 231+				next_hint = next_hint < context->current_cycle ? context->current_cycle : next_hint;
 232+				if (next_hint < context->int_cycle) {
 233+					context->int_cycle = next_hint;
 234+					context->int_num = 4;
 235+
 236+				}
 237+			}
 238+		}
 239+	}
 240+	if (context->int_cycle > context->current_cycle && context->int_pending == INT_PENDING_SR_CHANGE) {
 241+		context->int_pending = INT_PENDING_NONE;
 242+	}
 243+	/*if (context->int_cycle != old_int_cycle) {
 244+		printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter);
 245+		old_int_cycle = context->int_cycle;
 246+	}*/
 247+	
 248+	if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
 249+		context->target_cycle = context->current_cycle;
 250+		return;
 251+	}
 252+
 253+	context->target_cycle = context->int_cycle < context->sync_cycle ? context->int_cycle : context->sync_cycle;
 254+	if (context->should_return) {
 255+		context->target_cycle = context->current_cycle;
 256+	} else if (context->target_cycle < context->current_cycle) {
 257+		//Changes to SR can result in an interrupt cycle that's in the past
 258+		//This can cause issues with the implementation of STOP though
 259+		context->target_cycle = context->current_cycle;
 260+	}
 261+	if (context->target_cycle == context->int_cycle) {
 262+		//Currently delays from Z80 access and refresh are applied only when we sync
 263+		//this can cause extra latency when it comes to interrupts
 264+		//to prevent this code forces some extra synchronization in the period immediately before an interrupt
 265+		if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev1) {
 266+			context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev1;
 267+		} else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) {
 268+			context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2;
 269+		} else {
 270+			context->target_cycle = context->sync_cycle = context->current_cycle;
 271+		}
 272+		
 273+	}
 274+	/*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n",
 275+		context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7),
 276+		v_context->regs[REG_MODE_2] & 0x20, v_context->regs[REG_MODE_1] & 0x10, v_context->hint_counter, v_context->regs[REG_HINT], v_context->cycles / MCLKS_LINE);*/
 277+}
 278+
 279+//#define DO_DEBUG_PRINT
 280+#ifdef DO_DEBUG_PRINT
 281+#define dprintf printf
 282+#define dputs puts
 283+#else
 284+#define dprintf
 285+#define dputs
 286+#endif
 287+
 288+static void z80_next_int_pulse(z80_context * z_context)
 289+{
 290+	genesis_context * gen = z_context->system;
 291+	z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp);
 292+	z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS;
 293+	z_context->im2_vector = 0xFF;
 294+}
 295+
 296+static void sync_z80(z80_context * z_context, uint32_t mclks)
 297+{
 298+	if (z80_enabled) {
 299+		z80_run(z_context, mclks);
 300+	} else
 301+	{
 302+		z_context->Z80_CYCLE = mclks;
 303+	}
 304+}
 305+
 306+static void sync_sound(genesis_context * gen, uint32_t target)
 307+{
 308+	//printf("YM | Cycle: %d, bpos: %d, PSG | Cycle: %d, bpos: %d\n", gen->ym->current_cycle, gen->ym->buffer_pos, gen->psg->cycles, gen->psg->buffer_pos * 2);
 309+	while (target > gen->psg->cycles && target - gen->psg->cycles > MAX_SOUND_CYCLES) {
 310+		uint32_t cur_target = gen->psg->cycles + MAX_SOUND_CYCLES;
 311+		//printf("Running PSG to cycle %d\n", cur_target);
 312+		psg_run(gen->psg, cur_target);
 313+		//printf("Running YM-2612 to cycle %d\n", cur_target);
 314+		ym_run(gen->ym, cur_target);
 315+	}
 316+	psg_run(gen->psg, target);
 317+	ym_run(gen->ym, target);
 318+
 319+	//printf("Target: %d, YM bufferpos: %d, PSG bufferpos: %d\n", target, gen->ym->buffer_pos, gen->psg->buffer_pos * 2);
 320+}
 321+
 322+//TODO: move this inside the system context
 323+static uint32_t last_frame_num;
 324+
 325+//My refresh emulation isn't currently good enough and causes more problems than it solves
 326+#define REFRESH_EMULATION
 327+#ifdef REFRESH_EMULATION
 328+#define REFRESH_INTERVAL 128
 329+#define REFRESH_DELAY 2
 330+uint32_t last_sync_cycle;
 331+uint32_t refresh_counter;
 332+#endif
 333+
 334+#include <limits.h>
 335+#define ADJUST_BUFFER (8*MCLKS_LINE*313)
 336+#define MAX_NO_ADJUST (UINT_MAX-ADJUST_BUFFER)
 337+
 338+m68k_context * sync_components(m68k_context * context, uint32_t address)
 339+{
 340+	genesis_context * gen = context->system;
 341+	vdp_context * v_context = gen->vdp;
 342+	z80_context * z_context = gen->z80;
 343+#ifdef REFRESH_EMULATION
 344+	//lame estimation of refresh cycle delay
 345+	refresh_counter += context->current_cycle - last_sync_cycle;
 346+	if (!gen->bus_busy) {
 347+		context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 348+	}
 349+	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 350+#endif
 351+
 352+	uint32_t mclks = context->current_cycle;
 353+	sync_z80(z_context, mclks);
 354+	sync_sound(gen, mclks);
 355+	vdp_run_context(v_context, mclks);
 356+	if (mclks >= gen->reset_cycle) {
 357+		gen->reset_requested = 1;
 358+		context->should_return = 1;
 359+		gen->reset_cycle = CYCLE_NEVER;
 360+	}
 361+	if (v_context->frame != last_frame_num) {
 362+		//printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", last_frame_num, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot);
 363+		last_frame_num = v_context->frame;
 364+
 365+		if(exit_after){
 366+			--exit_after;
 367+			if (!exit_after) {
 368+				exit(0);
 369+			}
 370+		}
 371+		if (context->current_cycle > MAX_NO_ADJUST) {
 372+			uint32_t deduction = mclks - ADJUST_BUFFER;
 373+			vdp_adjust_cycles(v_context, deduction);
 374+			io_adjust_cycles(gen->io.ports, context->current_cycle, deduction);
 375+			io_adjust_cycles(gen->io.ports+1, context->current_cycle, deduction);
 376+			io_adjust_cycles(gen->io.ports+2, context->current_cycle, deduction);
 377+			if (gen->mapper_type == MAPPER_JCART) {
 378+				jcart_adjust_cycles(gen, deduction);
 379+			}
 380+			context->current_cycle -= deduction;
 381+			z80_adjust_cycles(z_context, deduction);
 382+			gen->ym->current_cycle -= deduction;
 383+			gen->psg->cycles -= deduction;
 384+			if (gen->ym->write_cycle != CYCLE_NEVER) {
 385+				gen->ym->write_cycle = gen->ym->write_cycle >= deduction ? gen->ym->write_cycle - deduction : 0;
 386+			}
 387+			if (gen->reset_cycle != CYCLE_NEVER) {
 388+				gen->reset_cycle -= deduction;
 389+			}
 390+		}
 391+	}
 392+	gen->frame_end = vdp_cycles_to_frame_end(v_context);
 393+	context->sync_cycle = gen->frame_end;
 394+	//printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
 395+	if (context->int_ack) {
 396+		//printf("acknowledging %d @ %d:%d, vcounter: %d, hslot: %d\n", context->int_ack, context->current_cycle, v_context->cycles, v_context->vcounter, v_context->hslot);
 397+		vdp_int_ack(v_context);
 398+		context->int_ack = 0;
 399+	}
 400+	if (!address && (gen->header.enter_debugger || gen->header.save_state)) {
 401+		context->sync_cycle = context->current_cycle + 1;
 402+	}
 403+	adjust_int_cycle(context, v_context);
 404+	if (gen->reset_cycle < context->target_cycle) {
 405+		context->target_cycle = gen->reset_cycle;
 406+	}
 407+	if (address) {
 408+		if (gen->header.enter_debugger) {
 409+			gen->header.enter_debugger = 0;
 410+			debugger(context, address);
 411+		}
 412+		if (gen->header.save_state && (z_context->pc || !z_context->native_pc || z_context->reset || !z_context->busreq)) {
 413+			uint8_t slot = gen->header.save_state - 1;
 414+			gen->header.save_state = 0;
 415+			if (z_context->native_pc && !z_context->reset) {
 416+				//advance Z80 core to the start of an instruction
 417+				while (!z_context->pc)
 418+				{
 419+					sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80);
 420+				}
 421+			}
 422+			char *save_path = slot == SERIALIZE_SLOT ? NULL : get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst");
 423+			if (use_native_states || slot == SERIALIZE_SLOT) {
 424+				serialize_buffer state;
 425+				init_serialize(&state);
 426+				genesis_serialize(gen, &state, address);
 427+				if (slot == SERIALIZE_SLOT) {
 428+					gen->serialize_tmp = state.data;
 429+					gen->serialize_size = state.size;
 430+					context->sync_cycle = context->current_cycle;
 431+					context->should_return = 1;
 432+				} else {
 433+					save_to_file(&state, save_path);
 434+					free(state.data);
 435+				}
 436+			} else {
 437+				save_gst(gen, save_path, address);
 438+			}
 439+			printf("Saved state to %s\n", save_path);
 440+			free(save_path);
 441+		} else if(gen->header.save_state) {
 442+			context->sync_cycle = context->current_cycle + 1;
 443+		}
 444+	}
 445+#ifdef REFRESH_EMULATION
 446+	last_sync_cycle = context->current_cycle;
 447+#endif
 448+	return context;
 449+}
 450+
 451+static m68k_context * vdp_port_write(uint32_t vdp_port, m68k_context * context, uint16_t value)
 452+{
 453+	if (vdp_port & 0x2700E0) {
 454+		fatal_error("machine freeze due to write to address %X\n", 0xC00000 | vdp_port);
 455+	}
 456+	vdp_port &= 0x1F;
 457+	//printf("vdp_port write: %X, value: %X, cycle: %d\n", vdp_port, value, context->current_cycle);
 458+#ifdef REFRESH_EMULATION
 459+	//do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access
 460+	refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle;
 461+	context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 462+	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 463+	last_sync_cycle = context->current_cycle;
 464+#endif
 465+	sync_components(context, 0);
 466+	genesis_context * gen = context->system;
 467+	vdp_context *v_context = gen->vdp;
 468+	uint32_t before_cycle = v_context->cycles;
 469+	if (vdp_port < 0x10) {
 470+		int blocked;
 471+		if (vdp_port < 4) {
 472+			while (vdp_data_port_write(v_context, value) < 0) {
 473+				while(v_context->flags & FLAG_DMA_RUN) {
 474+					vdp_run_dma_done(v_context, gen->frame_end);
 475+					if (v_context->cycles >= gen->frame_end) {
 476+						uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 477+						uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 478+						if (m68k_cycle_diff < cycle_diff) {
 479+							m68k_cycle_diff += MCLKS_PER_68K;
 480+						}
 481+						context->current_cycle += m68k_cycle_diff;
 482+						gen->bus_busy = 1;
 483+						sync_components(context, 0);
 484+						gen->bus_busy = 0;
 485+					}
 486+				}
 487+				//context->current_cycle = v_context->cycles;
 488+			}
 489+		} else if(vdp_port < 8) {
 490+			vdp_run_context_full(v_context, context->current_cycle);
 491+			before_cycle = v_context->cycles;
 492+			blocked = vdp_control_port_write(v_context, value);
 493+			if (blocked) {
 494+				while (blocked) {
 495+					while(v_context->flags & FLAG_DMA_RUN) {
 496+						vdp_run_dma_done(v_context, gen->frame_end);
 497+						if (v_context->cycles >= gen->frame_end) {
 498+							uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 499+							uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 500+							if (m68k_cycle_diff < cycle_diff) {
 501+								m68k_cycle_diff += MCLKS_PER_68K;
 502+							}
 503+							context->current_cycle += m68k_cycle_diff;
 504+							gen->bus_busy = 1;
 505+							sync_components(context, 0);
 506+							gen->bus_busy = 0;
 507+						}
 508+					}
 509+					
 510+					if (blocked < 0) {
 511+						blocked = vdp_control_port_write(v_context, value);
 512+					} else {
 513+						blocked = 0;
 514+					}
 515+				}
 516+			} else {
 517+				context->sync_cycle = gen->frame_end = vdp_cycles_to_frame_end(v_context);
 518+				//printf("Set sync cycle to: %d @ %d, vcounter: %d, hslot: %d\n", context->sync_cycle, context->current_cycle, v_context->vcounter, v_context->hslot);
 519+				adjust_int_cycle(context, v_context);
 520+			}
 521+		} else {
 522+			fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
 523+		}
 524+		if (v_context->cycles != before_cycle) {
 525+			//printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
 526+			uint32_t cycle_diff = v_context->cycles - context->current_cycle;
 527+			uint32_t m68k_cycle_diff = (cycle_diff / MCLKS_PER_68K) * MCLKS_PER_68K;
 528+			if (m68k_cycle_diff < cycle_diff) {
 529+				m68k_cycle_diff += MCLKS_PER_68K;
 530+			}
 531+			context->current_cycle += m68k_cycle_diff;
 532+			//Lock the Z80 out of the bus until the VDP access is complete
 533+			gen->bus_busy = 1;
 534+			sync_z80(gen->z80, v_context->cycles);
 535+			gen->bus_busy = 0;
 536+		}
 537+	} else if (vdp_port < 0x18) {
 538+		psg_write(gen->psg, value);
 539+	} else {
 540+		vdp_test_port_write(gen->vdp, value);
 541+	}
 542+#ifdef REFRESH_EMULATION
 543+	last_sync_cycle -= 4;
 544+	//refresh may have happened while we were waiting on the VDP,
 545+	//so advance refresh_counter but don't add any delays
 546+	if (vdp_port >= 4 && vdp_port < 8 && v_context->cycles != before_cycle) {
 547+		refresh_counter = 0;
 548+	} else {
 549+		refresh_counter += (context->current_cycle - last_sync_cycle);
 550+		refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 551+	}
 552+	last_sync_cycle = context->current_cycle;
 553+#endif
 554+	return context;
 555+}
 556+
 557+static m68k_context * vdp_port_write_b(uint32_t vdp_port, m68k_context * context, uint8_t value)
 558+{
 559+	return vdp_port_write(vdp_port, context, vdp_port < 0x10 ? value | value << 8 : ((vdp_port & 1) ? value : 0));
 560+}
 561+
 562+static void * z80_vdp_port_write(uint32_t vdp_port, void * vcontext, uint8_t value)
 563+{
 564+	z80_context * context = vcontext;
 565+	genesis_context * gen = context->system;
 566+	vdp_port &= 0xFF;
 567+	if (vdp_port & 0xE0) {
 568+		fatal_error("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port);
 569+	}
 570+	if (vdp_port < 0x10) {
 571+		//These probably won't currently interact well with the 68K accessing the VDP
 572+		if (vdp_port < 4) {
 573+			vdp_run_context(gen->vdp, context->Z80_CYCLE);
 574+			vdp_data_port_write(gen->vdp, value << 8 | value);
 575+		} else if (vdp_port < 8) {
 576+			vdp_run_context_full(gen->vdp, context->Z80_CYCLE);
 577+			vdp_control_port_write(gen->vdp, value << 8 | value);
 578+		} else {
 579+			fatal_error("Illegal write to HV Counter port %X\n", vdp_port);
 580+		}
 581+	} else if (vdp_port < 0x18) {
 582+		sync_sound(gen, context->Z80_CYCLE);
 583+		psg_write(gen->psg, value);
 584+	} else {
 585+		vdp_test_port_write(gen->vdp, value);
 586+	}
 587+	return context;
 588+}
 589+
 590+static uint16_t vdp_port_read(uint32_t vdp_port, m68k_context * context)
 591+{
 592+	if (vdp_port & 0x2700E0) {
 593+		fatal_error("machine freeze due to read from address %X\n", 0xC00000 | vdp_port);
 594+	}
 595+	vdp_port &= 0x1F;
 596+	uint16_t value;
 597+#ifdef REFRESH_EMULATION
 598+	//do refresh check here so we can avoid adding a penalty for a refresh that happens during a VDP access
 599+	refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle;
 600+	context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL));
 601+	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 602+	last_sync_cycle = context->current_cycle;
 603+#endif
 604+	sync_components(context, 0);
 605+	genesis_context *gen = context->system;
 606+	vdp_context * v_context = gen->vdp;
 607+	uint32_t before_cycle = v_context->cycles;
 608+	if (vdp_port < 0x10) {
 609+		if (vdp_port < 4) {
 610+			value = vdp_data_port_read(v_context);
 611+		} else if(vdp_port < 8) {
 612+			value = vdp_control_port_read(v_context);
 613+		} else {
 614+			value = vdp_hv_counter_read(v_context);
 615+			//printf("HV Counter: %X at cycle %d\n", value, v_context->cycles);
 616+		}
 617+	} else if (vdp_port < 0x18){
 618+		fatal_error("Illegal read from PSG  port %X\n", vdp_port);
 619+	} else {
 620+		value = vdp_test_port_read(v_context);
 621+	}
 622+	if (v_context->cycles != before_cycle) {
 623+		//printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle);
 624+		context->current_cycle = v_context->cycles;
 625+		//Lock the Z80 out of the bus until the VDP access is complete
 626+		genesis_context *gen = context->system;
 627+		gen->bus_busy = 1;
 628+		sync_z80(gen->z80, v_context->cycles);
 629+		gen->bus_busy = 0;
 630+	}
 631+#ifdef REFRESH_EMULATION
 632+	last_sync_cycle -= 4;
 633+	//refresh may have happened while we were waiting on the VDP,
 634+	//so advance refresh_counter but don't add any delays
 635+	refresh_counter += (context->current_cycle - last_sync_cycle);
 636+	refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL);
 637+	last_sync_cycle = context->current_cycle;
 638+#endif
 639+	return value;
 640+}
 641+
 642+static uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context)
 643+{
 644+	uint16_t value = vdp_port_read(vdp_port, context);
 645+	if (vdp_port & 1) {
 646+		return value;
 647+	} else {
 648+		return value >> 8;
 649+	}
 650+}
 651+
 652+static uint8_t z80_vdp_port_read(uint32_t vdp_port, void * vcontext)
 653+{
 654+	z80_context * context = vcontext;
 655+	if (vdp_port & 0xE0) {
 656+		fatal_error("machine freeze due to read from Z80 address %X\n", 0x7F00 | vdp_port);
 657+	}
 658+	genesis_context * gen = context->system;
 659+	//VDP access goes over the 68K bus like a bank area access
 660+	//typical delay from bus arbitration
 661+	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 662+	//TODO: add cycle for an access right after a previous one
 663+	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 664+	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
 665+	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
 666+
 667+
 668+	vdp_port &= 0x1F;
 669+	uint16_t ret;
 670+	if (vdp_port < 0x10) {
 671+		//These probably won't currently interact well with the 68K accessing the VDP
 672+		vdp_run_context(gen->vdp, context->Z80_CYCLE);
 673+		if (vdp_port < 4) {
 674+			ret = vdp_data_port_read(gen->vdp);
 675+		} else if (vdp_port < 8) {
 676+			ret = vdp_control_port_read(gen->vdp);
 677+		} else {
 678+			ret = vdp_hv_counter_read(gen->vdp);
 679+		}
 680+	} else {
 681+		//TODO: Figure out the correct value today
 682+		ret = 0xFFFF;
 683+	}
 684+	return vdp_port & 1 ? ret : ret >> 8;
 685+}
 686+
 687+//TODO: Move this inside the system context
 688+static uint32_t zram_counter = 0;
 689+
 690+static m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value)
 691+{
 692+	genesis_context * gen = context->system;
 693+	if (location < 0x10000) {
 694+		//Access to Z80 memory incurs a one 68K cycle wait state
 695+		context->current_cycle += MCLKS_PER_68K;
 696+		if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) {
 697+			location &= 0x7FFF;
 698+			if (location < 0x4000) {
 699+				gen->zram[location & 0x1FFF] = value;
 700+				z80_handle_code_write(location & 0x1FFF, gen->z80);
 701+			} else if (location < 0x6000) {
 702+				sync_sound(gen, context->current_cycle);
 703+				if (location & 1) {
 704+					ym_data_write(gen->ym, value);
 705+				} else if(location & 2) {
 706+					ym_address_write_part2(gen->ym, value);
 707+				} else {
 708+					ym_address_write_part1(gen->ym, value);
 709+				}
 710+			} else if (location == 0x6000) {
 711+				gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF;
 712+				if (gen->z80_bank_reg < 0x80) {
 713+					gen->z80->mem_pointers[1] = (gen->z80_bank_reg << 15) + ((char *)gen->z80->mem_pointers[2]);
 714+				} else {
 715+					gen->z80->mem_pointers[1] = NULL;
 716+				}
 717+			} else {
 718+				fatal_error("68K write to unhandled Z80 address %X\n", location);
 719+			}
 720+		}
 721+	} else {
 722+		location &= 0x1FFF;
 723+		if (location < 0x100) {
 724+			switch(location/2)
 725+			{
 726+			case 0x1:
 727+				io_data_write(gen->io.ports, value, context->current_cycle);
 728+				break;
 729+			case 0x2:
 730+				io_data_write(gen->io.ports+1, value, context->current_cycle);
 731+				break;
 732+			case 0x3:
 733+				io_data_write(gen->io.ports+2, value, context->current_cycle);
 734+				break;
 735+			case 0x4:
 736+				io_control_write(gen->io.ports, value, context->current_cycle);
 737+				break;
 738+			case 0x5:
 739+				io_control_write(gen->io.ports+1, value, context->current_cycle);
 740+				break;
 741+			case 0x6:
 742+				io_control_write(gen->io.ports+2, value, context->current_cycle);
 743+				break;
 744+			case 0x7:
 745+				gen->io.ports[0].serial_out = value;
 746+				break;
 747+			case 0x8:
 748+			case 0xB:
 749+			case 0xE:
 750+				//serial input port is not writeable
 751+				break;
 752+			case 0x9:
 753+				gen->io.ports[0].serial_ctrl = value;
 754+				break;
 755+			case 0xA:
 756+				gen->io.ports[1].serial_out = value;
 757+				break;
 758+			case 0xC:
 759+				gen->io.ports[1].serial_ctrl = value;
 760+				break;
 761+			case 0xD:
 762+				gen->io.ports[2].serial_out = value;
 763+				break;
 764+			case 0xF:
 765+				gen->io.ports[2].serial_ctrl = value;
 766+				break;
 767+			}
 768+		} else {
 769+			if (location == 0x1100) {
 770+				if (value & 1) {
 771+					dputs("bus requesting Z80");
 772+					if (z80_enabled) {
 773+						z80_assert_busreq(gen->z80, context->current_cycle);
 774+					} else {
 775+						gen->z80->busack = 1;
 776+					}
 777+				} else {
 778+					if (gen->z80->busreq) {
 779+						dputs("releasing z80 bus");
 780+						#ifdef DO_DEBUG_PRINT
 781+						char fname[20];
 782+						sprintf(fname, "zram-%d", zram_counter++);
 783+						FILE * f = fopen(fname, "wb");
 784+						fwrite(z80_ram, 1, sizeof(z80_ram), f);
 785+						fclose(f);
 786+						#endif
 787+					}
 788+					if (z80_enabled) {
 789+						z80_clear_busreq(gen->z80, context->current_cycle);
 790+					} else {
 791+						gen->z80->busack = 0;
 792+					}
 793+				}
 794+			} else if (location == 0x1200) {
 795+				sync_z80(gen->z80, context->current_cycle);
 796+				if (value & 1) {
 797+					if (z80_enabled) {
 798+						z80_clear_reset(gen->z80, context->current_cycle);
 799+					} else {
 800+						gen->z80->reset = 0;
 801+					}
 802+				} else {
 803+					if (z80_enabled) {
 804+						z80_assert_reset(gen->z80, context->current_cycle);
 805+					} else {
 806+						gen->z80->reset = 1;
 807+					}
 808+					ym_reset(gen->ym);
 809+				}
 810+			}
 811+		}
 812+	}
 813+	return context;
 814+}
 815+
 816+static m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value)
 817+{
 818+	if (location < 0x10000 || (location & 0x1FFF) >= 0x100) {
 819+		return io_write(location, context, value >> 8);
 820+	} else {
 821+		return io_write(location, context, value);
 822+	}
 823+}
 824+
 825+#define FOREIGN 0x80
 826+#define HZ50 0x40
 827+#define USA FOREIGN
 828+#define JAP 0x00
 829+#define EUR (HZ50|FOREIGN)
 830+#define NO_DISK 0x20
 831+
 832+static uint8_t io_read(uint32_t location, m68k_context * context)
 833+{
 834+	uint8_t value;
 835+	genesis_context *gen = context->system;
 836+	if (location < 0x10000) {
 837+		//Access to Z80 memory incurs a one 68K cycle wait state
 838+		context->current_cycle += MCLKS_PER_68K;
 839+		if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) {
 840+			location &= 0x7FFF;
 841+			if (location < 0x4000) {
 842+				value = gen->zram[location & 0x1FFF];
 843+			} else if (location < 0x6000) {
 844+				sync_sound(gen, context->current_cycle);
 845+				value = ym_read_status(gen->ym);
 846+			} else {
 847+				value = 0xFF;
 848+			}
 849+		} else {
 850+			value = 0xFF;
 851+		}
 852+	} else {
 853+		location &= 0x1FFF;
 854+		if (location < 0x100) {
 855+			switch(location/2)
 856+			{
 857+			case 0x0:
 858+				//version bits should be 0 for now since we're not emulating TMSS
 859+				value = gen->version_reg;
 860+				break;
 861+			case 0x1:
 862+				value = io_data_read(gen->io.ports, context->current_cycle);
 863+				break;
 864+			case 0x2:
 865+				value = io_data_read(gen->io.ports+1, context->current_cycle);
 866+				break;
 867+			case 0x3:
 868+				value = io_data_read(gen->io.ports+2, context->current_cycle);
 869+				break;
 870+			case 0x4:
 871+				value = gen->io.ports[0].control;
 872+				break;
 873+			case 0x5:
 874+				value = gen->io.ports[1].control;
 875+				break;
 876+			case 0x6:
 877+				value = gen->io.ports[2].control;
 878+				break;
 879+			case 0x7:
 880+				value = gen->io.ports[0].serial_out;
 881+				break;
 882+			case 0x8:
 883+				value = gen->io.ports[0].serial_in;
 884+				break;
 885+			case 0x9:
 886+				value = gen->io.ports[0].serial_ctrl;
 887+				break;
 888+			case 0xA:
 889+				value = gen->io.ports[1].serial_out;
 890+				break;
 891+			case 0xB:
 892+				value = gen->io.ports[1].serial_in;
 893+				break;
 894+			case 0xC:
 895+				value = gen->io.ports[1].serial_ctrl;
 896+				break;
 897+			case 0xD:
 898+				value = gen->io.ports[2].serial_out;
 899+				break;
 900+			case 0xE:
 901+				value = gen->io.ports[2].serial_in;
 902+				break;
 903+			case 0xF:
 904+				value = gen->io.ports[2].serial_ctrl;
 905+				break;
 906+			default:
 907+				value = 0xFF;
 908+			}
 909+		} else {
 910+			if (location == 0x1100) {
 911+				value = z80_enabled ? !z80_get_busack(gen->z80, context->current_cycle) : !gen->z80->busack;
 912+				value |= (get_open_bus_value(&gen->header) >> 8) & 0xFE;
 913+				dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d)\n", value, context->current_cycle, gen->z80->reset);
 914+			} else if (location == 0x1200) {
 915+				value = !gen->z80->reset;
 916+			} else {
 917+				value = 0xFF;
 918+				printf("Byte read of unknown IO location: %X\n", location);
 919+			}
 920+		}
 921+	}
 922+	return value;
 923+}
 924+
 925+static uint16_t io_read_w(uint32_t location, m68k_context * context)
 926+{
 927+	genesis_context *gen = context->system;
 928+	uint16_t value = io_read(location, context);
 929+	if (location < 0x10000 || (location & 0x1FFF) < 0x100) {
 930+		value = value | (value << 8);
 931+	} else {
 932+		value <<= 8;
 933+		value |= get_open_bus_value(&gen->header) & 0xFF;
 934+	}
 935+	return value;
 936+}
 937+
 938+static void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value)
 939+{
 940+	z80_context * context = vcontext;
 941+	genesis_context * gen = context->system;
 942+	sync_sound(gen, context->Z80_CYCLE);
 943+	if (location & 1) {
 944+		ym_data_write(gen->ym, value);
 945+	} else if (location & 2) {
 946+		ym_address_write_part2(gen->ym, value);
 947+	} else {
 948+		ym_address_write_part1(gen->ym, value);
 949+	}
 950+	return context;
 951+}
 952+
 953+static uint8_t z80_read_ym(uint32_t location, void * vcontext)
 954+{
 955+	z80_context * context = vcontext;
 956+	genesis_context * gen = context->system;
 957+	sync_sound(gen, context->Z80_CYCLE);
 958+	return ym_read_status(gen->ym);
 959+}
 960+
 961+static uint8_t z80_read_bank(uint32_t location, void * vcontext)
 962+{
 963+	z80_context * context = vcontext;
 964+	genesis_context *gen = context->system;
 965+	if (gen->bus_busy) {
 966+		context->Z80_CYCLE = gen->m68k->current_cycle;
 967+	}
 968+	//typical delay from bus arbitration
 969+	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 970+	//TODO: add cycle for an access right after a previous one
 971+	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 972+	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
 973+	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
 974+
 975+	location &= 0x7FFF;
 976+	if (context->mem_pointers[1]) {
 977+		return context->mem_pointers[1][location ^ 1];
 978+	}
 979+	uint32_t address = gen->z80_bank_reg << 15 | location;
 980+	if (address >= 0xC00000 && address < 0xE00000) {
 981+		return z80_vdp_port_read(location & 0xFF, context);
 982+	} else {
 983+		fprintf(stderr, "Unhandled read by Z80 from address %X through banked memory area (%X)\n", address, gen->z80_bank_reg << 15);
 984+	}
 985+	return 0;
 986+}
 987+
 988+static void *z80_write_bank(uint32_t location, void * vcontext, uint8_t value)
 989+{
 990+	z80_context * context = vcontext;
 991+	genesis_context *gen = context->system;
 992+	if (gen->bus_busy) {
 993+		context->Z80_CYCLE = gen->m68k->current_cycle;
 994+	}
 995+	//typical delay from bus arbitration
 996+	context->Z80_CYCLE += 3 * MCLKS_PER_Z80;
 997+	//TODO: add cycle for an access right after a previous one
 998+	//TODO: Below cycle time is an estimate based on the time between 68K !BG goes low and Z80 !MREQ goes high
 999+	//      Needs a new logic analyzer capture to get the actual delay on the 68K side
1000+	gen->m68k->current_cycle += 8 * MCLKS_PER_68K;
1001+
1002+	location &= 0x7FFF;
1003+	uint32_t address = gen->z80_bank_reg << 15 | location;
1004+	if (address >= 0xE00000) {
1005+		address &= 0xFFFF;
1006+		((uint8_t *)gen->work_ram)[address ^ 1] = value;
1007+	} else if (address >= 0xC00000) {
1008+		z80_vdp_port_write(location & 0xFF, context, value);
1009+	} else {
1010+		fprintf(stderr, "Unhandled write by Z80 to address %X through banked memory area\n", address);
1011+	}
1012+	return context;
1013+}
1014+
1015+static void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value)
1016+{
1017+	z80_context * context = vcontext;
1018+	genesis_context *gen = context->system;
1019+
1020+	gen->z80_bank_reg = (gen->z80_bank_reg >> 1 | value << 8) & 0x1FF;
1021+	update_z80_bank_pointer(context->system);
1022+
1023+	return context;
1024+}
1025+
1026+static void set_speed_percent(system_header * system, uint32_t percent)
1027+{
1028+	genesis_context *context = (genesis_context *)system;
1029+	uint32_t old_clock = context->master_clock;
1030+	context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100;
1031+	while (context->ym->current_cycle != context->psg->cycles) {
1032+		sync_sound(context, context->psg->cycles + MCLKS_PER_PSG);
1033+	}
1034+	ym_adjust_master_clock(context->ym, context->master_clock);
1035+	psg_adjust_master_clock(context->psg, context->master_clock);
1036+}
1037+
1038+void set_region(genesis_context *gen, rom_info *info, uint8_t region)
1039+{
1040+	if (!region) {
1041+		char * def_region = tern_find_path_default(config, "system\0default_region\0", (tern_val){.ptrval = "U"}, TVAL_PTR).ptrval;
1042+		if (!info->regions || (info->regions & translate_region_char(toupper(*def_region)))) {
1043+			region = translate_region_char(toupper(*def_region));
1044+		} else {
1045+			region = info->regions;
1046+		}
1047+	}
1048+	if (region & REGION_E) {
1049+		gen->version_reg = NO_DISK | EUR;
1050+	} else if (region & REGION_J) {
1051+		gen->version_reg = NO_DISK | JAP;
1052+	} else {
1053+		gen->version_reg = NO_DISK | USA;
1054+	}
1055+	
1056+	if (region & HZ50) {
1057+		gen->normal_clock = MCLKS_PAL;
1058+	} else {
1059+		gen->normal_clock = MCLKS_NTSC;
1060+	}
1061+	gen->master_clock = gen->normal_clock;
1062+}
1063+
1064+static uint8_t load_state(system_header *system, uint8_t slot)
1065+{
1066+	genesis_context *gen = (genesis_context *)system;
1067+	char *statepath = get_slot_name(system, slot, "state");
1068+	deserialize_buffer state;
1069+	uint32_t pc = 0;
1070+	uint8_t ret;
1071+	if (!gen->m68k->resume_pc) {
1072+		system->delayed_load_slot = slot + 1;
1073+		gen->m68k->should_return = 1;
1074+		ret = get_modification_time(statepath) != 0;
1075+		if (!ret) {
1076+			strcpy(statepath + strlen(statepath)-strlen("state"), "gst");
1077+			ret = get_modification_time(statepath) != 0;
1078+		}
1079+		goto done;
1080+	}
1081+	if (load_from_file(&state, statepath)) {
1082+		genesis_deserialize(&state, gen);
1083+		free(state.data);
1084+		//HACK
1085+		pc = gen->m68k->last_prefetch_address;
1086+		ret = 1;
1087+	} else {
1088+		strcpy(statepath + strlen(statepath)-strlen("state"), "gst");
1089+		pc = load_gst(gen, statepath);
1090+		ret = pc != 0;
1091+	}
1092+	if (ret) {
1093+		gen->m68k->resume_pc = get_native_address_trans(gen->m68k, pc);
1094+	}
1095+done:
1096+	free(statepath);
1097+	return ret;
1098+}
1099+
1100+static void handle_reset_requests(genesis_context *gen)
1101+{
1102+	while (gen->reset_requested || gen->header.delayed_load_slot)
1103+	{
1104+		if (gen->reset_requested) {
1105+			gen->reset_requested = 0;
1106+			gen->m68k->should_return = 0;
1107+			z80_assert_reset(gen->z80, gen->m68k->current_cycle);
1108+			z80_clear_busreq(gen->z80, gen->m68k->current_cycle);
1109+			ym_reset(gen->ym);
1110+			//Is there any sort of VDP reset?
1111+			m68k_reset(gen->m68k);
1112+		}
1113+		if (gen->header.delayed_load_slot) {
1114+			load_state(&gen->header, gen->header.delayed_load_slot - 1);
1115+			gen->header.delayed_load_slot = 0;
1116+			resume_68k(gen->m68k);
1117+		}
1118+	}
1119+	bindings_release_capture();
1120+	vdp_release_framebuffer(gen->vdp);
1121+	render_pause_source(gen->ym->audio);
1122+	render_pause_source(gen->psg->audio);
1123+}
1124+
1125+static void start_genesis(system_header *system, char *statefile)
1126+{
1127+	genesis_context *gen = (genesis_context *)system;
1128+	if (statefile) {
1129+		//first try loading as a native format savestate
1130+		deserialize_buffer state;
1131+		uint32_t pc;
1132+		if (load_from_file(&state, statefile)) {
1133+			genesis_deserialize(&state, gen);
1134+			free(state.data);
1135+			//HACK
1136+			pc = gen->m68k->last_prefetch_address;
1137+		} else {
1138+			pc = load_gst(gen, statefile);
1139+			if (!pc) {
1140+				fatal_error("Failed to load save state %s\n", statefile);
1141+			}
1142+		}
1143+		printf("Loaded %s\n", statefile);
1144+		if (gen->header.enter_debugger) {
1145+			gen->header.enter_debugger = 0;
1146+			insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
1147+		}
1148+		adjust_int_cycle(gen->m68k, gen->vdp);
1149+		start_68k_context(gen->m68k, pc);
1150+	} else {
1151+		if (gen->header.enter_debugger) {
1152+			gen->header.enter_debugger = 0;
1153+			uint32_t address = gen->cart[2] << 16 | gen->cart[3];
1154+			insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
1155+		}
1156+		m68k_reset(gen->m68k);
1157+	}
1158+	handle_reset_requests(gen);
1159+	return;
1160+}
1161+
1162+static void resume_genesis(system_header *system)
1163+{
1164+	genesis_context *gen = (genesis_context *)system;
1165+	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
1166+	bindings_reacquire_capture();
1167+	vdp_reacquire_framebuffer(gen->vdp);
1168+	render_resume_source(gen->ym->audio);
1169+	render_resume_source(gen->psg->audio);
1170+	resume_68k(gen->m68k);
1171+	handle_reset_requests(gen);
1172+}
1173+
1174+static void inc_debug_mode(system_header *system)
1175+{
1176+	genesis_context *gen = (genesis_context *)system;
1177+	vdp_inc_debug_mode(gen->vdp);
1178+}
1179+
1180+static void request_exit(system_header *system)
1181+{
1182+	genesis_context *gen = (genesis_context *)system;
1183+	gen->m68k->target_cycle = gen->m68k->current_cycle;
1184+	gen->m68k->should_return = 1;
1185+}
1186+
1187+static void persist_save(system_header *system)
1188+{
1189+	genesis_context *gen = (genesis_context *)system;
1190+	if (gen->save_type == SAVE_NONE) {
1191+		return;
1192+	}
1193+	FILE * f = fopen(save_filename, "wb");
1194+	if (!f) {
1195+		fprintf(stderr, "Failed to open %s file %s for writing\n", save_type_name(gen->save_type), save_filename);
1196+		return;
1197+	}
1198+	fwrite(gen->save_storage, 1, gen->save_size, f);
1199+	fclose(f);
1200+	printf("Saved %s to %s\n", save_type_name(gen->save_type), save_filename);
1201+}
1202+
1203+static void load_save(system_header *system)
1204+{
1205+	genesis_context *gen = (genesis_context *)system;
1206+	FILE * f = fopen(save_filename, "rb");
1207+	if (f) {
1208+		uint32_t read = fread(gen->save_storage, 1, gen->save_size, f);
1209+		fclose(f);
1210+		if (read > 0) {
1211+			printf("Loaded %s from %s\n", save_type_name(gen->save_type), save_filename);
1212+		}
1213+	}
1214+}
1215+
1216+static void soft_reset(system_header *system)
1217+{
1218+	genesis_context *gen = (genesis_context *)system;
1219+	if (gen->reset_cycle == CYCLE_NEVER) {
1220+		double random = (double)rand()/(double)RAND_MAX;
1221+		gen->reset_cycle = gen->m68k->current_cycle + random * MCLKS_LINE * (gen->version_reg & HZ50 ? LINES_PAL : LINES_NTSC);
1222+		if (gen->reset_cycle < gen->m68k->target_cycle) {
1223+			gen->m68k->target_cycle = gen->reset_cycle;
1224+		}
1225+	}
1226+}
1227+
1228+static void free_genesis(system_header *system)
1229+{
1230+	genesis_context *gen = (genesis_context *)system;
1231+	vdp_free(gen->vdp);
1232+	memmap_chunk *map = (memmap_chunk *)gen->m68k->options->gen.memmap;
1233+	m68k_options_free(gen->m68k->options);
1234+	free(gen->cart);
1235+	free(gen->m68k);
1236+	free(gen->work_ram);
1237+	z80_options_free(gen->z80->Z80_OPTS);
1238+	free(gen->z80);
1239+	free(gen->zram);
1240+	ym_free(gen->ym);
1241+	psg_free(gen->psg);
1242+	free(gen->header.save_dir);
1243+	free_rom_info(&gen->header.info);
1244+	free(gen->lock_on);
1245+	free(gen);
1246+}
1247+
1248+static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
1249+{
1250+	genesis_context *gen = (genesis_context *)system;
1251+	io_gamepad_down(&gen->io, gamepad_num, button);
1252+	if (gen->mapper_type == MAPPER_JCART) {
1253+		jcart_gamepad_down(gen, gamepad_num, button);
1254+	}
1255+}
1256+
1257+static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
1258+{
1259+	genesis_context *gen = (genesis_context *)system;
1260+	io_gamepad_up(&gen->io, gamepad_num, button);
1261+	if (gen->mapper_type == MAPPER_JCART) {
1262+		jcart_gamepad_up(gen, gamepad_num, button);
1263+	}
1264+}
1265+
1266+static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button)
1267+{
1268+	genesis_context *gen = (genesis_context *)system;
1269+	io_mouse_down(&gen->io, mouse_num, button);
1270+}
1271+
1272+static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button)
1273+{
1274+	genesis_context *gen = (genesis_context *)system;
1275+	io_mouse_up(&gen->io, mouse_num, button);
1276+}
1277+
1278+static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y)
1279+{
1280+	genesis_context *gen = (genesis_context *)system;
1281+	io_mouse_motion_absolute(&gen->io, mouse_num, x, y);
1282+}
1283+
1284+static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y)
1285+{
1286+	genesis_context *gen = (genesis_context *)system;
1287+	io_mouse_motion_relative(&gen->io, mouse_num, x, y);
1288+}
1289+
1290+static void keyboard_down(system_header *system, uint8_t scancode)
1291+{
1292+	genesis_context *gen = (genesis_context *)system;
1293+	io_keyboard_down(&gen->io, scancode);
1294+}
1295+
1296+static void keyboard_up(system_header *system, uint8_t scancode)
1297+{
1298+	genesis_context *gen = (genesis_context *)system;
1299+	io_keyboard_up(&gen->io, scancode);
1300+}
1301+
1302+static void set_audio_config(genesis_context *gen)
1303+{
1304+	char *config_gain;
1305+	config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
1306+	render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f);
1307+	config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval;
1308+	render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f);
1309+	
1310+	char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval;
1311+	ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset"));
1312+}
1313+
1314+static void config_updated(system_header *system)
1315+{
1316+	genesis_context *gen = (genesis_context *)system;
1317+	setup_io_devices(config, &system->info, &gen->io);
1318+	set_audio_config(gen);
1319+}
1320+
1321+genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region)
1322+{
1323+	static memmap_chunk z80_map[] = {
1324+		{ 0x0000, 0x4000,  0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL,              NULL },
1325+		{ 0x8000, 0x10000, 0x7FFF, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_bank,     z80_write_bank},
1326+		{ 0x4000, 0x6000,  0x0003, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_ym,       z80_write_ym},
1327+		{ 0x6000, 0x6100,  0xFFFF, 0, 0, 0,                                  NULL, NULL, NULL, NULL,              z80_write_bank_reg},
1328+		{ 0x7F00, 0x8000,  0x00FF, 0, 0, 0,                                  NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write}
1329+	};
1330+	genesis_context *gen = calloc(1, sizeof(genesis_context));
1331+	gen->header.set_speed_percent = set_speed_percent;
1332+	gen->header.start_context = start_genesis;
1333+	gen->header.resume_context = resume_genesis;
1334+	gen->header.load_save = load_save;
1335+	gen->header.persist_save = persist_save;
1336+	gen->header.load_state = load_state;
1337+	gen->header.soft_reset = soft_reset;
1338+	gen->header.free_context = free_genesis;
1339+	gen->header.get_open_bus_value = get_open_bus_value;
1340+	gen->header.request_exit = request_exit;
1341+	gen->header.inc_debug_mode = inc_debug_mode;
1342+	gen->header.gamepad_down = gamepad_down;
1343+	gen->header.gamepad_up = gamepad_up;
1344+	gen->header.mouse_down = mouse_down;
1345+	gen->header.mouse_up = mouse_up;
1346+	gen->header.mouse_motion_absolute = mouse_motion_absolute;
1347+	gen->header.mouse_motion_relative = mouse_motion_relative;
1348+	gen->header.keyboard_down = keyboard_down;
1349+	gen->header.keyboard_up = keyboard_up;
1350+	gen->header.config_updated = config_updated;
1351+	gen->header.serialize = serialize;
1352+	gen->header.deserialize = deserialize;
1353+	gen->header.type = SYSTEM_GENESIS;
1354+	gen->header.info = *rom;
1355+	set_region(gen, rom, force_region);
1356+
1357+	gen->vdp = init_vdp_context(gen->version_reg & 0x40);
1358+	gen->vdp->system = &gen->header;
1359+	gen->frame_end = vdp_cycles_to_frame_end(gen->vdp);
1360+	char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval;
1361+	gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
1362+	gen->int_latency_prev1 = MCLKS_PER_68K * 32;
1363+	gen->int_latency_prev2 = MCLKS_PER_68K * 16;
1364+	
1365+	render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
1366+	
1367+	gen->ym = malloc(sizeof(ym2612_context));
1368+	ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts);
1369+
1370+	gen->psg = malloc(sizeof(psg_context));
1371+	psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG);
1372+	
1373+	set_audio_config(gen);
1374+
1375+	z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES);
1376+	z80_options *z_opts = malloc(sizeof(z80_options));
1377+	init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF);
1378+	gen->z80 = init_z80_context(z_opts);
1379+	gen->z80->next_int_pulse = z80_next_int_pulse;
1380+	z80_assert_reset(gen->z80, 0);
1381+
1382+	gen->z80->system = gen;
1383+	gen->z80->mem_pointers[0] = gen->zram;
1384+	gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom;
1385+
1386+	gen->cart = main_rom;
1387+	gen->lock_on = lock_on;
1388+	gen->work_ram = calloc(2, RAM_WORDS);
1389+	if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval))
1390+	{
1391+		srand(time(NULL));
1392+		for (int i = 0; i < RAM_WORDS; i++)
1393+		{
1394+			gen->work_ram[i] = rand();
1395+		}
1396+		for (int i = 0; i < Z80_RAM_BYTES; i++)
1397+		{
1398+			gen->zram[i] = rand();
1399+		}
1400+		for (int i = 0; i < VRAM_SIZE; i++)
1401+		{
1402+			gen->vdp->vdpmem[i] = rand();
1403+		}
1404+		for (int i = 0; i < SAT_CACHE_SIZE; i++)
1405+		{
1406+			gen->vdp->sat_cache[i] = rand();
1407+		}
1408+		for (int i = 0; i < CRAM_SIZE; i++)
1409+		{
1410+			write_cram_internal(gen->vdp, i, rand());
1411+		}
1412+		for (int i = 0; i < VSRAM_SIZE; i++)
1413+		{
1414+			gen->vdp->vsram[i] = rand();
1415+		}
1416+	}
1417+	setup_io_devices(config, rom, &gen->io);
1418+	gen->header.has_keyboard = io_has_keyboard(&gen->io);
1419+
1420+	gen->mapper_type = rom->mapper_type;
1421+	gen->save_type = rom->save_type;
1422+	if (gen->save_type != SAVE_NONE) {
1423+		gen->save_ram_mask = rom->save_mask;
1424+		gen->save_size = rom->save_size;
1425+		gen->save_storage = rom->save_buffer;
1426+		gen->eeprom_map = rom->eeprom_map;
1427+		gen->num_eeprom = rom->num_eeprom;
1428+		if (gen->save_type == SAVE_I2C) {
1429+			eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size);
1430+		} else if (gen->save_type == SAVE_NOR) {
1431+			memcpy(&gen->nor, rom->nor, sizeof(gen->nor));
1432+			//nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus);
1433+		}
1434+	} else {
1435+		gen->save_storage = NULL;
1436+	}
1437+	
1438+	//This must happen before we generate memory access functions in init_m68k_opts
1439+	for (int i = 0; i < rom->map_chunks; i++)
1440+	{
1441+		if (rom->map[i].start == 0xE00000) {
1442+			rom->map[i].buffer = gen->work_ram;
1443+			break;
1444+		}
1445+	}
1446+
1447+	m68k_options *opts = malloc(sizeof(m68k_options));
1448+	init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K);
1449+	//TODO: make this configurable
1450+	opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY;
1451+	gen->m68k = init_68k_context(opts, NULL);
1452+	gen->m68k->system = gen;
1453+	opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL;
1454+	
1455+	//This must happen after the 68K context has been allocated
1456+	for (int i = 0; i < rom->map_chunks; i++)
1457+	{
1458+		if (rom->map[i].flags & MMAP_PTR_IDX) {
1459+			gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer;
1460+		}
1461+	}
1462+	
1463+	if (gen->mapper_type == MAPPER_SEGA) {
1464+		//initialize bank registers
1465+		for (int i = 1; i < sizeof(gen->bank_regs); i++)
1466+		{
1467+			gen->bank_regs[i] = i;
1468+		}
1469+	}
1470+
1471+	return gen;
1472+}
1473+
1474+genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region)
1475+{
1476+	static memmap_chunk base_map[] = {
1477+		{0xE00000, 0x1000000, 0xFFFF,   0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL,
1478+		           NULL,          NULL,         NULL,            NULL},
1479+		{0xC00000, 0xE00000,  0x1FFFFF, 0, 0, 0,                                  NULL,
1480+		           (read_16_fun)vdp_port_read,  (write_16_fun)vdp_port_write,
1481+		           (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
1482+		{0xA00000, 0xA12000,  0x1FFFF,  0, 0, 0,                                  NULL,
1483+		           (read_16_fun)io_read_w,      (write_16_fun)io_write_w,
1484+		           (read_8_fun)io_read,         (write_8_fun)io_write}
1485+	};
1486+	static tern_node *rom_db;
1487+	if (!rom_db) {
1488+		rom_db = load_rom_db();
1489+	}
1490+	rom_info info = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
1491+	rom = info.rom;
1492+	rom_size = info.rom_size;
1493+#ifndef BLASTEM_BIG_ENDIAN
1494+	byteswap_rom(rom_size, rom);
1495+	if (lock_on) {
1496+		byteswap_rom(lock_on_size, lock_on);
1497+	}
1498+#endif
1499+	char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval;
1500+	if (!m68k_divider) {
1501+		m68k_divider = "7";
1502+	}
1503+	MCLKS_PER_68K = atoi(m68k_divider);
1504+	if (!MCLKS_PER_68K) {
1505+		MCLKS_PER_68K = 7;
1506+	}
1507+	return alloc_init_genesis(&info, rom, lock_on, ym_opts, force_region);
1508+}
+71, -0
 1@@ -0,0 +1,71 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef GENESIS_H_
 8+#define GENESIS_H_
 9+
10+#include <stdint.h>
11+#include "system.h"
12+#include "m68k_core.h"
13+#include "z80_to_x86.h"
14+#include "ym2612.h"
15+#include "vdp.h"
16+#include "psg.h"
17+#include "io.h"
18+#include "romdb.h"
19+#include "arena.h"
20+#include "i2c.h"
21+
22+typedef struct genesis_context genesis_context;
23+
24+struct genesis_context {
25+	system_header   header;
26+	m68k_context    *m68k;
27+	z80_context     *z80;
28+	vdp_context     *vdp;
29+	ym2612_context  *ym;
30+	psg_context     *psg;
31+	uint16_t        *cart;
32+	uint16_t        *lock_on;
33+	uint16_t        *work_ram;
34+	uint8_t         *zram;
35+	void            *extra;
36+	uint8_t         *save_storage;
37+	void            *mapper_temp;
38+	eeprom_map      *eeprom_map;
39+	uint8_t         *serialize_tmp;
40+	size_t          serialize_size;
41+	uint32_t        num_eeprom;
42+	uint32_t        save_size;
43+	uint32_t        save_ram_mask;
44+	uint32_t        master_clock; //Current master clock value
45+	uint32_t        normal_clock; //Normal master clock (used to restore master clock after turbo mode)
46+	uint32_t        frame_end;
47+	uint32_t        max_cycles;
48+	uint32_t        int_latency_prev1;
49+	uint32_t        int_latency_prev2;
50+	uint32_t        reset_cycle;
51+	uint8_t         bank_regs[8];
52+	uint16_t        z80_bank_reg;
53+	uint16_t        mapper_start_index;
54+	uint8_t         mapper_type;
55+	uint8_t         save_type;
56+	sega_io         io;
57+	uint8_t         version_reg;
58+	uint8_t         bus_busy;
59+	uint8_t         reset_requested;
60+	eeprom_state    eeprom;
61+	nor_state       nor;
62+};
63+
64+#define RAM_WORDS 32 * 1024
65+#define Z80_RAM_BYTES 8 * 1024
66+
67+m68k_context * sync_components(m68k_context *context, uint32_t address);
68+genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t system_opts, uint8_t force_region);
69+void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc);
70+void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen);
71+
72+#endif //GENESIS_H_
+532, -0
  1@@ -0,0 +1,532 @@
  2+#!/usr/bin/env python
  3+
  4+def split_fields(line):
  5+	parts = []
  6+	while line:
  7+		field,_,line = line.partition('\t')
  8+		parts.append(field.strip())
  9+		while line.startswith('\t'):
 10+			line = line[1:]
 11+	return parts
 12+
 13+class Program(object):
 14+	def __init__(self, instruction):
 15+		self.avail_dregs = {0,1,2,3,4,5,6,7}
 16+		self.avail_aregs = {0,1,2,3,4,5,6,7}
 17+		instruction.consume_regs(self)
 18+		self.inst = instruction
 19+	
 20+	def dirname(self):
 21+		return self.inst.name + '_' + self.inst.size
 22+	def name(self):
 23+		return str(self.inst).replace('.', '_').replace('#', '_').replace(',', '_').replace(' ', '_').replace('(', '[').replace(')', ']')
 24+	
 25+	def write_rom_test(self, outfile):
 26+		outfile.write('\tdc.l $0, start\n')
 27+		needdivzero = self.inst.name.startswith('div')
 28+		needchk = self.inst.name.startswith('chk')
 29+		for i in xrange(0x8, 0x100, 0x4):
 30+			if needdivzero and i == 0x14:
 31+				outfile.write('\tdc.l div_zero_handler\n')
 32+			elif needchk and i == 0x18:
 33+				outfile.write('\tdc.l chk_handler\n')
 34+			else:
 35+				outfile.write('\tdc.l empty_handler\n')
 36+		outfile.write('\tdc.b "SEGA"\nempty_handler:\n\trte\n')
 37+		if needdivzero:
 38+			outfile.write('div_zero_handler:\n')
 39+			div_zero_count = self.get_dreg()
 40+			outfile.write('\taddq #1, ' + str(div_zero_count) + '\n')
 41+			outfile.write('\trte\n')
 42+		if needchk:
 43+			outfile.write('chk_handler:\n')
 44+			chk_count = self.get_dreg()
 45+			outfile.write('\taddq #1, ' + str(chk_count) + '\n')
 46+			outfile.write('\trte\n')
 47+		outfile.write('start:\n\tmove #0, CCR\n')
 48+		if needdivzero:
 49+			outfile.write('\tmoveq #0, ' + str(div_zero_count) + '\n')
 50+		already = {}
 51+		self.inst.write_init(outfile, already)
 52+		if 'label' in already:
 53+			outfile.write('lbl_' + str(already['label']) + ':\n')
 54+		outfile.write('\t'+str(self.inst)+'\n')
 55+		outfile.write('\t'+self.inst.save_result(self.get_dreg(), True) + '\n')
 56+		save_ccr = self.get_dreg()
 57+		outfile.write('\tmove SR, ' + str(save_ccr) + '\n')
 58+		outfile.write('\tmove #$1F, CCR\n')
 59+		self.inst.invalidate_dest(already)
 60+		self.inst.write_init(outfile, already)
 61+		if 'label' in already:
 62+			outfile.write('lbl_' + str(already['label']) + ':\n')
 63+		outfile.write('\t'+str(self.inst)+'\n')
 64+		outfile.write('\t'+self.inst.save_result(self.get_dreg(), False) + '\n')
 65+		outfile.write('\treset\nforever:\n\tbra.s forever\n')
 66+	
 67+	def consume_dreg(self, num):
 68+		self.avail_dregs.discard(num)
 69+	
 70+	def consume_areg(self, num):
 71+		self.avail_aregs.discard(num)
 72+	
 73+	def get_dreg(self):
 74+		return Register('d', self.avail_dregs.pop())
 75+
 76+class Dummy(object):
 77+	def __str__(self):
 78+		return ''
 79+	def write_init(self, outfile, size, already):
 80+		pass
 81+	def consume_regs(self, program):
 82+		pass
 83+
 84+dummy_op = Dummy()
 85+
 86+class Register(object):
 87+	def __init__(self, kind, num):
 88+		self.kind = kind
 89+		self.num = num
 90+	
 91+	def __str__(self):
 92+		if self.kind == 'd' or self.kind == 'a':
 93+			return self.kind + str(self.num)
 94+		return self.kind
 95+	
 96+	def write_init(self, outfile, size, already):
 97+		if not str(self) in already:
 98+			minv,maxv = get_size_range(size)
 99+			val = randint(minv,maxv)
100+			already[str(self)] = val
101+			outfile.write('\tmove.'+size+' #'+str(val)+', ' + str(self) + '\n')
102+	
103+	def consume_regs(self, program):
104+		if self.kind == 'd':
105+			program.consume_dreg(self.num)
106+		elif self.kind == 'a':
107+			program.consume_areg(self.num)
108+
109+def valid_ram_address(address, size='b'):
110+	return address >= 0xE00000 and address <= 0xFFFFFFFC and (address & 0xE00000) == 0xE00000 and (size == 'b' or not address & 1)
111+
112+def random_ram_address(mina=0xE00000, maxa=0xFFFFFFFC):
113+	return randint(mina/2, maxa/2)*2 | 0xE00000
114+
115+class Indexed(object):
116+	def __init__(self, base, index, index_size, disp):
117+		self.base = base
118+		self.index = index
119+		self.index_size = index_size
120+		self.disp = disp
121+	
122+	def write_init(self, outfile, size, already):
123+		if self.base.kind == 'pc':
124+			if str(self.index) in already:
125+				index = already[str(self.index)]
126+				if self.index_size == 'w':
127+					index = index & 0xFFFF
128+					#sign extend index
129+					if index & 0x8000:
130+						index -= 65536
131+				if index > -1024:
132+					index = already[str(self.index)] = 2 * randint(-16384, -512)
133+					outfile.write('\tmove.l #' + str(index) + ', ' + str(self.index) + '\n')
134+			else:
135+				index = already[str(self.index)] = 2 * randint(-16384, -512)
136+				outfile.write('\tmove.l #' + str(index) + ', ' + str(self.index) + '\n')
137+			num = already.get('label', 0)+1
138+			already['label'] = num
139+			if (already[str(self.index)] + self.disp) & 1:
140+				self.disp += 1
141+			address = 'lbl_' + str(num) + ' + 2 + ' + str(self.disp) + ' + ' + str(index)
142+		else:
143+			if self.base == self.index:
144+				if str(self.base) in already:
145+					if not valid_ram_address(already[str(self.base)]*2):
146+						del already[str(self.base)]
147+						self.write_init(outfile, size, already)
148+						return
149+					else:
150+						base = index = already[str(self.base)]
151+				else:
152+					base = index = already[str(self.base)] = random_ram_address()/2
153+					outfile.write('\tmove.l #' + str(base) + ', ' + str(self.base) + '\n')
154+			else:
155+				if str(self.base) in already:
156+					if not valid_ram_address(already[str(self.base)]):
157+						del already[str(self.base)]
158+						self.write_init(outfile, size, already)
159+						return
160+					else:
161+						base = already[str(self.base)]
162+				else:
163+					base = already[str(self.base)] = random_ram_address()
164+					outfile.write('\tmove.l #' + str(base) + ', ' + str(self.base) + '\n')
165+				if str(self.index) in already:
166+					index = already[str(self.index)]
167+					if self.index_size == 'w':
168+						index = index & 0xFFFF
169+						#sign extend index
170+						if index & 0x8000:
171+							index -= 65536
172+					if not valid_ram_address(base + index):
173+						index = already[str(self.index)] = randint(-64, 63)
174+						outfile.write('\tmove.l #' + str(index) + ', ' + str(self.index) + '\n')
175+				else:
176+					index = already[str(self.index)] = randint(-64, 63)
177+					outfile.write('\tmove.l #' + str(index) + ', ' + str(self.index) + '\n')
178+			address = base + index + self.disp
179+			if (address & 0xFFFFFF) < 0xE00000:
180+				if (address & 0xFFFFFF) < 128:
181+					self.disp -= (address & 0xFFFFFF)
182+				else:
183+					self.disp += 0xE00000-(address & 0xFFFFFF)
184+				if self.disp > 127:
185+					self.disp = 127
186+				elif self.disp < -128:
187+					self.disp = -128
188+				address = base + index + self.disp
189+			elif (address & 0xFFFFFF) > 0xFFFFFC:
190+				self.disp -= (address & 0xFFFFFF) - 0xFFFFFC
191+				if self.disp > 127:
192+					self.disp = 127
193+				elif self.disp < -128:
194+					self.disp = -128
195+				address = base + index + self.disp
196+			if size != 'b' and address & 1:
197+				self.disp = self.disp ^ 1
198+				address = base + index + self.disp
199+		minv,maxv = get_size_range(size)
200+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', (' + str(address) + ').l\n')
201+	
202+	def __str__(self):
203+		return '(' + str(self.disp) + ', ' + str(self.base) + ', ' + str(self.index) + '.' + self.index_size + ')'
204+	
205+	def consume_regs(self, program):
206+		self.base.consume_regs(program)
207+		self.index.consume_regs(program)
208+
209+class Displacement(object):
210+	def __init__(self, base, disp):
211+		self.base = base
212+		if disp & 1:
213+			disp += 1
214+		self.disp = disp 
215+	
216+	def write_init(self, outfile, size, already):
217+		if self.base.kind == 'pc':
218+			num = already.get('label', 0)+1
219+			already['label'] = num
220+			address = 'lbl_' + str(num) + ' + 2 + ' + str(self.disp)
221+		else:
222+			if str(self.base) in already:
223+				if not valid_ram_address(already[str(self.base)]):
224+					del already[str(self.base)]
225+					self.write_init(outfile, size, already)
226+					return
227+				else:
228+					base = already[str(self.base)]
229+			else:
230+				base = already[str(self.base)] = random_ram_address()
231+				outfile.write('\tmove.l #' + str(base) + ', ' + str(self.base) + '\n')
232+			address = base + self.disp
233+			if (address & 0xFFFFFF) < 0xE00000:
234+				if (address & 0xFFFFFF) < 0x10000:
235+					self.disp -= (address & 0xFFFFFF)
236+				else:
237+					self.disp += 0xE00000-(address & 0xFFFFFF)
238+				address = base + self.disp
239+			elif (address & 0xFFFFFF) > 0xFFFFFC:
240+				self.disp -= (address & 0xFFFFFF) - 0xFFFFFC
241+				address = base + self.disp
242+			if size != 'b' and address & 1:
243+				self.disp = self.disp ^ 1
244+				address = base + self.disp
245+		minv,maxv = get_size_range(size)
246+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', (' + str(address) + ').l\n')
247+	
248+	def __str__(self):
249+		return '(' + str(self.disp) + ', ' + str(self.base) + ')'
250+	
251+	def consume_regs(self, program):
252+		self.base.consume_regs(program)
253+	
254+class Indirect(object):
255+	def __init__(self, reg):
256+		self.reg = reg
257+	
258+	def __str__(self):
259+		return '(' + str(self.reg) + ')'
260+	
261+	def write_init(self, outfile, size, already):
262+		if str(self.reg) in already:
263+			if not valid_ram_address(already[str(self.reg)], size):
264+				del already[str(self.reg)]
265+				self.write_init(outfile, size, already)
266+				return
267+			else:
268+				address = already[str(self.reg)]
269+		else:
270+			address = random_ram_address()
271+			if size != 'b':
272+				address = address & 0xFFFFFFFE
273+			outfile.write('\tmove.l #' + str(address) + ', ' + str(self.reg) + '\n')
274+			already[str(self.reg)] = address
275+		minv,maxv = get_size_range(size)
276+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', (' + str(address) + ').l\n')
277+	
278+	def consume_regs(self, program):
279+		self.reg.consume_regs(program)
280+
281+class Increment(object):
282+	def __init__(self, reg):
283+		self.reg = reg
284+	
285+	def __str__(self):
286+		return '(' + str(self.reg) + ')+'
287+	
288+	def write_init(self, outfile, size, already):
289+		if str(self.reg) in already:
290+			if not valid_ram_address(already[str(self.reg)], size):
291+				del already[str(self.reg)]
292+				self.write_init(outfile, size, already)
293+				return
294+			else:
295+				address = already[str(self.reg)]
296+		else:
297+			address = random_ram_address()
298+			if size != 'b':
299+				address = address & 0xFFFFFFFE
300+			outfile.write('\tmove.l #' + str(address) + ', ' + str(self.reg) + '\n')
301+			already[str(self.reg)] = address
302+		minv,maxv = get_size_range(size)
303+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', (' + str(address) + ').l\n')
304+	
305+	def consume_regs(self, program):
306+		self.reg.consume_regs(program)
307+
308+class Decrement(object):
309+	def __init__(self, reg):
310+		self.reg = reg
311+	
312+	def __str__(self):
313+		return '-(' + str(self.reg) + ')'
314+	
315+	def write_init(self, outfile, size, already):
316+		if str(self.reg) in already:
317+			if not valid_ram_address(already[str(self.reg)]- 4 if size == 'l' else 2 if size == 'w' else 1, size):
318+				del already[str(self.reg)]
319+				self.write_init(outfile, size, already)
320+				return
321+			else:
322+				address = already[str(self.reg)]
323+		else:
324+			address = random_ram_address(mina=0xE00004)
325+			if size != 'b':
326+				address = address & 0xFFFFFFFE
327+			outfile.write('\tmove.l #' + str(address) + ', ' + str(self.reg) + '\n')
328+			already[str(self.reg)] = address
329+		minv,maxv = get_size_range(size)
330+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', (' + str(address) + ').l\n')
331+	
332+	def consume_regs(self, program):
333+		self.reg.consume_regs(program)
334+
335+class Absolute(object):
336+	def __init__(self, address, size):
337+		self.address = address
338+		self.size = size
339+	
340+	def __str__(self):
341+		return '(' + str(self.address) + ').' + self.size
342+	
343+	def write_init(self, outfile, size, already):
344+		minv,maxv = get_size_range(size)
345+		outfile.write('\tmove.' + size + ' #' + str(randint(minv, maxv)) + ', '+str(self)+'\n')
346+	
347+	def consume_regs(self, program):
348+		pass
349+
350+class Immediate(object):
351+	def __init__(self, value):
352+		self.value = value
353+	
354+	def __str__(self):
355+		return '#' + str(self.value)
356+	
357+	def write_init(self, outfile, size, already):
358+		pass
359+	
360+	def consume_regs(self, program):
361+		pass
362+		
363+all_dregs = [Register('d', i) for i in range(0, 8)]
364+all_aregs = [Register('a', i) for i in range(0, 8)]
365+all_indirect = [Indirect(reg) for reg in all_aregs]
366+all_predec = [Decrement(reg) for reg in all_aregs]
367+all_postinc = [Increment(reg) for reg in all_aregs]
368+from random import randint
369+def all_indexed():
370+	return [Indexed(base, index, index_size, randint(-128, 127)) for base in all_aregs for index in all_dregs + all_aregs for index_size in ('w','l')]
371+
372+def all_disp():
373+	return [Displacement(base, randint(-32768, 32767)) for base in all_aregs]
374+
375+def rand_pc_disp():
376+	return [Displacement(Register('pc', 0), randint(-32768, -1024)) for x in xrange(0, 8)]
377+
378+def all_pc_indexed():
379+	return [Indexed(Register('pc', 0), index, index_size, randint(-128, 127)) for index in all_dregs + all_aregs for index_size in ('w','l')]
380+
381+def rand_abs_short():
382+	return [Absolute(random_ram_address(0xFFFF8000), 'w') for x in xrange(0, 8)]
383+
384+def rand_abs_long():
385+	return [Absolute(random_ram_address(), 'l') for x in xrange(0, 8)]
386+
387+def get_size_range(size):
388+	if size == 'b':
389+		return (-128, 127)
390+	elif size == 'w':
391+		return (-32768, 32767)
392+	else:
393+		return (-2147483648, 2147483647)
394+
395+def rand_immediate(size):
396+	minv,maxv = get_size_range(size)
397+	
398+	return [Immediate(randint(minv, maxv)) for x in xrange(0,8)]
399+
400+def get_variations(mode, size):
401+	mapping = {
402+		'd':all_dregs,
403+		'a':all_aregs,
404+		'(a)':all_indirect,
405+		'-(a)':all_predec,
406+		'(a)+':all_postinc,
407+		'(n,a)':all_disp,
408+		'(n,a,x)':all_indexed,
409+		'(n,pc)':rand_pc_disp,
410+		'(n,pc,x)':all_pc_indexed,
411+		'(n).w':rand_abs_short,
412+		'(n).l':rand_abs_long
413+	}
414+	if mode in mapping:
415+		ret = mapping[mode]
416+		if type(ret) != list:
417+			ret = ret()
418+		return ret
419+	elif mode == '#n':
420+		return rand_immediate(size)
421+	elif mode.startswith('#(') and mode.endswith(')'):
422+		inner = mode[2:-1]
423+		start,sep,end = inner.rpartition('-')
424+		start,end = int(start),int(end)
425+		if end-start > 16:
426+			return [Immediate(randint(start, end)) for x in range(0,8)]
427+		else:
428+			return [Immediate(num) for num in range(start, end+1)]
429+	else:
430+		print "Don't know what to do with source type", mode
431+		return None
432+		
433+class Inst2Op(object):
434+	def __init__(self, name, size, src, dst):
435+		self.name = name
436+		self.size = size
437+		self.src = src
438+		self.dst = dst
439+	
440+	def __str__(self):
441+		return self.name + '.' + self.size + ' ' + str(self.src) + ', ' + str(self.dst)
442+	
443+	def write_init(self, outfile, already):
444+		self.src.write_init(outfile, self.size, already)
445+		self.dst.write_init(outfile, self.size, already)
446+	
447+	def invalidate_dest(self, already):
448+		if type(self.dst) == Register:
449+			del already[str(self.dst)]
450+	
451+	def save_result(self, reg, always):
452+		if always or type(self.dst) != Register:
453+			if type(self.dst) == Decrement:
454+				src = Increment(self.dst.reg)
455+			elif type(self.dst) == Increment:
456+				src = Decrement(self.dst.reg)
457+			else:
458+				src = self.dst
459+			return 'move.' + self.size + ' ' + str(src) + ', ' + str(reg)
460+		else:
461+			return ''
462+	
463+	def consume_regs(self, program):
464+		self.src.consume_regs(program)
465+		self.dst.consume_regs(program)
466+
467+class Inst1Op(Inst2Op):
468+	def __init__(self, name, size, dst):
469+		super(Inst1Op, self).__init__(name, size, dummy_op, dst)
470+	
471+	def __str__(self):
472+		return self.name + '.' + self.size + ' ' + str(self.dst)
473+
474+class Entry(object):
475+	def __init__(self, line):
476+		fields = split_fields(line)
477+		self.name = fields[0]
478+		sizes = fields[1]
479+		sources = fields[2].split(';')
480+		if len(fields) > 3:
481+			dests = fields[3].split(';')
482+		else:
483+			dests = None
484+		combos = []
485+		for size in sizes:
486+			for source in sources:
487+				if size != 'b' or source != 'a':
488+					if dests:
489+						for dest in dests:
490+							if size != 'b' or dest != 'a':
491+								combos.append((size, source, dest))
492+					else:
493+						combos.append((size, None, source))
494+		self.cases = combos
495+		
496+	def programs(self):
497+		res = []
498+		for (size, src, dst) in self.cases:
499+			dests = get_variations(dst, size)
500+			if src:
501+				sources = get_variations(src, size)
502+				for source in sources:
503+					for dest in dests:
504+						res.append(Program(Inst2Op(self.name, size, source, dest)))
505+			else:
506+				for dest in dests:
507+					res.append(Program(Inst1Op(self.name, size, dest)))
508+		return res
509+		
510+def process_entries(f):
511+	entries = []
512+	for line in f:
513+		if not line.startswith('Name') and not line.startswith('#') and len(line.strip()) > 0:
514+			entries.append(Entry(line))
515+	return entries
516+
517+from os import path, mkdir
518+def main(args):
519+	entries = process_entries(open('testcases.txt'))
520+	for entry in entries:
521+		programs = entry.programs()
522+		for program in programs:
523+			dname = program.dirname()
524+			if not path.exists('generated_tests/' + dname):
525+				mkdir('generated_tests/' + dname)
526+			f = open('generated_tests/' + dname + '/' + program.name() + '.s68', 'w')
527+			program.write_rom_test(f)
528+			f.close()
529+	
530+if __name__ == '__main__':
531+	import sys
532+	main(sys.argv)
533+
A gst.c
+505, -0
  1@@ -0,0 +1,505 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "genesis.h"
  8+#include "gst.h"
  9+#include <string.h>
 10+#include <stdio.h>
 11+
 12+#define GST_68K_REGS 0x80
 13+#define GST_68K_REG_SIZE (0xDA-GST_68K_REGS)
 14+#define GST_68K_PC_OFFSET (0xC8-GST_68K_REGS)
 15+#define GST_68K_SR_OFFSET (0xD0-GST_68K_REGS)
 16+#define GST_68K_USP_OFFSET (0xD2-GST_68K_REGS)
 17+#define GST_68K_SSP_OFFSET (0xD6-GST_68K_REGS)
 18+#define GST_68K_RAM  0x2478
 19+#define GST_Z80_REGS 0x404
 20+#define GST_Z80_REG_SIZE (0x440-GST_Z80_REGS)
 21+#define GST_Z80_RAM 0x474
 22+#define GST_VDP_REGS 0xFA
 23+#define GST_VDP_MEM 0x12478
 24+#define GST_YM_OFFSET 0x1E4
 25+#define GST_YM_SIZE (0x3E4-GST_YM_OFFSET)
 26+
 27+uint32_t read_le_32(uint8_t * data)
 28+{
 29+	return data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0];
 30+}
 31+
 32+uint16_t read_le_16(uint8_t * data)
 33+{
 34+	return data[1] << 8 | data[0];
 35+}
 36+
 37+uint16_t read_be_16(uint8_t * data)
 38+{
 39+	return data[0] << 8 | data[1];
 40+}
 41+
 42+void write_le_32(uint8_t * dst, uint32_t val)
 43+{
 44+	dst[0] = val;
 45+	dst[1] = val >> 8;
 46+	dst[2] = val >> 16;
 47+	dst[3] = val >> 24;
 48+}
 49+
 50+void write_le_16(uint8_t * dst, uint16_t val)
 51+{
 52+	dst[0] = val;
 53+	dst[1] = val >> 8;
 54+}
 55+
 56+void write_be_32(uint8_t * dst, uint32_t val)
 57+{
 58+	dst[0] = val >> 24;
 59+	dst[1] = val >> 16;
 60+	dst[2] = val >> 8;
 61+	dst[3] = val;
 62+}
 63+
 64+void write_be_16(uint8_t * dst, uint16_t val)
 65+{
 66+	dst[0] = val >> 8;
 67+	dst[1] = val;
 68+}
 69+
 70+uint32_t m68k_load_gst(m68k_context * context, FILE * gstfile)
 71+{
 72+	uint8_t buffer[GST_68K_REG_SIZE];
 73+	fseek(gstfile, GST_68K_REGS, SEEK_SET);
 74+	if (fread(buffer, 1, GST_68K_REG_SIZE, gstfile) != GST_68K_REG_SIZE) {
 75+		fputs("Failed to read 68K registers from savestate\n", stderr);
 76+		return 0;
 77+	}
 78+	uint8_t * curpos = buffer;
 79+	for (int i = 0; i < 8; i++) {
 80+		context->dregs[i] = read_le_32(curpos);
 81+		curpos += sizeof(uint32_t);
 82+	}
 83+	for (int i = 0; i < 8; i++) {
 84+		context->aregs[i] = read_le_32(curpos);
 85+		curpos += sizeof(uint32_t);
 86+	}
 87+	uint32_t pc = read_le_32(buffer + GST_68K_PC_OFFSET);
 88+	uint16_t sr = read_le_16(buffer + GST_68K_SR_OFFSET);
 89+	context->status = sr >> 8;
 90+	for (int flag = 4; flag >= 0; flag--) {
 91+		context->flags[flag] = sr & 1;
 92+		sr >>= 1;
 93+	}
 94+	if (context->status & (1 << 5)) {
 95+		context->aregs[8] = read_le_32(buffer + GST_68K_USP_OFFSET);
 96+	} else {
 97+		context->aregs[8] = read_le_32(buffer + GST_68K_SSP_OFFSET);
 98+	}
 99+	
100+	return pc;
101+}
102+
103+uint8_t m68k_save_gst(m68k_context * context, uint32_t pc, FILE * gstfile)
104+{
105+	uint8_t buffer[GST_68K_REG_SIZE];
106+	uint8_t * curpos = buffer;
107+	for (int i = 0; i < 8; i++) {
108+		write_le_32(curpos, context->dregs[i]);
109+		curpos += sizeof(uint32_t);
110+	}
111+	for (int i = 0; i < 8; i++) {
112+		write_le_32(curpos, context->aregs[i]);
113+		curpos += sizeof(uint32_t);
114+	}
115+	write_le_32(buffer + GST_68K_PC_OFFSET, pc);
116+	uint16_t sr = context->status << 3;
117+	for (int flag = 4; flag >= 0; flag--) {
118+		sr <<= 1;
119+		sr |= context->flags[flag];
120+	}
121+	write_le_16(buffer + GST_68K_SR_OFFSET, sr);
122+	if (context->status & (1 << 5)) {
123+		write_le_32(buffer + GST_68K_USP_OFFSET, context->aregs[8]);
124+		write_le_32(buffer + GST_68K_SSP_OFFSET, context->aregs[7]);
125+	} else {
126+		write_le_32(buffer + GST_68K_USP_OFFSET, context->aregs[7]);
127+		write_le_32(buffer + GST_68K_SSP_OFFSET, context->aregs[8]);
128+	}
129+	fseek(gstfile, GST_68K_REGS, SEEK_SET);
130+	if (fwrite(buffer, 1, GST_68K_REG_SIZE, gstfile) != GST_68K_REG_SIZE) {
131+		fputs("Failed to write 68K registers to savestate\n", stderr);
132+		return 0;
133+	}
134+
135+	return 1;
136+}
137+
138+uint8_t z80_load_gst(z80_context * context, FILE * gstfile)
139+{
140+	uint8_t regdata[GST_Z80_REG_SIZE];
141+	fseek(gstfile, GST_Z80_REGS, SEEK_SET);
142+	if (fread(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) {
143+		fputs("Failed to read Z80 registers from savestate\n", stderr);
144+		return 0;
145+	}
146+	uint8_t * curpos = regdata;
147+	uint8_t f = *(curpos++);
148+	context->flags[ZF_C] = f & 1;
149+	f >>= 1;
150+	context->flags[ZF_N] = f & 1;
151+	f >>= 1;
152+	context->flags[ZF_PV] = f & 1;
153+	f >>= 2;
154+	context->flags[ZF_H] = f & 1;
155+	f >>= 2;
156+	context->flags[ZF_Z] = f & 1;
157+	f >>= 1;
158+	context->flags[ZF_S] = f;
159+
160+	context->regs[Z80_A] = *curpos;
161+	curpos += 3;
162+	for (int reg = Z80_C; reg <= Z80_IYH; reg++) {
163+		context->regs[reg++] = *(curpos++);
164+		context->regs[reg] = *curpos;
165+		curpos += 3;
166+	}
167+	context->pc = read_le_16(curpos);
168+	curpos += 4;
169+	context->sp = read_le_16(curpos);
170+	curpos += 4;
171+	f = *(curpos++);
172+	context->alt_flags[ZF_C] = f & 1;
173+	f >>= 1;
174+	context->alt_flags[ZF_N] = f & 1;
175+	f >>= 1;
176+	context->alt_flags[ZF_PV] = f & 1;
177+	f >>= 2;
178+	context->alt_flags[ZF_H] = f & 1;
179+	f >>= 2;
180+	context->alt_flags[ZF_Z] = f & 1;
181+	f >>= 1;
182+	context->alt_flags[ZF_S] = f;
183+	context->alt_regs[Z80_A] = *curpos;
184+	curpos += 3;
185+	for (int reg = Z80_C; reg <= Z80_H; reg++) {
186+		context->alt_regs[reg++] = *(curpos++);
187+		context->alt_regs[reg] = *curpos;
188+		curpos += 3;
189+	}
190+	context->regs[Z80_I] = *curpos;
191+	curpos += 2;
192+	context->iff1 = context->iff2 = *curpos;
193+	curpos += 2;
194+	context->reset = !*(curpos++);
195+	context->busreq = *curpos;
196+	curpos += 3;
197+	uint32_t bank = read_le_32(curpos);
198+	if (bank < 0x400000) {
199+		context->mem_pointers[1] = context->mem_pointers[2] + bank;
200+	} else {
201+		context->mem_pointers[1] = NULL;
202+	}
203+	context->bank_reg = bank >> 15;
204+	uint8_t buffer[Z80_RAM_BYTES];
205+	fseek(gstfile, GST_Z80_RAM, SEEK_SET);
206+	if(fread(buffer, 1, sizeof(buffer), gstfile) != (8*1024)) {
207+		fputs("Failed to read Z80 RAM from savestate\n", stderr);
208+		return 0;
209+	}
210+	for (int i = 0; i < Z80_RAM_BYTES; i++)
211+	{
212+		if (context->mem_pointers[0][i] != buffer[i]) {
213+			context->mem_pointers[0][i] = buffer[i];
214+			z80_handle_code_write(i, context);
215+		}
216+	}
217+	context->native_pc = NULL;
218+	context->extra_pc = NULL;
219+	return 1;
220+}
221+
222+uint8_t vdp_load_gst(vdp_context * context, FILE * state_file)
223+{
224+	uint8_t tmp_buf[VRAM_SIZE];
225+	fseek(state_file, GST_VDP_REGS, SEEK_SET);
226+	if (fread(tmp_buf, 1, VDP_REGS, state_file) != VDP_REGS) {
227+		fputs("Failed to read VDP registers from savestate\n", stderr);
228+		return 0;
229+	}
230+	for (uint16_t i = 0; i < VDP_REGS; i++)
231+	{
232+		vdp_control_port_write(context, 0x8000 | (i << 8) | tmp_buf[i]);
233+	}
234+	if (fread(tmp_buf, 1, CRAM_SIZE*2, state_file) != CRAM_SIZE*2) {
235+		fputs("Failed to read CRAM from savestate\n", stderr);
236+		return 0;
237+	}
238+	for (int i = 0; i < CRAM_SIZE; i++) {
239+		uint16_t value;
240+		write_cram_internal(context, i, (tmp_buf[i*2+1] << 8) | tmp_buf[i*2]);
241+	}
242+	if (fread(tmp_buf, 2, VSRAM_SIZE, state_file) != VSRAM_SIZE) {
243+		fputs("Failed to read VSRAM from savestate\n", stderr);
244+		return 0;
245+	}
246+	for (int i = 0; i < VSRAM_SIZE; i++) {
247+		context->vsram[i] = (tmp_buf[i*2+1] << 8) | tmp_buf[i*2];
248+	}
249+	fseek(state_file, GST_VDP_MEM, SEEK_SET);
250+	if (fread(tmp_buf, 1, VRAM_SIZE, state_file) != VRAM_SIZE) {
251+		fputs("Failed to read VRAM from savestate\n", stderr);
252+		return 0;
253+	}
254+	for (int i = 0; i < VRAM_SIZE; i++) {
255+		context->vdpmem[i] = tmp_buf[i];
256+		vdp_check_update_sat_byte(context, i, tmp_buf[i]);
257+	}
258+	return 1;
259+}
260+
261+uint8_t vdp_save_gst(vdp_context * context, FILE * outfile)
262+{
263+	uint8_t tmp_buf[CRAM_SIZE*2];
264+	fseek(outfile, GST_VDP_REGS, SEEK_SET);
265+	if(fwrite(context->regs, 1, VDP_REGS, outfile) != VDP_REGS) {
266+		fputs("Error writing VDP regs to savestate\n", stderr);
267+		return 0;
268+	}
269+	for (int i = 0; i < CRAM_SIZE; i++)
270+	{
271+		tmp_buf[i*2] = context->cram[i];
272+		tmp_buf[i*2+1] = context->cram[i] >> 8;
273+	}
274+	if (fwrite(tmp_buf, 1, sizeof(tmp_buf), outfile) != sizeof(tmp_buf)) {
275+		fputs("Error writing CRAM to savestate\n", stderr);
276+		return 0;
277+	}
278+	for (int i = 0; i < VSRAM_SIZE; i++)
279+	{
280+		tmp_buf[i*2] = context->vsram[i];
281+		tmp_buf[i*2+1] = context->vsram[i] >> 8;
282+	}
283+	if (fwrite(tmp_buf, 2, VSRAM_SIZE, outfile) != VSRAM_SIZE) {
284+		fputs("Error writing VSRAM to savestate\n", stderr);
285+		return 0;
286+	}
287+	fseek(outfile, GST_VDP_MEM, SEEK_SET);
288+	if (fwrite(context->vdpmem, 1, VRAM_SIZE, outfile) != VRAM_SIZE) {
289+		fputs("Error writing VRAM to savestate\n", stderr);
290+		return 0;
291+	}
292+	return 1;
293+}
294+
295+uint8_t z80_save_gst(z80_context * context, FILE * gstfile)
296+{
297+	uint8_t regdata[GST_Z80_REG_SIZE];
298+	uint8_t * curpos = regdata;
299+	memset(regdata, 0, sizeof(regdata));
300+	uint8_t f = context->flags[ZF_S];
301+	f <<= 1;
302+	f |= context->flags[ZF_Z] ;
303+	f <<= 2;
304+	f |= context->flags[ZF_H];
305+	f <<= 2;
306+	f |= context->flags[ZF_PV];
307+	f <<= 1;
308+	f |= context->flags[ZF_N];
309+	f <<= 1;
310+	f |= context->flags[ZF_C];
311+	*(curpos++) = f;
312+	*curpos = context->regs[Z80_A];
313+
314+	curpos += 3;
315+	for (int reg = Z80_C; reg <= Z80_IYH; reg++) {
316+		*(curpos++) = context->regs[reg++];
317+		*curpos = context->regs[reg];
318+		curpos += 3;
319+	}
320+	write_le_16(curpos, context->pc);
321+	curpos += 4;
322+	write_le_16(curpos, context->sp);
323+	curpos += 4;
324+	f = context->alt_flags[ZF_S];
325+	f <<= 1;
326+	f |= context->alt_flags[ZF_Z] ;
327+	f <<= 2;
328+	f |= context->alt_flags[ZF_H];
329+	f <<= 2;
330+	f |= context->alt_flags[ZF_PV];
331+	f <<= 1;
332+	f |= context->alt_flags[ZF_N];
333+	f <<= 1;
334+	f |= context->alt_flags[ZF_C];
335+	*(curpos++) = f;
336+	*curpos = context->alt_regs[Z80_A];
337+	curpos += 3;
338+	for (int reg = Z80_C; reg <= Z80_H; reg++) {
339+		*(curpos++) = context->alt_regs[reg++];
340+		*curpos = context->alt_regs[reg];
341+		curpos += 3;
342+	}
343+	*curpos = context->regs[Z80_I];
344+	curpos += 2;
345+	*curpos = context->iff1;
346+	curpos += 2;
347+	*(curpos++) = !context->reset;
348+	*curpos = context->busreq;
349+	curpos += 3;
350+	uint32_t bank = context->bank_reg << 15;
351+	write_le_32(curpos, bank);
352+	fseek(gstfile, GST_Z80_REGS, SEEK_SET);
353+	if (fwrite(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) {
354+		return 0;
355+	}
356+	fseek(gstfile, GST_Z80_RAM, SEEK_SET);
357+	if(fwrite(context->mem_pointers[0], 1, 8*1024, gstfile) != (8*1024)) {
358+		fputs("Failed to write Z80 RAM to savestate\n", stderr);
359+		return 0;
360+	}
361+	return 1;
362+}
363+
364+uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile)
365+{
366+	uint8_t regdata[GST_YM_SIZE];
367+	fseek(gstfile, GST_YM_OFFSET, SEEK_SET);
368+	if (fread(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) {
369+		return 0;
370+	}
371+	for (int i = 0; i < sizeof(regdata); i++) {
372+		if (i & 0x100) {
373+			ym_address_write_part2(context, i & 0xFF);
374+		} else {
375+			ym_address_write_part1(context, i);
376+		}
377+		ym_data_write(context, regdata[i]);
378+	}
379+	return 1;
380+}
381+
382+uint8_t ym_save_gst(ym2612_context * context, FILE * gstfile)
383+{
384+	uint8_t regdata[GST_YM_SIZE];
385+	for (int i = 0; i < sizeof(regdata); i++) {
386+		if (i & 0x100) {
387+			int reg = (i & 0xFF);
388+			if (reg >= YM_PART2_START && reg < YM_REG_END) {
389+				regdata[i] = context->part2_regs[reg-YM_PART2_START];
390+			} else {
391+				regdata[i] = 0xFF;
392+			}
393+		} else {
394+			if (i >= YM_PART1_START && i < YM_REG_END) {
395+				regdata[i] = context->part1_regs[i-YM_PART1_START];
396+			} else {
397+				regdata[i] = 0xFF;
398+			}
399+		}
400+	}
401+	fseek(gstfile, GST_YM_OFFSET, SEEK_SET);
402+	if (fwrite(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) {
403+		return 0;
404+	}
405+	return 1;
406+}
407+
408+uint32_t load_gst(genesis_context * gen, char * fname)
409+{
410+	char buffer[4096];
411+	FILE * gstfile = fopen(fname, "rb");
412+	if (!gstfile) {
413+		fprintf(stderr, "Could not open file %s for reading\n", fname);
414+		goto error;
415+	}
416+	char ident[5];
417+	if (fread(ident, 1, sizeof(ident), gstfile) != sizeof(ident)) {
418+		fprintf(stderr, "Could not read ident code from %s\n", fname);
419+		goto error_close;
420+	}
421+	if (memcmp(ident, "GST\x40\xE0", 3) != 0) {
422+		fprintf(stderr, "%s doesn't appear to be a GST savestate. The ident code is %c%c%c\\x%X\\x%X instead of GST\\x40\\xE0.\n", fname, ident[0], ident[1], ident[2], ident[3], ident[4]);
423+		goto error_close;
424+	}
425+	uint32_t pc = m68k_load_gst(gen->m68k, gstfile);
426+	if (!pc) {
427+		goto error_close;
428+	}
429+	
430+	if (!vdp_load_gst(gen->vdp, gstfile)) {
431+		goto error_close;
432+	}
433+	if (!ym_load_gst(gen->ym, gstfile)) {
434+		goto error_close;
435+	}
436+	if (!z80_load_gst(gen->z80, gstfile)) {
437+		goto error_close;
438+	}
439+	gen->io.ports[0].control = 0x40;
440+	gen->io.ports[1].control = 0x40;
441+	
442+	fseek(gstfile, GST_68K_RAM, SEEK_SET);
443+	for (int i = 0; i < (32*1024);) {
444+		if (fread(buffer, 1, sizeof(buffer), gstfile) != sizeof(buffer)) {
445+			fputs("Failed to read 68K RAM from savestate\n", stderr);
446+			return 0;
447+		}
448+		for(char *curpos = buffer; curpos < (buffer + sizeof(buffer)); curpos += sizeof(uint16_t)) {
449+			uint16_t word = read_be_16(curpos);
450+			if (word != gen->work_ram[i]) {
451+				gen->work_ram[i] = word;
452+				m68k_handle_code_write(0xFF0000 | (i << 1), gen->m68k);
453+			}
454+			i++;
455+		}
456+	}
457+	fclose(gstfile);
458+	return pc;
459+
460+error_close:
461+	fclose(gstfile);
462+error:
463+	return 0;
464+}
465+
466+uint8_t save_gst(genesis_context * gen, char *fname, uint32_t m68k_pc)
467+{
468+	char buffer[4096];
469+	FILE * gstfile = fopen(fname, "wb");
470+	if (!gstfile) {
471+		fprintf(stderr, "Could not open %s for writing\n", fname);
472+		goto error;
473+	}
474+	if (fwrite("GST\x40\xE0", 1, 5, gstfile) != 5) {
475+		fputs("Error writing signature to savestate\n", stderr);
476+		goto error_close;
477+	}
478+	if (!m68k_save_gst(gen->m68k, m68k_pc, gstfile)) {
479+		goto error_close;
480+	}
481+	if (!z80_save_gst(gen->z80, gstfile)) {
482+		goto error_close;
483+	}
484+	if (!vdp_save_gst(gen->vdp, gstfile)) {
485+		goto error_close;
486+	}
487+	if (!ym_save_gst(gen->ym, gstfile)) {
488+		goto error_close;
489+	}
490+	fseek(gstfile, GST_68K_RAM, SEEK_SET);
491+	for (int i = 0; i < (32*1024);) {
492+		for(char *curpos = buffer; curpos < (buffer + sizeof(buffer)); curpos += sizeof(uint16_t)) {
493+			write_be_16(curpos, gen->work_ram[i++]);
494+		}
495+		if (fwrite(buffer, 1, sizeof(buffer), gstfile) != sizeof(buffer)) {
496+			fputs("Failed to write 68K RAM to savestate\n", stderr);
497+			return 0;
498+		}
499+	}
500+	return 1;
501+
502+error_close:
503+	fclose(gstfile);
504+error:
505+	return 0;
506+}
A gst.h
+13, -0
 1@@ -0,0 +1,13 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm. 
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef GST_H_
 8+#define GST_H_
 9+#include "blastem.h"
10+
11+uint8_t save_gst(genesis_context * gen, char *fname, uint32_t m68k_pc);
12+uint32_t load_gst(genesis_context * gen, char * fname);
13+
14+#endif //GST_H_
A hash.c
+101, -0
  1@@ -0,0 +1,101 @@
  2+#include <stdint.h>
  3+#include <string.h>
  4+
  5+//NOTE: This is only intended for use in file identification
  6+//Please do not use this in a cryptographic setting as no attempts have been
  7+//made at avoiding side channel attacks
  8+
  9+static uint32_t rotleft(uint32_t val, uint32_t shift)
 10+{
 11+	return val << shift | val >> (32-shift);
 12+}
 13+
 14+static void sha1_step(uint32_t *state, uint32_t f, uint32_t k, uint32_t w)
 15+{
 16+	uint32_t tmp = rotleft(state[0], 5) + f + state[4] + k + w;
 17+	state[4] = state[3];
 18+	state[3] = state[2];
 19+	state[2] = rotleft(state[1], 30);
 20+	state[1] = state[0];
 21+	state[0] = tmp;
 22+}
 23+
 24+static void sha1_chunk(uint8_t *chunk, uint32_t *hash)
 25+{
 26+	uint32_t state[5], w[80];
 27+	memcpy(state, hash, sizeof(state));
 28+	for (uint32_t src = 0; src < 64; src += 4)
 29+	{
 30+		w[src >> 2] = chunk[src] << 24 | chunk[src+1] << 16 | chunk[src+2] << 8 | chunk[src+3];
 31+	}
 32+	for (uint32_t cur = 16; cur < 80; cur++)
 33+	{
 34+		w[cur] = rotleft(w[cur-3] ^ w[cur-8] ^ w[cur-14] ^ w[cur-16], 1);
 35+	}
 36+	for (uint32_t cur = 0; cur < 20; cur++)
 37+	{
 38+		sha1_step(state, (state[1] & state[2]) | ((~state[1]) & state[3]), 0x5A827999, w[cur]);
 39+	}
 40+	for (uint32_t cur = 20; cur < 40; cur++)
 41+	{
 42+		sha1_step(state, state[1] ^ state[2] ^ state[3], 0x6ED9EBA1, w[cur]);
 43+	}
 44+	for (uint32_t cur = 40; cur < 60; cur++)
 45+	{
 46+		sha1_step(state, (state[1] & state[2]) | (state[1] & state[3]) | (state[2] & state[3]), 0x8F1BBCDC, w[cur]);
 47+	}
 48+	for (uint32_t cur = 60; cur < 80; cur++)
 49+	{
 50+		sha1_step(state, state[1] ^ state[2] ^ state[3], 0xCA62C1D6, w[cur]);
 51+	}
 52+	for (uint32_t i = 0; i < 5; i++)
 53+	{
 54+		hash[i] += state[i];
 55+	}
 56+}
 57+
 58+void sha1(uint8_t *data, uint64_t size, uint8_t *out)
 59+{
 60+	uint32_t hash[5] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0};
 61+	uint8_t last[128];
 62+	uint32_t last_size = 0;
 63+	if ((size & 63) != 0) {
 64+		for (uint32_t src = size - (size & 63); src < size; src++)
 65+		{
 66+			last[last_size++] = data[src];
 67+		}
 68+	}
 69+	uint64_t bitsize = size * 8;
 70+	size -= last_size;
 71+	last[last_size++] = 0x80;
 72+	while ((last_size & 63) != 56)
 73+	{
 74+		last[last_size++] = 0;
 75+	}
 76+	
 77+	last[last_size++] = bitsize >> 56;
 78+	last[last_size++] = bitsize >> 48;
 79+	last[last_size++] = bitsize >> 40;
 80+	last[last_size++] = bitsize >> 32;
 81+	last[last_size++] = bitsize >> 24;
 82+	last[last_size++] = bitsize >> 16;
 83+	last[last_size++] = bitsize >> 8;
 84+	last[last_size++] = bitsize;
 85+	
 86+	for (uint64_t cur = 0; cur < size; cur += 64)
 87+	{
 88+		sha1_chunk(data + cur, hash);
 89+	}
 90+	for (uint64_t cur = 0; cur < last_size; cur += 64)
 91+	{
 92+		sha1_chunk(last + cur, hash);
 93+	}
 94+	for (uint32_t cur = 0; cur < 20; cur += 4)
 95+	{
 96+		uint32_t val = hash[cur >> 2];
 97+		out[cur] = val >> 24;
 98+		out[cur+1] = val >> 16;
 99+		out[cur+2] = val >> 8;
100+		out[cur+3] = val;
101+	}
102+}
A hash.h
+12, -0
 1@@ -0,0 +1,12 @@
 2+#ifndef HASH_H_
 3+#define HASH_H_
 4+
 5+#include <stdint.h>
 6+
 7+//NOTE: This is only intended for use in file identification
 8+//Please do not use this in a cryptographic setting as no attempts have been
 9+//made at avoiding side channel attacks
10+
11+void sha1(uint8_t *data, uint64_t size, uint8_t *out);
12+
13+#endif //HASH_H_
A i2c.c
+250, -0
  1@@ -0,0 +1,250 @@
  2+#include "genesis.h"
  3+#include "util.h"
  4+
  5+enum {
  6+	I2C_IDLE,
  7+	I2C_START,
  8+	I2C_DEVICE_ACK,
  9+	I2C_ADDRESS_HI,
 10+	I2C_ADDRESS_HI_ACK,
 11+	I2C_ADDRESS,
 12+	I2C_ADDRESS_ACK,
 13+	I2C_READ,
 14+	I2C_READ_ACK,
 15+	I2C_WRITE,
 16+	I2C_WRITE_ACK
 17+};
 18+
 19+char * i2c_states[] = {
 20+	"idle",
 21+	"start",
 22+	"device ack",
 23+	"address hi",
 24+	"address hi ack",
 25+	"address",
 26+	"address ack",
 27+	"read",
 28+	"read_ack",
 29+	"write",
 30+	"write_ack"
 31+};
 32+
 33+void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size)
 34+{
 35+	state->slave_sda = 1;
 36+	state->host_sda = state->scl = 0;
 37+	state->buffer = buffer;
 38+	state->size = size;
 39+	state->state = I2C_IDLE;
 40+}
 41+
 42+void set_host_sda(eeprom_state *state, uint8_t val)
 43+{
 44+	if (state->scl) {
 45+		if (val & ~state->host_sda) {
 46+			//low to high, stop condition
 47+			state->state = I2C_IDLE;
 48+			state->slave_sda = 1;
 49+		} else if (~val & state->host_sda) {
 50+			//high to low, start condition
 51+			state->state = I2C_START;
 52+			state->slave_sda = 1;
 53+			state->counter = 8;
 54+		}
 55+	}
 56+	state->host_sda = val;
 57+}
 58+
 59+void set_scl(eeprom_state *state, uint8_t val)
 60+{
 61+	if (val & ~state->scl) {
 62+		//low to high transition
 63+		switch (state->state)
 64+		{
 65+		case I2C_START:
 66+		case I2C_ADDRESS_HI:
 67+		case I2C_ADDRESS:
 68+		case I2C_WRITE:
 69+			state->latch = state->host_sda | state->latch << 1;
 70+			state->counter--;
 71+			if (!state->counter) {
 72+				switch (state->state & 0x7F)
 73+				{
 74+				case I2C_START:
 75+					state->state = I2C_DEVICE_ACK;
 76+					break;
 77+				case I2C_ADDRESS_HI:
 78+					state->address = state->latch << 8;
 79+					state->state = I2C_ADDRESS_HI_ACK;
 80+					break;
 81+				case I2C_ADDRESS:
 82+					state->address |= state->latch;
 83+					state->state = I2C_ADDRESS_ACK;
 84+					break;
 85+				case I2C_WRITE:
 86+					state->buffer[state->address] = state->latch;
 87+					state->state = I2C_WRITE_ACK;
 88+					break;
 89+				}
 90+			}
 91+			break;
 92+		case I2C_DEVICE_ACK:
 93+			if (state->latch & 1) {
 94+				state->state = I2C_READ;
 95+				state->counter = 8;
 96+				if (state->size < 256) {
 97+					state->address = state->latch >> 1;
 98+				}
 99+				state->latch = state->buffer[state->address];
100+			} else {
101+				if (state->size < 256) {
102+					state->address = state->latch >> 1;
103+					state->state = I2C_WRITE;
104+				} else if (state->size < 4096) {
105+					state->address = (state->latch & 0xE) << 7;
106+					state->state = I2C_ADDRESS;
107+				} else {
108+					state->state = I2C_ADDRESS_HI;
109+				}
110+				state->counter = 8;
111+			}
112+			break;
113+		case I2C_ADDRESS_HI_ACK:
114+			state->state = I2C_ADDRESS;
115+			state->counter = 8;
116+			break;
117+		case I2C_ADDRESS_ACK:
118+			state->state = I2C_WRITE;
119+			state->address &= state->size-1;
120+			state->counter = 8;
121+			break;
122+		case I2C_READ:
123+			state->counter--;
124+			if (!state->counter) {
125+				state->state = I2C_READ_ACK;
126+			}
127+			break;
128+		case I2C_READ_ACK:
129+			state->state = I2C_READ;
130+			state->counter = 8;
131+			state->address++;
132+			//TODO: page mask
133+			state->address &= state->size-1;
134+			state->latch = state->buffer[state->address];
135+			break;
136+		case I2C_WRITE_ACK:
137+			state->state = I2C_WRITE;
138+			state->counter = 8;
139+			state->address++;
140+			//TODO: page mask
141+			state->address &= state->size-1;
142+			break;
143+		}
144+	} else if (~val & state->scl) {
145+		//high to low transition
146+		switch (state->state & 0x7F)
147+		{
148+		case I2C_DEVICE_ACK:
149+		case I2C_ADDRESS_HI_ACK:
150+		case I2C_ADDRESS_ACK:
151+		case I2C_READ_ACK:
152+		case I2C_WRITE_ACK:
153+			state->slave_sda = 0;
154+			break;
155+		case I2C_READ:
156+			state->slave_sda = state->latch >> 7;
157+			state->latch = state->latch << 1;
158+			break;
159+		default:
160+			state->slave_sda = 1;
161+			break;
162+		}
163+	}
164+	state->scl = val;
165+}
166+
167+uint8_t get_sda(eeprom_state *state)
168+{
169+	return state->host_sda & state->slave_sda;
170+}
171+
172+eeprom_map *find_eeprom_map(uint32_t address, genesis_context *gen)
173+{
174+	for (int i = 0; i < gen->num_eeprom; i++)
175+	{
176+		if (address >= gen->eeprom_map[i].start && address <= gen->eeprom_map[i].end) {
177+			return  gen->eeprom_map + i;
178+		}
179+	}
180+	return NULL;
181+}
182+
183+void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value)
184+{
185+	genesis_context *gen = ((m68k_context *)context)->system;
186+	eeprom_map *map = find_eeprom_map(address, gen);
187+	if (!map) {
188+		fatal_error("Could not find EEPROM map for address %X\n", address);
189+	}
190+	if (map->scl_mask) {
191+		set_scl(&gen->eeprom, (value & map->scl_mask) != 0);
192+	}
193+	if (map->sda_write_mask) {
194+		set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0);
195+	}
196+	return context;
197+}
198+
199+void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value)
200+{
201+	genesis_context *gen = ((m68k_context *)context)->system;
202+	eeprom_map *map = find_eeprom_map(address, gen);
203+	if (!map) {
204+		fatal_error("Could not find EEPROM map for address %X\n", address);
205+	}
206+
207+	uint16_t expanded, mask;
208+	if (address & 1) {
209+		expanded = value;
210+		mask = 0xFF;
211+	} else {
212+		expanded = value << 8;
213+		mask = 0xFF00;
214+	}
215+	if (map->scl_mask & mask) {
216+		set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0);
217+	}
218+	if (map->sda_write_mask & mask) {
219+		set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0);
220+	}
221+	return context;
222+}
223+
224+uint16_t read_eeprom_i2c_w(uint32_t address, void * context)
225+{
226+	genesis_context *gen = ((m68k_context *)context)->system;
227+	eeprom_map *map = find_eeprom_map(address, gen);
228+	if (!map) {
229+		fatal_error("Could not find EEPROM map for address %X\n", address);
230+	}
231+	uint16_t ret = 0;
232+	if (map->sda_read_bit < 16) {
233+		ret = get_sda(&gen->eeprom) << map->sda_read_bit;
234+	}
235+	return ret;	
236+}
237+
238+uint8_t read_eeprom_i2c_b(uint32_t address, void * context)
239+{
240+	genesis_context *gen = ((m68k_context *)context)->system;
241+	eeprom_map *map = find_eeprom_map(address, gen);
242+	if (!map) {
243+		fatal_error("Could not find EEPROM map for address %X\n", address);
244+	}
245+	uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8;
246+	uint8_t ret = 0;
247+	if (bit < 8) {
248+		ret = get_sda(&gen->eeprom) << bit;
249+	}
250+	return ret;
251+}
A i2c.h
+22, -0
 1@@ -0,0 +1,22 @@
 2+#ifndef I2C_H_
 3+#define I2C_H_
 4+
 5+typedef struct {
 6+	char        *buffer;
 7+	uint32_t    size;
 8+	uint16_t    address;
 9+	uint8_t     host_sda;
10+	uint8_t     slave_sda;
11+	uint8_t     scl;
12+	uint8_t     state;
13+	uint8_t     counter;
14+	uint8_t     latch;
15+} eeprom_state;
16+
17+void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size);
18+void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value);
19+void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value);
20+uint16_t read_eeprom_i2c_w(uint32_t address, void * context);
21+uint8_t read_eeprom_i2c_b(uint32_t address, void * context);
22+
23+#endif //I2C_H_
+316, -0
  1@@ -0,0 +1,316 @@
  2+#!/usr/bin/env python
  3+from PIL import Image
  4+
  5+def gchannel(Val):
  6+	return (Val >> 4) & 0xE
  7+
  8+threshold = 127
  9+
 10+def get_rgba(im, pixels=None, idx=None, color=None):
 11+	A = 255
 12+	if color is None:
 13+		color = pixels[idx]
 14+	if type(color) == int:
 15+		R, G, B = im.getpalette()[color*3:color*3+3]
 16+	else:
 17+		if len(color) == 4:
 18+			R, G, B, A = color
 19+		elif len(color) == 3:
 20+			R, G, B = color
 21+		else:
 22+			L, A = color
 23+			R = G = B = L
 24+	return (R, G, B, A)
 25+
 26+def get_gcolor(im, threshold, pixels=None, idx=None, color=None):
 27+	R,G,B,A = get_rgba(im, pixels, idx, color)
 28+	if A > threshold:
 29+		return (gchannel(R), gchannel(G), gchannel(B))
 30+	return 0
 31+
 32+def get_color_info(im, pixels, rng, threshold, exclude={}):
 33+	gencolors = {}
 34+	A = 255
 35+	pal = None
 36+	transparent = False
 37+	for idx in rng:
 38+		gcolor = get_gcolor(im, threshold, pixels, idx)
 39+		if type(gcolor) == tuple:
 40+			if not gcolor in exclude:
 41+				if gcolor in gencolors:
 42+					gencolors[gcolor] += 1
 43+				else:
 44+					gencolors[gcolor] = 1
 45+		else:
 46+			transparent = True
 47+	glist = [(gencolors[color], color) for color in gencolors]
 48+	glist.sort()
 49+	glist.reverse()
 50+	return glist
 51+
 52+def get_color_info_both(im, pixels, rng, threshold, exclude={}):
 53+	gencolors = {}
 54+	A = 255
 55+	pal = None
 56+	transparent = False
 57+	for idx in rng:
 58+		gcolor = get_gcolor(im, threshold, pixels, idx)
 59+		if type(gcolor) == tuple:
 60+			if not gcolor in exclude:
 61+				if not gcolor in gencolors:
 62+					_,best = best_match(gcolor, (exclude,))
 63+					gencolors[gcolor] = (color_dist(gcolor, best), 1)
 64+				else:
 65+					(dist, count) = gencolors[gcolor]
 66+					gencolors[gcolor] = (dist, count+1)
 67+		else:
 68+			transparent = True
 69+	glist = [(gencolors[color][0] * gencolors[color][1], color) for color in gencolors]
 70+	glist.sort()
 71+	glist.reverse()
 72+	
 73+	return glist
 74+
 75+def make_palette(im, trans_thresh, max_global, max_line):
 76+	pixels = im.getdata()
 77+	(width, height) = im.size
 78+	colors = get_color_info(im, pixels, xrange(0, height * width), trans_thresh)
 79+	print len(colors), 'distinct 9-bit colors in image'
 80+	glob_pal = {}
 81+	print 'Static Palette:'
 82+	while len(glob_pal) < max_global and len(colors):
 83+		idx = len(glob_pal)
 84+		(count, color) = colors[0]
 85+		print str(idx) + ':', color
 86+		glob_pal[color] = idx
 87+		colors = get_color_info_both(im, pixels, xrange(0, height * width), trans_thresh, glob_pal)
 88+	line_pals = []
 89+	if max_global < len(colors):
 90+		for line in xrange(0, height):
 91+			linestart = line * width
 92+			if len(glob_pal):
 93+				linecolors = get_color_info_both(im, pixels, xrange(linestart, linestart+width), trans_thresh, glob_pal)
 94+			else:
 95+				linecolors = get_color_info(im, pixels, xrange(linestart, linestart+width), trans_thresh)
 96+			line_pal = {}
 97+			while len(line_pal) < max_line and len(linecolors):
 98+				(score, color) = linecolors[0]
 99+				line_pal[color] = len(line_pal) + max_global
100+				if len(line_pal) < max_line:
101+					combo = dict(glob_pal)
102+					for color in line_pal:
103+						combo[color] = line_pal[color]
104+					linecolors = get_color_info_both(im, pixels, xrange(linestart, linestart+width), trans_thresh, combo)
105+			#for idx in xrange(0, min(max_line, len(linecolors))):
106+			#	(count, color) = linecolors[idx]
107+			#	line_pal[color] = idx + max_global
108+			line_pals.append(line_pal)
109+	return (glob_pal, line_pals, max_global, max_line)
110+
111+def color_dist(a, b):
112+	(ra, ga, ba) = a
113+	(rb, gb, bb) = b
114+	return (ra-rb)**2 + (ga-gb)**2 + (ba-bb)**2
115+
116+def best_match(gpixel, pals):
117+	bestdist = color_dist((0,0,0), (15, 15, 15))
118+	bestpalidx = 0
119+	bestcolor = (0,0,0)
120+	for i in xrange(0, len(pals)):
121+		pal = pals[i]
122+		for cur in pal:
123+			curdist = color_dist(gpixel, cur)
124+			if curdist < bestdist:
125+				bestdist = curdist
126+				bestpalidx = pal[cur]
127+				bestcolor = cur
128+	return (bestpalidx, bestcolor)
129+
130+def trans_image(im, trans_thresh, pal, chunky):
131+	(global_pal, line_pals, _, _) = pal
132+	pixels = im.getdata()
133+	(width, height) = im.size
134+	gpixels = []
135+	A = 255
136+	pal = None
137+	x = 0
138+	y = 0
139+	numchannels = len(im.getbands())
140+	offset = 1 if numchannels == 4 or numchannels == 2 else 0
141+	for pixel in pixels:
142+		if x == width:
143+			x = 0
144+			y += 1
145+			if width % 8 and not chunky:
146+				for i in xrange(0, 8-(width%8)):
147+					gpixels.append(0)
148+		gpixel = get_gcolor(im, trans_thresh, color=pixel)
149+		if type(gpixel) == tuple:
150+			if gpixel in global_pal:
151+				val = global_pal[gpixel]
152+			elif gpixel in line_pals[y]:
153+				val = line_pals[y][gpixel]
154+			else:
155+				bestpal,color = best_match(gpixel, (global_pal, line_pals[y]))
156+				val = bestpal
157+			gpixels.append(offset+val)
158+		else:
159+			gpixels.append(gpixel)
160+		x += 1
161+	if width % 8 and not chunky:
162+		for i in xrange(0, 8-(width%8)):
163+			gpixels.append(0)
164+		width += 8-(width%8)
165+	if height % 8 and not chunky:
166+		for y in xrange(0, 8-(height%8)):
167+			for x in xrange(0, width):
168+				gpixels.append(0)
169+		height += 8-(height%8)
170+
171+	return (width, height, gpixels)
172+
173+def appendword(b, word):
174+	b.append(word >> 8)
175+	b.append(word & 0xff)
176+
177+def to_tiles(palpix, raw=False, chunky=False, tile_height=8, sprite_order = False):
178+	(width, height, pixels) = palpix
179+	b = bytearray()
180+	if chunky:
181+		if not raw:
182+			appendword(b, width)
183+			appendword(b, height)
184+		for pixel in pixels:
185+			b.append(pixel)
186+	else:
187+		cwidth = width/8
188+		cheight = height/tile_height
189+		words = len(pixels)/4
190+		if not raw:
191+			appendword(b, words)
192+			appendword(b, cwidth)
193+			appendword(b, cheight)
194+
195+		if sprite_order:
196+			for cx in xrange(0, cwidth):
197+				xstart = cx * 8
198+				for cy in xrange(0, cheight):
199+					startoff = cy*tile_height*width + xstart
200+					for row in xrange(0, tile_height):
201+						rowoff = startoff + row*width
202+						for bytecol in xrange(0, 4):
203+							boff = bytecol * 2 + rowoff
204+							#print 'boff:', boff, 'len(pixels)', len(pixels), 'cx', cx, 'cy', cy, 'cwidth', cwidth, 'cheight', cheight
205+							#print 'pixels[boff]:', pixels[boff]
206+							b.append(pixels[boff] << 4 | pixels[boff+1])
207+		else:
208+			for cy in xrange(0, cheight):
209+				ystart = cy*tile_height*width
210+				for cx in xrange(0, cwidth):
211+					startoff = (cx*8) + ystart
212+					for row in xrange(0, tile_height):
213+						rowoff = startoff + row*width
214+						for bytecol in xrange(0, 4):
215+							boff = bytecol * 2 + rowoff
216+							#print 'boff:', boff, 'len(pixels)', len(pixels), 'cx', cx, 'cy', cy, 'cwidth', cwidth, 'cheight', cheight
217+							#print 'pixels[boff]:', pixels[boff]
218+							b.append(pixels[boff] << 4 | pixels[boff+1])
219+	return b
220+
221+def add_pal_entries(tiles, pal):
222+	(global_pal, line_pals, max_global, max_line) = pal
223+	tiles.append(max_global)
224+	tiles.append(max_line)
225+	pal_list = [(0, 0, 0)] * max_global
226+	for entry in global_pal:
227+		pal_list[global_pal[entry]] = entry
228+	for entry in pal_list:
229+		(R, G, B) = entry
230+		tiles.append(B)
231+		tiles.append(G << 4 | R)
232+	for line in line_pals:
233+		pal_list = [(0, 0, 0)] * max_line
234+		for entry in line:
235+			pal_list[line[entry]-max_global] = entry
236+		for entry in pal_list:
237+			(R, G, B) = entry
238+			tiles.append(B)
239+			tiles.append(G << 4 | R)
240+
241+
242+
243+def main(argv):
244+
245+	posargs = []
246+	omit_pal = raw = chunky = False
247+	expect_option = None
248+	options = {}
249+	tile_height = 8
250+	sprite_order = False
251+	for i in xrange(1, len(argv)):
252+		if argv[i].startswith('-'):
253+			if argv[i] == '-r':
254+				raw = True
255+			elif argv[i] == '-p':
256+				omit_pal = True
257+			elif argv[i] == '-o':
258+				sprite_order = True
259+			elif argv[i] == '-c':
260+				chunky = True
261+			elif argv[i] == '-i':
262+				tile_height = 16
263+			elif argv[i] == '-s' or argv[i] == '--spec':
264+				expect_option = 'specfile'
265+			else:
266+				print 'Unrecognized switch', argv[i]
267+				return
268+		elif not expect_option is None:
269+			options[expect_option] = argv[i]
270+			expect_option = None
271+		else:
272+			posargs.append(argv[i])
273+	if len(posargs) < 2 and not ('specfile' in options and len(posargs) >= 1):
274+		print "Usage: img2tiles.py [OPTIONS] infile outfile [STATIC_COLORS [DYNAMIC_COLORS]]"
275+		return
276+	if 'specfile' in options:
277+		props = open(options['specfile']).read().strip().split(',')
278+		fname,static_colors,dynamic_colors = props[0:3]
279+		for prop in props[3:]:
280+			if prop == 'chunky':
281+				chunky = True
282+			elif prop == 'raw':
283+				raw = True
284+			elif prop == 'nopal':
285+				omit_pal = True
286+			elif prop == 'interlace':
287+				tile_height = 16
288+			elif prop == 'sprite':
289+				sprite_order = True
290+		static_colors = int(static_colors)
291+		dynamic_colors = int(dynamic_colors)
292+		outfile = posargs[0]
293+	else:
294+		fname = posargs[0]
295+		outfile = posargs[1]
296+		static_colors = 8
297+		dynamic_colors = 8
298+		if len(posargs) > 2:
299+			static_colors = int(posargs[2])
300+			dynamic_colors = 16-static_colors
301+		if len(posargs) > 3:
302+			dynamic_colors = int(posargs[3])
303+	if dynamic_colors + static_colors > 16:
304+		print "No more than 16 combined dynamic and static colors are allowed"
305+		return
306+	im = Image.open(fname)
307+	pal = make_palette(im, threshold, static_colors, dynamic_colors)
308+	palpix = trans_image(im, threshold, pal, chunky)
309+	tiles = to_tiles(palpix, raw, chunky, tile_height, sprite_order)
310+	if not omit_pal:
311+		bits = add_pal_entries(tiles, pal)
312+	out = open(outfile, 'wb')
313+	out.write(tiles)
314+
315+if __name__ == '__main__':
316+	import sys
317+	main(sys.argv)
A io.c
+1107, -0
   1@@ -0,0 +1,1107 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include <unistd.h>
   8+#include <fcntl.h>
   9+#include <sys/socket.h>
  10+#include <sys/un.h>
  11+#include <sys/types.h>
  12+#include <sys/stat.h>
  13+#include <errno.h>
  14+#include <string.h>
  15+#include <stdlib.h>
  16+
  17+#include "serialize.h"
  18+#include "io.h"
  19+#include "blastem.h"
  20+#include "render.h"
  21+#include "util.h"
  22+#include "bindings.h"
  23+
  24+#define CYCLE_NEVER 0xFFFFFFFF
  25+#define MIN_POLL_INTERVAL 6840
  26+
  27+const char * device_type_names[] = {
  28+	"None",
  29+	"SMS gamepad",
  30+	"3-button gamepad",
  31+	"6-button gamepad",
  32+	"Mega Mouse",
  33+	"Saturn Keyboard",
  34+	"XBAND Keyboard",
  35+	"Menacer",
  36+	"Justifier",
  37+	"Sega multi-tap",
  38+	"EA 4-way Play cable A",
  39+	"EA 4-way Play cable B",
  40+	"Sega Parallel Transfer Board",
  41+	"Generic Device"
  42+};
  43+
  44+#define GAMEPAD_TH0 0
  45+#define GAMEPAD_TH1 1
  46+#define GAMEPAD_EXTRA 2
  47+#define GAMEPAD_NONE 0xF
  48+
  49+#define IO_TH0 0
  50+#define IO_TH1 1
  51+#define IO_STATE 2
  52+
  53+enum {
  54+	IO_WRITE_PENDING,
  55+	IO_WRITTEN,
  56+	IO_READ_PENDING,
  57+	IO_READ
  58+};
  59+
  60+typedef struct {
  61+	uint8_t states[2], value;
  62+} gp_button_def;
  63+
  64+
  65+static gp_button_def button_defs[NUM_GAMEPAD_BUTTONS] = {
  66+	[DPAD_UP] = {.states = {GAMEPAD_TH0, GAMEPAD_TH1}, .value = 0x1},
  67+	[DPAD_DOWN] = {.states = {GAMEPAD_TH0, GAMEPAD_TH1}, .value = 0x2},
  68+	[DPAD_LEFT] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x4},
  69+	[DPAD_RIGHT] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x8},
  70+	[BUTTON_A] = {.states = {GAMEPAD_TH0, GAMEPAD_NONE}, .value = 0x10},
  71+	[BUTTON_B] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x10},
  72+	[BUTTON_C] = {.states = {GAMEPAD_TH1, GAMEPAD_NONE}, .value = 0x20},
  73+	[BUTTON_START] = {.states = {GAMEPAD_TH0, GAMEPAD_NONE}, .value = 0x20},
  74+	[BUTTON_X] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x4},
  75+	[BUTTON_Y] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x2},
  76+	[BUTTON_Z] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x1},
  77+	[BUTTON_MODE] = {.states = {GAMEPAD_EXTRA, GAMEPAD_NONE}, .value = 0x8},
  78+};
  79+
  80+static io_port *find_gamepad(sega_io *io, uint8_t gamepad_num)
  81+{
  82+	for (int i = 0; i < 3; i++)
  83+	{
  84+		io_port *port = io->ports + i;
  85+		if (port->device_type < IO_MOUSE && port->device.pad.gamepad_num == gamepad_num) {
  86+			return port;
  87+		}
  88+	}
  89+	return NULL;
  90+}
  91+
  92+static io_port *find_mouse(sega_io *io, uint8_t mouse_num)
  93+{
  94+	for (int i = 0; i < 3; i++)
  95+	{
  96+		io_port *port = io->ports + i;
  97+		if (port->device_type == IO_MOUSE && port->device.mouse.mouse_num == mouse_num) {
  98+			return port;
  99+		}
 100+	}
 101+	return NULL;
 102+}
 103+
 104+static io_port *find_keyboard(sega_io *io)
 105+{
 106+	for (int i = 0; i < 3; i++)
 107+	{
 108+		io_port *port = io->ports + i;
 109+		if (port->device_type == IO_SATURN_KEYBOARD || port->device_type == IO_XBAND_KEYBOARD) {
 110+			return port;
 111+		}
 112+	}
 113+	return NULL;
 114+}
 115+
 116+void io_port_gamepad_down(io_port *port, uint8_t button)
 117+{
 118+	gp_button_def *def = button_defs + button;
 119+	port->input[def->states[0]] |= def->value;
 120+	if (def->states[1] != GAMEPAD_NONE) {
 121+		port->input[def->states[1]] |= def->value;
 122+	}
 123+}
 124+
 125+void io_port_gamepad_up(io_port *port, uint8_t button)
 126+{
 127+	gp_button_def *def = button_defs + button;
 128+	port->input[def->states[0]] &= ~def->value;
 129+	if (def->states[1] != GAMEPAD_NONE) {
 130+		port->input[def->states[1]] &= ~def->value;
 131+	}
 132+}
 133+
 134+void io_gamepad_down(sega_io *io, uint8_t gamepad_num, uint8_t button)
 135+{
 136+	io_port *port = find_gamepad(io, gamepad_num);
 137+	if (port) {
 138+		io_port_gamepad_down(port, button);
 139+	}
 140+}
 141+
 142+void io_gamepad_up(sega_io *io, uint8_t gamepad_num, uint8_t button)
 143+{
 144+	io_port *port = find_gamepad(io, gamepad_num);
 145+	if (port) {
 146+		io_port_gamepad_up(port, button);
 147+	}
 148+}
 149+
 150+void io_mouse_down(sega_io *io, uint8_t mouse_num, uint8_t button)
 151+{
 152+	io_port *port = find_mouse(io, mouse_num);
 153+	if (port) {
 154+		port->input[0] |= button;
 155+	}
 156+}
 157+
 158+void io_mouse_up(sega_io *io, uint8_t mouse_num, uint8_t button)
 159+{
 160+	io_port *port = find_mouse(io, mouse_num);
 161+	if (port) {
 162+		port->input[0] &= ~button;
 163+	}
 164+}
 165+
 166+void io_mouse_motion_absolute(sega_io *io, uint8_t mouse_num, uint16_t x, uint16_t y)
 167+{
 168+	io_port *port = find_mouse(io, mouse_num);
 169+	if (port) {
 170+		port->device.mouse.cur_x = x;
 171+		port->device.mouse.cur_y = y;
 172+	}
 173+}
 174+
 175+void io_mouse_motion_relative(sega_io *io, uint8_t mouse_num, int32_t x, int32_t y)
 176+{
 177+	io_port *port = find_mouse(io, mouse_num);
 178+	if (port) {
 179+		port->device.mouse.cur_x += x;
 180+		port->device.mouse.cur_y += y;
 181+	}
 182+}
 183+
 184+void store_key_event(io_port *keyboard_port, uint16_t code)
 185+{
 186+	if (keyboard_port && keyboard_port->device.keyboard.write_pos != keyboard_port->device.keyboard.read_pos) {
 187+		//there's room in the buffer, record this event
 188+		keyboard_port->device.keyboard.events[keyboard_port->device.keyboard.write_pos] = code;
 189+		if (keyboard_port->device.keyboard.read_pos == 0xFF) {
 190+			//ring buffer was empty, update read_pos to indicate there is now data
 191+			keyboard_port->device.keyboard.read_pos = keyboard_port->device.keyboard.write_pos;
 192+		}
 193+		keyboard_port->device.keyboard.write_pos = (keyboard_port->device.keyboard.write_pos + 1) & 7;
 194+	}
 195+}
 196+
 197+void io_keyboard_down(sega_io *io, uint8_t scancode)
 198+{
 199+	store_key_event(find_keyboard(io), scancode);
 200+}
 201+
 202+void io_keyboard_up(sega_io *io, uint8_t scancode)
 203+{
 204+	store_key_event(find_keyboard(io), 0xF000 | scancode);
 205+}
 206+
 207+uint8_t io_has_keyboard(sega_io *io)
 208+{
 209+	return find_keyboard(io) != NULL;
 210+}
 211+
 212+void process_device(char * device_type, io_port * port)
 213+{
 214+	//assuming that the io_port struct has been zeroed if this is the first time this has been called
 215+	if (!device_type)
 216+	{
 217+		return;
 218+	}
 219+
 220+	const int gamepad_len = strlen("gamepad");
 221+	if (startswith(device_type, "gamepad"))
 222+	{
 223+		if (
 224+			(device_type[gamepad_len] != '3' && device_type[gamepad_len] != '6' && device_type[gamepad_len] != '2')
 225+			|| device_type[gamepad_len+1] != '.' || device_type[gamepad_len+2] < '1'
 226+			|| device_type[gamepad_len+2] > '8' || device_type[gamepad_len+3] != 0
 227+		) {
 228+			warning("%s is not a valid gamepad type\n", device_type);
 229+		} else if (device_type[gamepad_len] == '3') {
 230+			port->device_type = IO_GAMEPAD3;
 231+		} else if (device_type[gamepad_len] == '2') {
 232+			port->device_type = IO_GAMEPAD2;
 233+		} else {
 234+			port->device_type = IO_GAMEPAD6;
 235+		}
 236+		port->device.pad.gamepad_num = device_type[gamepad_len+2] - '0';
 237+	} else if(startswith(device_type, "mouse")) {
 238+		if (port->device_type != IO_MOUSE) {
 239+			port->device_type = IO_MOUSE;
 240+			port->device.mouse.mouse_num = device_type[strlen("mouse")+1] - '0';
 241+			port->device.mouse.last_read_x = 0;
 242+			port->device.mouse.last_read_y = 0;
 243+			port->device.mouse.cur_x = 0;
 244+			port->device.mouse.cur_y = 0;
 245+			port->device.mouse.latched_x = 0;
 246+			port->device.mouse.latched_y = 0;
 247+			port->device.mouse.ready_cycle = CYCLE_NEVER;
 248+			port->device.mouse.tr_counter = 0;
 249+		}
 250+	} else if(!strcmp(device_type, "saturn keyboard")) {
 251+		if (port->device_type != IO_SATURN_KEYBOARD) {
 252+			port->device_type = IO_SATURN_KEYBOARD;
 253+			port->device.keyboard.read_pos = 0xFF;
 254+			port->device.keyboard.write_pos = 0;
 255+		}
 256+	} else if(!strcmp(device_type, "xband keyboard")) {
 257+		if (port->device_type != IO_XBAND_KEYBOARD) {
 258+			port->device_type = IO_XBAND_KEYBOARD;
 259+			port->device.keyboard.read_pos = 0xFF;
 260+			port->device.keyboard.write_pos = 0;
 261+		}
 262+	} else if(!strcmp(device_type, "sega_parallel")) {
 263+		if (port->device_type != IO_SEGA_PARALLEL) {
 264+			port->device_type = IO_SEGA_PARALLEL;
 265+			port->device.stream.data_fd = -1;
 266+			port->device.stream.listen_fd = -1;
 267+		}
 268+	} else if(!strcmp(device_type, "generic")) {
 269+		if (port->device_type != IO_GENERIC) {
 270+			port->device_type = IO_GENERIC;
 271+			port->device.stream.data_fd = -1;
 272+			port->device.stream.listen_fd = -1;
 273+		}
 274+	}
 275+}
 276+
 277+char * io_name(int i)
 278+{
 279+	switch (i)
 280+	{
 281+	case 0:
 282+		return "1";
 283+	case 1:
 284+		return "2";
 285+	case 2:
 286+		return "EXT";
 287+	default:
 288+		return "invalid";
 289+	}
 290+}
 291+
 292+static char * sockfile_name;
 293+static void cleanup_sockfile()
 294+{
 295+	unlink(sockfile_name);
 296+}
 297+
 298+void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
 299+{
 300+	io_port * ports = io->ports;
 301+	tern_node *io_nodes = tern_find_path(config, "io\0devices\0", TVAL_NODE).ptrval;
 302+	char * io_1 = rom->port1_override ? rom->port1_override : tern_find_ptr_default(io_nodes, "1", "gamepad6.1");
 303+	char * io_2 = rom->port2_override ? rom->port2_override : tern_find_ptr_default(io_nodes, "2", "gamepad6.2");
 304+	char * io_ext = rom->ext_override ? rom->ext_override : tern_find_ptr(io_nodes, "ext");
 305+
 306+	process_device(io_1, ports);
 307+	process_device(io_2, ports+1);
 308+	process_device(io_ext, ports+2);
 309+
 310+	uint8_t mouse_mode;
 311+	if (ports[0].device_type == IO_MOUSE || ports[1].device_type == IO_MOUSE || ports[2].device_type == IO_MOUSE) {
 312+		if (rom->mouse_mode && !strcmp(rom->mouse_mode, "absolute")) {
 313+			mouse_mode = MOUSE_ABSOLUTE;
 314+		} else {
 315+			mouse_mode = MOUSE_CAPTURE;
 316+		}
 317+	} else {
 318+		mouse_mode = MOUSE_NONE;
 319+	}
 320+	bindings_set_mouse_mode(mouse_mode);
 321+
 322+	for (int i = 0; i < 3; i++)
 323+	{
 324+		if (ports[i].device_type == IO_SEGA_PARALLEL && ports[i].device.stream.data_fd == -1)
 325+		{
 326+			char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0", TVAL_PTR).ptrval;
 327+			if (!pipe_name)
 328+			{
 329+				warning("IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
 330+				ports[i].device_type = IO_NONE;
 331+			} else {
 332+				debug_message("IO port: %s connected to device '%s' with pipe name: %s\n", io_name(i), device_type_names[ports[i].device_type], pipe_name);
 333+				if (!strcmp("stdin", pipe_name))
 334+				{
 335+					ports[i].device.stream.data_fd = STDIN_FILENO;
 336+				} else {
 337+					if (mkfifo(pipe_name, 0666) && errno != EEXIST)
 338+					{
 339+						warning("Failed to create fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
 340+						ports[i].device_type = IO_NONE;
 341+					} else {
 342+						ports[i].device.stream.data_fd = open(pipe_name, O_NONBLOCK | O_RDONLY);
 343+						if (ports[i].device.stream.data_fd == -1)
 344+						{
 345+							warning("Failed to open fifo %s for Sega parallel board emulation: %d %s\n", pipe_name, errno, strerror(errno));
 346+							ports[i].device_type = IO_NONE;
 347+						}
 348+					}
 349+				}
 350+			}
 351+		} else if (ports[i].device_type == IO_GENERIC && ports[i].device.stream.data_fd == -1) {
 352+			char *sock_name = tern_find_path(config, "io\0socket\0", TVAL_PTR).ptrval;
 353+			if (!sock_name)
 354+			{
 355+				warning("IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
 356+				ports[i].device_type = IO_NONE;
 357+			} else {
 358+				debug_message("IO port: %s connected to device '%s' with socket name: %s\n", io_name(i), device_type_names[ports[i].device_type], sock_name);
 359+				ports[i].device.stream.data_fd = -1;
 360+				ports[i].device.stream.listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
 361+				size_t pathlen = strlen(sock_name);
 362+				size_t addrlen = offsetof(struct sockaddr_un, sun_path) + pathlen + 1;
 363+				struct sockaddr_un *saddr = malloc(addrlen);
 364+				saddr->sun_family = AF_UNIX;
 365+				memcpy(saddr->sun_path, sock_name, pathlen+1);
 366+				if (bind(ports[i].device.stream.listen_fd, (struct sockaddr *)saddr, addrlen))
 367+				{
 368+					warning("Failed to bind socket for IO Port %s to path %s: %d %s\n", io_name(i), sock_name, errno, strerror(errno));
 369+					goto cleanup_sock;
 370+				}
 371+				if (listen(ports[i].device.stream.listen_fd, 1))
 372+				{
 373+					warning("Failed to listen on socket for IO Port %s: %d %s\n", io_name(i), errno, strerror(errno));
 374+					goto cleanup_sockfile;
 375+				}
 376+				sockfile_name = sock_name;
 377+				atexit(cleanup_sockfile);
 378+				continue;
 379+cleanup_sockfile:
 380+				unlink(sock_name);
 381+cleanup_sock:
 382+				close(ports[i].device.stream.listen_fd);
 383+				ports[i].device_type = IO_NONE;
 384+			}
 385+		} else
 386+		if (ports[i].device_type == IO_GAMEPAD3 || ports[i].device_type == IO_GAMEPAD6 || ports[i].device_type == IO_GAMEPAD2) {
 387+			debug_message("IO port %s connected to gamepad #%d with type '%s'\n", io_name(i), ports[i].device.pad.gamepad_num, device_type_names[ports[i].device_type]);
 388+		} else {
 389+			debug_message("IO port %s connected to device '%s'\n", io_name(i), device_type_names[ports[i].device_type]);
 390+		}
 391+	}
 392+}
 393+
 394+
 395+#define TH 0x40
 396+#define TR 0x20
 397+#define TH_TIMEOUT 56000
 398+
 399+void mouse_check_ready(io_port *port, uint32_t current_cycle)
 400+{
 401+	if (current_cycle >= port->device.mouse.ready_cycle) {
 402+		port->device.mouse.tr_counter++;
 403+		port->device.mouse.ready_cycle = CYCLE_NEVER;
 404+		if (port->device.mouse.tr_counter == 3) {
 405+			port->device.mouse.latched_x = port->device.mouse.cur_x;
 406+			port->device.mouse.latched_y = port->device.mouse.cur_y;
 407+			/* FIXME mouse mode owned by bindings now
 408+			if (current_io->mouse_mode == MOUSE_ABSOLUTE) {
 409+				//avoid overflow in absolute mode
 410+				int deltax = port->device.mouse.latched_x - port->device.mouse.last_read_x;
 411+				if (abs(deltax) > 255) {
 412+					port->device.mouse.latched_x = port->device.mouse.last_read_x + (deltax > 0 ? 255 : -255);
 413+				}
 414+				int deltay = port->device.mouse.latched_y - port->device.mouse.last_read_y;
 415+				if (abs(deltay) > 255) {
 416+					port->device.mouse.latched_y = port->device.mouse.last_read_y + (deltay > 0 ? 255 : -255);
 417+				}
 418+			}*/
 419+		}
 420+	}
 421+}
 422+
 423+uint32_t last_poll_cycle;
 424+void io_adjust_cycles(io_port * port, uint32_t current_cycle, uint32_t deduction)
 425+{
 426+	/*uint8_t control = pad->control | 0x80;
 427+	uint8_t th = control & pad->output;
 428+	if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
 429+		printf("adjust_cycles | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, current_cycle);
 430+	}*/
 431+	if (port->device_type == IO_GAMEPAD6)
 432+	{
 433+		if (current_cycle >= port->device.pad.timeout_cycle)
 434+		{
 435+			port->device.pad.th_counter = 0;
 436+		} else {
 437+			port->device.pad.timeout_cycle -= deduction;
 438+		}
 439+	} else if (port->device_type == IO_MOUSE) {
 440+		mouse_check_ready(port, current_cycle);
 441+		if (port->device.mouse.ready_cycle != CYCLE_NEVER) {
 442+			port->device.mouse.ready_cycle -= deduction;
 443+		}
 444+	}
 445+	for (int i = 0; i < 8; i++)
 446+	{
 447+		if (port->slow_rise_start[i] != CYCLE_NEVER) {
 448+			if (port->slow_rise_start[i] >= deduction) {
 449+				port->slow_rise_start[i] -= deduction;
 450+			} else {
 451+				port->slow_rise_start[i] = CYCLE_NEVER;
 452+			}
 453+		}
 454+	}
 455+	if (last_poll_cycle >= deduction) {
 456+		last_poll_cycle -= deduction;
 457+	} else {
 458+		last_poll_cycle = 0;
 459+	}
 460+}
 461+
 462+static void wait_for_connection(io_port * port)
 463+{
 464+	if (port->device.stream.data_fd == -1)
 465+	{
 466+		debug_message("Waiting for socket connection...");
 467+		port->device.stream.data_fd = accept(port->device.stream.listen_fd, NULL, NULL);
 468+		fcntl(port->device.stream.data_fd, F_SETFL, O_NONBLOCK | O_RDWR);
 469+	}
 470+}
 471+
 472+static void service_pipe(io_port * port)
 473+{
 474+	uint8_t value;
 475+	int numRead = read(port->device.stream.data_fd, &value, sizeof(value));
 476+	if (numRead > 0)
 477+	{
 478+		port->input[IO_TH0] = (value & 0xF) | 0x10;
 479+		port->input[IO_TH1] = (value >> 4) | 0x10;
 480+	} else if(numRead == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
 481+		warning("Error reading pipe for IO port: %d %s\n", errno, strerror(errno));
 482+	}
 483+}
 484+
 485+static void service_socket(io_port *port)
 486+{
 487+	uint8_t buf[32];
 488+	uint8_t blocking = 0;
 489+	int numRead = 0;
 490+	while (numRead <= 0)
 491+	{
 492+		numRead = recv(port->device.stream.data_fd, buf, sizeof(buf), 0);
 493+		if (numRead > 0)
 494+		{
 495+			port->input[IO_TH0] = buf[numRead-1];
 496+			if (port->input[IO_STATE] == IO_READ_PENDING)
 497+			{
 498+				port->input[IO_STATE] = IO_READ;
 499+				if (blocking)
 500+				{
 501+					//pending read satisfied, back to non-blocking mode
 502+					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
 503+				}
 504+			} else if (port->input[IO_STATE] == IO_WRITTEN) {
 505+				port->input[IO_STATE] = IO_READ;
 506+			}
 507+		} else if (numRead == 0) {
 508+			port->device.stream.data_fd = -1;
 509+			wait_for_connection(port);
 510+		} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
 511+			warning("Error reading from socket for IO port: %d %s\n", errno, strerror(errno));
 512+			close(port->device.stream.data_fd);
 513+			wait_for_connection(port);
 514+		} else if (port->input[IO_STATE] == IO_READ_PENDING) {
 515+			//clear the nonblocking flag so the next read will block
 516+			if (!blocking)
 517+			{
 518+				fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
 519+				blocking = 1;
 520+			}
 521+		} else {
 522+			//no new data, but that's ok
 523+			break;
 524+		}
 525+	}
 526+
 527+	if (port->input[IO_STATE] == IO_WRITE_PENDING)
 528+	{
 529+		uint8_t value = port->output & port->control;
 530+		int written = 0;
 531+		blocking = 0;
 532+		while (written <= 0)
 533+		{
 534+			send(port->device.stream.data_fd, &value, sizeof(value), 0);
 535+			if (written > 0)
 536+			{
 537+				port->input[IO_STATE] = IO_WRITTEN;
 538+				if (blocking)
 539+				{
 540+					//pending write satisfied, back to non-blocking mode
 541+					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR | O_NONBLOCK);
 542+				}
 543+			} else if (written == 0) {
 544+				port->device.stream.data_fd = -1;
 545+				wait_for_connection(port);
 546+			} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
 547+				warning("Error writing to socket for IO port: %d %s\n", errno, strerror(errno));
 548+				close(port->device.stream.data_fd);
 549+				wait_for_connection(port);
 550+			} else {
 551+				//clear the nonblocking flag so the next write will block
 552+				if (!blocking)
 553+				{
 554+					fcntl(port->device.stream.data_fd, F_SETFL, O_RDWR);
 555+					blocking = 1;
 556+				}
 557+			}
 558+		}
 559+	}
 560+}
 561+
 562+const int mouse_delays[] = {112*7, 120*7, 96*7, 132*7, 104*7, 96*7, 112*7, 96*7};
 563+
 564+enum {
 565+	KB_SETUP,
 566+	KB_READ,
 567+	KB_WRITE
 568+};
 569+
 570+void io_control_write(io_port *port, uint8_t value, uint32_t current_cycle)
 571+{
 572+	uint8_t changes = value ^ port->control;
 573+	if (changes) {
 574+		for (int i = 0; i < 8; i++)
 575+		{
 576+			if (!(value & 1 << i) && !(port->output & 1 << i)) {
 577+				//port switched from output to input and the output value was 0
 578+				//since there is a weak pull-up on input pins, this will lead
 579+				//to a slow rise from 0 to 1 if the pin isn't being externally driven
 580+				port->slow_rise_start[i] = current_cycle;
 581+			} else {
 582+				port->slow_rise_start[i] = CYCLE_NEVER;
 583+			}
 584+		}
 585+		port->control = value;
 586+	}
 587+}
 588+
 589+void io_data_write(io_port * port, uint8_t value, uint32_t current_cycle)
 590+{
 591+	uint8_t old_output = (port->control & port->output) | (~port->control & 0xFF);
 592+	uint8_t output = (port->control & value) | (~port->control & 0xFF);
 593+	switch (port->device_type)
 594+	{
 595+	case IO_GAMEPAD6:
 596+		//check if TH has changed
 597+		if ((old_output & TH) ^ (output & TH)) {
 598+			if (current_cycle >= port->device.pad.timeout_cycle) {
 599+				port->device.pad.th_counter = 0;
 600+			}
 601+			if ((output & TH)) {
 602+				port->device.pad.th_counter++;
 603+			}
 604+			port->device.pad.timeout_cycle = current_cycle + TH_TIMEOUT;
 605+		}
 606+		break;
 607+	case IO_MOUSE:
 608+		mouse_check_ready(port, current_cycle);
 609+		if (output & TH) {
 610+			//request is over or mouse is being reset
 611+			if (port->device.mouse.tr_counter) {
 612+				//request is over
 613+				port->device.mouse.last_read_x = port->device.mouse.latched_x;
 614+				port->device.mouse.last_read_y = port->device.mouse.latched_y;
 615+			}
 616+			port->device.mouse.tr_counter = 0;
 617+			port->device.mouse.ready_cycle = CYCLE_NEVER;
 618+		} else {
 619+			if ((output & TR) != (old_output & TR)) {
 620+				int delay_index = port->device.mouse.tr_counter >= sizeof(mouse_delays) ? sizeof(mouse_delays)-1 : port->device.mouse.tr_counter;
 621+				port->device.mouse.ready_cycle = current_cycle + mouse_delays[delay_index];
 622+			}
 623+		}
 624+		break;
 625+	case IO_SATURN_KEYBOARD:
 626+		if (output & TH) {
 627+			//request is over
 628+			if (port->device.keyboard.tr_counter >= 10 && port->device.keyboard.read_pos != 0xFF) {
 629+				//remove scan code from buffer
 630+				port->device.keyboard.read_pos++;
 631+				port->device.keyboard.read_pos &= 7;
 632+				if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 633+					port->device.keyboard.read_pos = 0xFF;
 634+				}
 635+			}
 636+			port->device.keyboard.tr_counter = 0;
 637+		} else {
 638+			if ((output & TR) != (old_output & TR)) {
 639+				port->device.keyboard.tr_counter++;
 640+			}
 641+		}
 642+		break;
 643+	case IO_XBAND_KEYBOARD:
 644+		if (output & TH) {
 645+			//request is over
 646+			if (
 647+				port->device.keyboard.mode == KB_READ && port->device.keyboard.tr_counter > 6
 648+				&& (port->device.keyboard.tr_counter & 1)
 649+			) {
 650+				if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 651+					port->device.keyboard.events[port->device.keyboard.read_pos] &= 0xFF;
 652+				} else {
 653+					port->device.keyboard.read_pos++;
 654+					port->device.keyboard.read_pos &= 7;
 655+					if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 656+						port->device.keyboard.read_pos = 0xFF;
 657+					}
 658+				}
 659+			}
 660+			port->device.keyboard.tr_counter = 0;
 661+			port->device.keyboard.mode = KB_SETUP;
 662+		} else {
 663+			if ((output & TR) != (old_output & TR)) {
 664+				port->device.keyboard.tr_counter++;
 665+				if (port->device.keyboard.tr_counter == 2) {
 666+					port->device.keyboard.mode = (output & 0xF) ? KB_READ : KB_WRITE;
 667+				} else if (port->device.keyboard.mode == KB_WRITE) {
 668+					switch (port->device.keyboard.tr_counter)
 669+					{
 670+					case 3:
 671+						//host writes 0b0001
 672+						break;
 673+					case 4:
 674+						//host writes 0b0000
 675+						break;
 676+					case 5:
 677+						//host writes 0b0000
 678+						break;
 679+					case 6:
 680+						port->device.keyboard.cmd = output << 4;
 681+						break;
 682+					case 7:
 683+						port->device.keyboard.cmd |= output & 0xF;
 684+						//TODO: actually do something with the command
 685+						break;
 686+					}
 687+				} else if (
 688+					port->device.keyboard.mode == KB_READ && port->device.keyboard.tr_counter > 7
 689+					&& !(port->device.keyboard.tr_counter & 1)
 690+				) {
 691+					
 692+					if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 693+						port->device.keyboard.events[port->device.keyboard.read_pos] &= 0xFF;
 694+					} else {
 695+						port->device.keyboard.read_pos++;
 696+						port->device.keyboard.read_pos &= 7;
 697+						if (port->device.keyboard.read_pos == port->device.keyboard.write_pos) {
 698+							port->device.keyboard.read_pos = 0xFF;
 699+						}
 700+					}
 701+				}
 702+			}
 703+		}
 704+		break;
 705+	case IO_GENERIC:
 706+		wait_for_connection(port);
 707+		port->input[IO_STATE] = IO_WRITE_PENDING;
 708+		service_socket(port);
 709+		break;
 710+	}
 711+	port->output = value;
 712+
 713+}
 714+
 715+uint8_t get_scancode_bytes(io_port *port)
 716+{
 717+	if (port->device.keyboard.read_pos == 0xFF) {
 718+		return 0;
 719+	}
 720+	uint8_t bytes = 0, read_pos = port->device.keyboard.read_pos;
 721+	do {
 722+		bytes += port->device.keyboard.events[read_pos] & 0xFF00 ? 2 : 1;
 723+		read_pos++;
 724+		read_pos &= 7;
 725+	} while (read_pos != port->device.keyboard.write_pos);
 726+	
 727+	return bytes;
 728+}
 729+
 730+#define SLOW_RISE_DEVICE (30*7)
 731+#define SLOW_RISE_INPUT (12*7)
 732+
 733+static uint8_t get_output_value(io_port *port, uint32_t current_cycle, uint32_t slow_rise_delay)
 734+{
 735+	uint8_t output = (port->control | 0x80) & port->output;
 736+	for (int i = 0; i < 8; i++)
 737+	{
 738+		if (!(port->control & 1 << i)) {
 739+			if (port->slow_rise_start[i] != CYCLE_NEVER) {
 740+				if (current_cycle - port->slow_rise_start[i] >= slow_rise_delay) {
 741+					output |= 1 << i;
 742+				}
 743+			} else {
 744+				output |= 1 << i;
 745+			}
 746+		}
 747+	}
 748+	return output;
 749+}
 750+
 751+uint8_t io_data_read(io_port * port, uint32_t current_cycle)
 752+{
 753+	uint8_t output = get_output_value(port, current_cycle, SLOW_RISE_DEVICE);
 754+	uint8_t control = port->control | 0x80;
 755+	uint8_t th = output & 0x40;
 756+	uint8_t input;
 757+	uint8_t device_driven;
 758+	if (current_cycle - last_poll_cycle > MIN_POLL_INTERVAL) {
 759+		process_events();
 760+		last_poll_cycle = current_cycle;
 761+	}
 762+	switch (port->device_type)
 763+	{
 764+	case IO_GAMEPAD2:
 765+		input = ~port->input[GAMEPAD_TH1];
 766+		device_driven = 0x3F;
 767+		break;
 768+	case IO_GAMEPAD3:
 769+	{
 770+		input = port->input[th ? GAMEPAD_TH1 : GAMEPAD_TH0];
 771+		if (!th) {
 772+			input |= 0xC;
 773+		}
 774+		//controller output is logically inverted
 775+		input = ~input;
 776+		device_driven = 0x3F;
 777+		break;
 778+	}
 779+	case IO_GAMEPAD6:
 780+	{
 781+		if (current_cycle >= port->device.pad.timeout_cycle) {
 782+			port->device.pad.th_counter = 0;
 783+		}
 784+		/*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
 785+			printf("io_data_read | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, port->input[GAMEPAD_TH0], port->input[GAMEPAD_TH1], port->th_counter,port->timeout_cycle, context->current_cycle);
 786+		}*/
 787+		if (th) {
 788+			if (port->device.pad.th_counter == 3) {
 789+				input = port->input[GAMEPAD_EXTRA];
 790+			} else {
 791+				input = port->input[GAMEPAD_TH1];
 792+			}
 793+		} else {
 794+			if (port->device.pad.th_counter == 2) {
 795+				input = port->input[GAMEPAD_TH0] | 0xF;
 796+			} else if(port->device.pad.th_counter == 3) {
 797+				input = port->input[GAMEPAD_TH0]  & 0x30;
 798+			} else {
 799+				input = port->input[GAMEPAD_TH0] | 0xC;
 800+			}
 801+		}
 802+		//controller output is logically inverted
 803+		input = ~input;
 804+		device_driven = 0x3F;
 805+		break;
 806+	}
 807+	case IO_MOUSE:
 808+	{
 809+		mouse_check_ready(port, current_cycle);
 810+		uint8_t tr = output & TR;
 811+		if (th) {
 812+			if (tr) {
 813+				input = 0x10;
 814+			} else {
 815+				input = 0;
 816+			}
 817+		} else {
 818+
 819+			int16_t delta_x = port->device.mouse.latched_x - port->device.mouse.last_read_x;
 820+			int16_t delta_y = port->device.mouse.last_read_y - port->device.mouse.latched_y;
 821+			switch (port->device.mouse.tr_counter)
 822+			{
 823+			case 0:
 824+				input = 0xB;
 825+				break;
 826+			case 1:
 827+			case 2:
 828+				input = 0xF;
 829+				break;
 830+			case 3:
 831+				input = 0;
 832+				if (delta_y > 255 || delta_y < -255) {
 833+					input |= 8;
 834+				}
 835+				if (delta_x > 255 || delta_x < -255) {
 836+					input |= 4;
 837+				}
 838+				if (delta_y < 0) {
 839+					input |= 2;
 840+				}
 841+				if (delta_x < 0) {
 842+					input |= 1;
 843+				}
 844+				break;
 845+			case 4:
 846+				input = port->input[0];
 847+				break;
 848+			case 5:
 849+				input = delta_x >> 4 & 0xF;
 850+				break;
 851+			case 6:
 852+				input = delta_x & 0xF;
 853+				break;
 854+			case 7:
 855+				input = delta_y >> 4 & 0xF;
 856+				break;
 857+			case 8:
 858+			default:
 859+				input = delta_y & 0xF;
 860+				break;
 861+			}
 862+			input |= ((port->device.mouse.tr_counter & 1) == 0) << 4;
 863+		}
 864+		device_driven = 0x1F;
 865+		break;
 866+	}
 867+	case IO_SATURN_KEYBOARD:
 868+	{
 869+		if (th) {
 870+			input = 0x11;
 871+		} else {
 872+			uint16_t code = port->device.keyboard.read_pos == 0xFF ? 0 
 873+				: port->device.keyboard.events[port->device.keyboard.read_pos];
 874+			switch (port->device.keyboard.tr_counter)
 875+			{
 876+			case 0:
 877+				input = 1;
 878+				break;
 879+			case 1:
 880+				//Saturn peripheral ID
 881+				input = 3;
 882+				break;
 883+			case 2:
 884+				//data size
 885+				input = 4;
 886+				break;
 887+			case 3:
 888+				//d-pad
 889+				//TODO: set these based on keyboard state
 890+				input = 0xF;
 891+				break;
 892+			case 4:
 893+				//Start ABC
 894+				//TODO: set these based on keyboard state
 895+				input = 0xF;
 896+				break;
 897+			case 5:
 898+				//R XYZ
 899+				//TODO: set these based on keyboard state
 900+				input = 0xF;
 901+				break;
 902+			case 6:
 903+				//L and KBID
 904+				//TODO: set L based on keyboard state
 905+				input = 0x8;
 906+				break;
 907+			case 7:
 908+				//Capslock, Numlock, Scrolllock
 909+				//TODO: set these based on keyboard state
 910+				input = 0;
 911+				break;
 912+			case 8:
 913+				input = 6;
 914+				if (code & 0xFF00) {
 915+					//break
 916+					input |= 1;
 917+				} else if (code) {
 918+					input |= 8;
 919+				}
 920+				break;
 921+			case 9:
 922+				input = code >> 4 & 0xF;
 923+				break;
 924+			case 10:
 925+				input = code & 0xF;
 926+				break;
 927+			case 11:
 928+				input = 0;
 929+				break;
 930+			default:
 931+				input = 1;
 932+				break;
 933+			}
 934+			input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4;
 935+		}
 936+		device_driven = 0x1F;
 937+		break;
 938+	}
 939+	case IO_XBAND_KEYBOARD:
 940+	{
 941+		if (th) {
 942+			input = 0x1C;
 943+		} else {
 944+			uint8_t size;
 945+			if (port->device.keyboard.mode == KB_SETUP || port->device.keyboard.mode == KB_READ) {
 946+				switch (port->device.keyboard.tr_counter)
 947+				{
 948+				case 0:
 949+					input = 0x3;
 950+					break;
 951+				case 1:
 952+					input = 0x6;
 953+					break;
 954+				case 2:
 955+					//This is where thoe host indicates a read or write
 956+					//presumably, the keyboard only outputs this if the host
 957+					//is not already driving the data bus low
 958+					input = 0x9;
 959+					break;
 960+				case 3:
 961+					size = get_scancode_bytes(port);
 962+					if (size) {
 963+						++size;
 964+					}
 965+					if (size > 15) {
 966+						size = 15;
 967+					}
 968+					input = size;
 969+					break;
 970+				case 4:
 971+				case 5:
 972+					//always send packet type 0 for now
 973+					input = 0;
 974+					break;
 975+				default:
 976+					if (port->device.keyboard.read_pos == 0xFF) {
 977+						//we've run out of bytes
 978+						input = 0;
 979+					} else if (port->device.keyboard.events[port->device.keyboard.read_pos] & 0xFF00) {
 980+						if (port->device.keyboard.tr_counter & 1) {
 981+							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 8 & 0xF;
 982+						} else {
 983+							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 12;
 984+						}
 985+					} else {
 986+						if (port->device.keyboard.tr_counter & 1) {
 987+							input = port->device.keyboard.events[port->device.keyboard.read_pos] & 0xF;
 988+						} else {
 989+							input = port->device.keyboard.events[port->device.keyboard.read_pos] >> 4;
 990+						}
 991+					}
 992+					break;
 993+				}
 994+			} else {
 995+				input = 0xF;
 996+			}
 997+			input |= ((port->device.keyboard.tr_counter & 1) == 0) << 4;
 998+		}
 999+		//this is not strictly correct at all times, but good enough for now
1000+		device_driven = 0x1F;
1001+		break;
1002+	}
1003+	case IO_SEGA_PARALLEL:
1004+		if (!th)
1005+		{
1006+			service_pipe(port);
1007+		}
1008+		input = port->input[th ? IO_TH1 : IO_TH0];
1009+		device_driven = 0x3F;
1010+		break;
1011+	case IO_GENERIC:
1012+		if (port->input[IO_TH0] & 0x80 && port->input[IO_STATE] == IO_WRITTEN)
1013+		{
1014+			//device requested a blocking read after writes
1015+			port->input[IO_STATE] = IO_READ_PENDING;
1016+		}
1017+		service_socket(port);
1018+		input = port->input[IO_TH0];
1019+		device_driven = 0x7F;
1020+		break;
1021+	default:
1022+		input = 0;
1023+		device_driven = 0;
1024+		break;
1025+	}
1026+	uint8_t value = (input & (~control) & device_driven) | (port->output & control);
1027+	//deal with pins that are configured as inputs, but not being actively driven by the device
1028+	uint8_t floating = (~device_driven) & (~control);
1029+	if (floating) {
1030+		value |= get_output_value(port, current_cycle, SLOW_RISE_INPUT) & floating;
1031+	}
1032+	/*if (port->input[GAMEPAD_TH0] || port->input[GAMEPAD_TH1]) {
1033+		printf ("value: %X\n", value);
1034+	}*/
1035+	return value;
1036+}
1037+
1038+void io_serialize(io_port *port, serialize_buffer *buf)
1039+{
1040+	save_int8(buf, port->output);
1041+	save_int8(buf, port->control);
1042+	save_int8(buf, port->serial_out);
1043+	save_int8(buf, port->serial_in);
1044+	save_int8(buf, port->serial_ctrl);
1045+	save_int8(buf, port->device_type);
1046+	save_buffer32(buf, port->slow_rise_start, 8);
1047+	switch (port->device_type)
1048+	{
1049+	case IO_GAMEPAD6:
1050+		save_int32(buf, port->device.pad.timeout_cycle);
1051+		save_int16(buf, port->device.pad.th_counter);
1052+		break;
1053+	case IO_MOUSE:
1054+		save_int32(buf, port->device.mouse.ready_cycle);
1055+		save_int16(buf, port->device.mouse.last_read_x);
1056+		save_int16(buf, port->device.mouse.last_read_y);
1057+		save_int16(buf, port->device.mouse.latched_x);
1058+		save_int16(buf, port->device.mouse.latched_y);
1059+		save_int8(buf, port->device.mouse.tr_counter);
1060+		break;
1061+	case IO_SATURN_KEYBOARD:
1062+	case IO_XBAND_KEYBOARD:
1063+		save_int8(buf, port->device.keyboard.tr_counter);
1064+		if (port->device_type == IO_XBAND_KEYBOARD) {
1065+			save_int8(buf, port->device.keyboard.mode);
1066+			save_int8(buf, port->device.keyboard.cmd);
1067+		}
1068+		break;
1069+	}
1070+}
1071+
1072+void io_deserialize(deserialize_buffer *buf, void *vport)
1073+{
1074+	io_port *port = vport;
1075+	port->output = load_int8(buf);
1076+	port->control = load_int8(buf);
1077+	port->serial_out = load_int8(buf);
1078+	port->serial_in = load_int8(buf);
1079+	port->serial_ctrl = load_int8(buf);
1080+	uint8_t device_type = load_int8(buf);
1081+	if (device_type != port->device_type) {
1082+		warning("Loaded save state has a different device type from the current configuration");
1083+		return;
1084+	}
1085+	switch (port->device_type)
1086+	{
1087+	case IO_GAMEPAD6:
1088+		port->device.pad.timeout_cycle = load_int32(buf);
1089+		port->device.pad.th_counter = load_int16(buf);
1090+		break;
1091+	case IO_MOUSE:
1092+		port->device.mouse.ready_cycle = load_int32(buf);
1093+		port->device.mouse.last_read_x = load_int16(buf);
1094+		port->device.mouse.last_read_y = load_int16(buf);
1095+		port->device.mouse.latched_x = load_int16(buf);
1096+		port->device.mouse.latched_y = load_int16(buf);
1097+		port->device.mouse.tr_counter = load_int8(buf);
1098+		break;
1099+	case IO_SATURN_KEYBOARD:
1100+	case IO_XBAND_KEYBOARD:
1101+		port->device.keyboard.tr_counter = load_int8(buf);
1102+		if (port->device_type == IO_XBAND_KEYBOARD) {
1103+			port->device.keyboard.mode = load_int8(buf);
1104+			port->device.keyboard.cmd = load_int8(buf);
1105+		}
1106+		break;
1107+	}
1108+}
A io.h
+130, -0
  1@@ -0,0 +1,130 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef IO_H_
  8+#define IO_H_
  9+#include <stdint.h>
 10+#include "tern.h"
 11+#include "romdb.h"
 12+#include "serialize.h"
 13+
 14+enum {
 15+	IO_NONE,
 16+	IO_GAMEPAD2,
 17+	IO_GAMEPAD3,
 18+	IO_GAMEPAD6,
 19+	IO_MOUSE,
 20+	IO_SATURN_KEYBOARD,
 21+	IO_XBAND_KEYBOARD,
 22+	IO_MENACER,
 23+	IO_JUSTIFIER,
 24+	IO_SEGA_MULTI,
 25+	IO_EA_MULTI_A,
 26+	IO_EA_MULTI_B,
 27+	IO_SEGA_PARALLEL,
 28+	IO_GENERIC
 29+};
 30+
 31+typedef struct {
 32+	union {
 33+		struct {
 34+			uint32_t timeout_cycle;
 35+			uint16_t th_counter;
 36+			uint16_t gamepad_num;
 37+		} pad;
 38+		struct {
 39+			int data_fd;
 40+			int listen_fd;
 41+		} stream;
 42+		struct {
 43+			uint32_t ready_cycle;
 44+			uint16_t last_read_x;
 45+			uint16_t last_read_y;
 46+			uint16_t cur_x;
 47+			uint16_t cur_y;
 48+			uint16_t latched_x;
 49+			uint16_t latched_y;
 50+			uint8_t  tr_counter;
 51+			uint8_t  mouse_num;
 52+		} mouse;
 53+		struct {
 54+			uint16_t events[8];
 55+			uint8_t  read_pos;
 56+			uint8_t  write_pos;
 57+			uint8_t  tr_counter;
 58+			uint8_t  mode;
 59+			uint8_t  cmd;
 60+		} keyboard;
 61+	} device;
 62+	uint8_t  output;
 63+	uint8_t  control;
 64+	uint8_t  input[3];
 65+	uint32_t slow_rise_start[8];
 66+	uint8_t  serial_out;
 67+	uint8_t  serial_in;
 68+	uint8_t  serial_ctrl;
 69+	uint8_t  device_type;
 70+} io_port;
 71+
 72+typedef struct {
 73+	io_port	ports[3];
 74+} sega_io;
 75+
 76+//pseudo gamepad for buttons on main console unit
 77+#define GAMEPAD_MAIN_UNIT 255
 78+
 79+enum {
 80+	BUTTON_INVALID,
 81+	DPAD_UP,
 82+	DPAD_DOWN,
 83+	DPAD_LEFT,
 84+	DPAD_RIGHT,
 85+	BUTTON_A,
 86+	BUTTON_B,
 87+	BUTTON_C,
 88+	BUTTON_START,
 89+	BUTTON_X,
 90+	BUTTON_Y,
 91+	BUTTON_Z,
 92+	BUTTON_MODE,
 93+	NUM_GAMEPAD_BUTTONS
 94+};
 95+
 96+enum {
 97+	MAIN_UNIT_PAUSE
 98+};
 99+
100+enum {
101+	MOUSE_LEFT = 1,
102+	MOUSE_RIGHT = 2,
103+	MOUSE_MIDDLE = 4,
104+	MOUSE_START = 8,
105+	PSEUDO_BUTTON_MOTION=0xFF
106+};
107+
108+void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io);
109+void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction);
110+void io_control_write(io_port *port, uint8_t value, uint32_t current_cycle);
111+void io_data_write(io_port * pad, uint8_t value, uint32_t current_cycle);
112+uint8_t io_data_read(io_port * pad, uint32_t current_cycle);
113+void io_serialize(io_port *port, serialize_buffer *buf);
114+void io_deserialize(deserialize_buffer *buf, void *vport);
115+
116+void io_port_gamepad_down(io_port *port, uint8_t button);
117+void io_port_gamepad_up(io_port *port, uint8_t button);
118+void io_gamepad_down(sega_io *io, uint8_t gamepad_num, uint8_t button);
119+void io_gamepad_up(sega_io *io, uint8_t gamepad_num, uint8_t button);
120+void io_mouse_down(sega_io *io, uint8_t mouse_num, uint8_t button);
121+void io_mouse_up(sega_io *io, uint8_t mouse_num, uint8_t button);
122+void io_mouse_motion_absolute(sega_io *io, uint8_t mouse_num, uint16_t x, uint16_t y);
123+void io_mouse_motion_relative(sega_io *io, uint8_t mouse_num, int32_t x, int32_t y);
124+void io_keyboard_down(sega_io *io, uint8_t scancode);
125+void io_keyboard_up(sega_io *io, uint8_t scancode);
126+uint8_t io_has_keyboard(sega_io *io);
127+
128+extern const char * device_type_names[];
129+
130+#endif //IO_H_
131+
+88, -0
 1@@ -0,0 +1,88 @@
 2+#include <stdlib.h>
 3+#include "genesis.h"
 4+
 5+static io_port *get_ports(m68k_context *m68k)
 6+{
 7+	genesis_context *gen = m68k->system;
 8+	if (!gen->extra) {
 9+		io_port *ports = calloc(2, sizeof(io_port));
10+		ports[0].device_type = IO_GAMEPAD3;
11+		ports[0].device.pad.gamepad_num = 3;
12+		ports[1].device_type = IO_GAMEPAD3;
13+		ports[1].device.pad.gamepad_num = 4;
14+		io_control_write(ports, 0x40, 0);
15+		io_control_write(ports + 1, 0x40, 0);
16+		gen->extra = ports;
17+	}
18+		
19+	return gen->extra;
20+}
21+
22+void *jcart_write_w(uint32_t address, void *context, uint16_t value)
23+{
24+	m68k_context *m68k= context;
25+	io_port *ports = get_ports(m68k);
26+	value = value << 6 & 0x40;
27+	io_data_write(ports, value, m68k->current_cycle);
28+	io_data_write(ports + 1, value, m68k->current_cycle);
29+	return context;
30+}
31+
32+void *jcart_write_b(uint32_t address, void *context, uint8_t value)
33+{
34+	if (address & 1) {
35+		return jcart_write_w(address, context, value);
36+	}
37+	return context;
38+}
39+
40+uint16_t jcart_read_w(uint32_t address, void *context)
41+{
42+	m68k_context *m68k= context;
43+	io_port *ports = get_ports(m68k);
44+	//according to Eke, bit 14 is forced low, at least on the Micro Machines 2 cart
45+	//TODO: Test behavior of actual cart
46+	uint16_t value = io_data_read(ports, m68k->current_cycle) << 8;
47+	value |= io_data_read(ports + 1, m68k->current_cycle);
48+	return value;
49+}
50+
51+uint8_t jcart_read_b(uint32_t address, void *context)
52+{
53+	m68k_context *m68k= context;
54+	io_port *ports = get_ports(m68k);
55+	return io_data_read(ports + (address & 1), m68k->current_cycle);
56+}
57+
58+void jcart_adjust_cycles(genesis_context *context, uint32_t deduction)
59+{
60+	io_port *ports = get_ports(context->m68k);
61+	io_adjust_cycles(ports, context->m68k->current_cycle, deduction);
62+	io_adjust_cycles(ports + 1, context->m68k->current_cycle, deduction);
63+}
64+
65+void jcart_gamepad_down(genesis_context *context, uint8_t gamepad_num, uint8_t button)
66+{
67+	io_port *ports = get_ports(context->m68k);
68+	if (gamepad_num == ports[1].device.pad.gamepad_num) {
69+		ports++;
70+	} else if (gamepad_num != ports[0].device.pad.gamepad_num) {
71+		ports = NULL;
72+	}
73+	if (ports) {
74+		io_port_gamepad_down(ports, button);
75+	}
76+}
77+
78+void jcart_gamepad_up(genesis_context *context, uint8_t gamepad_num, uint8_t button)
79+{
80+	io_port *ports = get_ports(context->m68k);
81+	if (gamepad_num == ports[1].device.pad.gamepad_num) {
82+		ports++;
83+	} else if (gamepad_num != ports[0].device.pad.gamepad_num) {
84+		ports = NULL;
85+	}
86+	if (ports) {
87+		io_port_gamepad_up(ports, button);
88+	}
89+}
+12, -0
 1@@ -0,0 +1,12 @@
 2+#ifndef JCART_H_
 3+#define JCART_H_
 4+
 5+void *jcart_write_w(uint32_t address, void *context, uint16_t value);
 6+void *jcart_write_b(uint32_t address, void *context, uint8_t value);
 7+uint16_t jcart_read_w(uint32_t address, void *context);
 8+uint8_t jcart_read_b(uint32_t address, void *context);
 9+void jcart_adjust_cycles(genesis_context *context, uint32_t deduction);
10+void jcart_gamepad_down(genesis_context *context, uint8_t gamepad_num, uint8_t button);
11+void jcart_gamepad_up(genesis_context *context, uint8_t gamepad_num, uint8_t button);
12+
13+#endif //JCART_H_
+1276, -0
   1@@ -0,0 +1,1276 @@
   2+/*
   3+ Copyright 2014 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "m68k_core.h"
   8+#include "m68k_internal.h"
   9+#include "68kinst.h"
  10+#include "backend.h"
  11+#include "gen.h"
  12+#include "util.h"
  13+#include "serialize.h"
  14+#include <stdio.h>
  15+#include <stddef.h>
  16+#include <stdlib.h>
  17+#include <string.h>
  18+
  19+char disasm_buf[1024];
  20+
  21+int8_t native_reg(m68k_op_info * op, m68k_options * opts)
  22+{
  23+	if (op->addr_mode == MODE_REG) {
  24+		return opts->dregs[op->params.regs.pri];
  25+	}
  26+	if (op->addr_mode == MODE_AREG) {
  27+		return opts->aregs[op->params.regs.pri];
  28+	}
  29+	return -1;
  30+}
  31+
  32+size_t dreg_offset(uint8_t reg)
  33+{
  34+	return offsetof(m68k_context, dregs) + sizeof(uint32_t) * reg;
  35+}
  36+
  37+size_t areg_offset(uint8_t reg)
  38+{
  39+	return offsetof(m68k_context, aregs) + sizeof(uint32_t) * reg;
  40+}
  41+
  42+//must be called with an m68k_op_info that uses a register
  43+size_t reg_offset(m68k_op_info *op)
  44+{
  45+	return op->addr_mode == MODE_REG ? dreg_offset(op->params.regs.pri) : areg_offset(op->params.regs.pri);
  46+}
  47+
  48+void m68k_print_regs(m68k_context * context)
  49+{
  50+	printf("XNZVC\n%d%d%d%d%d\n", context->flags[0], context->flags[1], context->flags[2], context->flags[3], context->flags[4]);
  51+	for (int i = 0; i < 8; i++) {
  52+		printf("d%d: %X\n", i, context->dregs[i]);
  53+	}
  54+	for (int i = 0; i < 8; i++) {
  55+		printf("a%d: %X\n", i, context->aregs[i]);
  56+	}
  57+}
  58+
  59+void m68k_read_size(m68k_options *opts, uint8_t size)
  60+{
  61+	switch (size)
  62+	{
  63+	case OPSIZE_BYTE:
  64+		call(&opts->gen.code, opts->read_8);
  65+		break;
  66+	case OPSIZE_WORD:
  67+		call(&opts->gen.code, opts->read_16);
  68+		break;
  69+	case OPSIZE_LONG:
  70+		call(&opts->gen.code, opts->read_32);
  71+		break;
  72+	}
  73+}
  74+
  75+void m68k_write_size(m68k_options *opts, uint8_t size, uint8_t lowfirst)
  76+{
  77+	switch (size)
  78+	{
  79+	case OPSIZE_BYTE:
  80+		call(&opts->gen.code, opts->write_8);
  81+		break;
  82+	case OPSIZE_WORD:
  83+		call(&opts->gen.code, opts->write_16);
  84+		break;
  85+	case OPSIZE_LONG:
  86+		if (lowfirst) {
  87+			call(&opts->gen.code, opts->write_32_lowfirst);
  88+		} else {
  89+			call(&opts->gen.code, opts->write_32_highfirst);
  90+		}
  91+		break;
  92+	}
  93+}
  94+
  95+void m68k_save_result(m68kinst * inst, m68k_options * opts)
  96+{
  97+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) {
  98+		if (inst->dst.addr_mode == MODE_AREG_PREDEC && 
  99+			((inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) || (inst->op == M68K_NBCD))
 100+		) {
 101+			areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
 102+		}
 103+		m68k_write_size(opts, inst->extra.size, 1);
 104+	}
 105+}
 106+
 107+static void translate_m68k_lea_pea(m68k_options * opts, m68kinst * inst)
 108+{
 109+	code_info *code = &opts->gen.code;
 110+	int8_t dst_reg = inst->op == M68K_PEA ? opts->gen.scratch1 : native_reg(&(inst->dst), opts);
 111+	switch(inst->src.addr_mode)
 112+	{
 113+	case MODE_AREG_INDIRECT:
 114+		cycles(&opts->gen, BUS);
 115+		if (dst_reg >= 0) {
 116+			areg_to_native(opts, inst->src.params.regs.pri, dst_reg);
 117+		} else {
 118+			if (opts->aregs[inst->src.params.regs.pri] >= 0) {
 119+				native_to_areg(opts, opts->aregs[inst->src.params.regs.pri], inst->dst.params.regs.pri);
 120+			} else {
 121+				areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1);
 122+				native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 123+			}
 124+		}
 125+		break;
 126+	case MODE_AREG_DISPLACE:
 127+		cycles(&opts->gen, 8);
 128+		calc_areg_displace(opts, &inst->src, dst_reg >= 0 ? dst_reg : opts->gen.scratch1);
 129+		if (dst_reg < 0) {
 130+			native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 131+		}
 132+		break;
 133+	case MODE_AREG_INDEX_DISP8:
 134+		cycles(&opts->gen, 12);
 135+		if (dst_reg < 0 || inst->dst.params.regs.pri == inst->src.params.regs.pri || inst->dst.params.regs.pri == (inst->src.params.regs.sec >> 1 & 0x7)) {
 136+			dst_reg = opts->gen.scratch1;
 137+		}
 138+		calc_areg_index_disp8(opts, &inst->src, dst_reg);
 139+		if (dst_reg == opts->gen.scratch1 && inst->op != M68K_PEA) {
 140+			native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 141+		}
 142+		break;
 143+	case MODE_PC_DISPLACE:
 144+		cycles(&opts->gen, 8);
 145+		if (inst->op == M68K_PEA) {
 146+			ldi_native(opts, inst->src.params.regs.displacement + inst->address+2, dst_reg);
 147+		} else {
 148+			ldi_areg(opts, inst->src.params.regs.displacement + inst->address+2, inst->dst.params.regs.pri);
 149+		}
 150+		break;
 151+	case MODE_PC_INDEX_DISP8:
 152+		cycles(&opts->gen, BUS*3);
 153+		if (dst_reg < 0 || inst->dst.params.regs.pri == (inst->src.params.regs.sec >> 1 & 0x7)) {
 154+			dst_reg = opts->gen.scratch1;
 155+		}
 156+		ldi_native(opts, inst->address+2, dst_reg);
 157+		calc_index_disp8(opts, &inst->src, dst_reg);
 158+		if (dst_reg == opts->gen.scratch1 && inst->op != M68K_PEA) {
 159+			native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 160+		}
 161+		break;
 162+	case MODE_ABSOLUTE:
 163+	case MODE_ABSOLUTE_SHORT:
 164+		cycles(&opts->gen, (inst->src.addr_mode == MODE_ABSOLUTE) ? BUS * 3 : BUS * 2);
 165+		if (inst->op == M68K_PEA) {
 166+			ldi_native(opts, inst->src.params.immed, dst_reg);
 167+		} else {
 168+			ldi_areg(opts, inst->src.params.immed, inst->dst.params.regs.pri);
 169+		}
 170+		break;
 171+	default:
 172+		m68k_disasm(inst, disasm_buf);
 173+		fatal_error("%X: %s\naddress mode %d not implemented (lea src)\n", inst->address, disasm_buf, inst->src.addr_mode);
 174+	}
 175+	if (inst->op == M68K_PEA) {
 176+		subi_areg(opts, 4, 7);
 177+		areg_to_native(opts, 7, opts->gen.scratch2);
 178+		call(code, opts->write_32_lowfirst);
 179+	}
 180+}
 181+
 182+static void push_const(m68k_options *opts, int32_t value)
 183+{
 184+	ldi_native(opts, value, opts->gen.scratch1);
 185+	subi_areg(opts, 4, 7);
 186+	areg_to_native(opts, 7, opts->gen.scratch2);
 187+	call(&opts->gen.code, opts->write_32_highfirst);
 188+}
 189+
 190+void jump_m68k_abs(m68k_options * opts, uint32_t address)
 191+{
 192+	code_info *code = &opts->gen.code;
 193+	code_ptr dest_addr = get_native_address(opts, address);
 194+	if (!dest_addr) {
 195+		opts->gen.deferred = defer_address(opts->gen.deferred, address, code->cur + 1);
 196+		//dummy address to be replaced later, make sure it generates a 4-byte displacement
 197+		dest_addr = code->cur + 256;
 198+	}
 199+	jmp(code, dest_addr);
 200+	//this used to call opts->native_addr for destinations in RAM, but that shouldn't be needed
 201+	//since instruction retranslation patches the original native instruction location
 202+}
 203+
 204+static void translate_m68k_bsr(m68k_options * opts, m68kinst * inst)
 205+{
 206+	code_info *code = &opts->gen.code;
 207+	int32_t disp = inst->src.params.immed;
 208+	uint32_t after = inst->address + (inst->variant == VAR_BYTE ? 2 : 4);
 209+	//TODO: Add cycles in the right place relative to pushing the return address on the stack
 210+	cycles(&opts->gen, 10);
 211+	push_const(opts, after);
 212+	jump_m68k_abs(opts, inst->address + 2 + disp);
 213+}
 214+
 215+static void translate_m68k_jmp_jsr(m68k_options * opts, m68kinst * inst)
 216+{
 217+	uint8_t is_jsr = inst->op == M68K_JSR;
 218+	code_info *code = &opts->gen.code;
 219+	code_ptr dest_addr;
 220+	uint8_t sec_reg;
 221+	uint32_t after;
 222+	uint32_t m68k_addr;
 223+	switch(inst->src.addr_mode)
 224+	{
 225+	case MODE_AREG_INDIRECT:
 226+		cycles(&opts->gen, BUS*2);
 227+		if (is_jsr) {
 228+			push_const(opts, inst->address+2);
 229+		}
 230+		areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1);
 231+		call(code, opts->native_addr);
 232+		jmp_r(code, opts->gen.scratch1);
 233+		break;
 234+	case MODE_AREG_DISPLACE:
 235+		cycles(&opts->gen, BUS*2);
 236+		if (is_jsr) {
 237+			push_const(opts, inst->address+4);
 238+		}
 239+		calc_areg_displace(opts, &inst->src, opts->gen.scratch1);
 240+		call(code, opts->native_addr);
 241+		jmp_r(code, opts->gen.scratch1);
 242+		break;
 243+	case MODE_AREG_INDEX_DISP8:
 244+		cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct
 245+		if (is_jsr) {
 246+			push_const(opts, inst->address+4);
 247+		}
 248+		calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1);
 249+		call(code, opts->native_addr);
 250+		jmp_r(code, opts->gen.scratch1);
 251+		break;
 252+	case MODE_PC_DISPLACE:
 253+		//TODO: Add cycles in the right place relative to pushing the return address on the stack
 254+		cycles(&opts->gen, 10);
 255+		if (is_jsr) {
 256+			push_const(opts, inst->address+4);
 257+		}
 258+		jump_m68k_abs(opts, inst->src.params.regs.displacement + inst->address + 2);
 259+		break;
 260+	case MODE_PC_INDEX_DISP8:
 261+		cycles(&opts->gen, BUS*3);//TODO: CHeck that this is correct
 262+		if (is_jsr) {
 263+			push_const(opts, inst->address+4);
 264+		}
 265+		ldi_native(opts, inst->address+2, opts->gen.scratch1);
 266+		calc_index_disp8(opts, &inst->src, opts->gen.scratch1);
 267+		call(code, opts->native_addr);
 268+		jmp_r(code, opts->gen.scratch1);
 269+		break;
 270+	case MODE_ABSOLUTE:
 271+	case MODE_ABSOLUTE_SHORT:
 272+		//TODO: Add cycles in the right place relative to pushing the return address on the stack
 273+		cycles(&opts->gen, inst->src.addr_mode == MODE_ABSOLUTE ? 12 : 10);
 274+		if (is_jsr) {
 275+			push_const(opts, inst->address + (inst->src.addr_mode == MODE_ABSOLUTE ? 6 : 4));
 276+		}
 277+		jump_m68k_abs(opts, inst->src.params.immed);
 278+		break;
 279+	default:
 280+		m68k_disasm(inst, disasm_buf);
 281+		fatal_error("%s\naddress mode %d not yet supported (%s)\n", disasm_buf, inst->src.addr_mode, is_jsr ? "jsr" : "jmp");
 282+	}
 283+}
 284+
 285+static void translate_m68k_unlk(m68k_options * opts, m68kinst * inst)
 286+{
 287+	cycles(&opts->gen, BUS);
 288+	if (inst->dst.params.regs.pri != 7) {
 289+		areg_to_native(opts, inst->dst.params.regs.pri, opts->aregs[7]);
 290+	}
 291+	areg_to_native(opts, 7, opts->gen.scratch1);
 292+	call(&opts->gen.code, opts->read_32);
 293+	native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 294+	if (inst->dst.params.regs.pri != 7) {
 295+		addi_areg(opts, 4, 7);
 296+	}
 297+}
 298+
 299+static void translate_m68k_link(m68k_options * opts, m68kinst * inst)
 300+{
 301+	//compensate for displacement word
 302+	cycles(&opts->gen, BUS);
 303+	subi_areg(opts, 4, 7);
 304+	areg_to_native(opts, 7, opts->gen.scratch2);
 305+	areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1);
 306+	call(&opts->gen.code, opts->write_32_highfirst);
 307+	native_to_areg(opts, opts->aregs[7], inst->src.params.regs.pri);
 308+	addi_areg(opts, inst->dst.params.immed, 7);
 309+	//prefetch
 310+	cycles(&opts->gen, BUS);
 311+}
 312+
 313+static void translate_m68k_rts(m68k_options * opts, m68kinst * inst)
 314+{
 315+	code_info *code = &opts->gen.code;
 316+	areg_to_native(opts, 7, opts->gen.scratch1);
 317+	addi_areg(opts, 4, 7);
 318+	call(code, opts->read_32);
 319+	cycles(&opts->gen, 2*BUS);
 320+	call(code, opts->native_addr);
 321+	jmp_r(code, opts->gen.scratch1);
 322+}
 323+
 324+static void translate_m68k_rtr(m68k_options *opts, m68kinst * inst)
 325+{
 326+	code_info *code = &opts->gen.code;
 327+	//Read saved CCR
 328+	areg_to_native(opts, 7, opts->gen.scratch1);
 329+	call(code, opts->read_16);
 330+	addi_areg(opts, 2, 7);
 331+	call(code, opts->set_ccr);
 332+	//Read saved PC
 333+	areg_to_native(opts, 7, opts->gen.scratch1);
 334+	call(code, opts->read_32);
 335+	addi_areg(opts, 4, 7);
 336+	//Get native address and jump to it
 337+	call(code, opts->native_addr);
 338+	jmp_r(code, opts->gen.scratch1);
 339+}
 340+
 341+static void translate_m68k_trap(m68k_options *opts, m68kinst *inst)
 342+{
 343+	code_info *code = &opts->gen.code;
 344+	uint32_t vector, pc = inst->address;
 345+	switch (inst->op)
 346+	{
 347+	case M68K_TRAP:
 348+		vector = inst->src.params.immed + VECTOR_TRAP_0;
 349+		pc += 2;
 350+		break;
 351+	case M68K_A_LINE_TRAP:
 352+		vector = VECTOR_LINE_1010;
 353+		break;
 354+	case M68K_F_LINE_TRAP:
 355+		vector = VECTOR_LINE_1111;
 356+		break;
 357+	}
 358+	ldi_native(opts, vector, opts->gen.scratch2);
 359+	ldi_native(opts, pc, opts->gen.scratch1);
 360+	jmp(code, opts->trap);
 361+}
 362+
 363+static void translate_m68k_illegal(m68k_options *opts, m68kinst *inst)
 364+{
 365+	code_info *code = &opts->gen.code;
 366+	cycles(&opts->gen, BUS);
 367+	ldi_native(opts, VECTOR_ILLEGAL_INST, opts->gen.scratch2);
 368+	ldi_native(opts, inst->address, opts->gen.scratch1);
 369+	jmp(code, opts->trap);
 370+}
 371+
 372+static void translate_m68k_move_usp(m68k_options *opts, m68kinst *inst)
 373+{
 374+	m68k_trap_if_not_supervisor(opts, inst);
 375+	cycles(&opts->gen, BUS);
 376+	int8_t reg;
 377+	if (inst->src.addr_mode == MODE_UNUSED) {
 378+		reg = native_reg(&inst->dst, opts);
 379+		if (reg < 0) {
 380+			reg = opts->gen.scratch1;
 381+		}
 382+		areg_to_native(opts, 8, reg);
 383+		if (reg == opts->gen.scratch1) {
 384+			native_to_areg(opts, opts->gen.scratch1, inst->dst.params.regs.pri);
 385+		}
 386+	} else {
 387+		reg = native_reg(&inst->src, opts);
 388+		if (reg < 0) {
 389+			reg = opts->gen.scratch1;
 390+			areg_to_native(opts, inst->src.params.regs.pri, reg);
 391+		}
 392+		native_to_areg(opts, reg, 8);
 393+	}
 394+}
 395+
 396+static void translate_movem_regtomem_reglist(m68k_options * opts, m68kinst *inst)
 397+{
 398+	code_info *code = &opts->gen.code;
 399+	int8_t bit,reg,dir;
 400+	if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
 401+		reg = 15;
 402+		dir = -1;
 403+	} else {
 404+		reg = 0;
 405+		dir = 1;
 406+	}
 407+	for(bit=0; reg < 16 && reg >= 0; reg += dir, bit++) {
 408+		if (inst->src.params.immed & (1 << bit)) {
 409+			if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
 410+				subi_native(opts, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch2);
 411+			}
 412+			push_native(opts, opts->gen.scratch2);
 413+			if (reg > 7) {
 414+				areg_to_native(opts, reg-8, opts->gen.scratch1);
 415+			} else {
 416+				dreg_to_native(opts, reg, opts->gen.scratch1);
 417+			}
 418+			if (inst->extra.size == OPSIZE_LONG) {
 419+				call(code, opts->write_32_lowfirst);
 420+			} else {
 421+				call(code, opts->write_16);
 422+			}
 423+			pop_native(opts, opts->gen.scratch2);
 424+			if (inst->dst.addr_mode != MODE_AREG_PREDEC) {
 425+				addi_native(opts, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch2);
 426+			}
 427+		}
 428+	}
 429+}
 430+
 431+static void translate_movem_memtoreg_reglist(m68k_options * opts, m68kinst *inst)
 432+{
 433+	code_info *code = &opts->gen.code;
 434+	for(uint8_t reg = 0; reg < 16; reg ++) {
 435+		if (inst->dst.params.immed & (1 << reg)) {
 436+			push_native(opts, opts->gen.scratch1);
 437+			if (inst->extra.size == OPSIZE_LONG) {
 438+				call(code, opts->read_32);
 439+			} else {
 440+				call(code, opts->read_16);
 441+			}
 442+			if (inst->extra.size == OPSIZE_WORD) {
 443+				sign_extend16_native(opts, opts->gen.scratch1);
 444+			}
 445+			if (reg > 7) {
 446+				native_to_areg(opts, opts->gen.scratch1, reg-8);
 447+			} else {
 448+				native_to_dreg(opts, opts->gen.scratch1, reg);
 449+			}
 450+			pop_native(opts, opts->gen.scratch1);
 451+			addi_native(opts, (inst->extra.size == OPSIZE_LONG) ? 4 : 2, opts->gen.scratch1);
 452+		}
 453+	}
 454+}
 455+
 456+static code_ptr get_movem_impl(m68k_options *opts, m68kinst *inst)
 457+{
 458+	uint8_t reg_to_mem = inst->src.addr_mode == MODE_REG;
 459+	uint8_t size = inst->extra.size;
 460+	int8_t dir = reg_to_mem && inst->dst.addr_mode == MODE_AREG_PREDEC ? -1 : 1;
 461+	uint16_t reglist = reg_to_mem ? inst->src.params.immed : inst->dst.params.immed;
 462+	for (uint32_t i = 0; i < opts->num_movem; i++)
 463+	{
 464+		if (
 465+			opts->big_movem[i].reglist == reglist && opts->big_movem[i].reg_to_mem == reg_to_mem
 466+			&& opts->big_movem[i].size == size && opts->big_movem[i].dir == dir
 467+		) {
 468+			return opts->big_movem[i].impl;
 469+		}
 470+	}
 471+	if (opts->num_movem == opts->movem_storage) {
 472+		if (!opts->movem_storage) {
 473+			opts->movem_storage = 4;
 474+		} else {
 475+			opts->movem_storage *= 2;
 476+		}
 477+		opts->big_movem = realloc(opts->big_movem, sizeof(movem_fun) * opts->movem_storage);
 478+	}
 479+	if (!opts->extra_code.cur) {
 480+		init_code_info(&opts->extra_code);
 481+	}
 482+	check_alloc_code(&opts->extra_code, 512);
 483+	code_ptr impl = opts->extra_code.cur;
 484+	code_info tmp = opts->gen.code;
 485+	opts->gen.code = opts->extra_code;
 486+	if (reg_to_mem) {
 487+		translate_movem_regtomem_reglist(opts, inst);
 488+	} else {
 489+		translate_movem_memtoreg_reglist(opts, inst);
 490+	}
 491+	opts->extra_code = opts->gen.code;
 492+	opts->gen.code = tmp;
 493+	
 494+	rts(&opts->extra_code);
 495+	return impl;
 496+}
 497+
 498+static void translate_m68k_movem(m68k_options * opts, m68kinst * inst)
 499+{
 500+	code_info *code = &opts->gen.code;
 501+	uint8_t early_cycles;
 502+	uint16_t num_regs = inst->src.addr_mode == MODE_REG ? inst->src.params.immed : inst->dst.params.immed;
 503+	{	
 504+		//TODO: Move this popcount alg to a utility function
 505+		uint16_t a = (num_regs & 0b1010101010101010) >> 1;
 506+		uint16_t b = num_regs & 0b0101010101010101;
 507+		num_regs = a + b;
 508+		a = (num_regs & 0b1100110011001100) >> 2;
 509+		b = num_regs & 0b0011001100110011;
 510+		num_regs = a + b;
 511+		a = (num_regs & 0b1111000011110000) >> 4;
 512+		b = num_regs & 0b0000111100001111;
 513+		num_regs = a + b;
 514+		a = (num_regs & 0b1111111100000000) >> 8;
 515+		b = num_regs & 0b0000000011111111;
 516+		num_regs = a + b;
 517+	}
 518+	if(inst->src.addr_mode == MODE_REG) {
 519+		//reg to mem
 520+		early_cycles = 8;
 521+		switch (inst->dst.addr_mode)
 522+		{
 523+		case MODE_AREG_INDIRECT:
 524+		case MODE_AREG_PREDEC:
 525+			areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
 526+			break;
 527+		case MODE_AREG_DISPLACE:
 528+			early_cycles += BUS;
 529+			calc_areg_displace(opts, &inst->dst, opts->gen.scratch2);
 530+			break;
 531+		case MODE_AREG_INDEX_DISP8:
 532+			early_cycles += 6;
 533+			calc_areg_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 534+			break;
 535+		case MODE_PC_DISPLACE:
 536+			early_cycles += BUS;
 537+			ldi_native(opts, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2);
 538+			break;
 539+		case MODE_PC_INDEX_DISP8:
 540+			early_cycles += 6;
 541+			ldi_native(opts, inst->address+2, opts->gen.scratch2);
 542+			calc_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 543+		case MODE_ABSOLUTE:
 544+			early_cycles += 4;
 545+		case MODE_ABSOLUTE_SHORT:
 546+			early_cycles += 4;
 547+			ldi_native(opts, inst->dst.params.immed, opts->gen.scratch2);
 548+			break;
 549+		default:
 550+			m68k_disasm(inst, disasm_buf);
 551+			fatal_error("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode);
 552+		}
 553+		
 554+		cycles(&opts->gen, early_cycles);
 555+		if (num_regs <= 9) {
 556+			translate_movem_regtomem_reglist(opts, inst);
 557+		} else {
 558+			call(code, get_movem_impl(opts, inst));
 559+		}
 560+		if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
 561+			native_to_areg(opts, opts->gen.scratch2, inst->dst.params.regs.pri);
 562+		}
 563+	} else {
 564+		//mem to reg
 565+		early_cycles = 8; //includes prefetch
 566+		switch (inst->src.addr_mode)
 567+		{
 568+		case MODE_AREG_INDIRECT:
 569+		case MODE_AREG_POSTINC:
 570+			areg_to_native(opts, inst->src.params.regs.pri, opts->gen.scratch1);
 571+			break;
 572+		case MODE_AREG_DISPLACE:
 573+			early_cycles += BUS;
 574+			calc_areg_displace(opts, &inst->src, opts->gen.scratch1);
 575+			break;
 576+		case MODE_AREG_INDEX_DISP8:
 577+			early_cycles += 6;
 578+			calc_areg_index_disp8(opts, &inst->src, opts->gen.scratch1);
 579+			break;
 580+		case MODE_PC_DISPLACE:
 581+			early_cycles += BUS;
 582+			ldi_native(opts, inst->src.params.regs.displacement + inst->address+2, opts->gen.scratch1);
 583+			break;
 584+		case MODE_PC_INDEX_DISP8:
 585+			early_cycles += 6;
 586+			ldi_native(opts, inst->address+2, opts->gen.scratch1);
 587+			calc_index_disp8(opts, &inst->src, opts->gen.scratch1);
 588+			break;
 589+		case MODE_ABSOLUTE:
 590+			early_cycles += 4;
 591+		case MODE_ABSOLUTE_SHORT:
 592+			early_cycles += 4;
 593+			ldi_native(opts, inst->src.params.immed, opts->gen.scratch1);
 594+			break;
 595+		default:
 596+			m68k_disasm(inst, disasm_buf);
 597+			fatal_error("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode);
 598+		}
 599+		cycles(&opts->gen, early_cycles);
 600+		
 601+		if (num_regs <= 9) {
 602+			translate_movem_memtoreg_reglist(opts, inst);
 603+		} else {
 604+			call(code, get_movem_impl(opts, inst));
 605+		}
 606+		if (inst->src.addr_mode == MODE_AREG_POSTINC) {
 607+			native_to_areg(opts, opts->gen.scratch1, inst->src.params.regs.pri);
 608+		}
 609+		//Extra read
 610+		call(code, opts->read_16);
 611+	}
 612+}
 613+
 614+static void translate_m68k_nop(m68k_options *opts, m68kinst *inst)
 615+{
 616+	cycles(&opts->gen, BUS);
 617+}
 618+
 619+void swap_ssp_usp(m68k_options * opts)
 620+{
 621+	areg_to_native(opts, 7, opts->gen.scratch2);
 622+	areg_to_native(opts, 8, opts->aregs[7]);
 623+	native_to_areg(opts, opts->gen.scratch2, 8);
 624+}
 625+
 626+static void translate_m68k_rte(m68k_options *opts, m68kinst *inst)
 627+{
 628+	m68k_trap_if_not_supervisor(opts, inst);
 629+	
 630+	code_info *code = &opts->gen.code;
 631+	//Read saved SR
 632+	areg_to_native(opts, 7, opts->gen.scratch1);
 633+	call(code, opts->read_16);
 634+	addi_areg(opts, 2, 7);
 635+	call(code, opts->set_sr);
 636+	//Read saved PC
 637+	areg_to_native(opts, 7, opts->gen.scratch1);
 638+	call(code, opts->read_32);
 639+	addi_areg(opts, 4, 7);
 640+	check_user_mode_swap_ssp_usp(opts);
 641+	cycles(&opts->gen, 2*BUS);
 642+	//Get native address, sync components, recalculate integer points and jump to returned address
 643+	call(code, opts->native_addr_and_sync);
 644+	jmp_r(code, opts->gen.scratch1);
 645+}
 646+
 647+code_ptr get_native_address(m68k_options *opts, uint32_t address)
 648+{
 649+	native_map_slot * native_code_map = opts->gen.native_code_map;
 650+	
 651+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
 652+	if (mem_chunk) {
 653+		//calculate the lowest alias for this address
 654+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
 655+	} else {
 656+		address &= opts->gen.address_mask;
 657+	}
 658+	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
 659+	if (!native_code_map[chunk].base) {
 660+		return NULL;
 661+	}
 662+	uint32_t offset = address % NATIVE_CHUNK_SIZE;
 663+	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET || native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
 664+		return NULL;
 665+	}
 666+	return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
 667+}
 668+
 669+code_ptr get_native_from_context(m68k_context * context, uint32_t address)
 670+{
 671+	return get_native_address(context->options, address);
 672+}
 673+
 674+uint32_t get_instruction_start(m68k_options *opts, uint32_t address)
 675+{
 676+	native_map_slot * native_code_map = opts->gen.native_code_map;
 677+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
 678+	if (mem_chunk) {
 679+		//calculate the lowest alias for this address
 680+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
 681+	} else {
 682+		address &= opts->gen.address_mask;
 683+	}
 684+	
 685+	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
 686+	if (!native_code_map[chunk].base) {
 687+		return 0;
 688+	}
 689+	uint32_t offset = address % NATIVE_CHUNK_SIZE;
 690+	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
 691+		return 0;
 692+	}
 693+	while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
 694+	{
 695+		--address;
 696+		chunk = address / NATIVE_CHUNK_SIZE;
 697+		offset = address % NATIVE_CHUNK_SIZE;
 698+	}
 699+	return address;
 700+}
 701+
 702+static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size)
 703+{
 704+	m68k_options * opts = context->options;
 705+	native_map_slot * native_code_map = opts->gen.native_code_map;
 706+	uint32_t meta_off;
 707+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
 708+	if (mem_chunk) {
 709+		if (mem_chunk->flags & MMAP_CODE) {
 710+			uint32_t masked = (address - mem_chunk->start) & mem_chunk->mask;
 711+			uint32_t final_off = masked + meta_off;
 712+			uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
 713+			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
 714+
 715+			uint32_t slot = final_off / 1024;
 716+			if (!opts->gen.ram_inst_sizes[slot]) {
 717+				opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 512);
 718+			}
 719+			opts->gen.ram_inst_sizes[slot][(final_off/2) & 511] = native_size;
 720+
 721+			//TODO: Deal with case in which end of instruction is in a different memory chunk
 722+			masked = (address + size - 1) & mem_chunk->mask;
 723+			final_off = masked + meta_off;
 724+			ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
 725+			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
 726+		}
 727+		//calculate the lowest alias for this address
 728+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
 729+	} else {
 730+		address &= opts->gen.address_mask;
 731+	}
 732+	
 733+	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
 734+	if (!native_code_map[chunk].base) {
 735+		native_code_map[chunk].base = native_addr;
 736+		native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 737+		memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 738+	}
 739+	uint32_t offset = address % NATIVE_CHUNK_SIZE;
 740+	native_code_map[chunk].offsets[offset] = native_addr-native_code_map[chunk].base;
 741+	for(address++,size-=1; size; address++,size-=1) {
 742+		address &= opts->gen.address_mask;
 743+		chunk = address / NATIVE_CHUNK_SIZE;
 744+		offset = address % NATIVE_CHUNK_SIZE;
 745+		if (!native_code_map[chunk].base) {
 746+			native_code_map[chunk].base = native_addr;
 747+			native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 748+			memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
 749+		}
 750+		if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
 751+			//TODO: Better handling of overlapping instructions
 752+			native_code_map[chunk].offsets[offset] = EXTENSION_WORD;
 753+		}
 754+	}
 755+}
 756+
 757+static uint8_t get_native_inst_size(m68k_options * opts, uint32_t address)
 758+{
 759+	uint32_t meta_off;
 760+	memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
 761+	if (chunk) {
 762+		meta_off += (address - chunk->start) & chunk->mask;
 763+	}
 764+	uint32_t slot = meta_off/1024;
 765+	return opts->gen.ram_inst_sizes[slot][(meta_off/2)%512];
 766+}
 767+
 768+uint8_t m68k_is_terminal(m68kinst * inst)
 769+{
 770+	return inst->op == M68K_RTS || inst->op == M68K_RTE || inst->op == M68K_RTR || inst->op == M68K_JMP
 771+		|| inst->op == M68K_TRAP || inst->op == M68K_ILLEGAL || inst->op == M68K_INVALID
 772+		|| (inst->op == M68K_BCC && inst->extra.cond == COND_TRUE);
 773+}
 774+
 775+static void m68k_handle_deferred(m68k_context * context)
 776+{
 777+	m68k_options * opts = context->options;
 778+	process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
 779+	if (opts->gen.deferred) {
 780+		translate_m68k_stream(opts->gen.deferred->address, context);
 781+	}
 782+}
 783+
 784+uint16_t m68k_get_ir(m68k_context *context)
 785+{
 786+	uint32_t inst_addr = get_instruction_start(context->options, context->last_prefetch_address-2);
 787+	uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->options->gen);
 788+	if (native_addr) {
 789+		return *native_addr;
 790+	}
 791+	fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address);
 792+	return 0xFFFF;
 793+}
 794+
 795+static m68k_debug_handler find_breakpoint(m68k_context *context, uint32_t address)
 796+{
 797+	for (uint32_t i = 0; i < context->num_breakpoints; i++)
 798+	{
 799+		if (context->breakpoints[i].address == address) {
 800+			return context->breakpoints[i].handler;
 801+		}
 802+	}
 803+	return NULL;
 804+}
 805+
 806+void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler)
 807+{
 808+	if (!find_breakpoint(context, address)) {
 809+		if (context->bp_storage == context->num_breakpoints) {
 810+			context->bp_storage *= 2;
 811+			if (context->bp_storage < 4) {
 812+				context->bp_storage = 4;
 813+			}
 814+			context->breakpoints = realloc(context->breakpoints, context->bp_storage * sizeof(m68k_breakpoint));
 815+		}
 816+		context->breakpoints[context->num_breakpoints++] = (m68k_breakpoint){
 817+			.handler = bp_handler,
 818+			.address = address
 819+		};
 820+		m68k_breakpoint_patch(context, address, bp_handler, NULL);
 821+	}
 822+}
 823+
 824+m68k_context *m68k_bp_dispatcher(m68k_context *context, uint32_t address)
 825+{
 826+	m68k_debug_handler handler = find_breakpoint(context, address);
 827+	if (handler) {
 828+		handler(context, address);
 829+	} else {
 830+		//spurious breakoint?
 831+		warning("Spurious breakpoing at %X\n", address);
 832+		remove_breakpoint(context, address);
 833+	}
 834+	
 835+	return context;
 836+}
 837+
 838+typedef enum {
 839+	RAW_FUNC = 1,
 840+	BINARY_ARITH,
 841+	UNARY_ARITH,
 842+	OP_FUNC
 843+} impl_type;
 844+
 845+typedef void (*raw_fun)(m68k_options * opts, m68kinst *inst);
 846+typedef void (*op_fun)(m68k_options * opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 847+
 848+typedef struct {
 849+	union {
 850+		raw_fun  raw;
 851+		uint32_t flag_mask;
 852+		op_fun   op;
 853+	} impl;
 854+	impl_type itype;
 855+} impl_info;
 856+
 857+#define RAW_IMPL(inst, fun)     [inst] = { .impl = { .raw = fun }, .itype = RAW_FUNC }
 858+#define OP_IMPL(inst, fun)      [inst] = { .impl = { .op = fun }, .itype = OP_FUNC }
 859+#define UNARY_IMPL(inst, mask)  [inst] = { .impl = { .flag_mask = mask }, .itype = UNARY_ARITH }
 860+#define BINARY_IMPL(inst, mask) [inst] = { .impl = { .flag_mask = mask}, .itype = BINARY_ARITH }
 861+
 862+static impl_info m68k_impls[] = {
 863+	//math
 864+	BINARY_IMPL(M68K_ADD, X|N|Z|V|C),
 865+	BINARY_IMPL(M68K_SUB, X|N|Z|V|C),
 866+	//z flag is special cased for ADDX/SUBX
 867+	BINARY_IMPL(M68K_ADDX, X|N|V|C),
 868+	BINARY_IMPL(M68K_SUBX, X|N|V|C),
 869+	OP_IMPL(M68K_ABCD, translate_m68k_abcd_sbcd),
 870+	OP_IMPL(M68K_SBCD, translate_m68k_abcd_sbcd),
 871+	OP_IMPL(M68K_NBCD, translate_m68k_abcd_sbcd),
 872+	BINARY_IMPL(M68K_AND, N|Z|V0|C0),
 873+	BINARY_IMPL(M68K_EOR, N|Z|V0|C0),
 874+	BINARY_IMPL(M68K_OR, N|Z|V0|C0),
 875+	RAW_IMPL(M68K_CMP, translate_m68k_cmp),
 876+	OP_IMPL(M68K_DIVS, translate_m68k_div),
 877+	OP_IMPL(M68K_DIVU, translate_m68k_div),
 878+	OP_IMPL(M68K_MULS, translate_m68k_mul),
 879+	OP_IMPL(M68K_MULU, translate_m68k_mul),
 880+	RAW_IMPL(M68K_EXT, translate_m68k_ext),
 881+	UNARY_IMPL(M68K_NEG, X|N|Z|V|C),
 882+	OP_IMPL(M68K_NEGX, translate_m68k_negx),
 883+	UNARY_IMPL(M68K_NOT, N|Z|V|C),
 884+	UNARY_IMPL(M68K_TST, N|Z|V0|C0),
 885+
 886+	//shift/rotate
 887+	OP_IMPL(M68K_ASL, translate_m68k_sl),
 888+	OP_IMPL(M68K_LSL, translate_m68k_sl),
 889+	OP_IMPL(M68K_ASR, translate_m68k_asr),
 890+	OP_IMPL(M68K_LSR, translate_m68k_lsr),
 891+	OP_IMPL(M68K_ROL, translate_m68k_rot),
 892+	OP_IMPL(M68K_ROR, translate_m68k_rot),
 893+	OP_IMPL(M68K_ROXL, translate_m68k_rot),
 894+	OP_IMPL(M68K_ROXR, translate_m68k_rot),
 895+	UNARY_IMPL(M68K_SWAP, N|Z|V0|C0),
 896+
 897+	//bit
 898+	OP_IMPL(M68K_BCHG, translate_m68k_bit),
 899+	OP_IMPL(M68K_BCLR, translate_m68k_bit),
 900+	OP_IMPL(M68K_BSET, translate_m68k_bit),
 901+	OP_IMPL(M68K_BTST, translate_m68k_bit),
 902+
 903+	//data movement
 904+	RAW_IMPL(M68K_MOVE, translate_m68k_move),
 905+	RAW_IMPL(M68K_MOVEM, translate_m68k_movem),
 906+	RAW_IMPL(M68K_MOVEP, translate_m68k_movep),
 907+	RAW_IMPL(M68K_MOVE_USP, translate_m68k_move_usp),
 908+	RAW_IMPL(M68K_LEA, translate_m68k_lea_pea),
 909+	RAW_IMPL(M68K_PEA, translate_m68k_lea_pea),
 910+	UNARY_IMPL(M68K_CLR, N0|V0|C0|Z1),
 911+	OP_IMPL(M68K_EXG, translate_m68k_exg),
 912+	RAW_IMPL(M68K_SCC, translate_m68k_scc),
 913+
 914+	//function calls and branches
 915+	RAW_IMPL(M68K_BCC, translate_m68k_bcc),
 916+	RAW_IMPL(M68K_BSR, translate_m68k_bsr),
 917+	RAW_IMPL(M68K_DBCC, translate_m68k_dbcc),
 918+	RAW_IMPL(M68K_JMP, translate_m68k_jmp_jsr),
 919+	RAW_IMPL(M68K_JSR, translate_m68k_jmp_jsr),
 920+	RAW_IMPL(M68K_RTS, translate_m68k_rts),
 921+	RAW_IMPL(M68K_RTE, translate_m68k_rte),
 922+	RAW_IMPL(M68K_RTR, translate_m68k_rtr),
 923+	RAW_IMPL(M68K_LINK, translate_m68k_link),
 924+	RAW_IMPL(M68K_UNLK, translate_m68k_unlk),
 925+
 926+	//SR/CCR stuff
 927+	RAW_IMPL(M68K_ANDI_CCR, translate_m68k_andi_ori_ccr_sr),
 928+	RAW_IMPL(M68K_ANDI_SR, translate_m68k_andi_ori_ccr_sr),
 929+	RAW_IMPL(M68K_EORI_CCR, translate_m68k_eori_ccr_sr),
 930+	RAW_IMPL(M68K_EORI_SR, translate_m68k_eori_ccr_sr),
 931+	RAW_IMPL(M68K_ORI_CCR, translate_m68k_andi_ori_ccr_sr),
 932+	RAW_IMPL(M68K_ORI_SR, translate_m68k_andi_ori_ccr_sr),
 933+	OP_IMPL(M68K_MOVE_CCR, translate_m68k_move_ccr_sr),
 934+	OP_IMPL(M68K_MOVE_SR, translate_m68k_move_ccr_sr),
 935+	OP_IMPL(M68K_MOVE_FROM_SR, translate_m68k_move_from_sr),
 936+	RAW_IMPL(M68K_STOP, translate_m68k_stop),
 937+
 938+	//traps
 939+	OP_IMPL(M68K_CHK, translate_m68k_chk),
 940+	RAW_IMPL(M68K_TRAP, translate_m68k_trap),
 941+	RAW_IMPL(M68K_A_LINE_TRAP, translate_m68k_trap),
 942+	RAW_IMPL(M68K_F_LINE_TRAP, translate_m68k_trap),
 943+	RAW_IMPL(M68K_TRAPV, translate_m68k_trapv),
 944+	RAW_IMPL(M68K_ILLEGAL, translate_m68k_illegal),
 945+	RAW_IMPL(M68K_INVALID, translate_m68k_illegal),
 946+
 947+	//misc
 948+	RAW_IMPL(M68K_NOP, translate_m68k_nop),
 949+	RAW_IMPL(M68K_RESET, translate_m68k_reset),
 950+	RAW_IMPL(M68K_TAS, translate_m68k_tas),
 951+};
 952+
 953+static void translate_m68k(m68k_context *context, m68kinst * inst)
 954+{
 955+	m68k_options * opts = context->options;
 956+	if (inst->address & 1) {
 957+		translate_m68k_odd(opts, inst);
 958+		return;
 959+	}
 960+	code_ptr start = opts->gen.code.cur;
 961+	check_cycles_int(&opts->gen, inst->address);
 962+	
 963+	m68k_debug_handler bp;
 964+	if ((bp = find_breakpoint(context, inst->address))) {
 965+		m68k_breakpoint_patch(context, inst->address, bp, start);
 966+	}
 967+	
 968+	//log_address(&opts->gen, inst->address, "M68K: %X @ %d\n");
 969+	if (
 970+		(inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE) 
 971+		|| (inst->dst.addr_mode > MODE_AREG && inst->dst.addr_mode < MODE_IMMEDIATE)
 972+		|| (inst->op == M68K_BCC && (inst->src.params.immed & 1))
 973+	) {
 974+		//Not accurate for all cases, but probably good enough for now
 975+		m68k_set_last_prefetch(opts, inst->address + inst->bytes);
 976+	}
 977+	impl_info * info = m68k_impls + inst->op;
 978+	if (info->itype == RAW_FUNC) {
 979+		info->impl.raw(opts, inst);
 980+		return;
 981+	}
 982+
 983+	host_ea src_op, dst_op;
 984+	uint8_t needs_int_latch = 0;
 985+	if (inst->src.addr_mode != MODE_UNUSED) {
 986+		needs_int_latch |= translate_m68k_op(inst, &src_op, opts, 0);
 987+	}
 988+	if (inst->dst.addr_mode != MODE_UNUSED) {
 989+		needs_int_latch |= translate_m68k_op(inst, &dst_op, opts, 1);
 990+	}
 991+	if (needs_int_latch) {
 992+		m68k_check_cycles_int_latch(opts);
 993+	}
 994+	if (info->itype == OP_FUNC) {
 995+		info->impl.op(opts, inst, &src_op, &dst_op);
 996+	} else if (info->itype == BINARY_ARITH) {
 997+		translate_m68k_arith(opts, inst, info->impl.flag_mask, &src_op, &dst_op);
 998+	} else if (info->itype == UNARY_ARITH) {
 999+		translate_m68k_unary(opts, inst, info->impl.flag_mask, inst->dst.addr_mode != MODE_UNUSED ? &dst_op : &src_op);
1000+	} else {
1001+		m68k_disasm(inst, disasm_buf);
1002+		fatal_error("%X: %s\ninstruction %d not yet implemented\n", inst->address, disasm_buf, inst->op);
1003+	}
1004+	if (opts->gen.code.stack_off) {
1005+		m68k_disasm(inst, disasm_buf);
1006+		fatal_error("Stack offset is %X after %X: %s\n", opts->gen.code.stack_off, inst->address, disasm_buf);
1007+	}
1008+}
1009+
1010+void translate_m68k_stream(uint32_t address, m68k_context * context)
1011+{
1012+	m68kinst instbuf;
1013+	m68k_options * opts = context->options;
1014+	code_info *code = &opts->gen.code;
1015+	if(get_native_address(opts, address)) {
1016+		return;
1017+	}
1018+	uint16_t *encoded, *next;
1019+	do {
1020+		if (opts->address_log) {
1021+			fprintf(opts->address_log, "%X\n", address);
1022+			fflush(opts->address_log);
1023+		}
1024+		do {
1025+			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
1026+			if (!encoded) {
1027+				code_ptr start = code->cur;
1028+				translate_out_of_bounds(opts, address);
1029+				code_ptr after = code->cur;
1030+				map_native_address(context, address, start, 2, after-start);
1031+				break;
1032+			}
1033+			code_ptr existing = get_native_address(opts, address);
1034+			if (existing) {
1035+				jmp(code, existing);
1036+				break;
1037+			}
1038+			next = m68k_decode(encoded, &instbuf, address);
1039+			if (instbuf.op == M68K_INVALID) {
1040+				instbuf.src.params.immed = *encoded;
1041+			}
1042+			uint16_t m68k_size = (next-encoded)*2;
1043+			address += m68k_size;
1044+			//char disbuf[1024];
1045+			//m68k_disasm(&instbuf, disbuf);
1046+			//printf("%X: %s\n", instbuf.address, disbuf);
1047+
1048+			//make sure the beginning of the code for an instruction is contiguous
1049+			check_code_prologue(code);
1050+			code_ptr start = code->cur;
1051+			translate_m68k(context, &instbuf);
1052+			code_ptr after = code->cur;
1053+			map_native_address(context, instbuf.address, start, m68k_size, after-start);
1054+		} while(!m68k_is_terminal(&instbuf) && !(address & 1));
1055+		process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
1056+		if (opts->gen.deferred) {
1057+			address = opts->gen.deferred->address;
1058+		}
1059+	} while(opts->gen.deferred);
1060+}
1061+
1062+void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
1063+{
1064+	m68k_options * opts = context->options;
1065+	code_info *code = &opts->gen.code;
1066+	uint8_t orig_size = get_native_inst_size(opts, address);
1067+	code_ptr orig_start = get_native_address(context->options, address);
1068+	uint32_t orig = address;
1069+	code_info orig_code = {orig_start, orig_start + orig_size + 5, 0};
1070+	uint16_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
1071+	m68kinst instbuf;
1072+	after = m68k_decode(inst, &instbuf, orig);
1073+	if (orig_size != MAX_NATIVE_SIZE) {
1074+		deferred_addr * orig_deferred = opts->gen.deferred;
1075+
1076+		//make sure we have enough code space for the max size instruction
1077+		check_alloc_code(code, MAX_NATIVE_SIZE);
1078+		code_ptr native_start = code->cur;
1079+		translate_m68k(context, &instbuf);
1080+		code_ptr native_end = code->cur;
1081+		/*uint8_t is_terminal = m68k_is_terminal(&instbuf);
1082+		if ((native_end - native_start) <= orig_size) {
1083+			code_ptr native_next;
1084+			if (!is_terminal) {
1085+				native_next = get_native_address(context->native_code_map, orig + (after-inst)*2);
1086+			}
1087+			if (is_terminal || (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - native_start)) > 5))) {
1088+				printf("Using original location: %p\n", orig_code.cur);
1089+				remove_deferred_until(&opts->gen.deferred, orig_deferred);
1090+				code_info tmp;
1091+				tmp.cur = code->cur;
1092+				tmp.last = code->last;
1093+				code->cur = orig_code.cur;
1094+				code->last = orig_code.last;
1095+				translate_m68k(context, &instbuf);
1096+				native_end = orig_code.cur = code->cur;
1097+				code->cur = tmp.cur;
1098+				code->last = tmp.last;
1099+				if (!is_terminal) {
1100+					nop_fill_or_jmp_next(&orig_code, orig_start + orig_size, native_next);
1101+				}
1102+				m68k_handle_deferred(context);
1103+				return orig_start;
1104+			}
1105+		}*/
1106+
1107+		map_native_address(context, instbuf.address, native_start, (after-inst)*2, MAX_NATIVE_SIZE);
1108+
1109+		jmp(&orig_code, native_start);
1110+		if (!m68k_is_terminal(&instbuf)) {
1111+			code_ptr native_end = code->cur;
1112+			code->cur = native_start + MAX_NATIVE_SIZE;
1113+			code_ptr rest = get_native_address_trans(context, orig + (after-inst)*2);
1114+			code_info tmp_code = {
1115+				.cur = native_end,
1116+				.last = native_start + MAX_NATIVE_SIZE,
1117+				.stack_off = code->stack_off
1118+			};
1119+			jmp(&tmp_code, rest);
1120+		} else {
1121+			code->cur = native_start + MAX_NATIVE_SIZE;
1122+		}
1123+		m68k_handle_deferred(context);
1124+		return native_start;
1125+	} else {
1126+		code_info tmp = *code;
1127+		*code = orig_code;
1128+		translate_m68k(context, &instbuf);
1129+		orig_code = *code;
1130+		*code = tmp;
1131+		if (!m68k_is_terminal(&instbuf)) {
1132+			jmp(&orig_code, get_native_address_trans(context, orig + (after-inst)*2));
1133+		}
1134+		m68k_handle_deferred(context);
1135+		return orig_start;
1136+	}
1137+}
1138+
1139+code_ptr get_native_address_trans(m68k_context * context, uint32_t address)
1140+{
1141+	code_ptr ret = get_native_address(context->options, address);
1142+	if (!ret) {
1143+		translate_m68k_stream(address, context);
1144+		ret = get_native_address(context->options, address);
1145+	}
1146+	return ret;
1147+}
1148+
1149+void remove_breakpoint(m68k_context * context, uint32_t address)
1150+{
1151+	for (uint32_t i = 0; i < context->num_breakpoints; i++)
1152+	{
1153+		if (context->breakpoints[i].address == address) {
1154+			if (i != (context->num_breakpoints-1)) {
1155+				context->breakpoints[i] = context->breakpoints[context->num_breakpoints-1];
1156+			}
1157+			context->num_breakpoints--;
1158+			break;
1159+		}
1160+	}
1161+	code_ptr native = get_native_address(context->options, address);
1162+	if (!native) {
1163+		return;
1164+	}
1165+	code_info tmp = context->options->gen.code;
1166+	context->options->gen.code.cur = native;
1167+	context->options->gen.code.last = native + MAX_NATIVE_SIZE;
1168+	check_cycles_int(&context->options->gen, address);
1169+	context->options->gen.code = tmp;
1170+}
1171+
1172+void start_68k_context(m68k_context * context, uint32_t address)
1173+{
1174+	code_ptr addr = get_native_address_trans(context, address);
1175+	m68k_options * options = context->options;
1176+	options->start_context(addr, context);
1177+}
1178+
1179+void resume_68k(m68k_context *context)
1180+{
1181+	code_ptr addr = context->resume_pc;
1182+	context->resume_pc = NULL;
1183+	m68k_options * options = context->options;
1184+	context->should_return = 0;
1185+	options->start_context(addr, context);
1186+}
1187+
1188+void m68k_reset(m68k_context * context)
1189+{
1190+	//TODO: Actually execute the M68K reset vector rather than simulating some of its behavior
1191+	uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->options->gen);
1192+	context->aregs[7] = reset_vec[0] << 16 | reset_vec[1];
1193+	uint32_t address = reset_vec[2] << 16 | reset_vec[3];
1194+	start_68k_context(context, address);
1195+}
1196+
1197+void m68k_options_free(m68k_options *opts)
1198+{
1199+	for (uint32_t address = 0; address < opts->gen.address_mask; address += NATIVE_CHUNK_SIZE)
1200+	{
1201+		uint32_t chunk = address / NATIVE_CHUNK_SIZE;
1202+		if (opts->gen.native_code_map[chunk].base) {
1203+			free(opts->gen.native_code_map[chunk].offsets);
1204+		}
1205+	}
1206+	free(opts->gen.native_code_map);
1207+	uint32_t ram_inst_slots = ram_size(&opts->gen) / 1024;
1208+	for (uint32_t i = 0; i < ram_inst_slots; i++)
1209+	{
1210+		free(opts->gen.ram_inst_sizes[i]);
1211+	}
1212+	free(opts->gen.ram_inst_sizes);
1213+	free(opts->big_movem);
1214+	free(opts);
1215+}
1216+
1217+
1218+m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler)
1219+{
1220+	m68k_context * context = calloc(1, sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8);
1221+	context->options = opts;
1222+	context->int_cycle = CYCLE_NEVER;
1223+	context->status = 0x27;
1224+	context->reset_handler = (code_ptr)reset_handler;
1225+	return context;
1226+}
1227+
1228+void m68k_serialize(m68k_context *context, uint32_t pc, serialize_buffer *buf)
1229+{
1230+	for (int i = 0; i < 8; i++)
1231+	{
1232+		save_int32(buf, context->dregs[i]);
1233+	}
1234+	for (int i = 0; i < 9; i++)
1235+	{
1236+		save_int32(buf, context->aregs[i]);
1237+	}
1238+	save_int32(buf, pc);
1239+	uint16_t sr = context->status << 3;
1240+	for (int flag = 4; flag >= 0; flag--) {
1241+		sr <<= 1;
1242+		sr |= context->flags[flag] != 0;
1243+	}
1244+	save_int16(buf, sr);
1245+	save_int32(buf, context->current_cycle);
1246+	save_int32(buf, context->int_cycle);
1247+	save_int8(buf, context->int_num);
1248+	save_int8(buf, context->int_pending);
1249+	save_int8(buf, context->trace_pending);
1250+}
1251+
1252+void m68k_deserialize(deserialize_buffer *buf, void *vcontext)
1253+{
1254+	m68k_context *context = vcontext;
1255+	for (int i = 0; i < 8; i++)
1256+	{
1257+		context->dregs[i] = load_int32(buf);
1258+	}
1259+	for (int i = 0; i < 9; i++)
1260+	{
1261+		context->aregs[i] = load_int32(buf);
1262+	}
1263+	//hack until both PC and IR registers are represented properly
1264+	context->last_prefetch_address = load_int32(buf);
1265+	uint16_t sr = load_int16(buf);
1266+	context->status = sr >> 8;
1267+	for (int flag = 0; flag < 5; flag++)
1268+	{
1269+		context->flags[flag] = sr & 1;
1270+		sr >>= 1;
1271+	}
1272+	context->current_cycle = load_int32(buf);
1273+	context->int_cycle = load_int32(buf);
1274+	context->int_num = load_int8(buf);
1275+	context->int_pending = load_int8(buf);
1276+	context->trace_pending = load_int8(buf);
1277+}
+124, -0
  1@@ -0,0 +1,124 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef M68K_CORE_H_
  8+#define M68K_CORE_H_
  9+#include <stdint.h>
 10+#include <stdio.h>
 11+#include "backend.h"
 12+#include "serialize.h"
 13+//#include "68kinst.h"
 14+struct m68kinst;
 15+
 16+#define NUM_MEM_AREAS 8
 17+#define NATIVE_MAP_CHUNKS (64*1024)
 18+#define NATIVE_CHUNK_SIZE ((16 * 1024 * 1024 / NATIVE_MAP_CHUNKS))
 19+#define MAX_NATIVE_SIZE 255
 20+
 21+#define M68K_OPT_BROKEN_READ_MODIFY 1
 22+
 23+#define INT_PENDING_SR_CHANGE 254
 24+#define INT_PENDING_NONE 255
 25+
 26+#define M68K_STATUS_TRACE 0x80
 27+
 28+typedef void (*start_fun)(uint8_t * addr, void * context);
 29+
 30+typedef struct {
 31+	code_ptr impl;
 32+	uint16_t reglist;
 33+	uint8_t  reg_to_mem;
 34+	uint8_t  size;
 35+	int8_t   dir;
 36+} movem_fun;
 37+
 38+typedef struct {
 39+	cpu_options     gen;
 40+
 41+	int8_t          dregs[8];
 42+	int8_t          aregs[8];
 43+	int8_t			flag_regs[5];
 44+	FILE            *address_log;
 45+	code_ptr        read_16;
 46+	code_ptr        write_16;
 47+	code_ptr        read_8;
 48+	code_ptr        write_8;
 49+	code_ptr        read_32;
 50+	code_ptr        write_32_lowfirst;
 51+	code_ptr        write_32_highfirst;
 52+	code_ptr        do_sync;
 53+	code_ptr        handle_int_latch;
 54+	code_ptr        trap;
 55+	start_fun       start_context;
 56+	code_ptr        retrans_stub;
 57+	code_ptr        native_addr;
 58+	code_ptr        native_addr_and_sync;
 59+	code_ptr		get_sr;
 60+	code_ptr		set_sr;
 61+	code_ptr		set_ccr;
 62+	code_ptr        bp_stub;
 63+	code_info       extra_code;
 64+	movem_fun       *big_movem;
 65+	uint32_t        num_movem;
 66+	uint32_t        movem_storage;
 67+	code_word       prologue_start;
 68+} m68k_options;
 69+
 70+typedef struct m68k_context m68k_context;
 71+typedef void (*m68k_debug_handler)(m68k_context *context, uint32_t pc);
 72+
 73+typedef struct {
 74+	m68k_debug_handler handler;
 75+	uint32_t           address;
 76+} m68k_breakpoint;
 77+
 78+struct m68k_context {
 79+	uint8_t         flags[5];
 80+	uint8_t         status;
 81+	uint16_t        int_ack;
 82+	uint32_t        dregs[8];
 83+	uint32_t        aregs[9];
 84+	uint32_t		target_cycle; //cycle at which the next synchronization or interrupt occurs
 85+	uint32_t		current_cycle;
 86+	uint32_t        sync_cycle;
 87+	uint32_t        int_cycle;
 88+	uint32_t        int_num;
 89+	uint32_t        last_prefetch_address;
 90+	uint16_t        *mem_pointers[NUM_MEM_AREAS];
 91+	code_ptr        resume_pc;
 92+	code_ptr        reset_handler;
 93+	m68k_options    *options;
 94+	void            *system;
 95+	m68k_breakpoint *breakpoints;
 96+	uint32_t        num_breakpoints;
 97+	uint32_t        bp_storage;
 98+	uint8_t         int_pending;
 99+	uint8_t         trace_pending;
100+	uint8_t         should_return;
101+	uint8_t         ram_code_flags[];
102+};
103+
104+typedef m68k_context *(*m68k_reset_handler)(m68k_context *context);
105+
106+
107+void translate_m68k_stream(uint32_t address, m68k_context * context);
108+void start_68k_context(m68k_context * context, uint32_t address);
109+void resume_68k(m68k_context *context);
110+void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider);
111+m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler);
112+void m68k_reset(m68k_context * context);
113+void m68k_options_free(m68k_options *opts);
114+void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler);
115+void remove_breakpoint(m68k_context * context, uint32_t address);
116+m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context);
117+uint32_t get_instruction_start(m68k_options *opts, uint32_t address);
118+uint16_t m68k_get_ir(m68k_context *context);
119+void m68k_print_regs(m68k_context * context);
120+void m68k_invalidate_code_range(m68k_context *context, uint32_t start, uint32_t end);
121+void m68k_serialize(m68k_context *context, uint32_t pc, serialize_buffer *buf);
122+void m68k_deserialize(deserialize_buffer *buf, void *vcontext);
123+
124+#endif //M68K_CORE_H_
125+
+3219, -0
   1@@ -0,0 +1,3219 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "gen_x86.h"
   8+#include "m68k_core.h"
   9+#include "m68k_internal.h"
  10+#include "68kinst.h"
  11+#include "mem.h"
  12+#include "backend.h"
  13+#include "util.h"
  14+#include <stdio.h>
  15+#include <stddef.h>
  16+#include <stdlib.h>
  17+#include <string.h>
  18+
  19+enum {
  20+	FLAG_X,
  21+	FLAG_N,
  22+	FLAG_Z,
  23+	FLAG_V,
  24+	FLAG_C
  25+};
  26+
  27+void set_flag(m68k_options * opts, uint8_t val, uint8_t flag)
  28+{
  29+	if (opts->flag_regs[flag] >= 0) {
  30+		mov_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B);
  31+	} else {
  32+		int8_t offset = offsetof(m68k_context, flags) + flag;
  33+		if (offset) {
  34+			mov_irdisp(&opts->gen.code, val, opts->gen.context_reg, offset, SZ_B);
  35+		} else {
  36+			mov_irind(&opts->gen.code, val, opts->gen.context_reg, SZ_B);
  37+		}
  38+	}
  39+}
  40+
  41+void set_flag_cond(m68k_options *opts, uint8_t cond, uint8_t flag)
  42+{
  43+	if (opts->flag_regs[flag] >= 0) {
  44+		setcc_r(&opts->gen.code, cond, opts->flag_regs[flag]);
  45+	} else {
  46+		int8_t offset = offsetof(m68k_context, flags) + flag;
  47+		if (offset) {
  48+			setcc_rdisp(&opts->gen.code, cond, opts->gen.context_reg, offset);
  49+		} else {
  50+			setcc_rind(&opts->gen.code, cond, opts->gen.context_reg);
  51+		}
  52+	}
  53+}
  54+
  55+void check_flag(m68k_options *opts, uint8_t flag)
  56+{
  57+	if (opts->flag_regs[flag] >= 0) {
  58+		cmp_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B);
  59+	} else {
  60+		cmp_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
  61+	}
  62+}
  63+
  64+void flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
  65+{
  66+	if (opts->flag_regs[flag] >= 0) {
  67+		mov_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
  68+	} else {
  69+		int8_t offset = offsetof(m68k_context, flags) + flag;
  70+		if (offset) {
  71+			mov_rdispr(&opts->gen.code, opts->gen.context_reg, offset, reg, SZ_B);
  72+		} else {
  73+			mov_rindr(&opts->gen.code, opts->gen.context_reg, reg, SZ_B);
  74+		}
  75+	}
  76+}
  77+
  78+void reg_to_flag(m68k_options *opts, uint8_t reg, uint8_t flag)
  79+{
  80+	if (opts->flag_regs[flag] >= 0) {
  81+		mov_rr(&opts->gen.code, reg, opts->flag_regs[flag], SZ_B);
  82+	} else {
  83+		int8_t offset = offsetof(m68k_context, flags) + flag;
  84+		if (offset) {
  85+			mov_rrdisp(&opts->gen.code, reg, opts->gen.context_reg, offset, SZ_B);
  86+		} else {
  87+			mov_rrind(&opts->gen.code, reg, opts->gen.context_reg, SZ_B);
  88+		}
  89+	}
  90+}
  91+
  92+void flag_to_flag(m68k_options *opts, uint8_t flag1, uint8_t flag2)
  93+{
  94+	code_info *code = &opts->gen.code;
  95+	if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) {
  96+		mov_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B);
  97+	} else if(opts->flag_regs[flag1] >= 0) {
  98+		mov_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
  99+	} else if (opts->flag_regs[flag2] >= 0) {
 100+		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->flag_regs[flag2], SZ_B);
 101+	} else {
 102+		push_r(code, opts->gen.scratch1);
 103+		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B);
 104+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 105+		pop_r(code, opts->gen.scratch1);
 106+	}
 107+}
 108+
 109+void update_flags(m68k_options *opts, uint32_t update_mask)
 110+{
 111+	uint8_t native_flags[] = {0, CC_S, CC_Z, CC_O, CC_C};
 112+	for (int8_t flag = FLAG_C; flag >= FLAG_X; --flag)
 113+	{
 114+		if (update_mask & X0 << (flag*3)) {
 115+			set_flag(opts, 0, flag);
 116+		} else if(update_mask & X1 << (flag*3)) {
 117+			set_flag(opts, 1, flag);
 118+		} else if(update_mask & X << (flag*3)) {
 119+			if (flag == FLAG_X) {
 120+				if (opts->flag_regs[FLAG_C] >= 0 || !(update_mask & (C0|C1|C))) {
 121+					flag_to_flag(opts, FLAG_C, FLAG_X);
 122+				} else if(update_mask & C0) {
 123+					set_flag(opts, 0, flag);
 124+				} else if(update_mask & C1) {
 125+					set_flag(opts, 1, flag);
 126+				} else {
 127+					set_flag_cond(opts, CC_C, flag);
 128+				}
 129+			} else {
 130+				set_flag_cond(opts, native_flags[flag], flag);
 131+			}
 132+		}
 133+	}
 134+}
 135+
 136+void flag_to_carry(m68k_options * opts, uint8_t flag)
 137+{
 138+	if (opts->flag_regs[flag] >= 0) {
 139+		bt_ir(&opts->gen.code, 0, opts->flag_regs[flag], SZ_B);
 140+	} else {
 141+		bt_irdisp(&opts->gen.code, 0, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
 142+	}
 143+}
 144+
 145+void or_flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
 146+{
 147+	if (opts->flag_regs[flag] >= 0) {
 148+		or_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
 149+	} else {
 150+		or_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B);
 151+	}
 152+}
 153+
 154+void xor_flag_to_reg(m68k_options *opts, uint8_t flag, uint8_t reg)
 155+{
 156+	if (opts->flag_regs[flag] >= 0) {
 157+		xor_rr(&opts->gen.code, opts->flag_regs[flag], reg, SZ_B);
 158+	} else {
 159+		xor_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, reg, SZ_B);
 160+	}
 161+}
 162+
 163+void xor_flag(m68k_options *opts, uint8_t val, uint8_t flag)
 164+{
 165+	if (opts->flag_regs[flag] >= 0) {
 166+		xor_ir(&opts->gen.code, val, opts->flag_regs[flag], SZ_B);
 167+	} else {
 168+		xor_irdisp(&opts->gen.code, val, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, SZ_B);
 169+	}
 170+}
 171+
 172+void cmp_flags(m68k_options *opts, uint8_t flag1, uint8_t flag2)
 173+{
 174+	code_info *code = &opts->gen.code;
 175+	if (opts->flag_regs[flag1] >= 0 && opts->flag_regs[flag2] >= 0) {
 176+		cmp_rr(code, opts->flag_regs[flag1], opts->flag_regs[flag2], SZ_B);
 177+	} else if(opts->flag_regs[flag1] >= 0 || opts->flag_regs[flag2] >= 0) {
 178+		if (opts->flag_regs[flag2] >= 0) {
 179+			uint8_t tmp = flag1;
 180+			flag1 = flag2;
 181+			flag2 = tmp;
 182+		}
 183+		cmp_rrdisp(code, opts->flag_regs[flag1], opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 184+	} else {
 185+		mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag1, opts->gen.scratch1, SZ_B);
 186+		cmp_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, flags) + flag2, SZ_B);
 187+	}
 188+}
 189+
 190+void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 191+{
 192+	if (opts->aregs[reg] >= 0) {
 193+		mov_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D);
 194+	} else {
 195+		mov_rdispr(&opts->gen.code, opts->gen.context_reg,  areg_offset(reg), native_reg, SZ_D);
 196+	}
 197+}
 198+
 199+void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 200+{
 201+	if (opts->dregs[reg] >= 0) {
 202+		mov_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D);
 203+	} else {
 204+		mov_rdispr(&opts->gen.code, opts->gen.context_reg,  dreg_offset(reg), native_reg, SZ_D);
 205+	}
 206+}
 207+
 208+void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 209+{
 210+	if (opts->aregs[reg] >= 0) {
 211+		movsx_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_W, SZ_D);
 212+	} else {
 213+		movsx_rdispr(&opts->gen.code, opts->gen.context_reg,  areg_offset(reg), native_reg, SZ_W, SZ_D);
 214+	}
 215+}
 216+
 217+void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 218+{
 219+	if (opts->dregs[reg] >= 0) {
 220+		movsx_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_W, SZ_D);
 221+	} else {
 222+		movsx_rdispr(&opts->gen.code, opts->gen.context_reg,  dreg_offset(reg), native_reg, SZ_W, SZ_D);
 223+	}
 224+}
 225+
 226+void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg)
 227+	{
 228+	if (opts->aregs[reg] >= 0) {
 229+		mov_rr(&opts->gen.code, native_reg, opts->aregs[reg], SZ_D);
 230+	} else {
 231+		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, areg_offset(reg), SZ_D);
 232+	}
 233+}
 234+
 235+void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg)
 236+{
 237+	if (opts->dregs[reg] >= 0) {
 238+		mov_rr(&opts->gen.code, native_reg, opts->dregs[reg], SZ_D);
 239+	} else {
 240+		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, dreg_offset(reg), SZ_D);
 241+	}
 242+}
 243+
 244+void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg)
 245+{
 246+	if (opts->aregs[reg] >= 0) {
 247+		mov_ir(&opts->gen.code, value, opts->aregs[reg], SZ_D);
 248+	} else {
 249+		mov_irdisp(&opts->gen.code, value, opts->gen.context_reg, areg_offset(reg), SZ_D);
 250+	}
 251+}
 252+
 253+void ldi_native(m68k_options *opts, int32_t value, uint8_t reg)
 254+{
 255+	mov_ir(&opts->gen.code, value, reg, SZ_D);
 256+}
 257+
 258+void addi_native(m68k_options *opts, int32_t value, uint8_t reg)
 259+{
 260+	add_ir(&opts->gen.code, value, reg, SZ_D);
 261+			}
 262+
 263+void subi_native(m68k_options *opts, int32_t value, uint8_t reg)
 264+{
 265+	sub_ir(&opts->gen.code, value, reg, SZ_D);
 266+}
 267+
 268+void push_native(m68k_options *opts, uint8_t reg)
 269+{
 270+	push_r(&opts->gen.code, reg);
 271+}
 272+
 273+void pop_native(m68k_options *opts, uint8_t reg)
 274+{
 275+	pop_r(&opts->gen.code, reg);
 276+}
 277+
 278+void sign_extend16_native(m68k_options *opts, uint8_t reg)
 279+{
 280+	movsx_rr(&opts->gen.code, reg, reg, SZ_W, SZ_D);
 281+}
 282+
 283+void addi_areg(m68k_options *opts, int32_t val, uint8_t reg)
 284+{
 285+	if (opts->aregs[reg] >= 0) {
 286+		add_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D);
 287+	} else {
 288+		add_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D);
 289+	}
 290+}
 291+
 292+void subi_areg(m68k_options *opts, int32_t val, uint8_t reg)
 293+{
 294+	if (opts->aregs[reg] >= 0) {
 295+		sub_ir(&opts->gen.code, val, opts->aregs[reg], SZ_D);
 296+	} else {
 297+		sub_irdisp(&opts->gen.code, val, opts->gen.context_reg, areg_offset(reg), SZ_D);
 298+	}
 299+}
 300+
 301+void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 302+{
 303+	if (opts->aregs[reg] >= 0) {
 304+		add_rr(&opts->gen.code, opts->aregs[reg], native_reg, SZ_D);
 305+	} else {
 306+		add_rdispr(&opts->gen.code, opts->gen.context_reg, areg_offset(reg), native_reg, SZ_D);
 307+	}
 308+}
 309+
 310+void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg)
 311+{
 312+	if (opts->dregs[reg] >= 0) {
 313+		add_rr(&opts->gen.code, opts->dregs[reg], native_reg, SZ_D);
 314+	} else {
 315+		add_rdispr(&opts->gen.code, opts->gen.context_reg, dreg_offset(reg), native_reg, SZ_D);
 316+	}
 317+}
 318+
 319+void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 320+{
 321+	areg_to_native(opts, op->params.regs.pri, native_reg);
 322+	add_ir(&opts->gen.code, op->params.regs.displacement & 0x8000 ? op->params.regs.displacement | 0xFFFF0000 : op->params.regs.displacement, native_reg, SZ_D);
 323+}
 324+
 325+void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 326+{
 327+	uint8_t sec_reg = (op->params.regs.sec >> 1) & 0x7;
 328+	if (op->params.regs.sec & 1) {
 329+		if (op->params.regs.sec & 0x10) {
 330+			add_areg_native(opts, sec_reg, native_reg);
 331+		} else {
 332+			add_dreg_native(opts, sec_reg, native_reg);
 333+		}
 334+	} else {
 335+		uint8_t other_reg = native_reg == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1;
 336+		if (op->params.regs.sec & 0x10) {
 337+			areg_to_native_sx(opts, sec_reg, other_reg);
 338+		} else {
 339+			dreg_to_native_sx(opts, sec_reg, other_reg);
 340+		}
 341+		add_rr(&opts->gen.code, other_reg, native_reg, SZ_D);
 342+	}
 343+	if (op->params.regs.displacement) {
 344+		add_ir(&opts->gen.code, op->params.regs.displacement, native_reg, SZ_D);
 345+	}
 346+}
 347+
 348+void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg)
 349+{
 350+	areg_to_native(opts, op->params.regs.pri, native_reg);
 351+	calc_index_disp8(opts, op, native_reg);
 352+}
 353+
 354+void m68k_check_cycles_int_latch(m68k_options *opts)
 355+{
 356+	code_info *code = &opts->gen.code;
 357+	check_alloc_code(code, 3*MAX_INST_LEN);
 358+	uint8_t cc;
 359+	if (opts->gen.limit < 0) {
 360+		cmp_ir(code, 1, opts->gen.cycles, SZ_D);
 361+		cc = CC_NS;
 362+	} else {
 363+		cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
 364+		cc = CC_A;
 365+	}
 366+	code_ptr jmp_off = code->cur+1;
 367+	jcc(code, cc, jmp_off+1);
 368+	call(code, opts->handle_int_latch);
 369+	*jmp_off = code->cur - (jmp_off+1);
 370+}
 371+
 372+uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst)
 373+{
 374+	code_info *code = &opts->gen.code;
 375+	m68k_op_info *op = dst ? &inst->dst : &inst->src;
 376+	int8_t reg = native_reg(op, opts);
 377+	uint8_t sec_reg;
 378+	uint8_t ret = 1;
 379+	int32_t dec_amount, inc_amount;
 380+	if (reg >= 0) {
 381+		ea->mode = MODE_REG_DIRECT;
 382+		if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 383+			movsx_rr(code, reg, opts->gen.scratch1, SZ_W, SZ_D);
 384+			ea->base = opts->gen.scratch1;
 385+#ifdef X86_32
 386+		} else if (reg > RBX && inst->extra.size == OPSIZE_BYTE) {
 387+			mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 388+			ea->base = opts->gen.scratch1;
 389+#endif
 390+		} else {
 391+			ea->base = reg;
 392+		}
 393+		return 0;
 394+	}
 395+	switch (op->addr_mode)
 396+	{
 397+	case MODE_REG:
 398+	case MODE_AREG:
 399+		//We only get one memory parameter, so if the dst operand is a register in memory,
 400+		//we need to copy this to a temp register first if we're translating the src operand
 401+		if (dst || native_reg(&(inst->dst), opts) >= 0 || inst->dst.addr_mode == MODE_UNUSED || !(inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)
 402+		    || inst->op == M68K_EXG) {
 403+
 404+			ea->mode = MODE_REG_DISPLACE8;
 405+			ea->base = opts->gen.context_reg;
 406+			ea->disp = reg_offset(op);
 407+		} else {
 408+			if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 409+				movsx_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, SZ_W, SZ_D);
 410+			} else {
 411+				mov_rdispr(code, opts->gen.context_reg, reg_offset(op), opts->gen.scratch1, inst->extra.size);
 412+			}
 413+			ea->mode = MODE_REG_DIRECT;
 414+			ea->base = opts->gen.scratch1;
 415+			//we're explicitly handling the areg dest here, so we exit immediately
 416+			return 0;
 417+		}
 418+		ret = 0;
 419+		break;
 420+	case MODE_AREG_PREDEC:
 421+		if (dst && inst->src.addr_mode == MODE_AREG_PREDEC) {
 422+			push_r(code, opts->gen.scratch1);
 423+		}
 424+		dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 :1));
 425+		if (!dst) {
 426+			cycles(&opts->gen, PREDEC_PENALTY);
 427+		}
 428+		subi_areg(opts, dec_amount, op->params.regs.pri);
 429+	case MODE_AREG_INDIRECT:
 430+	case MODE_AREG_POSTINC:
 431+		areg_to_native(opts, op->params.regs.pri, opts->gen.scratch1);
 432+		m68k_read_size(opts, inst->extra.size);
 433+
 434+		if (dst) {
 435+			if (inst->src.addr_mode == MODE_AREG_PREDEC) {
 436+				//restore src operand to opts->gen.scratch2
 437+				pop_r(code, opts->gen.scratch2);
 438+			} else {
 439+				//save reg value in opts->gen.scratch2 so we can use it to save the result in memory later
 440+				areg_to_native(opts, op->params.regs.pri, opts->gen.scratch2);
 441+			}
 442+		}
 443+
 444+		if (op->addr_mode == MODE_AREG_POSTINC) {
 445+			inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (op->params.regs.pri == 7 ? 2 : 1));
 446+			addi_areg(opts, inc_amount, op->params.regs.pri);
 447+		}
 448+		ea->mode = MODE_REG_DIRECT;
 449+		ea->base = (!dst && inst->dst.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) ? opts->gen.scratch2 : opts->gen.scratch1;
 450+		break;
 451+	case MODE_AREG_DISPLACE:
 452+		cycles(&opts->gen, BUS);
 453+		calc_areg_displace(opts, op, opts->gen.scratch1);
 454+		if (dst) {
 455+			push_r(code, opts->gen.scratch1);
 456+		}
 457+		m68k_read_size(opts, inst->extra.size);
 458+		if (dst) {
 459+			pop_r(code, opts->gen.scratch2);
 460+		}
 461+
 462+		ea->mode = MODE_REG_DIRECT;
 463+		ea->base = opts->gen.scratch1;
 464+		break;
 465+	case MODE_AREG_INDEX_DISP8:
 466+		cycles(&opts->gen, 6);
 467+		calc_areg_index_disp8(opts, op, opts->gen.scratch1);
 468+		if (dst) {
 469+			push_r(code, opts->gen.scratch1);
 470+		}
 471+		m68k_read_size(opts, inst->extra.size);
 472+		if (dst) {
 473+			pop_r(code, opts->gen.scratch2);
 474+		}
 475+
 476+		ea->mode = MODE_REG_DIRECT;
 477+		ea->base = opts->gen.scratch1;
 478+		break;
 479+	case MODE_PC_DISPLACE:
 480+		cycles(&opts->gen, BUS);
 481+		mov_ir(code, op->params.regs.displacement + inst->address+2, opts->gen.scratch1, SZ_D);
 482+		if (dst) {
 483+			push_r(code, opts->gen.scratch1);
 484+		}
 485+		m68k_read_size(opts, inst->extra.size);
 486+		if (dst) {
 487+			pop_r(code, opts->gen.scratch2);
 488+		}
 489+
 490+		ea->mode = MODE_REG_DIRECT;
 491+		ea->base = opts->gen.scratch1;
 492+		break;
 493+	case MODE_PC_INDEX_DISP8:
 494+		cycles(&opts->gen, 6);
 495+		mov_ir(code, inst->address+2, opts->gen.scratch1, SZ_D);
 496+		calc_index_disp8(opts, op, opts->gen.scratch1);
 497+		if (dst) {
 498+			push_r(code, opts->gen.scratch1);
 499+		}
 500+		m68k_read_size(opts, inst->extra.size);
 501+		if (dst) {
 502+			pop_r(code, opts->gen.scratch2);
 503+		}
 504+
 505+		ea->mode = MODE_REG_DIRECT;
 506+		ea->base = opts->gen.scratch1;
 507+		break;
 508+	case MODE_ABSOLUTE:
 509+	case MODE_ABSOLUTE_SHORT:
 510+		cycles(&opts->gen, op->addr_mode == MODE_ABSOLUTE ? BUS*2 : BUS);
 511+		mov_ir(code, op->params.immed, opts->gen.scratch1, SZ_D);
 512+		if (dst) {
 513+			push_r(code, opts->gen.scratch1);
 514+		}
 515+		m68k_read_size(opts, inst->extra.size);
 516+		if (dst) {
 517+			pop_r(code, opts->gen.scratch2);
 518+		}
 519+
 520+		ea->mode = MODE_REG_DIRECT;
 521+		ea->base = opts->gen.scratch1;
 522+		break;
 523+	case MODE_IMMEDIATE:
 524+	case MODE_IMMEDIATE_WORD:
 525+		if (inst->variant != VAR_QUICK) {
 526+			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG && op->addr_mode == MODE_IMMEDIATE) ? BUS*2 : BUS);
 527+		}
 528+		ea->mode = MODE_IMMED;
 529+		ea->disp = op->params.immed;
 530+		//sign extend value when the destination is an address register
 531+		if (inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && ea->disp & 0x8000) {
 532+			ea->disp |= 0xFFFF0000;
 533+		}
 534+		return inst->variant != VAR_QUICK;
 535+	default:
 536+		m68k_disasm(inst, disasm_buf);
 537+		fatal_error("%X: %s\naddress mode %d not implemented (%s)\n", inst->address, disasm_buf, op->addr_mode, dst ? "dst" : "src");
 538+	}
 539+	if (!dst && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD) {
 540+		if (ea->mode == MODE_REG_DIRECT) {
 541+			movsx_rr(code, ea->base, opts->gen.scratch1, SZ_W, SZ_D);
 542+		} else {
 543+			movsx_rdispr(code, ea->base, ea->disp, opts->gen.scratch1, SZ_W, SZ_D);
 544+			ea->mode = MODE_REG_DIRECT;
 545+		}
 546+		ea->base = opts->gen.scratch1;
 547+	}
 548+	return ret;
 549+}
 550+
 551+void check_user_mode_swap_ssp_usp(m68k_options *opts)
 552+{
 553+	code_info * code = &opts->gen.code;
 554+	//Check if we've switched to user mode and swap stack pointers if needed
 555+	bt_irdisp(code, 5, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
 556+	code_ptr end_off = code->cur + 1;
 557+	jcc(code, CC_C, code->cur + 2);
 558+	swap_ssp_usp(opts);
 559+	*end_off = code->cur - (end_off + 1);
 560+}
 561+
 562+void translate_m68k_move(m68k_options * opts, m68kinst * inst)
 563+{
 564+	code_info *code = &opts->gen.code;
 565+	int8_t reg, flags_reg, sec_reg;
 566+	uint8_t dir = 0;
 567+	int32_t offset;
 568+	int32_t inc_amount, dec_amount;
 569+	host_ea src;
 570+	uint8_t needs_int_latch = translate_m68k_op(inst, &src, opts, 0);
 571+	reg = native_reg(&(inst->dst), opts);
 572+
 573+	if (inst->dst.addr_mode != MODE_AREG) {
 574+		if (src.mode == MODE_REG_DIRECT) {
 575+			flags_reg = src.base;
 576+		} else {
 577+			if (reg >= 0) {
 578+				flags_reg = reg;
 579+			} else {
 580+				if(src.mode == MODE_REG_DISPLACE8) {
 581+					mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 582+				} else {
 583+					mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 584+				}
 585+				src.mode = MODE_REG_DIRECT;
 586+				flags_reg = src.base = opts->gen.scratch1;
 587+			}
 588+		}
 589+	}
 590+	uint8_t size = inst->extra.size;
 591+	switch(inst->dst.addr_mode)
 592+	{
 593+	case MODE_AREG:
 594+		size = OPSIZE_LONG;
 595+	case MODE_REG:
 596+		if (reg >= 0) {
 597+			if (src.mode == MODE_REG_DIRECT) {
 598+				mov_rr(code, src.base, reg, size);
 599+			} else if (src.mode == MODE_REG_DISPLACE8) {
 600+				mov_rdispr(code, src.base, src.disp, reg, size);
 601+			} else {
 602+				mov_ir(code, src.disp, reg, size);
 603+			}
 604+		} else if(src.mode == MODE_REG_DIRECT) {
 605+			mov_rrdisp(code, src.base, opts->gen.context_reg, reg_offset(&(inst->dst)), size);
 606+		} else {
 607+			mov_irdisp(code, src.disp, opts->gen.context_reg, reg_offset(&(inst->dst)), size);
 608+		}
 609+		break;
 610+	case MODE_AREG_PREDEC:
 611+		dec_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
 612+	case MODE_AREG_INDIRECT:
 613+	case MODE_AREG_POSTINC:
 614+		if (src.mode == MODE_REG_DIRECT) {
 615+			if (src.base != opts->gen.scratch1) {
 616+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 617+			}
 618+		} else if (src.mode == MODE_REG_DISPLACE8) {
 619+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 620+		} else {
 621+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 622+		}
 623+		if (inst->dst.addr_mode == MODE_AREG_PREDEC) {
 624+			subi_areg(opts, dec_amount, inst->dst.params.regs.pri);
 625+		}
 626+		areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2);
 627+		break;
 628+	case MODE_AREG_DISPLACE:
 629+		cycles(&opts->gen, BUS);
 630+		calc_areg_displace(opts, &inst->dst, opts->gen.scratch2);
 631+		if (src.mode == MODE_REG_DIRECT) {
 632+			if (src.base != opts->gen.scratch1) {
 633+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 634+			}
 635+		} else if (src.mode == MODE_REG_DISPLACE8) {
 636+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 637+		} else {
 638+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 639+		}
 640+		break;
 641+	case MODE_AREG_INDEX_DISP8:
 642+		cycles(&opts->gen, 6);//TODO: Check to make sure this is correct
 643+		//calc_areg_index_disp8 will clober scratch1 when a 16-bit index is used
 644+		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 645+			push_r(code, opts->gen.scratch1);
 646+		}
 647+		calc_areg_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 648+		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 649+			pop_r(code, opts->gen.scratch1);
 650+		}
 651+		if (src.mode == MODE_REG_DIRECT) {
 652+			if (src.base != opts->gen.scratch1) {
 653+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 654+			}
 655+		} else if (src.mode == MODE_REG_DISPLACE8) {
 656+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 657+		} else {
 658+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 659+		}
 660+		break;
 661+	case MODE_PC_DISPLACE:
 662+		cycles(&opts->gen, BUS);
 663+		mov_ir(code, inst->dst.params.regs.displacement + inst->address+2, opts->gen.scratch2, SZ_D);
 664+		if (src.mode == MODE_REG_DIRECT) {
 665+			if (src.base != opts->gen.scratch1) {
 666+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 667+			}
 668+		} else if (src.mode == MODE_REG_DISPLACE8) {
 669+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 670+		} else {
 671+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 672+		}
 673+		break;
 674+	case MODE_PC_INDEX_DISP8:
 675+		cycles(&opts->gen, 6);//TODO: Check to make sure this is correct
 676+		mov_ir(code, inst->address, opts->gen.scratch2, SZ_D);
 677+		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 678+			push_r(code, opts->gen.scratch1);
 679+		}
 680+		calc_index_disp8(opts, &inst->dst, opts->gen.scratch2);
 681+		if (src.base == opts->gen.scratch1 && !(inst->dst.params.regs.sec & 1)) {
 682+			pop_r(code, opts->gen.scratch1);
 683+		}
 684+		if (src.mode == MODE_REG_DIRECT) {
 685+			if (src.base != opts->gen.scratch1) {
 686+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 687+			}
 688+		} else if (src.mode == MODE_REG_DISPLACE8) {
 689+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 690+		} else {
 691+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 692+		}
 693+		break;
 694+	case MODE_ABSOLUTE:
 695+	case MODE_ABSOLUTE_SHORT:
 696+		if (src.mode == MODE_REG_DIRECT) {
 697+			if (src.base != opts->gen.scratch1) {
 698+				mov_rr(code, src.base, opts->gen.scratch1, inst->extra.size);
 699+			}
 700+		} else if (src.mode == MODE_REG_DISPLACE8) {
 701+			mov_rdispr(code, src.base, src.disp, opts->gen.scratch1, inst->extra.size);
 702+		} else {
 703+			mov_ir(code, src.disp, opts->gen.scratch1, inst->extra.size);
 704+		}
 705+		if (inst->dst.addr_mode == MODE_ABSOLUTE) {
 706+			cycles(&opts->gen, BUS*2);
 707+		} else {
 708+			cycles(&opts->gen, BUS);
 709+		}
 710+		mov_ir(code, inst->dst.params.immed, opts->gen.scratch2, SZ_D);
 711+		break;
 712+	default:
 713+		m68k_disasm(inst, disasm_buf);
 714+		fatal_error("%X: %s\naddress mode %d not implemented (move dst)\n", inst->address, disasm_buf, inst->dst.addr_mode);
 715+	}
 716+
 717+	if (inst->dst.addr_mode != MODE_AREG) {
 718+		cmp_ir(code, 0, flags_reg, inst->extra.size);
 719+		update_flags(opts, N|Z|V0|C0);
 720+	}
 721+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG) {
 722+		if (inst->extra.size == OPSIZE_LONG) {
 723+			//We want the int latch to occur between the two writes,
 724+			//but that's a pain to do without refactoring how 32-bit writes work
 725+			//workaround it by temporarily increasing the cycle count before the check
 726+			cycles(&opts->gen, BUS);
 727+		}
 728+		m68k_check_cycles_int_latch(opts);
 729+		if (inst->extra.size == OPSIZE_LONG) {
 730+			//and then backing out that extra increment here before the write happens
 731+			cycles(&opts->gen, -BUS);
 732+		}
 733+		m68k_write_size(opts, inst->extra.size, inst->dst.addr_mode == MODE_AREG_PREDEC);
 734+		if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
 735+			inc_amount = inst->extra.size == OPSIZE_WORD ? 2 : (inst->extra.size == OPSIZE_LONG ? 4 : (inst->dst.params.regs.pri == 7 ? 2 : 1));
 736+			addi_areg(opts, inc_amount, inst->dst.params.regs.pri);
 737+		}
 738+	} else if (needs_int_latch) {
 739+		m68k_check_cycles_int_latch(opts);
 740+	}
 741+
 742+	//add cycles for prefetch
 743+	cycles(&opts->gen, BUS);
 744+}
 745+
 746+void translate_m68k_ext(m68k_options * opts, m68kinst * inst)
 747+{
 748+	code_info *code = &opts->gen.code;
 749+	host_ea dst_op;
 750+	uint8_t dst_size = inst->extra.size;
 751+	inst->extra.size--;
 752+	translate_m68k_op(inst, &dst_op, opts, 1);
 753+	if (dst_op.mode == MODE_REG_DIRECT) {
 754+		movsx_rr(code, dst_op.base, dst_op.base, inst->extra.size, dst_size);
 755+		cmp_ir(code, 0, dst_op.base, dst_size);
 756+	} else {
 757+		movsx_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, inst->extra.size, dst_size);
 758+		cmp_ir(code, 0, opts->gen.scratch1, dst_size);
 759+		mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, dst_size);
 760+	}
 761+	inst->extra.size = dst_size;
 762+	update_flags(opts, N|V0|C0|Z);
 763+	cycles(&opts->gen, BUS);
 764+	//M68K EXT only operates on registers so no need for a call to save result here
 765+}
 766+
 767+uint8_t m68k_eval_cond(m68k_options * opts, uint8_t cc)
 768+{
 769+	uint8_t cond = CC_NZ;
 770+	switch (cc)
 771+	{
 772+	case COND_HIGH:
 773+		cond = CC_Z;
 774+	case COND_LOW_SAME:
 775+		flag_to_reg(opts, FLAG_Z, opts->gen.scratch1);
 776+		or_flag_to_reg(opts, FLAG_C, opts->gen.scratch1);
 777+		break;
 778+	case COND_CARRY_CLR:
 779+		cond = CC_Z;
 780+	case COND_CARRY_SET:
 781+		check_flag(opts, FLAG_C);
 782+		break;
 783+	case COND_NOT_EQ:
 784+		cond = CC_Z;
 785+	case COND_EQ:
 786+		check_flag(opts, FLAG_Z);
 787+		break;
 788+	case COND_OVERF_CLR:
 789+		cond = CC_Z;
 790+	case COND_OVERF_SET:
 791+		check_flag(opts, FLAG_V);
 792+		break;
 793+	case COND_PLUS:
 794+		cond = CC_Z;
 795+	case COND_MINUS:
 796+		check_flag(opts, FLAG_N);
 797+		break;
 798+	case COND_GREATER_EQ:
 799+		cond = CC_Z;
 800+	case COND_LESS:
 801+		cmp_flags(opts, FLAG_N, FLAG_V);
 802+		break;
 803+	case COND_GREATER:
 804+		cond = CC_Z;
 805+	case COND_LESS_EQ:
 806+		flag_to_reg(opts, FLAG_V, opts->gen.scratch1);
 807+		xor_flag_to_reg(opts, FLAG_N, opts->gen.scratch1);
 808+		or_flag_to_reg(opts, FLAG_Z, opts->gen.scratch1);
 809+		break;
 810+	}
 811+	return cond;
 812+}
 813+
 814+void translate_m68k_bcc(m68k_options * opts, m68kinst * inst)
 815+{
 816+	code_info *code = &opts->gen.code;
 817+	
 818+	int32_t disp = inst->src.params.immed;
 819+	uint32_t after = inst->address + 2;
 820+	if (inst->extra.cond == COND_TRUE) {
 821+		cycles(&opts->gen, 10);
 822+		jump_m68k_abs(opts, after + disp);
 823+	} else {
 824+		uint8_t cond = m68k_eval_cond(opts, inst->extra.cond);
 825+		code_ptr do_branch = code->cur + 1;
 826+		jcc(code, cond, do_branch);
 827+		
 828+		cycles(&opts->gen, inst->variant == VAR_BYTE ? 8 : 12);
 829+		code_ptr done = code->cur + 1;
 830+		jmp(code, done);
 831+		
 832+		*do_branch = code->cur - (do_branch + 1);
 833+		cycles(&opts->gen, 10);
 834+		code_ptr dest_addr = get_native_address(opts, after + disp);
 835+		if (!dest_addr) {
 836+			opts->gen.deferred = defer_address(opts->gen.deferred, after + disp, code->cur + 1);
 837+			//dummy address to be replaced later, make sure it generates a 4-byte displacement
 838+			dest_addr = code->cur + 256;
 839+		}
 840+		jmp(code, dest_addr);
 841+		
 842+		*done = code->cur - (done + 1);
 843+	}
 844+}
 845+
 846+void translate_m68k_scc(m68k_options * opts, m68kinst * inst)
 847+{
 848+	code_info *code = &opts->gen.code;
 849+	uint8_t cond = inst->extra.cond;
 850+	host_ea dst_op;
 851+	inst->extra.size = OPSIZE_BYTE;
 852+	translate_m68k_op(inst, &dst_op, opts, 1);
 853+	if (cond == COND_TRUE || cond == COND_FALSE) {
 854+		if ((inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG) && inst->extra.cond == COND_TRUE) {
 855+			cycles(&opts->gen, 6);
 856+		} else {
 857+			cycles(&opts->gen, BUS);
 858+		}
 859+		if (dst_op.mode == MODE_REG_DIRECT) {
 860+			mov_ir(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, SZ_B);
 861+		} else {
 862+			mov_irdisp(code, cond == COND_TRUE ? 0xFF : 0, dst_op.base, dst_op.disp, SZ_B);
 863+		}
 864+	} else {
 865+		uint8_t cc = m68k_eval_cond(opts, cond);
 866+		check_alloc_code(code, 6*MAX_INST_LEN);
 867+		code_ptr true_off = code->cur + 1;
 868+		jcc(code, cc, code->cur+2);
 869+		cycles(&opts->gen, BUS);
 870+		if (dst_op.mode == MODE_REG_DIRECT) {
 871+			mov_ir(code, 0, dst_op.base, SZ_B);
 872+		} else {
 873+			mov_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
 874+		}
 875+		code_ptr end_off = code->cur+1;
 876+		jmp(code, code->cur+2);
 877+		*true_off = code->cur - (true_off+1);
 878+		cycles(&opts->gen, 6);
 879+		if (dst_op.mode == MODE_REG_DIRECT) {
 880+			mov_ir(code, 0xFF, dst_op.base, SZ_B);
 881+		} else {
 882+			mov_irdisp(code, 0xFF, dst_op.base, dst_op.disp, SZ_B);
 883+		}
 884+		*end_off = code->cur - (end_off+1);
 885+	}
 886+	m68k_save_result(inst, opts);
 887+}
 888+
 889+void translate_m68k_dbcc(m68k_options * opts, m68kinst * inst)
 890+{
 891+	code_info *code = &opts->gen.code;
 892+	//best case duration
 893+	cycles(&opts->gen, 10);
 894+	code_ptr skip_loc = NULL;
 895+	//TODO: Check if COND_TRUE technically valid here even though
 896+	//it's basically a slow NOP
 897+	if (inst->extra.cond != COND_FALSE) {
 898+		uint8_t cond = m68k_eval_cond(opts, inst->extra.cond);
 899+		check_alloc_code(code, 6*MAX_INST_LEN);
 900+		skip_loc = code->cur + 1;
 901+		jcc(code, cond, code->cur + 2);
 902+	}
 903+	if (opts->dregs[inst->dst.params.regs.pri] >= 0) {
 904+		sub_ir(code, 1, opts->dregs[inst->dst.params.regs.pri], SZ_W);
 905+		cmp_ir(code, -1, opts->dregs[inst->dst.params.regs.pri], SZ_W);
 906+	} else {
 907+		sub_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W);
 908+		cmp_irdisp(code, -1, opts->gen.context_reg, offsetof(m68k_context, dregs) + 4 * inst->dst.params.regs.pri, SZ_W);
 909+	}
 910+	code_ptr loop_end_loc = code->cur + 1;
 911+	jcc(code, CC_Z, code->cur + 2);
 912+	uint32_t after = inst->address + 2;
 913+	jump_m68k_abs(opts, after + inst->src.params.immed);
 914+	*loop_end_loc = code->cur - (loop_end_loc+1);
 915+	if (skip_loc) {
 916+		cycles(&opts->gen, 2);
 917+		*skip_loc = code->cur - (skip_loc+1);
 918+		cycles(&opts->gen, 2);
 919+	} else {
 920+		cycles(&opts->gen, 4);
 921+	}
 922+}
 923+
 924+void translate_m68k_movep(m68k_options * opts, m68kinst * inst)
 925+{
 926+	code_info *code = &opts->gen.code;
 927+	int8_t reg;
 928+	cycles(&opts->gen, BUS*2);
 929+	if (inst->src.addr_mode == MODE_REG) {
 930+		calc_areg_displace(opts, &inst->dst, opts->gen.scratch2);
 931+		reg = native_reg(&(inst->src), opts);
 932+		if (inst->extra.size == OPSIZE_LONG) {
 933+			if (reg >= 0) {
 934+				mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 935+				shr_ir(code, 24, opts->gen.scratch1, SZ_D);
 936+				push_r(code, opts->gen.scratch2);
 937+				call(code, opts->write_8);
 938+				pop_r(code, opts->gen.scratch2);
 939+				mov_rr(code, reg, opts->gen.scratch1, SZ_D);
 940+				shr_ir(code, 16, opts->gen.scratch1, SZ_D);
 941+
 942+			} else {
 943+				mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+3, opts->gen.scratch1, SZ_B);
 944+				push_r(code, opts->gen.scratch2);
 945+				call(code, opts->write_8);
 946+				pop_r(code, opts->gen.scratch2);
 947+				mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+2, opts->gen.scratch1, SZ_B);
 948+			}
 949+			add_ir(code, 2, opts->gen.scratch2, SZ_D);
 950+			push_r(code, opts->gen.scratch2);
 951+			call(code, opts->write_8);
 952+			pop_r(code, opts->gen.scratch2);
 953+			add_ir(code, 2, opts->gen.scratch2, SZ_D);
 954+		}
 955+		if (reg >= 0) {
 956+			mov_rr(code, reg, opts->gen.scratch1, SZ_W);
 957+			shr_ir(code, 8, opts->gen.scratch1, SZ_W);
 958+			push_r(code, opts->gen.scratch2);
 959+			call(code, opts->write_8);
 960+			pop_r(code, opts->gen.scratch2);
 961+			mov_rr(code, reg, opts->gen.scratch1, SZ_W);
 962+		} else {
 963+			mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src))+1, opts->gen.scratch1, SZ_B);
 964+			push_r(code, opts->gen.scratch2);
 965+			call(code, opts->write_8);
 966+			pop_r(code, opts->gen.scratch2);
 967+			mov_rdispr(code, opts->gen.context_reg, reg_offset(&(inst->src)), opts->gen.scratch1, SZ_B);
 968+		}
 969+		add_ir(code, 2, opts->gen.scratch2, SZ_D);
 970+		call(code, opts->write_8);
 971+	} else {
 972+		calc_areg_displace(opts, &inst->src, opts->gen.scratch1);
 973+		reg = native_reg(&(inst->dst), opts);
 974+		if (inst->extra.size == OPSIZE_LONG) {
 975+			if (reg >= 0) {
 976+				push_r(code, opts->gen.scratch1);
 977+				call(code, opts->read_8);
 978+				shl_ir(code, 24, opts->gen.scratch1, SZ_D);
 979+				mov_rr(code, opts->gen.scratch1, reg, SZ_D);
 980+				pop_r(code, opts->gen.scratch1);
 981+				add_ir(code, 2, opts->gen.scratch1, SZ_D);
 982+				push_r(code, opts->gen.scratch1);
 983+				call(code, opts->read_8);
 984+				movzx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B, SZ_W);
 985+				shl_ir(code, 16, opts->gen.scratch1, SZ_D);
 986+				or_rr(code, opts->gen.scratch1, reg, SZ_D);
 987+			} else {
 988+				push_r(code, opts->gen.scratch1);
 989+				call(code, opts->read_8);
 990+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+3, SZ_B);
 991+				pop_r(code, opts->gen.scratch1);
 992+				add_ir(code, 2, opts->gen.scratch1, SZ_D);
 993+				push_r(code, opts->gen.scratch1);
 994+				call(code, opts->read_8);
 995+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+2, SZ_B);
 996+			}
 997+			pop_r(code, opts->gen.scratch1);
 998+			add_ir(code, 2, opts->gen.scratch1, SZ_D);
 999+		}
1000+		push_r(code, opts->gen.scratch1);
1001+		call(code, opts->read_8);
1002+		if (reg >= 0) {
1003+
1004+			shl_ir(code, 8, opts->gen.scratch1, SZ_W);
1005+			mov_rr(code, opts->gen.scratch1, reg, SZ_W);
1006+			pop_r(code, opts->gen.scratch1);
1007+			add_ir(code, 2, opts->gen.scratch1, SZ_D);
1008+			call(code, opts->read_8);
1009+			mov_rr(code, opts->gen.scratch1, reg, SZ_B);
1010+		} else {
1011+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst))+1, SZ_B);
1012+			pop_r(code, opts->gen.scratch1);
1013+			add_ir(code, 2, opts->gen.scratch1, SZ_D);
1014+			call(code, opts->read_8);
1015+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, reg_offset(&(inst->dst)), SZ_B);
1016+		}
1017+	}
1018+}
1019+
1020+typedef void (*shift_ir_t)(code_info *code, uint8_t val, uint8_t dst, uint8_t size);
1021+typedef void (*shift_irdisp_t)(code_info *code, uint8_t val, uint8_t dst_base, int32_t disp, uint8_t size);
1022+typedef void (*shift_clr_t)(code_info *code, uint8_t dst, uint8_t size);
1023+typedef void (*shift_clrdisp_t)(code_info *code, uint8_t dst_base, int32_t disp, uint8_t size);
1024+
1025+void translate_shift(m68k_options * opts, m68kinst * inst, host_ea *src_op, host_ea * dst_op, shift_ir_t shift_ir, shift_irdisp_t shift_irdisp, shift_clr_t shift_clr, shift_clrdisp_t shift_clrdisp, shift_ir_t special, shift_irdisp_t special_disp)
1026+{
1027+	code_info *code = &opts->gen.code;
1028+	code_ptr end_off = NULL;
1029+	code_ptr nz_off = NULL;
1030+	code_ptr z_off = NULL;
1031+	if (inst->src.addr_mode == MODE_UNUSED) {
1032+		cycles(&opts->gen, BUS);
1033+		//Memory shift
1034+		shift_ir(code, 1, dst_op->base, SZ_W);
1035+	} else {
1036+		if (src_op->mode == MODE_IMMED) {
1037+			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + 2 * src_op->disp);
1038+			if (src_op->disp != 1 && inst->op == M68K_ASL) {
1039+				set_flag(opts, 0, FLAG_V);
1040+				for (int i = 0; i < src_op->disp; i++) {
1041+					if (dst_op->mode == MODE_REG_DIRECT) {
1042+						shift_ir(code, 1, dst_op->base, inst->extra.size);
1043+					} else {
1044+						shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1045+					}
1046+					check_alloc_code(code, 2*MAX_INST_LEN);
1047+					code_ptr after_flag_set = code->cur + 1;
1048+					jcc(code, CC_NO, code->cur + 2);
1049+					set_flag(opts, 1, FLAG_V);
1050+					*after_flag_set = code->cur - (after_flag_set+1);
1051+				}
1052+			} else {
1053+				if (dst_op->mode == MODE_REG_DIRECT) {
1054+					shift_ir(code, src_op->disp, dst_op->base, inst->extra.size);
1055+				} else {
1056+					shift_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1057+				}
1058+				set_flag_cond(opts, CC_O, FLAG_V);
1059+			}
1060+		} else {
1061+			cycles(&opts->gen, inst->extra.size == OPSIZE_LONG ? 8 : 6);
1062+			if (src_op->base != RCX) {
1063+				if (src_op->mode == MODE_REG_DIRECT) {
1064+					mov_rr(code, src_op->base, RCX, SZ_B);
1065+				} else {
1066+					mov_rdispr(code, src_op->base, src_op->disp, RCX, SZ_B);
1067+				}
1068+
1069+			}
1070+			and_ir(code, 63, RCX, SZ_D);
1071+			check_alloc_code(code, 7*MAX_INST_LEN);
1072+			nz_off = code->cur + 1;
1073+			jcc(code, CC_NZ, code->cur + 2);
1074+			//Flag behavior for shift count of 0 is different for x86 than 68K
1075+			if (dst_op->mode == MODE_REG_DIRECT) {
1076+				cmp_ir(code, 0, dst_op->base, inst->extra.size);
1077+			} else {
1078+				cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1079+			}
1080+			set_flag_cond(opts, CC_Z, FLAG_Z);
1081+			set_flag_cond(opts, CC_S, FLAG_N);
1082+			set_flag(opts, 0, FLAG_C);
1083+			//For other instructions, this flag will be set below
1084+			if (inst->op == M68K_ASL) {
1085+				set_flag(opts, 0, FLAG_V);
1086+			}
1087+			z_off = code->cur + 1;
1088+			jmp(code, code->cur + 2);
1089+			*nz_off = code->cur - (nz_off + 1);
1090+			//add 2 cycles for every bit shifted
1091+			mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
1092+			imul_rr(code, RCX, opts->gen.scratch2, SZ_D);
1093+			add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D);
1094+			if (inst->op == M68K_ASL) {
1095+				//ASL has Overflow flag behavior that depends on all of the bits shifted through the MSB
1096+				//Easiest way to deal with this is to shift one bit at a time
1097+				set_flag(opts, 0, FLAG_V);
1098+				check_alloc_code(code, 5*MAX_INST_LEN);
1099+				code_ptr loop_start = code->cur;
1100+				if (dst_op->mode == MODE_REG_DIRECT) {
1101+					shift_ir(code, 1, dst_op->base, inst->extra.size);
1102+				} else {
1103+					shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1104+				}
1105+				code_ptr after_flag_set = code->cur + 1;
1106+				jcc(code, CC_NO, code->cur + 2);
1107+				set_flag(opts, 1, FLAG_V);
1108+				*after_flag_set = code->cur - (after_flag_set+1);
1109+				loop(code, loop_start);
1110+			} else {
1111+				//x86 shifts modulo 32 for operand sizes less than 64-bits
1112+				//but M68K shifts modulo 64, so we need to check for large shifts here
1113+				cmp_ir(code, 32, RCX, SZ_B);
1114+				check_alloc_code(code, 14*MAX_INST_LEN);
1115+				code_ptr norm_shift_off = code->cur + 1;
1116+				jcc(code, CC_L, code->cur + 2);
1117+				if (special) {
1118+					code_ptr after_flag_set = NULL;
1119+					if (inst->extra.size == OPSIZE_LONG) {
1120+						code_ptr neq_32_off = code->cur + 1;
1121+						jcc(code, CC_NZ, code->cur + 2);
1122+
1123+						//set the carry bit to the lsb
1124+						if (dst_op->mode == MODE_REG_DIRECT) {
1125+							special(code, 1, dst_op->base, SZ_D);
1126+						} else {
1127+							special_disp(code, 1, dst_op->base, dst_op->disp, SZ_D);
1128+						}
1129+						set_flag_cond(opts, CC_C, FLAG_C);
1130+						after_flag_set = code->cur + 1;
1131+						jmp(code, code->cur + 2);
1132+						*neq_32_off = code->cur - (neq_32_off+1);
1133+					}
1134+					set_flag(opts, 0, FLAG_C);
1135+					if (after_flag_set) {
1136+						*after_flag_set = code->cur - (after_flag_set+1);
1137+					}
1138+					set_flag(opts, 1, FLAG_Z);
1139+					set_flag(opts, 0, FLAG_N);
1140+					if (dst_op->mode == MODE_REG_DIRECT) {
1141+						xor_rr(code, dst_op->base, dst_op->base, inst->extra.size);
1142+					} else {
1143+						mov_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1144+					}
1145+				} else {
1146+					if (dst_op->mode == MODE_REG_DIRECT) {
1147+						shift_ir(code, 31, dst_op->base, inst->extra.size);
1148+						shift_ir(code, 1, dst_op->base, inst->extra.size);
1149+					} else {
1150+						shift_irdisp(code, 31, dst_op->base, dst_op->disp, inst->extra.size);
1151+						shift_irdisp(code, 1, dst_op->base, dst_op->disp, inst->extra.size);
1152+					}
1153+
1154+				}
1155+				end_off = code->cur + 1;
1156+				jmp(code, code->cur + 2);
1157+				*norm_shift_off = code->cur - (norm_shift_off+1);
1158+				if (dst_op->mode == MODE_REG_DIRECT) {
1159+					shift_clr(code, dst_op->base, inst->extra.size);
1160+				} else {
1161+					shift_clrdisp(code, dst_op->base, dst_op->disp, inst->extra.size);
1162+				}
1163+			}
1164+		}
1165+
1166+	}
1167+	if (!special && end_off) {
1168+		*end_off = code->cur - (end_off + 1);
1169+	}
1170+	update_flags(opts, C|Z|N);
1171+	if (special && end_off) {
1172+		*end_off = code->cur - (end_off + 1);
1173+	}
1174+	//set X flag to same as C flag
1175+	if (opts->flag_regs[FLAG_C] >= 0) {
1176+		flag_to_flag(opts, FLAG_C, FLAG_X);
1177+	} else {
1178+		set_flag_cond(opts, CC_C, FLAG_X);
1179+	}
1180+	if (z_off) {
1181+		*z_off = code->cur - (z_off + 1);
1182+	}
1183+	if (inst->op != M68K_ASL) {
1184+		set_flag(opts, 0, FLAG_V);
1185+	}
1186+	if (inst->src.addr_mode == MODE_UNUSED) {
1187+		m68k_save_result(inst, opts);
1188+	}
1189+}
1190+
1191+void translate_m68k_reset(m68k_options *opts, m68kinst *inst)
1192+{
1193+	code_info *code = &opts->gen.code;
1194+	//RESET instructions take a long time to give peripherals time to reset themselves
1195+	cycles(&opts->gen, 132);
1196+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, reset_handler), opts->gen.scratch1, SZ_PTR);
1197+	cmp_ir(code, 0, opts->gen.scratch1, SZ_PTR);
1198+	code_ptr no_reset_handler = code->cur + 1;
1199+	jcc(code, CC_Z, code->cur+2);
1200+	call(code, opts->gen.save_context);
1201+	call_args_r(code, opts->gen.scratch1, 1, opts->gen.context_reg);
1202+	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
1203+	call(code, opts->gen.load_context);
1204+	*no_reset_handler = code->cur - (no_reset_handler + 1);
1205+}
1206+
1207+void op_ir(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, uint8_t size)
1208+{
1209+	switch (inst->op)
1210+	{
1211+	case M68K_ADD:  add_ir(code, val, dst, size); break;
1212+	case M68K_ADDX: adc_ir(code, val, dst, size); break;
1213+	case M68K_AND:  and_ir(code, val, dst, size); break;
1214+	case M68K_BTST: bt_ir(code, val, dst, size); break;
1215+	case M68K_BSET: bts_ir(code, val, dst, size); break;
1216+	case M68K_BCLR: btr_ir(code, val, dst, size); break;
1217+	case M68K_BCHG: btc_ir(code, val, dst, size); break;
1218+	case M68K_CMP:  cmp_ir(code, val, dst, size); break;
1219+	case M68K_EOR:  xor_ir(code, val, dst, size); break;
1220+	case M68K_OR:   or_ir(code, val, dst, size); break;
1221+	case M68K_ROL:  rol_ir(code, val, dst, size); break;
1222+	case M68K_ROR:  ror_ir(code, val, dst, size); break;
1223+	case M68K_ROXL: rcl_ir(code, val, dst, size); break;
1224+	case M68K_ROXR: rcr_ir(code, val, dst, size); break;
1225+	case M68K_SUB:  sub_ir(code, val, dst, size); break;
1226+	case M68K_SUBX: sbb_ir(code, val, dst, size); break;
1227+	}
1228+}
1229+
1230+void op_irdisp(code_info *code, m68kinst *inst, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
1231+{
1232+	switch (inst->op)
1233+	{
1234+	case M68K_ADD:  add_irdisp(code, val, dst, disp, size); break;
1235+	case M68K_ADDX: adc_irdisp(code, val, dst, disp, size); break;
1236+	case M68K_AND:  and_irdisp(code, val, dst, disp, size); break;
1237+	case M68K_BTST: bt_irdisp(code, val, dst, disp, size); break;
1238+	case M68K_BSET: bts_irdisp(code, val, dst, disp, size); break;
1239+	case M68K_BCLR: btr_irdisp(code, val, dst, disp, size); break;
1240+	case M68K_BCHG: btc_irdisp(code, val, dst, disp, size); break;
1241+	case M68K_CMP:  cmp_irdisp(code, val, dst, disp, size); break;
1242+	case M68K_EOR:  xor_irdisp(code, val, dst, disp, size); break;
1243+	case M68K_OR:   or_irdisp(code, val, dst, disp, size); break;
1244+	case M68K_ROL:  rol_irdisp(code, val, dst, disp, size); break;
1245+	case M68K_ROR:  ror_irdisp(code, val, dst, disp, size); break;
1246+	case M68K_ROXL: rcl_irdisp(code, val, dst, disp, size); break;
1247+	case M68K_ROXR: rcr_irdisp(code, val, dst, disp, size); break;
1248+	case M68K_SUB:  sub_irdisp(code, val, dst, disp, size); break;
1249+	case M68K_SUBX: sbb_irdisp(code, val, dst, disp, size); break;
1250+	}
1251+}
1252+
1253+void op_rr(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, uint8_t size)
1254+{
1255+	switch (inst->op)
1256+	{
1257+	case M68K_ADD:  add_rr(code, src, dst, size); break;
1258+	case M68K_ADDX: adc_rr(code, src, dst, size); break;
1259+	case M68K_AND:  and_rr(code, src, dst, size); break;
1260+	case M68K_BTST: bt_rr(code, src, dst, size); break;
1261+	case M68K_BSET: bts_rr(code, src, dst, size); break;
1262+	case M68K_BCLR: btr_rr(code, src, dst, size); break;
1263+	case M68K_BCHG: btc_rr(code, src, dst, size); break;
1264+	case M68K_CMP:  cmp_rr(code, src, dst, size); break;
1265+	case M68K_EOR:  xor_rr(code, src, dst, size); break;
1266+	case M68K_OR:   or_rr(code, src, dst, size); break;
1267+	case M68K_SUB:  sub_rr(code, src, dst, size); break;
1268+	case M68K_SUBX: sbb_rr(code, src, dst, size); break;
1269+	}
1270+}
1271+
1272+void op_rrdisp(code_info *code, m68kinst *inst, uint8_t src, uint8_t dst, int32_t disp, uint8_t size)
1273+{
1274+	switch(inst->op)
1275+	{
1276+	case M68K_ADD:  add_rrdisp(code, src, dst, disp, size); break;
1277+	case M68K_ADDX: adc_rrdisp(code, src, dst, disp, size); break;
1278+	case M68K_AND:  and_rrdisp(code, src, dst, disp, size); break;
1279+	case M68K_BTST: bt_rrdisp(code, src, dst, disp, size); break;
1280+	case M68K_BSET: bts_rrdisp(code, src, dst, disp, size); break;
1281+	case M68K_BCLR: btr_rrdisp(code, src, dst, disp, size); break;
1282+	case M68K_BCHG: btc_rrdisp(code, src, dst, disp, size); break;
1283+	case M68K_CMP:  cmp_rrdisp(code, src, dst, disp, size); break;
1284+	case M68K_EOR:  xor_rrdisp(code, src, dst, disp, size); break;
1285+	case M68K_OR:   or_rrdisp(code, src, dst, disp, size); break;
1286+	case M68K_SUB:  sub_rrdisp(code, src, dst, disp, size); break;
1287+	case M68K_SUBX: sbb_rrdisp(code, src, dst, disp, size); break;
1288+	}
1289+}
1290+
1291+void op_rdispr(code_info *code, m68kinst *inst, uint8_t src, int32_t disp, uint8_t dst, uint8_t size)
1292+{
1293+	switch (inst->op)
1294+	{
1295+	case M68K_ADD:  add_rdispr(code, src, disp, dst, size); break;
1296+	case M68K_ADDX: adc_rdispr(code, src, disp, dst, size); break;
1297+	case M68K_AND:  and_rdispr(code, src, disp, dst, size); break;
1298+	case M68K_CMP:  cmp_rdispr(code, src, disp, dst, size); break;
1299+	case M68K_EOR:  xor_rdispr(code, src, disp, dst, size); break;
1300+	case M68K_OR:   or_rdispr(code, src, disp, dst, size); break;
1301+	case M68K_SUB:  sub_rdispr(code, src, disp, dst, size); break;
1302+	case M68K_SUBX: sbb_rdispr(code, src, disp, dst, size); break;
1303+	}
1304+}
1305+
1306+void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op)
1307+{
1308+	code_info *code = &opts->gen.code;
1309+	uint8_t size = inst->dst.addr_mode == MODE_AREG ? OPSIZE_LONG : inst->extra.size;
1310+	
1311+	uint32_t numcycles;
1312+	if ((inst->op == M68K_ADDX || inst->op == M68K_SUBX) && inst->src.addr_mode != MODE_REG) {
1313+		numcycles = 6;
1314+	} else if (size == OPSIZE_LONG) {
1315+		if (inst->op == M68K_CMP) {
1316+			numcycles = 6;
1317+		} else if (inst->op == M68K_AND && inst->variant == VAR_IMMEDIATE) {
1318+			numcycles = 6;
1319+		} else if (inst->op == M68K_ADD && inst->dst.addr_mode == MODE_AREG && inst->extra.size == OPSIZE_WORD && inst->variant == VAR_QUICK) {
1320+			numcycles = 4;
1321+		} else if (inst->dst.addr_mode <= MODE_AREG) {
1322+			numcycles = inst->src.addr_mode <= MODE_AREG || inst->src.addr_mode == MODE_IMMEDIATE ? 8 : 6;
1323+		} else {
1324+			numcycles = 4;
1325+		}
1326+	} else {
1327+		numcycles = 4;
1328+	}
1329+	cycles(&opts->gen, numcycles);
1330+	
1331+	if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1332+		flag_to_carry(opts, FLAG_X);
1333+	}
1334+	
1335+	if (src_op->mode == MODE_REG_DIRECT) {
1336+		if (dst_op->mode == MODE_REG_DIRECT) {
1337+			op_rr(code, inst, src_op->base, dst_op->base, size);
1338+		} else {
1339+			op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1340+		}
1341+	} else if (src_op->mode == MODE_REG_DISPLACE8) {
1342+		op_rdispr(code, inst, src_op->base, src_op->disp, dst_op->base, size);
1343+	} else {
1344+		if (dst_op->mode == MODE_REG_DIRECT) {
1345+			op_ir(code, inst, src_op->disp, dst_op->base, size);
1346+		} else {
1347+			op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, size);
1348+		}
1349+	}
1350+	if (inst->dst.addr_mode != MODE_AREG || inst->op == M68K_CMP) {
1351+		update_flags(opts, flag_mask);
1352+		if (inst->op == M68K_ADDX || inst->op == M68K_SUBX) {
1353+			check_alloc_code(code, 2*MAX_INST_LEN);
1354+			code_ptr after_flag_set = code->cur + 1;
1355+			jcc(code, CC_Z, code->cur + 2);
1356+			set_flag(opts, 0, FLAG_Z);
1357+			*after_flag_set = code->cur - (after_flag_set+1);
1358+		}
1359+	}
1360+	if (inst->op != M68K_CMP) {
1361+		m68k_save_result(inst, opts);
1362+	}
1363+}
1364+
1365+void translate_m68k_cmp(m68k_options * opts, m68kinst * inst)
1366+{
1367+	code_info *code = &opts->gen.code;
1368+	uint8_t size = inst->extra.size;
1369+	host_ea src_op, dst_op;
1370+	translate_m68k_op(inst, &src_op, opts, 0);
1371+	if (inst->dst.addr_mode == MODE_AREG_POSTINC) {
1372+		push_r(code, opts->gen.scratch1);
1373+		translate_m68k_op(inst, &dst_op, opts, 1);
1374+		pop_r(code, opts->gen.scratch2);
1375+		src_op.base = opts->gen.scratch2;
1376+	} else {
1377+		translate_m68k_op(inst, &dst_op, opts, 1);
1378+		if (inst->dst.addr_mode == MODE_AREG && size == OPSIZE_WORD) {
1379+			size = OPSIZE_LONG;
1380+		}
1381+	}
1382+	translate_m68k_arith(opts, inst, N|Z|V|C, &src_op, &dst_op);
1383+}
1384+
1385+void translate_m68k_tas(m68k_options *opts, m68kinst *inst)
1386+{
1387+	code_info *code = &opts->gen.code;
1388+	host_ea op;
1389+	translate_m68k_op(inst, &op, opts, 1);
1390+	if (op.mode == MODE_REG_DIRECT) {
1391+		cmp_ir(code, 0, op.base, SZ_B);
1392+	} else {
1393+		cmp_irdisp(code, 0, op.base, op.disp, SZ_B);
1394+	}
1395+	update_flags(opts, N|Z|V0|C0);
1396+	if (inst->dst.addr_mode == MODE_REG) {
1397+		cycles(&opts->gen, BUS);
1398+		if (op.mode == MODE_REG_DIRECT) {
1399+			bts_ir(code, 7, op.base, SZ_B);
1400+		} else {
1401+			bts_irdisp(code, 7, op.base, op.disp, SZ_B);
1402+		}
1403+	} else {
1404+		if (opts->gen.flags & M68K_OPT_BROKEN_READ_MODIFY) {
1405+			//2 cycles for processing
1406+			//4 for failed writeback
1407+			//4 for prefetch
1408+			cycles(&opts->gen, BUS * 2 + 2);
1409+		} else {
1410+			cycles(&opts->gen, 2);
1411+			bts_ir(code, 7, op.base, SZ_B);
1412+			m68k_save_result(inst, opts);
1413+			cycles(&opts->gen, BUS);
1414+		}
1415+	}
1416+}
1417+
1418+void op_r(code_info *code, m68kinst *inst, uint8_t dst, uint8_t size)
1419+{
1420+	switch(inst->op)
1421+	{
1422+	case M68K_CLR:   xor_rr(code, dst, dst, size); break;
1423+	case M68K_NEG:   neg_r(code, dst, size); break;
1424+	case M68K_NOT:   not_r(code, dst, size); cmp_ir(code, 0, dst, size); break;
1425+	case M68K_ROL:   rol_clr(code, dst, size); break;
1426+	case M68K_ROR:   ror_clr(code, dst, size); break;
1427+	case M68K_ROXL:  rcl_clr(code, dst, size); break;
1428+	case M68K_ROXR:  rcr_clr(code, dst, size); break;
1429+	case M68K_SWAP:  rol_ir(code, 16, dst, SZ_D); cmp_ir(code, 0, dst, SZ_D); break;
1430+	case M68K_TST:   cmp_ir(code, 0, dst, size); break;
1431+	}
1432+}
1433+
1434+void op_rdisp(code_info *code, m68kinst *inst, uint8_t dst, int32_t disp, uint8_t size)
1435+{
1436+	switch(inst->op)
1437+	{
1438+	case M68K_CLR:   mov_irdisp(code, 0, dst, disp, size); break;
1439+	case M68K_NEG:   neg_rdisp(code, dst, disp, size); break;
1440+	case M68K_NOT:   not_rdisp(code, dst, disp, size); cmp_irdisp(code, 0, dst, disp, size); break;
1441+	case M68K_ROL:   rol_clrdisp(code, dst, disp, size); break;
1442+	case M68K_ROR:   ror_clrdisp(code, dst, disp, size); break;
1443+	case M68K_ROXL:  rcl_clrdisp(code, dst, disp, size); break;
1444+	case M68K_ROXR:  rcr_clrdisp(code, dst, disp, size); break;
1445+	case M68K_SWAP:  rol_irdisp(code, 16, dst, disp, SZ_D); cmp_irdisp(code, 0, dst, disp, SZ_D); break;
1446+	case M68K_TST:   cmp_irdisp(code, 0, dst, disp, size); break;
1447+	}
1448+}
1449+
1450+void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op)
1451+{
1452+	code_info *code = &opts->gen.code;
1453+	uint32_t num_cycles = BUS;
1454+	if (inst->extra.size == OPSIZE_LONG && (inst->dst.addr_mode == MODE_REG || inst->dst.addr_mode == MODE_AREG)) {
1455+		num_cycles += 2;
1456+	}
1457+	cycles(&opts->gen, num_cycles);
1458+	if (dst_op->mode == MODE_REG_DIRECT) {
1459+		op_r(code, inst, dst_op->base, inst->extra.size);
1460+	} else {
1461+		op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
1462+	}
1463+	update_flags(opts, flag_mask);
1464+	m68k_save_result(inst, opts);
1465+}
1466+
1467+void translate_m68k_abcd_sbcd(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1468+{
1469+	code_info *code = &opts->gen.code;
1470+	if (inst->op == M68K_NBCD) {
1471+		if (dst_op->base != opts->gen.scratch2) {
1472+			if (dst_op->mode == MODE_REG_DIRECT) {
1473+				mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_B);
1474+			} else {
1475+				mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_B);
1476+			}
1477+		}
1478+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B);
1479+	} else {
1480+		if (src_op->base != opts->gen.scratch2) {
1481+			if (src_op->mode == MODE_REG_DIRECT) {
1482+				mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1483+			} else {
1484+				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1485+			}
1486+		}
1487+		if (dst_op->base != opts->gen.scratch1) {
1488+			if (dst_op->mode == MODE_REG_DIRECT) {
1489+				mov_rr(code, dst_op->base, opts->gen.scratch1, SZ_B);
1490+			} else {
1491+				mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, SZ_B);
1492+			}
1493+		}
1494+	}
1495+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
1496+		//destination is in memory so we need to preserve scratch2 for the write at the end
1497+		push_r(code, opts->gen.scratch2);
1498+	}
1499+	//MC68000 User's Manual suggests NBCD hides the 2 cycle penalty during the write cycle somehow
1500+	cycles(&opts->gen, inst->op == M68K_NBCD && inst->dst.addr_mode != MODE_REG_DIRECT ? BUS : BUS + 2);
1501+	uint8_t other_reg;
1502+	//WARNING: This may need adjustment if register assignments change
1503+	if (opts->gen.scratch2 > RBX) {
1504+		other_reg = RAX;
1505+		xchg_rr(code, opts->gen.scratch2, RAX, SZ_D);
1506+	} else {
1507+		other_reg = opts->gen.scratch2;
1508+	}
1509+	mov_rr(code, opts->gen.scratch1, opts->gen.scratch1 + (AH-RAX), SZ_B);
1510+	mov_rr(code, other_reg, other_reg + (AH-RAX), SZ_B);
1511+	and_ir(code, 0xF, opts->gen.scratch1 + (AH-RAX), SZ_B);
1512+	and_ir(code, 0xF, other_reg + (AH-RAX), SZ_B);
1513+	//do op on low nibble so we can determine if an adjustment is necessary
1514+	flag_to_carry(opts, FLAG_X);
1515+	if (inst->op == M68K_ABCD) {
1516+		adc_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1517+	} else {
1518+		sbb_rr(code, other_reg + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1519+	}
1520+	cmp_ir(code, inst->op == M68K_SBCD ? 0x10 : 0xA, opts->gen.scratch1 + (AH-RAX), SZ_B);
1521+	mov_ir(code, 0xA0, other_reg + (AH-RAX), SZ_B);
1522+	code_ptr no_adjust = code->cur+1;
1523+	//add correction factor if necessary
1524+	jcc(code, CC_B, no_adjust);
1525+	mov_ir(code, 6, opts->gen.scratch1 + (AH-RAX), SZ_B);
1526+	mov_ir(code, inst->op == M68K_ABCD ? 0x9A : 0xA6, other_reg + (AH-RAX), SZ_B);
1527+	code_ptr after_adjust = code->cur+1;
1528+	jmp(code, after_adjust);
1529+
1530+	*no_adjust = code->cur - (no_adjust+1);
1531+	xor_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1 + (AH-RAX), SZ_B);
1532+	*after_adjust = code->cur - (after_adjust+1);
1533+
1534+	//do op on full byte
1535+	flag_to_carry(opts, FLAG_X);
1536+	if (inst->op == M68K_ABCD) {
1537+		adc_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1538+	} else {
1539+		sbb_rr(code, other_reg, opts->gen.scratch1, SZ_B);
1540+	}
1541+	set_flag(opts, 0, FLAG_C);
1542+	//determine if we need a correction on the upper nibble
1543+	code_ptr def_adjust = code->cur+1;
1544+	jcc(code, CC_C, def_adjust);
1545+	if (inst->op == M68K_SBCD) {
1546+		no_adjust = code->cur+1;
1547+		jmp(code, no_adjust);
1548+	} else {
1549+		cmp_rr(code, other_reg + (AH-RAX), opts->gen.scratch1, SZ_B);
1550+		no_adjust = code->cur+1;
1551+		jcc(code, CC_B, no_adjust);
1552+	}
1553+	*def_adjust = code->cur - (def_adjust + 1);
1554+	set_flag(opts, 1, FLAG_C);
1555+	or_ir(code, 0x60, opts->gen.scratch1 + (AH-RAX), SZ_B);
1556+	*no_adjust = code->cur - (no_adjust+1);
1557+	if (inst->op == M68K_ABCD) {
1558+		add_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1559+	} else {
1560+		sub_rr(code, opts->gen.scratch1 + (AH-RAX), opts->gen.scratch1, SZ_B);
1561+	}
1562+	code_ptr no_ensure_carry = code->cur+1;
1563+	jcc(code, CC_NC, no_ensure_carry);
1564+	set_flag(opts, 1, FLAG_C);
1565+	*no_ensure_carry = code->cur - (no_ensure_carry+1);
1566+	//restore RAX if necessary
1567+	if (opts->gen.scratch2 > RBX) {
1568+		mov_rr(code, opts->gen.scratch2, RAX, SZ_D);
1569+	}
1570+	//V flag is set based on the result of the addition/subtraction of the
1571+	//result and the correction factor
1572+	set_flag_cond(opts, CC_O, FLAG_V);
1573+
1574+	flag_to_flag(opts, FLAG_C, FLAG_X);
1575+
1576+	cmp_ir(code, 0, opts->gen.scratch1, SZ_B);
1577+	set_flag_cond(opts, CC_S, FLAG_N);
1578+	code_ptr no_setz = code->cur+1;
1579+	jcc(code, CC_Z, no_setz);
1580+	set_flag(opts, 0, FLAG_Z);
1581+	*no_setz = code->cur - (no_setz + 1);
1582+	if (dst_op->base != opts->gen.scratch1) {
1583+		if (dst_op->mode == MODE_REG_DIRECT) {
1584+			mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_B);
1585+		} else {
1586+			mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_B);
1587+		}
1588+	}
1589+	if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_AREG_PREDEC) {
1590+		//destination is in memory so we need to restore scratch2 for the write at the end
1591+		pop_r(code, opts->gen.scratch2);
1592+	}
1593+	m68k_save_result(inst, opts);
1594+}
1595+
1596+void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1597+{
1598+	translate_shift(opts, inst, src_op, dst_op, shl_ir, shl_irdisp, shl_clr, shl_clrdisp, shr_ir, shr_irdisp);
1599+}
1600+
1601+void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1602+{
1603+	translate_shift(opts, inst, src_op, dst_op, sar_ir, sar_irdisp, sar_clr, sar_clrdisp, NULL, NULL);
1604+}
1605+
1606+void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1607+{
1608+	translate_shift(opts, inst, src_op, dst_op, shr_ir, shr_irdisp, shr_clr, shr_clrdisp, shl_ir, shl_irdisp);
1609+}
1610+
1611+void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1612+{
1613+	code_info *code = &opts->gen.code;
1614+	cycles(&opts->gen, inst->extra.size == OPSIZE_BYTE ? 4 : (
1615+			inst->op == M68K_BTST ? 6 : (inst->op == M68K_BCLR ? 10 : 8))
1616+	);
1617+	if (src_op->mode == MODE_IMMED) {
1618+		if (inst->extra.size == OPSIZE_BYTE) {
1619+			src_op->disp &= 0x7;
1620+		}
1621+		if (dst_op->mode == MODE_REG_DIRECT) {
1622+			op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
1623+		} else {
1624+			op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1625+		}
1626+	} else {
1627+		if (src_op->mode == MODE_REG_DISPLACE8 || (inst->dst.addr_mode != MODE_REG && src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2)) {
1628+			if (dst_op->base == opts->gen.scratch1) {
1629+				push_r(code, opts->gen.scratch2);
1630+				if (src_op->mode == MODE_REG_DIRECT) {
1631+					mov_rr(code, src_op->base, opts->gen.scratch2, SZ_B);
1632+				} else {
1633+					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch2, SZ_B);
1634+				}
1635+				src_op->base = opts->gen.scratch2;
1636+			} else {
1637+				if (src_op->mode == MODE_REG_DIRECT) {
1638+					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
1639+				} else {
1640+					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
1641+				}
1642+				src_op->base = opts->gen.scratch1;
1643+				}
1644+			}
1645+			uint8_t size = inst->extra.size;
1646+		if (dst_op->mode == MODE_REG_DISPLACE8) {
1647+			if (src_op->base != opts->gen.scratch1 && src_op->base != opts->gen.scratch2) {
1648+				if (src_op->mode == MODE_REG_DIRECT) {
1649+					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_D);
1650+				} else {
1651+					mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1652+					src_op->mode = MODE_REG_DIRECT;
1653+				}
1654+				src_op->base = opts->gen.scratch1;
1655+			}
1656+			//b### with register destination is modulo 32
1657+			//x86 with a memory destination isn't modulo anything
1658+			//so use an and here to force the value to be modulo 32
1659+			and_ir(code, 31, opts->gen.scratch1, SZ_D);
1660+		} else if(inst->dst.addr_mode != MODE_REG) {
1661+			//b### with memory destination is modulo 8
1662+			//x86-64 doesn't support 8-bit bit operations
1663+			//so we fake it by forcing the bit number to be modulo 8
1664+			and_ir(code, 7, src_op->base, SZ_D);
1665+			size = SZ_D;
1666+		}
1667+		if (dst_op->mode == MODE_IMMED) {
1668+			dst_op->base = src_op->base == opts->gen.scratch1 ? opts->gen.scratch2 : opts->gen.scratch1;
1669+			mov_ir(code, dst_op->disp, dst_op->base, SZ_B);
1670+			dst_op->mode = MODE_REG_DIRECT;
1671+		}
1672+		if (dst_op->mode == MODE_REG_DIRECT) {
1673+			op_rr(code, inst, src_op->base, dst_op->base, size);
1674+		} else {
1675+			op_rrdisp(code, inst, src_op->base, dst_op->base, dst_op->disp, size);
1676+		}
1677+		if (src_op->base == opts->gen.scratch2) {
1678+			pop_r(code, opts->gen.scratch2);
1679+		}
1680+	}
1681+	//x86 sets the carry flag to the value of the bit tested
1682+	//68K sets the zero flag to the complement of the bit tested
1683+	set_flag_cond(opts, CC_NC, FLAG_Z);
1684+	if (inst->op != M68K_BTST) {
1685+		m68k_save_result(inst, opts);
1686+	}
1687+}
1688+
1689+void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1690+	{
1691+	code_info *code = &opts->gen.code;
1692+	cycles(&opts->gen, 6);
1693+	if (dst_op->mode == MODE_REG_DIRECT) {
1694+		cmp_ir(code, 0, dst_op->base, inst->extra.size);
1695+	} else {
1696+		cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
1697+	}
1698+	uint32_t isize;
1699+	switch(inst->src.addr_mode)
1700+	{
1701+	case MODE_AREG_DISPLACE:
1702+	case MODE_AREG_INDEX_DISP8:
1703+	case MODE_ABSOLUTE_SHORT:
1704+	case MODE_PC_INDEX_DISP8:
1705+	case MODE_PC_DISPLACE:
1706+	case MODE_IMMEDIATE:
1707+		isize = 4;
1708+		break;
1709+	case MODE_ABSOLUTE:
1710+		isize = 6;
1711+		break;
1712+	default:
1713+		isize = 2;
1714+	}
1715+	//make sure we won't start a new chunk in the middle of these branches
1716+	check_alloc_code(code, MAX_INST_LEN * 11);
1717+	code_ptr passed = code->cur + 1;
1718+	jcc(code, CC_GE, code->cur + 2);
1719+	set_flag(opts, 1, FLAG_N);
1720+	mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1721+	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1722+	jmp(code, opts->trap);
1723+	*passed = code->cur - (passed+1);
1724+	if (dst_op->mode == MODE_REG_DIRECT) {
1725+		if (src_op->mode == MODE_REG_DIRECT) {
1726+			cmp_rr(code, src_op->base, dst_op->base, inst->extra.size);
1727+		} else if(src_op->mode == MODE_REG_DISPLACE8) {
1728+			cmp_rdispr(code, src_op->base, src_op->disp, dst_op->base, inst->extra.size);
1729+		} else {
1730+			cmp_ir(code, src_op->disp, dst_op->base, inst->extra.size);
1731+		}
1732+	} else if(dst_op->mode == MODE_REG_DISPLACE8) {
1733+		if (src_op->mode == MODE_REG_DIRECT) {
1734+			cmp_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, inst->extra.size);
1735+		} else {
1736+			cmp_irdisp(code, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
1737+		}
1738+	}
1739+	passed = code->cur + 1;
1740+	jcc(code, CC_LE, code->cur + 2);
1741+	set_flag(opts, 0, FLAG_N);
1742+	mov_ir(code, VECTOR_CHK, opts->gen.scratch2, SZ_D);
1743+	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1744+	jmp(code, opts->trap);
1745+	*passed = code->cur - (passed+1);
1746+	cycles(&opts->gen, 4);
1747+}
1748+
1749+static uint32_t divu(uint32_t dividend, m68k_context *context, uint32_t divisor_shift)
1750+{
1751+	uint16_t quotient = 0;
1752+	uint8_t force = 0;
1753+	uint16_t bit = 0;
1754+	uint32_t cycles = 6;
1755+	for (int i = 0; i < 16; i++)
1756+	{
1757+		force = dividend >> 31;
1758+		quotient = quotient << 1 | bit;
1759+		dividend = dividend << 1;
1760+		
1761+		if (force || dividend >= divisor_shift) {
1762+			dividend -= divisor_shift;
1763+			cycles += force ? 4 : 6;
1764+			bit = 1;
1765+		} else {
1766+			bit = 0;
1767+			cycles += 8;
1768+		}
1769+	}
1770+	cycles += force ? 6 : bit ? 4 : 2;
1771+	context->current_cycle += cycles * context->options->gen.clock_divider;
1772+	quotient = quotient << 1 | bit;
1773+	return dividend | quotient;
1774+}
1775+
1776+static uint32_t divs(uint32_t dividend, m68k_context *context, uint32_t divisor_shift)
1777+{
1778+	uint32_t orig_divisor = divisor_shift, orig_dividend = dividend;
1779+	if (divisor_shift & 0x80000000) {
1780+		divisor_shift = 0 - divisor_shift;
1781+	}
1782+	
1783+	uint32_t cycles = 12;
1784+	if (dividend & 0x80000000) {
1785+		//dvs10
1786+		dividend = 0 - dividend;
1787+		cycles += 2;
1788+	}
1789+	if (divisor_shift <= dividend) {
1790+		context->flags[FLAG_V] = 1;
1791+		context->flags[FLAG_N] = 1;
1792+		context->flags[FLAG_Z] = 0;
1793+		cycles += 2;
1794+		context->current_cycle += cycles * context->options->gen.clock_divider;
1795+		return orig_dividend;
1796+	}
1797+	uint16_t quotient = 0;
1798+	uint16_t bit = 0;
1799+	for (int i = 0; i < 15; i++)
1800+	{
1801+		quotient = quotient << 1 | bit;
1802+		dividend = dividend << 1;
1803+		
1804+		if (dividend >= divisor_shift) {
1805+			dividend -= divisor_shift;
1806+			cycles += 6;
1807+			bit = 1;
1808+		} else {
1809+			bit = 0;
1810+			cycles += 8;
1811+		}
1812+	}
1813+	quotient = quotient << 1 | bit;
1814+	dividend = dividend << 1;
1815+	if (dividend >= divisor_shift) {
1816+		dividend -= divisor_shift;
1817+		quotient = quotient << 1 | 1;
1818+	} else {
1819+		quotient = quotient << 1;
1820+	}
1821+	cycles += 4;
1822+	
1823+	context->flags[FLAG_V] = 0;
1824+	if (orig_divisor & 0x80000000) {
1825+		cycles += 16; //was 10
1826+		if (orig_dividend & 0x80000000) {
1827+			if (quotient & 0x8000) {
1828+				context->flags[FLAG_V] = 1;
1829+				context->flags[FLAG_N] = 1;
1830+				context->flags[FLAG_Z] = 0;
1831+				context->current_cycle += cycles * context->options->gen.clock_divider;
1832+				return orig_dividend;
1833+			} else {
1834+				dividend = -dividend;
1835+			}
1836+		} else {
1837+			quotient = -quotient;
1838+			if (quotient && !(quotient & 0x8000)) {
1839+				context->flags[FLAG_V] = 1;
1840+			}
1841+		}
1842+	} else if (orig_dividend & 0x80000000) {
1843+		cycles += 18; // was 12
1844+		quotient = -quotient;
1845+		if (quotient && !(quotient & 0x8000)) {
1846+			context->flags[FLAG_V] = 1;
1847+		} else {
1848+			dividend = -dividend;
1849+		}
1850+	} else {
1851+		cycles += 14; //was 10
1852+		if (quotient & 0x8000) {
1853+			context->flags[FLAG_V] = 1;
1854+		}
1855+	}
1856+	if (context->flags[FLAG_V]) {
1857+		context->flags[FLAG_N] = 1;
1858+		context->flags[FLAG_Z] = 0;
1859+		context->current_cycle += cycles * context->options->gen.clock_divider;
1860+		return orig_dividend;
1861+	}
1862+	context->flags[FLAG_N] = (quotient & 0x8000) ? 1 : 0;
1863+	context->flags[FLAG_Z] = quotient == 0;
1864+	//V was cleared above, C is cleared by the generated machine code
1865+	context->current_cycle += cycles * context->options->gen.clock_divider;
1866+	return dividend | quotient;
1867+}
1868+
1869+void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1870+{
1871+	code_info *code = &opts->gen.code;
1872+	check_alloc_code(code, MAX_NATIVE_SIZE);
1873+	set_flag(opts, 0, FLAG_C);
1874+	if (dst_op->mode == MODE_REG_DIRECT) {
1875+		mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D);
1876+	} else {
1877+		mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D);
1878+	}
1879+	if (src_op->mode == MODE_IMMED) {
1880+		mov_ir(code, src_op->disp << 16, opts->gen.scratch1, SZ_D);
1881+	} else {
1882+		if (src_op->mode == MODE_REG_DISPLACE8) {
1883+			movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
1884+		} else if (src_op->base != opts->gen.scratch1) {
1885+			movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
1886+		}
1887+		shl_ir(code, 16, opts->gen.scratch1, SZ_D);
1888+	}
1889+	cmp_ir(code, 0, opts->gen.scratch1, SZ_D);
1890+	code_ptr not_zero = code->cur+1;
1891+	jcc(code, CC_NZ, not_zero);
1892+	
1893+	//TODO: Check that opts->trap includes the cycles conumed by the first trap0 microinstruction
1894+	cycles(&opts->gen, 4);
1895+	uint32_t isize = 2;
1896+	switch(inst->src.addr_mode)
1897+	{
1898+	case MODE_AREG_DISPLACE:
1899+	case MODE_AREG_INDEX_DISP8:
1900+	case MODE_ABSOLUTE_SHORT:
1901+	case MODE_PC_DISPLACE:
1902+	case MODE_PC_INDEX_DISP8:
1903+	case MODE_IMMEDIATE:
1904+		isize = 4;
1905+		break;
1906+	case MODE_ABSOLUTE:
1907+		isize = 6;
1908+		break;
1909+	}
1910+	//zero seems to clear all flags
1911+	update_flags(opts, N0|Z0|V0);
1912+	mov_ir(code, VECTOR_INT_DIV_ZERO, opts->gen.scratch2, SZ_D);
1913+	mov_ir(code, inst->address+isize, opts->gen.scratch1, SZ_D);
1914+	jmp(code, opts->trap);
1915+	
1916+	*not_zero = code->cur - (not_zero + 1);
1917+	code_ptr end = NULL;
1918+	if (inst->op == M68K_DIVU) {
1919+		//initial overflow check needs to be done in the C code for divs
1920+		//but can be done before dumping state to mem in divu as an optimization
1921+		cmp_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_D);
1922+		code_ptr not_overflow = code->cur+1;
1923+		jcc(code, CC_C, not_overflow);
1924+		
1925+		//overflow seems to always set the N and clear Z
1926+		update_flags(opts, N1|Z0|V1);
1927+		cycles(&opts->gen, 10);
1928+		end = code->cur+1;
1929+		jmp(code, end);
1930+		
1931+		*not_overflow = code->cur - (not_overflow + 1);
1932+	}
1933+	call(code, opts->gen.save_context);
1934+	push_r(code, opts->gen.context_reg);
1935+	//TODO: inline the functionality of divudivs/ so we don't need to dump context to memory
1936+	call_args(code, (code_ptr)(inst->op == M68K_DIVU ? divu : divs), 3, opts->gen.scratch2, opts->gen.context_reg, opts->gen.scratch1);
1937+	pop_r(code, opts->gen.context_reg);
1938+	mov_rr(code, RAX, opts->gen.scratch1, SZ_D);
1939+	
1940+	call(code, opts->gen.load_context);
1941+	
1942+	if (inst->op == M68K_DIVU) {
1943+		cmp_ir(code, 0, opts->gen.scratch1, SZ_W);
1944+		update_flags(opts, V0|Z|N);
1945+	}
1946+	
1947+	if (dst_op->mode == MODE_REG_DIRECT) {
1948+		mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_D);
1949+	} else {
1950+		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D);
1951+	}
1952+	if (end) {
1953+		*end = code->cur - (end + 1);
1954+	}
1955+}
1956+
1957+void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
1958+{
1959+	code_info *code = &opts->gen.code;
1960+	cycles(&opts->gen, 6);
1961+	if (dst_op->mode == MODE_REG_DIRECT) {
1962+		mov_rr(code, dst_op->base, opts->gen.scratch2, SZ_D);
1963+		if (src_op->mode == MODE_REG_DIRECT) {
1964+			mov_rr(code, src_op->base, dst_op->base, SZ_D);
1965+			mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1966+		} else {
1967+			mov_rdispr(code, src_op->base, src_op->disp, dst_op->base, SZ_D);
1968+			mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1969+		}
1970+	} else {
1971+		mov_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_D);
1972+		if (src_op->mode == MODE_REG_DIRECT) {
1973+			mov_rrdisp(code, src_op->base, dst_op->base, dst_op->disp, SZ_D);
1974+			mov_rr(code, opts->gen.scratch2, src_op->base, SZ_D);
1975+		} else {
1976+			mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_D);
1977+			mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_D);
1978+			mov_rrdisp(code, opts->gen.scratch2, src_op->base, src_op->disp, SZ_D);
1979+		}
1980+	}
1981+}
1982+
1983+
1984+
1985+static uint32_t mulu_cycles(uint16_t value)
1986+{
1987+	//4 for prefetch, 2-cycles per bit x 16, 2 for cleanup
1988+	uint32_t cycles = 38;
1989+	uint16_t a = (value & 0b1010101010101010) >> 1;
1990+	uint16_t b = value & 0b0101010101010101;
1991+	value = a + b;
1992+	a = (value & 0b1100110011001100) >> 2;
1993+	b = value & 0b0011001100110011;
1994+	value = a + b;
1995+	a = (value & 0b1111000011110000) >> 4;
1996+	b = value & 0b0000111100001111;
1997+	value = a + b;
1998+	a = (value & 0b1111111100000000) >> 8;
1999+	b = value & 0b0000000011111111;
2000+	value = a + b;
2001+	return cycles + 2*value;
2002+}
2003+
2004+static uint32_t muls_cycles(uint16_t value)
2005+{
2006+	//muls timing is essentially the same as muls, but it's based on the number of 0/1
2007+	//transitions rather than the number of 1 bits. xoring the value with itself shifted
2008+	//by one effectively sets one bit for every transition
2009+	return mulu_cycles((value << 1) ^ value);
2010+}
2011+
2012+void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2013+{
2014+	code_info *code = &opts->gen.code;
2015+	if (src_op->mode == MODE_IMMED) {
2016+		cycles(&opts->gen, inst->op == M68K_MULU ? mulu_cycles(src_op->disp) : muls_cycles(src_op->disp));
2017+		mov_ir(code, inst->op == M68K_MULU ? (src_op->disp & 0xFFFF) : ((src_op->disp & 0x8000) ? src_op->disp | 0xFFFF0000 : src_op->disp), opts->gen.scratch1, SZ_D);
2018+	} else if (src_op->mode == MODE_REG_DIRECT) {
2019+		if (inst->op == M68K_MULS) {
2020+			movsx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
2021+		} else {
2022+			movzx_rr(code, src_op->base, opts->gen.scratch1, SZ_W, SZ_D);
2023+		}
2024+	} else {
2025+		if (inst->op == M68K_MULS) {
2026+			movsx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
2027+		} else {
2028+			movzx_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W, SZ_D);
2029+		}
2030+	}
2031+	if (src_op->mode != MODE_IMMED) {
2032+		//TODO: Inline cycle calculation so we don't need to save/restore a bunch of registers
2033+		//save context to memory and call the relevant C function for calculating the cycle count
2034+		call(code, opts->gen.save_context);
2035+		push_r(code, opts->gen.scratch1);
2036+		push_r(code, opts->gen.context_reg);
2037+		call_args(code, (code_ptr)(inst->op == M68K_MULS ? muls_cycles : mulu_cycles), 1, opts->gen.scratch1);
2038+		pop_r(code, opts->gen.context_reg);
2039+		//turn 68K cycles into master clock cycles and add to the current cycle count
2040+		imul_irr(code, opts->gen.clock_divider, RAX, RAX, SZ_D);
2041+		add_rrdisp(code, RAX, opts->gen.context_reg, offsetof(m68k_context, current_cycle), SZ_D);
2042+		//restore context and scratch1
2043+		call(code, opts->gen.load_context);
2044+		pop_r(code, opts->gen.scratch1);
2045+	}
2046+	
2047+	uint8_t dst_reg;
2048+	if (dst_op->mode == MODE_REG_DIRECT) {
2049+		dst_reg = dst_op->base;
2050+		if (inst->op == M68K_MULS) {
2051+			movsx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2052+		} else {
2053+			movzx_rr(code, dst_reg, dst_reg, SZ_W, SZ_D);
2054+		}
2055+	} else {
2056+		dst_reg = opts->gen.scratch2;
2057+		if (inst->op == M68K_MULS) {
2058+			movsx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
2059+		} else {
2060+			movzx_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch2, SZ_W, SZ_D);
2061+		}
2062+	}
2063+	imul_rr(code, opts->gen.scratch1, dst_reg, SZ_D);
2064+	if (dst_op->mode == MODE_REG_DISPLACE8) {
2065+		mov_rrdisp(code, dst_reg, dst_op->base, dst_op->disp, SZ_D);
2066+	}
2067+	cmp_ir(code, 0, dst_reg, SZ_D);
2068+	update_flags(opts, N|Z|V0|C0);
2069+}
2070+
2071+void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2072+{
2073+	code_info *code = &opts->gen.code;
2074+	cycles(&opts->gen, BUS);
2075+	if (dst_op->mode == MODE_REG_DIRECT) {
2076+		if (dst_op->base == opts->gen.scratch1) {
2077+			push_r(code, opts->gen.scratch2);
2078+			xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, inst->extra.size);
2079+			flag_to_carry(opts, FLAG_X);
2080+			sbb_rr(code, dst_op->base, opts->gen.scratch2, inst->extra.size);
2081+			mov_rr(code, opts->gen.scratch2, dst_op->base, inst->extra.size);
2082+			pop_r(code, opts->gen.scratch2);
2083+		} else {
2084+			xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2085+			flag_to_carry(opts, FLAG_X);
2086+			sbb_rr(code, dst_op->base, opts->gen.scratch1, inst->extra.size);
2087+			mov_rr(code, opts->gen.scratch1, dst_op->base, inst->extra.size);
2088+		}
2089+	} else {
2090+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, inst->extra.size);
2091+		flag_to_carry(opts, FLAG_X);
2092+		sbb_rdispr(code, dst_op->base, dst_op->disp, opts->gen.scratch1, inst->extra.size);
2093+		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, inst->extra.size);
2094+	}
2095+	set_flag_cond(opts, CC_C, FLAG_C);
2096+	code_ptr after_flag_set = code->cur + 1;
2097+	jcc(code, CC_Z, code->cur + 2);
2098+	set_flag(opts, 0, FLAG_Z);
2099+	*after_flag_set = code->cur - (after_flag_set+1);
2100+	set_flag_cond(opts, CC_S, FLAG_N);
2101+	set_flag_cond(opts, CC_O, FLAG_V);
2102+	if (opts->flag_regs[FLAG_C] >= 0) {
2103+		flag_to_flag(opts, FLAG_C, FLAG_X);
2104+	} else {
2105+		set_flag_cond(opts, CC_C, FLAG_X);
2106+	}
2107+	m68k_save_result(inst, opts);
2108+}
2109+
2110+void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2111+{
2112+	code_info *code = &opts->gen.code;
2113+	int32_t init_flags = C|V0;
2114+	if (inst->src.addr_mode == MODE_UNUSED) {
2115+		cycles(&opts->gen, BUS);
2116+		//Memory rotate
2117+		if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2118+			flag_to_carry(opts, FLAG_X);
2119+			init_flags |= X;
2120+		}
2121+		op_ir(code, inst, 1, dst_op->base, inst->extra.size);
2122+		update_flags(opts, init_flags);
2123+		cmp_ir(code, 0, dst_op->base, inst->extra.size);
2124+		update_flags(opts, Z|N);
2125+		m68k_save_result(inst, opts);
2126+	} else {
2127+		if (src_op->mode == MODE_IMMED) {
2128+			cycles(&opts->gen, (inst->extra.size == OPSIZE_LONG ? 8 : 6) + src_op->disp*2);
2129+			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2130+				flag_to_carry(opts, FLAG_X);
2131+				init_flags |= X;
2132+			}
2133+			if (dst_op->mode == MODE_REG_DIRECT) {
2134+				op_ir(code, inst, src_op->disp, dst_op->base, inst->extra.size);
2135+			} else {
2136+				op_irdisp(code, inst, src_op->disp, dst_op->base, dst_op->disp, inst->extra.size);
2137+			}
2138+			update_flags(opts, init_flags);
2139+		} else {
2140+			if (src_op->mode == MODE_REG_DIRECT) {
2141+				if (src_op->base != opts->gen.scratch1) {
2142+					mov_rr(code, src_op->base, opts->gen.scratch1, SZ_B);
2143+				}
2144+			} else {
2145+				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_B);
2146+			}
2147+			and_ir(code, 63, opts->gen.scratch1, SZ_D);
2148+			code_ptr zero_off = code->cur + 1;
2149+			jcc(code, CC_Z, code->cur + 2);
2150+			//add 2 cycles for every bit shifted
2151+			mov_ir(code, 2 * opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
2152+			imul_rr(code, RCX, opts->gen.scratch2, SZ_D);
2153+			add_rr(code, opts->gen.scratch2, opts->gen.cycles, SZ_D);
2154+			cmp_ir(code, 32, opts->gen.scratch1, SZ_B);
2155+			code_ptr norm_off = code->cur + 1;
2156+			jcc(code, CC_L, code->cur + 2);
2157+			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2158+				flag_to_carry(opts, FLAG_X);
2159+				init_flags |= X;
2160+			} else {
2161+				sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2162+			}
2163+			if (dst_op->mode == MODE_REG_DIRECT) {
2164+				op_ir(code, inst, 31, dst_op->base, inst->extra.size);
2165+				op_ir(code, inst, 1, dst_op->base, inst->extra.size);
2166+			} else {
2167+				op_irdisp(code, inst, 31, dst_op->base, dst_op->disp, inst->extra.size);
2168+				op_irdisp(code, inst, 1, dst_op->base, dst_op->disp, inst->extra.size);
2169+			}
2170+
2171+			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2172+				set_flag_cond(opts, CC_C, FLAG_X);
2173+				sub_ir(code, 32, opts->gen.scratch1, SZ_B);
2174+				*norm_off = code->cur - (norm_off+1);
2175+				flag_to_carry(opts, FLAG_X);
2176+			} else {
2177+				*norm_off = code->cur - (norm_off+1);
2178+			}
2179+			if (dst_op->mode == MODE_REG_DIRECT) {
2180+				op_r(code, inst, dst_op->base, inst->extra.size);
2181+			} else {
2182+				op_rdisp(code, inst, dst_op->base, dst_op->disp, inst->extra.size);
2183+			}
2184+			update_flags(opts, init_flags);
2185+			code_ptr end_off = code->cur + 1;
2186+			jmp(code, code->cur + 2);
2187+			*zero_off = code->cur - (zero_off+1);
2188+			if (inst->op == M68K_ROXR || inst->op == M68K_ROXL) {
2189+				//Carry flag is set to X flag when count is 0, this is different from ROR/ROL
2190+				flag_to_flag(opts, FLAG_X, FLAG_C);
2191+			} else {
2192+				set_flag(opts, 0, FLAG_C);
2193+			}
2194+			*end_off = code->cur - (end_off+1);
2195+		}
2196+		if (dst_op->mode == MODE_REG_DIRECT) {
2197+			cmp_ir(code, 0, dst_op->base, inst->extra.size);
2198+		} else {
2199+			cmp_irdisp(code, 0, dst_op->base, dst_op->disp, inst->extra.size);
2200+		}
2201+		update_flags(opts, Z|N);
2202+	}
2203+}
2204+
2205+#define BIT_SUPERVISOR 5
2206+
2207+void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst)
2208+{
2209+	code_info *code = &opts->gen.code;
2210+	//check supervisor bit in SR and trap if not in supervisor mode
2211+	bt_irdisp(code, BIT_SUPERVISOR, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2212+	code_ptr in_sup_mode = code->cur + 1;
2213+	jcc(code, CC_C, code->cur + 2);
2214+	
2215+	ldi_native(opts, VECTOR_PRIV_VIOLATION, opts->gen.scratch2);
2216+	ldi_native(opts, inst->address, opts->gen.scratch1);
2217+	jmp(code, opts->trap);
2218+	
2219+	*in_sup_mode = code->cur - (in_sup_mode + 1);
2220+}
2221+
2222+void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst)
2223+{
2224+	code_info *code = &opts->gen.code;
2225+	if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) {
2226+		m68k_trap_if_not_supervisor(opts, inst);
2227+	}
2228+	cycles(&opts->gen, 20);
2229+	uint32_t flag_mask = 0;
2230+	uint32_t base_flag = inst->op == M68K_ANDI_SR || inst->op == M68K_ANDI_CCR ? X0 : X1;
2231+	for (int i = 0; i < 5; i++)
2232+	{
2233+		if ((base_flag == X0) ^ ((inst->src.params.immed & 1 << i) > 0))
2234+		{
2235+			flag_mask |= base_flag << ((4 - i) * 3);
2236+		}
2237+	}
2238+	update_flags(opts, flag_mask);
2239+	if (inst->op == M68K_ANDI_SR || inst->op == M68K_ORI_SR) {
2240+		if (inst->op == M68K_ANDI_SR) {
2241+			and_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2242+		} else {
2243+			or_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2244+		}
2245+		if (inst->op == M68K_ANDI_SR && !(inst->src.params.immed & (1 << (BIT_SUPERVISOR + 8)))) {
2246+			//leave supervisor mode
2247+			swap_ssp_usp(opts);
2248+		}
2249+		if ((inst->op == M68K_ANDI_SR && (inst->src.params.immed  & 0x700) != 0x700)
2250+		    || (inst->op == M68K_ORI_SR && inst->src.params.immed & 0x8700)) {
2251+			if (inst->op == M68K_ANDI_SR) {
2252+				//set int pending flag in case we trigger an interrupt as a result of the mask change
2253+				mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2254+			}
2255+			call(code, opts->do_sync);
2256+		}
2257+	}
2258+}
2259+
2260+void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst)
2261+{
2262+	code_info *code = &opts->gen.code;
2263+	if (inst->op == M68K_EORI_SR) {
2264+		m68k_trap_if_not_supervisor(opts, inst);
2265+	}
2266+	cycles(&opts->gen, 20);
2267+	if (inst->src.params.immed & 0x1) {
2268+		xor_flag(opts, 1, FLAG_C);
2269+	}
2270+	if (inst->src.params.immed & 0x2) {
2271+		xor_flag(opts, 1, FLAG_V);
2272+	}
2273+	if (inst->src.params.immed & 0x4) {
2274+		xor_flag(opts, 1, FLAG_Z);
2275+	}
2276+	if (inst->src.params.immed & 0x8) {
2277+		xor_flag(opts, 1, FLAG_N);
2278+	}
2279+	if (inst->src.params.immed & 0x10) {
2280+		xor_flag(opts, 1, FLAG_X);
2281+	}
2282+	if (inst->op == M68K_EORI_SR) {
2283+		xor_irdisp(code, inst->src.params.immed >> 8, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2284+		if (inst->src.params.immed & 0x8700) {
2285+			//set int pending flag in case we trigger an interrupt as a result of the mask change
2286+			mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2287+			call(code, opts->do_sync);
2288+		}
2289+	}
2290+}
2291+
2292+void set_all_flags(m68k_options *opts, uint8_t flags)
2293+{
2294+	uint32_t flag_mask = flags & 0x10 ? X1 : X0;
2295+	flag_mask |= flags & 0x8 ? N1 : N0;
2296+	flag_mask |= flags & 0x4 ? Z1 : Z0;
2297+	flag_mask |= flags & 0x2 ? V1 : V0;
2298+	flag_mask |= flags & 0x1 ? C1 : C0;
2299+	update_flags(opts, flag_mask);
2300+}
2301+
2302+void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2303+{
2304+	code_info *code = &opts->gen.code;
2305+	if (inst->op == M68K_MOVE_SR) {
2306+		m68k_trap_if_not_supervisor(opts, inst);
2307+	}
2308+	if (src_op->mode == MODE_IMMED) {
2309+		set_all_flags(opts, src_op->disp);
2310+		if (inst->op == M68K_MOVE_SR) {
2311+			mov_irdisp(code, (src_op->disp >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2312+			if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2313+				//leave supervisor mode
2314+				swap_ssp_usp(opts);
2315+			}
2316+			if (((src_op->disp >> 8) & 7) < 7) {
2317+				//set int pending flag in case we trigger an interrupt as a result of the mask change
2318+				mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2319+			}
2320+			call(code, opts->do_sync);
2321+		}
2322+		cycles(&opts->gen, 12);
2323+	} else {
2324+		if (src_op->base != opts->gen.scratch1) {
2325+			if (src_op->mode == MODE_REG_DIRECT) {
2326+				mov_rr(code, src_op->base, opts->gen.scratch1, SZ_W);
2327+			} else {
2328+				mov_rdispr(code, src_op->base, src_op->disp, opts->gen.scratch1, SZ_W);
2329+			}
2330+		}
2331+		if (inst->op == M68K_MOVE_SR) {
2332+			call(code, opts->set_sr);
2333+			call(code, opts->do_sync);
2334+		} else {
2335+			call(code, opts->set_ccr);
2336+		}
2337+		cycles(&opts->gen, 12);
2338+	}
2339+}
2340+
2341+void translate_m68k_stop(m68k_options *opts, m68kinst *inst)
2342+{
2343+	m68k_trap_if_not_supervisor(opts, inst);
2344+	//manual says 4 cycles, but it has to be at least 8 since it's a 2-word instruction
2345+	//possibly even 12 since that's how long MOVE to SR takes
2346+	//On further thought prefetch + the fact that this stops the CPU may make
2347+	//Motorola's accounting make sense here
2348+	code_info *code = &opts->gen.code;
2349+	cycles(&opts->gen, BUS*2);
2350+	set_all_flags(opts,  inst->src.params.immed);
2351+	mov_irdisp(code, (inst->src.params.immed >> 8), opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2352+	if (!((inst->src.params.immed >> 8) & (1 << BIT_SUPERVISOR))) {
2353+		//leave supervisor mode
2354+		swap_ssp_usp(opts);
2355+	}
2356+	code_ptr loop_top = code->cur;
2357+		call(code, opts->do_sync);
2358+		cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
2359+		code_ptr normal_cycle_up = code->cur + 1;
2360+		jcc(code, CC_A, code->cur + 2);
2361+			cycles(&opts->gen, BUS);
2362+			code_ptr after_cycle_up = code->cur + 1;
2363+			jmp(code, code->cur + 2);
2364+		*normal_cycle_up = code->cur - (normal_cycle_up + 1);
2365+			mov_rr(code, opts->gen.limit, opts->gen.cycles, SZ_D);
2366+		*after_cycle_up = code->cur - (after_cycle_up+1);
2367+		cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2368+	jcc(code, CC_C, loop_top);
2369+	//set int pending flag so interrupt fires immediately after stop is done
2370+	mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2371+}
2372+
2373+void translate_m68k_trapv(m68k_options *opts, m68kinst *inst)
2374+{
2375+	code_info *code = &opts->gen.code;
2376+	cycles(&opts->gen, BUS);
2377+	flag_to_carry(opts, FLAG_V);
2378+	code_ptr no_trap = code->cur + 1;
2379+	jcc(code, CC_NC, no_trap);
2380+	ldi_native(opts, VECTOR_TRAPV, opts->gen.scratch2);
2381+	ldi_native(opts, inst->address+2, opts->gen.scratch1);
2382+	jmp(code, opts->trap);
2383+	*no_trap = code->cur - (no_trap + 1);
2384+}
2385+
2386+void translate_m68k_odd(m68k_options *opts, m68kinst *inst)
2387+{
2388+	code_info *code = &opts->gen.code;
2389+	//swap USP and SSP if not already in supervisor mode
2390+	check_user_mode_swap_ssp_usp(opts);
2391+	//save PC
2392+	subi_areg(opts, 4, 7);
2393+	areg_to_native(opts, 7, opts->gen.scratch2);
2394+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2395+	call(code, opts->write_32_lowfirst);
2396+	//save status register
2397+	subi_areg(opts, 2, 7);
2398+	call(code, opts->get_sr);
2399+	areg_to_native(opts, 7, opts->gen.scratch2);
2400+	call(code, opts->write_16);
2401+	//save instruction register
2402+	subi_areg(opts, 2, 7);
2403+	//calculate IR
2404+	push_r(code, opts->gen.context_reg);
2405+	call(code, opts->gen.save_context);
2406+	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2407+	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2408+	pop_r(code, opts->gen.context_reg);
2409+	push_r(code, RAX); //save it for use in the "info" word
2410+	call(code, opts->gen.load_context);
2411+	//write it to the stack
2412+	areg_to_native(opts, 7, opts->gen.scratch2);
2413+	call(code, opts->write_16);
2414+	//save access address
2415+	subi_areg(opts, 4, 7);
2416+	mov_ir(code, inst->address, opts->gen.scratch1, SZ_D);
2417+	areg_to_native(opts, 7, opts->gen.scratch2);
2418+	call(code, opts->write_32_lowfirst);
2419+	//save FC, I/N and R/W word'
2420+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2421+	//FC3 is basically the same as the supervisor bit
2422+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2423+	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2424+	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2425+	//set FC1 to one to indicate instruction fetch, and R/W to indicate read
2426+	or_ir(code, 0x12, opts->gen.scratch1, SZ_B);
2427+	//set undefined bits to IR value
2428+	pop_r(code, opts->gen.scratch2);
2429+	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2430+	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2431+	subi_areg(opts, 2, 7);
2432+	areg_to_native(opts, 7, opts->gen.scratch2);
2433+	call(code, opts->write_16);
2434+	//set supervisor bit
2435+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2436+	//load vector address
2437+	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2438+	call(code, opts->read_32);
2439+	call(code, opts->native_addr_and_sync);
2440+	cycles(&opts->gen, 18);
2441+	jmp_r(code, opts->gen.scratch1);
2442+}
2443+
2444+void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op)
2445+{
2446+	code_info *code = &opts->gen.code;
2447+	cycles(&opts->gen, inst->dst.addr_mode == MODE_REG_DIRECT ? BUS+2 : BUS);
2448+	call(code, opts->get_sr);
2449+	if (dst_op->mode == MODE_REG_DIRECT) {
2450+		mov_rr(code, opts->gen.scratch1, dst_op->base, SZ_W);
2451+	} else {
2452+		mov_rrdisp(code, opts->gen.scratch1, dst_op->base, dst_op->disp, SZ_W);
2453+	}
2454+	m68k_save_result(inst, opts);
2455+}
2456+
2457+void m68k_out_of_bounds_execution(uint32_t address)
2458+{
2459+	fatal_error("M68K attempted to execute code at unmapped or I/O address %X\n", address);
2460+}
2461+
2462+void translate_out_of_bounds(m68k_options *opts, uint32_t address)
2463+{
2464+	code_info *code = &opts->gen.code;
2465+	check_cycles_int(&opts->gen, address);
2466+	mov_ir(code, address, opts->gen.scratch1, SZ_D);
2467+	call_args(code, (code_ptr)m68k_out_of_bounds_execution, 1, opts->gen.scratch1);
2468+}
2469+
2470+void m68k_set_last_prefetch(m68k_options *opts, uint32_t address)
2471+{
2472+	mov_irdisp(&opts->gen.code, address, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), SZ_D);
2473+}
2474+
2475+void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst)
2476+{
2477+	if (next_inst == old_end && next_inst - code->cur < 2) {
2478+		while (code->cur < old_end) {
2479+			*(code->cur++) = 0x90; //NOP
2480+		}
2481+	} else {
2482+		jmp(code, next_inst);
2483+	}
2484+}
2485+
2486+#define M68K_MAX_INST_SIZE (2*(1+2+2))
2487+
2488+m68k_context * m68k_handle_code_write(uint32_t address, m68k_context * context)
2489+{
2490+	m68k_options * options = context->options;
2491+	uint32_t inst_start = get_instruction_start(options, address);
2492+	while (inst_start && (address - inst_start) < M68K_MAX_INST_SIZE) {
2493+		code_ptr dst = get_native_address(context->options, inst_start);
2494+		patch_for_retranslate(&options->gen, dst, options->retrans_stub);
2495+		inst_start = get_instruction_start(options, inst_start - 2);
2496+	}
2497+	return context;
2498+}
2499+
2500+void m68k_invalidate_code_range(m68k_context *context, uint32_t start, uint32_t end)
2501+{
2502+	m68k_options *opts = context->options;
2503+	native_map_slot *native_code_map = opts->gen.native_code_map;
2504+	memmap_chunk const *mem_chunk = find_map_chunk(start, &opts->gen, 0, NULL);
2505+	if (mem_chunk) {
2506+		//calculate the lowest alias for this address
2507+		start = mem_chunk->start + ((start - mem_chunk->start) & mem_chunk->mask);
2508+	}
2509+	mem_chunk = find_map_chunk(end, &opts->gen, 0, NULL);
2510+	if (mem_chunk) {
2511+		//calculate the lowest alias for this address
2512+		end = mem_chunk->start + ((end - mem_chunk->start) & mem_chunk->mask);
2513+	}
2514+	uint32_t start_chunk = start / NATIVE_CHUNK_SIZE, end_chunk = end / NATIVE_CHUNK_SIZE;
2515+	for (uint32_t chunk = start_chunk; chunk <= end_chunk; chunk++)
2516+	{
2517+		if (native_code_map[chunk].base) {
2518+			uint32_t start_offset = chunk == start_chunk ? start % NATIVE_CHUNK_SIZE : 0;
2519+			uint32_t end_offset = chunk == end_chunk ? end % NATIVE_CHUNK_SIZE : NATIVE_CHUNK_SIZE;
2520+			for (uint32_t offset = start_offset; offset < end_offset; offset++)
2521+			{
2522+				if (native_code_map[chunk].offsets[offset] != INVALID_OFFSET && native_code_map[chunk].offsets[offset] != EXTENSION_WORD) {
2523+					patch_for_retranslate(&opts->gen, native_code_map[chunk].base + native_code_map[chunk].offsets[offset], opts->retrans_stub);
2524+					/*code_info code;
2525+					code.cur = native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
2526+					code.last = code.cur + 32;
2527+					code.stack_off = 0;
2528+					mov_ir(&code, chunk * NATIVE_CHUNK_SIZE + offset, opts->gen.scratch2, SZ_D);
2529+					jmp(&code, opts->retrans_stub);*/
2530+				}
2531+			}
2532+		}
2533+	}
2534+}
2535+
2536+void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr)
2537+{
2538+	m68k_options * opts = context->options;
2539+	code_info native;
2540+	native.cur = native_addr ? native_addr : get_native_address(context->options, address);
2541+	
2542+	if (!native.cur) {
2543+		return;
2544+	}
2545+	
2546+	if (*native.cur != opts->prologue_start) {
2547+		//instruction has already been patched, probably for retranslation
2548+		return;
2549+	}
2550+	native.last = native.cur + 128;
2551+	native.stack_off = 0;
2552+	code_ptr start_native = native.cur;
2553+	mov_ir(&native, address, opts->gen.scratch1, SZ_D);
2554+	
2555+	
2556+	call(&native, opts->bp_stub);
2557+}
2558+
2559+void init_m68k_opts(m68k_options * opts, memmap_chunk * memmap, uint32_t num_chunks, uint32_t clock_divider)
2560+{
2561+	memset(opts, 0, sizeof(*opts));
2562+	opts->gen.memmap = memmap;
2563+	opts->gen.memmap_chunks = num_chunks;
2564+	opts->gen.address_size = SZ_D;
2565+	opts->gen.address_mask = 0xFFFFFF;
2566+	opts->gen.byte_swap = 1;
2567+	opts->gen.max_address = 0x1000000;
2568+	opts->gen.bus_cycles = BUS;
2569+	opts->gen.clock_divider = clock_divider;
2570+	opts->gen.mem_ptr_off = offsetof(m68k_context, mem_pointers);
2571+	opts->gen.ram_flags_off = offsetof(m68k_context, ram_code_flags);
2572+	opts->gen.ram_flags_shift = 11;
2573+	for (int i = 0; i < 8; i++)
2574+	{
2575+		opts->dregs[i] = opts->aregs[i] = -1;
2576+	}
2577+#ifdef X86_64
2578+	opts->dregs[0] = R10;
2579+	opts->dregs[1] = R11;
2580+	opts->dregs[2] = R12;
2581+	opts->dregs[3] = R8;
2582+	opts->aregs[0] = R13;
2583+	opts->aregs[1] = R14;
2584+	opts->aregs[2] = R9;
2585+	opts->aregs[7] = R15;
2586+
2587+	opts->flag_regs[0] = -1;
2588+	opts->flag_regs[1] = RBX;
2589+	opts->flag_regs[2] = RDX;
2590+	opts->flag_regs[3] = BH;
2591+	opts->flag_regs[4] = DH;
2592+
2593+	opts->gen.scratch2 = RDI;
2594+#else
2595+	opts->dregs[0] = RDX;
2596+	opts->aregs[7] = RDI;
2597+
2598+	for (int i = 0; i < 5; i++)
2599+	{
2600+		opts->flag_regs[i] = -1;
2601+	}
2602+	opts->gen.scratch2 = RBX;
2603+#endif
2604+	opts->gen.context_reg = RSI;
2605+	opts->gen.cycles = RAX;
2606+	opts->gen.limit = RBP;
2607+	opts->gen.scratch1 = RCX;
2608+	opts->gen.align_error_mask = 1;
2609+
2610+
2611+	opts->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2612+	memset(opts->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
2613+	opts->gen.deferred = NULL;
2614+
2615+	uint32_t inst_size_size = sizeof(uint8_t *) * ram_size(&opts->gen) / 1024;
2616+	opts->gen.ram_inst_sizes = malloc(inst_size_size);
2617+	memset(opts->gen.ram_inst_sizes, 0, inst_size_size);
2618+
2619+	code_info *code = &opts->gen.code;
2620+	init_code_info(code);
2621+
2622+	opts->gen.save_context = code->cur;
2623+	for (int i = 0; i < 5; i++)
2624+		if (opts->flag_regs[i] >= 0) {
2625+			mov_rrdisp(code, opts->flag_regs[i], opts->gen.context_reg, offsetof(m68k_context, flags) + i, SZ_B);
2626+		}
2627+	for (int i = 0; i < 8; i++)
2628+	{
2629+		if (opts->dregs[i] >= 0) {
2630+			mov_rrdisp(code, opts->dregs[i], opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, SZ_D);
2631+		}
2632+		if (opts->aregs[i] >= 0) {
2633+			mov_rrdisp(code, opts->aregs[i], opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, SZ_D);
2634+		}
2635+	}
2636+	mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(m68k_context, current_cycle), SZ_D);
2637+	retn(code);
2638+
2639+	opts->gen.load_context = code->cur;
2640+	for (int i = 0; i < 5; i++)
2641+	{
2642+		if (opts->flag_regs[i] >= 0) {
2643+			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + i, opts->flag_regs[i], SZ_B);
2644+		}
2645+	}
2646+	for (int i = 0; i < 8; i++)
2647+	{
2648+		if (opts->dregs[i] >= 0) {
2649+			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, dregs) + sizeof(uint32_t) * i, opts->dregs[i], SZ_D);
2650+		}
2651+		if (opts->aregs[i] >= 0) {
2652+			mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, aregs) + sizeof(uint32_t) * i, opts->aregs[i], SZ_D);
2653+		}
2654+	}
2655+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, current_cycle), opts->gen.cycles, SZ_D);
2656+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, target_cycle), opts->gen.limit, SZ_D);
2657+	retn(code);
2658+
2659+	opts->start_context = (start_fun)code->cur;
2660+	save_callee_save_regs(code);
2661+#ifdef X86_64
2662+	if (opts->gen.scratch2 != RDI) {
2663+		mov_rr(code, RDI, opts->gen.scratch2, SZ_PTR);
2664+	}
2665+#else
2666+	mov_rdispr(code, RSP, 20, opts->gen.scratch2, SZ_D);
2667+	mov_rdispr(code, RSP, 24, opts->gen.context_reg, SZ_D);
2668+#endif
2669+	call(code, opts->gen.load_context);
2670+	call_r(code, opts->gen.scratch2);
2671+	call(code, opts->gen.save_context);
2672+	restore_callee_save_regs(code);
2673+	retn(code);
2674+
2675+	opts->native_addr = code->cur;
2676+	call(code, opts->gen.save_context);
2677+	push_r(code, opts->gen.context_reg);
2678+	call_args(code, (code_ptr)get_native_address_trans, 2, opts->gen.context_reg, opts->gen.scratch1);
2679+	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg
2680+	pop_r(code, opts->gen.context_reg);
2681+	call(code, opts->gen.load_context);
2682+	retn(code);
2683+
2684+	opts->native_addr_and_sync = code->cur;
2685+	call(code, opts->gen.save_context);
2686+	push_r(code, opts->gen.scratch1);
2687+
2688+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
2689+	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2690+	pop_r(code, RSI); //restore saved address from opts->gen.scratch1
2691+	push_r(code, RAX); //save context pointer for later
2692+	call_args(code, (code_ptr)get_native_address_trans, 2, RAX, RSI);
2693+	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR); //move result to scratch reg
2694+	pop_r(code, opts->gen.context_reg);
2695+	call(code, opts->gen.load_context);
2696+	retn(code);
2697+
2698+	opts->gen.handle_cycle_limit = code->cur;
2699+	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
2700+	code_ptr skip_sync = code->cur + 1;
2701+	jcc(code, CC_C, code->cur + 2);
2702+	opts->do_sync = code->cur;
2703+	push_r(code, opts->gen.scratch1);
2704+	push_r(code, opts->gen.scratch2);
2705+	call(code, opts->gen.save_context);
2706+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
2707+	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2708+	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
2709+	call(code, opts->gen.load_context);
2710+	pop_r(code, opts->gen.scratch2);
2711+	pop_r(code, opts->gen.scratch1);
2712+	*skip_sync = code->cur - (skip_sync+1);
2713+	retn(code);
2714+
2715+	opts->gen.handle_code_write = (code_ptr)m68k_handle_code_write;
2716+	
2717+	check_alloc_code(code, 256);
2718+	opts->gen.handle_align_error_write = code->cur;
2719+	code->cur += 256;
2720+	check_alloc_code(code, 256);
2721+	opts->gen.handle_align_error_read = code->cur;
2722+	code->cur += 256;
2723+	
2724+	opts->read_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_16, NULL);
2725+	opts->read_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, READ_8, NULL);
2726+	opts->write_16 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_16, NULL);
2727+	opts->write_8 = gen_mem_fun(&opts->gen, memmap, num_chunks, WRITE_8, NULL);
2728+
2729+	opts->read_32 = code->cur;
2730+	push_r(code, opts->gen.scratch1);
2731+	call(code, opts->read_16);
2732+	mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_W);
2733+	pop_r(code, opts->gen.scratch1);
2734+	push_r(code, opts->gen.scratch2);
2735+	add_ir(code, 2, opts->gen.scratch1, SZ_D);
2736+	call(code, opts->read_16);
2737+	pop_r(code, opts->gen.scratch2);
2738+	movzx_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W, SZ_D);
2739+	shl_ir(code, 16, opts->gen.scratch2, SZ_D);
2740+	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_D);
2741+	retn(code);
2742+
2743+	opts->write_32_lowfirst = code->cur;
2744+	push_r(code, opts->gen.scratch2);
2745+	push_r(code, opts->gen.scratch1);
2746+	add_ir(code, 2, opts->gen.scratch2, SZ_D);
2747+	call(code, opts->write_16);
2748+	pop_r(code, opts->gen.scratch1);
2749+	pop_r(code, opts->gen.scratch2);
2750+	shr_ir(code, 16, opts->gen.scratch1, SZ_D);
2751+	jmp(code, opts->write_16);
2752+
2753+	opts->write_32_highfirst = code->cur;
2754+	push_r(code, opts->gen.scratch1);
2755+	push_r(code, opts->gen.scratch2);
2756+	shr_ir(code, 16, opts->gen.scratch1, SZ_D);
2757+	call(code, opts->write_16);
2758+	pop_r(code, opts->gen.scratch2);
2759+	pop_r(code, opts->gen.scratch1);
2760+	add_ir(code, 2, opts->gen.scratch2, SZ_D);
2761+	jmp(code, opts->write_16);
2762+
2763+	opts->get_sr = code->cur;
2764+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2765+	shl_ir(code, 8, opts->gen.scratch1, SZ_W);
2766+	if (opts->flag_regs[FLAG_X] >= 0) {
2767+		mov_rr(code, opts->flag_regs[FLAG_X], opts->gen.scratch1, SZ_B);
2768+	} else {
2769+		int8_t offset = offsetof(m68k_context, flags);
2770+		if (offset) {
2771+			mov_rdispr(code, opts->gen.context_reg, offset, opts->gen.scratch1, SZ_B);
2772+		} else {
2773+			mov_rindr(code, opts->gen.context_reg, opts->gen.scratch1, SZ_B);
2774+		}
2775+	}
2776+	for (int flag = FLAG_N; flag <= FLAG_C; flag++)
2777+	{
2778+		shl_ir(code, 1, opts->gen.scratch1, SZ_B);
2779+		if (opts->flag_regs[flag] >= 0) {
2780+			or_rr(code, opts->flag_regs[flag], opts->gen.scratch1, SZ_B);
2781+		} else {
2782+			or_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, flags) + flag, opts->gen.scratch1, SZ_B);
2783+		}
2784+	}
2785+	retn(code);
2786+
2787+	opts->set_sr = code->cur;
2788+	for (int flag = FLAG_C; flag >= FLAG_X; flag--)
2789+	{
2790+		rcr_ir(code, 1, opts->gen.scratch1, SZ_B);
2791+		if (opts->flag_regs[flag] >= 0) {
2792+			setcc_r(code, CC_C, opts->flag_regs[flag]);
2793+		} else {
2794+			int8_t offset = offsetof(m68k_context, flags) + flag;
2795+			if (offset) {
2796+				setcc_rdisp(code, CC_C, opts->gen.context_reg, offset);
2797+			} else {
2798+				setcc_rind(code, CC_C, opts->gen.context_reg);
2799+			}
2800+		}
2801+	}
2802+	shr_ir(code, 8, opts->gen.scratch1, SZ_W);
2803+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2804+	//set int pending flag in case we trigger an interrupt as a result of the mask change
2805+	mov_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
2806+	retn(code);
2807+
2808+	opts->set_ccr = code->cur;
2809+	for (int flag = FLAG_C; flag >= FLAG_X; flag--)
2810+	{
2811+		rcr_ir(code, 1, opts->gen.scratch1, SZ_B);
2812+		if (opts->flag_regs[flag] >= 0) {
2813+			setcc_r(code, CC_C, opts->flag_regs[flag]);
2814+		} else {
2815+			int8_t offset = offsetof(m68k_context, flags) + flag;
2816+			if (offset) {
2817+				setcc_rdisp(code, CC_C, opts->gen.context_reg, offset);
2818+			} else {
2819+				setcc_rind(code, CC_C, opts->gen.context_reg);
2820+			}
2821+		}
2822+	}
2823+	retn(code);
2824+	
2825+	code_info tmp_code = *code;
2826+	code->cur = opts->gen.handle_align_error_write;
2827+	code->last = code->cur + 256;
2828+	//unwind the stack one functinon call
2829+	add_ir(code, 16, RSP, SZ_PTR);
2830+	//save address that triggered error so we can write it to the 68K stack at the appropriate place
2831+	push_r(code, opts->gen.scratch2);
2832+	//swap USP and SSP if not already in supervisor mode
2833+	check_user_mode_swap_ssp_usp(opts);
2834+	//save PC
2835+	subi_areg(opts, 4, 7);
2836+	areg_to_native(opts, 7, opts->gen.scratch2);
2837+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2838+	call(code, opts->write_32_lowfirst);
2839+	//save status register
2840+	subi_areg(opts, 2, 7);
2841+	call(code, opts->get_sr);
2842+	areg_to_native(opts, 7, opts->gen.scratch2);
2843+	call(code, opts->write_16);
2844+	//save instruction register
2845+	subi_areg(opts, 2, 7);
2846+	//calculate IR
2847+	push_r(code, opts->gen.context_reg);
2848+	call(code, opts->gen.save_context);
2849+	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2850+	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2851+	pop_r(code, opts->gen.context_reg);
2852+	pop_r(code, opts->gen.scratch2); //access address
2853+	push_r(code, RAX); //save it for use in the "info" word
2854+	push_r(code, opts->gen.scratch2); //access address
2855+	call(code, opts->gen.load_context);
2856+	//write it to the stack
2857+	areg_to_native(opts, 7, opts->gen.scratch2);
2858+	call(code, opts->write_16);
2859+	//save access address
2860+	subi_areg(opts, 4, 7);
2861+	pop_r(code, opts->gen.scratch1);
2862+	areg_to_native(opts, 7, opts->gen.scratch2);
2863+	call(code, opts->write_32_lowfirst);
2864+	//save FC, I/N and R/W word'
2865+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2866+	//FC3 is basically the same as the supervisor bit
2867+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2868+	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2869+	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2870+	//set FC0 to one to indicate data access
2871+	or_ir(code, 1, opts->gen.scratch1, SZ_B);
2872+	//set undefined bits to IR value
2873+	pop_r(code, opts->gen.scratch2);
2874+	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2875+	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2876+	subi_areg(opts, 2, 7);
2877+	areg_to_native(opts, 7, opts->gen.scratch2);
2878+	call(code, opts->write_16);
2879+	//set supervisor bit
2880+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2881+	//load vector address
2882+	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2883+	call(code, opts->read_32);
2884+	call(code, opts->native_addr_and_sync);
2885+	cycles(&opts->gen, 18);
2886+	jmp_r(code, opts->gen.scratch1);
2887+	
2888+	code->cur = opts->gen.handle_align_error_read;
2889+	code->last = code->cur + 256;
2890+	//unwind the stack one functinon call
2891+	add_ir(code, 16, RSP, SZ_PTR);
2892+	//save address that triggered error so we can write it to the 68K stack at the appropriate place
2893+	push_r(code, opts->gen.scratch1);
2894+	//swap USP and SSP if not already in supervisor mode
2895+	check_user_mode_swap_ssp_usp(opts);
2896+	//save PC
2897+	subi_areg(opts, 4, 7);
2898+	areg_to_native(opts, 7, opts->gen.scratch2);
2899+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, last_prefetch_address), opts->gen.scratch1, SZ_D);
2900+	call(code, opts->write_32_lowfirst);
2901+	//save status register
2902+	subi_areg(opts, 2, 7);
2903+	call(code, opts->get_sr);
2904+	areg_to_native(opts, 7, opts->gen.scratch2);
2905+	call(code, opts->write_16);
2906+	//save instruction register
2907+	subi_areg(opts, 2, 7);
2908+	//calculate IR
2909+	push_r(code, opts->gen.context_reg);
2910+	call(code, opts->gen.save_context);
2911+	call_args_abi(code, (code_ptr)m68k_get_ir, 1, opts->gen.context_reg);
2912+	mov_rr(code, RAX, opts->gen.scratch1, SZ_W);
2913+	pop_r(code, opts->gen.context_reg);
2914+	pop_r(code, opts->gen.scratch2); //access address
2915+	push_r(code, RAX); //save it for use in the "info" word
2916+	push_r(code, opts->gen.scratch2); //access address
2917+	call(code, opts->gen.load_context);
2918+	//write it to the stack
2919+	areg_to_native(opts, 7, opts->gen.scratch2);
2920+	call(code, opts->write_16);
2921+	//save access address
2922+	subi_areg(opts, 4, 7);
2923+	pop_r(code, opts->gen.scratch1);
2924+	areg_to_native(opts, 7, opts->gen.scratch2);
2925+	call(code, opts->write_32_lowfirst);
2926+	//save FC, I/N and R/W word'
2927+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_W);
2928+	//FC3 is basically the same as the supervisor bit
2929+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, status), opts->gen.scratch1, SZ_B);
2930+	shr_ir(code, 3, opts->gen.scratch1, SZ_B);
2931+	and_ir(code, 4, opts->gen.scratch1, SZ_B);
2932+	//set FC0 to one to indicate data access, and R/W to indicate read
2933+	or_ir(code, 0x11, opts->gen.scratch1, SZ_B);
2934+	//set undefined bits to IR value
2935+	pop_r(code, opts->gen.scratch2);
2936+	and_ir(code, 0xFFE0, opts->gen.scratch2, SZ_W);
2937+	or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
2938+	subi_areg(opts, 2, 7);
2939+	areg_to_native(opts, 7, opts->gen.scratch2);
2940+	call(code, opts->write_16);
2941+	//set supervisor bit
2942+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2943+	//load vector address
2944+	mov_ir(code, 4 * VECTOR_ADDRESS_ERROR, opts->gen.scratch1, SZ_D);
2945+	call(code, opts->read_32);
2946+	call(code, opts->native_addr_and_sync);
2947+	cycles(&opts->gen, 18);
2948+	jmp_r(code, opts->gen.scratch1);
2949+	
2950+	*code = tmp_code;
2951+
2952+	opts->gen.handle_cycle_limit_int = code->cur;
2953+	//calculate stack adjust size
2954+	add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
2955+	uint32_t adjust_size = code->cur - opts->gen.handle_cycle_limit_int;
2956+	code->cur = opts->gen.handle_cycle_limit_int;
2957+	//handle trace mode
2958+	cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2959+	code_ptr do_trace = code->cur + 1;
2960+	jcc(code, CC_NZ, do_trace);
2961+	bt_irdisp(code, 7, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
2962+	code_ptr no_trace = code->cur + 1;
2963+	jcc(code, CC_NC, no_trace);
2964+	mov_irdisp(code, 1, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2965+	*no_trace = code->cur - (no_trace + 1);
2966+	//handle interrupts
2967+	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
2968+	code_ptr do_int = code->cur + 2; 
2969+	jcc(code, CC_NC, do_int+512);//force 32-bit displacement
2970+	//handle component synchronization
2971+	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.cycles, SZ_D);
2972+	skip_sync = code->cur + 1;
2973+	jcc(code, CC_C, code->cur + 2);
2974+	call(code, opts->gen.save_context);
2975+	call_args_abi(code, (code_ptr)sync_components, 2, opts->gen.context_reg, opts->gen.scratch1);
2976+	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
2977+	jmp(code, opts->gen.load_context);
2978+	*skip_sync = code->cur - (skip_sync+1);
2979+	cmp_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, should_return), SZ_B);
2980+	code_ptr do_ret = code->cur + 1;
2981+	jcc(code, CC_NZ, do_ret);
2982+	retn(code);
2983+	*do_ret = code->cur - (do_ret+1);
2984+	uint32_t tmp_stack_off = code->stack_off;
2985+	//fetch return address and adjust RSP
2986+	pop_r(code, opts->gen.scratch1);
2987+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
2988+	add_ir(code, adjust_size, opts->gen.scratch1, SZ_PTR);
2989+	//save return address for restoring later
2990+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, resume_pc), SZ_PTR);
2991+	retn(code);
2992+	code->stack_off = tmp_stack_off;
2993+	*do_trace = code->cur - (do_trace + 1);
2994+	//clear out trace pending flag
2995+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
2996+	//save PC as stored in scratch1 for later
2997+	push_r(code, opts->gen.scratch1);
2998+	//swap USP and SSP if not already in supervisor mode
2999+	check_user_mode_swap_ssp_usp(opts);
3000+	//save status register
3001+	subi_areg(opts, 6, 7);
3002+	call(code, opts->get_sr);
3003+	cycles(&opts->gen, 6);
3004+	//save SR to stack
3005+	areg_to_native(opts, 7, opts->gen.scratch2);
3006+	call(code, opts->write_16);
3007+	//update the status register
3008+	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3009+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3010+	//save PC
3011+	areg_to_native(opts, 7, opts->gen.scratch2);
3012+	add_ir(code, 2, opts->gen.scratch2, SZ_D);
3013+	pop_r(code, opts->gen.scratch1);
3014+	call(code, opts->write_32_lowfirst);
3015+	//read vector
3016+	mov_ir(code, 0x24, opts->gen.scratch1, SZ_D);
3017+	call(code, opts->read_32);
3018+	call(code, opts->native_addr_and_sync);
3019+	//2 prefetch bus operations + 2 idle bus cycles
3020+	cycles(&opts->gen, 10);
3021+	//discard function return address
3022+	pop_r(code, opts->gen.scratch2);
3023+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3024+	jmp_r(code, opts->gen.scratch1);
3025+	
3026+	code->stack_off = tmp_stack_off;
3027+	
3028+	*((uint32_t *)do_int) = code->cur - (do_int+4);
3029+	//implement 1 instruction latency
3030+	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3031+	do_int = code->cur + 1;
3032+	jcc(code, CC_NZ, do_int);
3033+	//store current interrupt number so it doesn't change before we start processing the vector
3034+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3035+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3036+	retn(code);
3037+	*do_int = code->cur - (do_int + 1);
3038+	//Check if int_pending has an actual interrupt priority in it
3039+	cmp_irdisp(code, INT_PENDING_SR_CHANGE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3040+	code_ptr already_int_num = code->cur + 1;
3041+	jcc(code, CC_NZ, already_int_num);
3042+	
3043+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch2, SZ_B);
3044+	mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3045+	
3046+	*already_int_num = code->cur - (already_int_num + 1);
3047+	//save PC as stored in scratch1 for later
3048+	push_r(code, opts->gen.scratch1);
3049+	//set target cycle to sync cycle
3050+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, sync_cycle), opts->gen.limit, SZ_D);
3051+	//swap USP and SSP if not already in supervisor mode
3052+	check_user_mode_swap_ssp_usp(opts);
3053+	//save status register
3054+	subi_areg(opts, 6, 7);
3055+	call(code, opts->get_sr);
3056+	//6 cycles before SR gets saved
3057+	cycles(&opts->gen, 6);
3058+	//save SR to stack
3059+	areg_to_native(opts, 7, opts->gen.scratch2);
3060+	call(code, opts->write_16);
3061+	//interrupt ack cycle
3062+	//the Genesis responds to these exclusively with !VPA which means its a slow
3063+	//6800 operation. documentation says these can take between 10 and 19 cycles.
3064+	//actual results measurements seem to suggest it's actually between 9 and 18
3065+	//WARNING: this code might break with register assignment changes
3066+	//save RDX
3067+	push_r(code, RDX);
3068+	//save cycle count
3069+	mov_rr(code, RAX, opts->gen.scratch1, SZ_D);
3070+	//clear top doubleword of dividend
3071+	xor_rr(code, RDX, RDX, SZ_D);
3072+	//set divisor to clock divider
3073+	mov_ir(code, opts->gen.clock_divider, opts->gen.scratch2, SZ_D);
3074+	div_r(code, opts->gen.scratch2, SZ_D);
3075+	//discard remainder
3076+	xor_rr(code, RDX, RDX, SZ_D);
3077+	//set divisor to 10, the period of E
3078+	mov_ir(code, 10, opts->gen.scratch2, SZ_D);
3079+	div_r(code, opts->gen.scratch2, SZ_D);
3080+	//delay will be (9 + 4 + the remainder) * clock_divider
3081+	//the extra 4 is to cover the idle bus period after the ack
3082+	add_ir(code, 9 + 4, RDX, SZ_D);
3083+	mov_ir(code, opts->gen.clock_divider, RAX, SZ_D);
3084+	mul_r(code, RDX, SZ_D);
3085+	pop_r(code, RDX);
3086+	//add saved cycle count to result
3087+	add_rr(code, opts->gen.scratch1, RAX, SZ_D);
3088+
3089+	//update status register
3090+	and_irdisp(code, 0x78, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3091+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3092+	//clear trace pending flag
3093+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
3094+	//need to separate int priority and interrupt vector, but for now mask out large interrupt numbers
3095+	and_ir(code, 0x7, opts->gen.scratch1, SZ_B);
3096+	or_ir(code, 0x20, opts->gen.scratch1, SZ_B);
3097+	or_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3098+
3099+	pop_r(code, opts->gen.scratch1);
3100+
3101+	//save PC
3102+	areg_to_native(opts, 7, opts->gen.scratch2);
3103+	add_ir(code, 2, opts->gen.scratch2, SZ_D);
3104+	call(code, opts->write_32_lowfirst);
3105+
3106+	//grab saved interrupt number
3107+	xor_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_D);
3108+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_pending), opts->gen.scratch1, SZ_B);
3109+	//ack the interrupt (happens earlier on hardware, but shouldn't be an observable difference)
3110+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_ack), SZ_W);
3111+	//calculate the vector address
3112+	shl_ir(code, 2, opts->gen.scratch1, SZ_D);
3113+	add_ir(code, 0x60, opts->gen.scratch1, SZ_D);
3114+	//clear out pending flag
3115+	mov_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3116+	//read vector
3117+	call(code, opts->read_32);
3118+	call(code, opts->native_addr_and_sync);
3119+	//2 prefetch bus operations + 2 idle bus cycles
3120+	cycles(&opts->gen, 10);
3121+	tmp_stack_off = code->stack_off;
3122+	//discard function return address
3123+	pop_r(code, opts->gen.scratch2);
3124+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3125+	jmp_r(code, opts->gen.scratch1);
3126+	code->stack_off = tmp_stack_off;
3127+	
3128+	opts->handle_int_latch = code->cur;
3129+	cmp_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_cycle), opts->gen.cycles, SZ_D);
3130+	code_ptr do_latch = code->cur + 1; 
3131+	jcc(code, CC_NC, do_latch);
3132+	retn(code);
3133+	*do_latch = code->cur - (do_latch + 1);
3134+	cmp_irdisp(code, INT_PENDING_NONE, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3135+	do_latch = code->cur + 1;
3136+	jcc(code, CC_Z, do_latch);
3137+	retn(code);
3138+	*do_latch = code->cur - (do_latch + 1);
3139+	//store current interrupt number so it doesn't change before we start processing the vector
3140+	push_r(code, opts->gen.scratch1);
3141+	mov_rdispr(code, opts->gen.context_reg, offsetof(m68k_context, int_num), opts->gen.scratch1, SZ_B);
3142+	mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(m68k_context, int_pending), SZ_B);
3143+	pop_r(code, opts->gen.scratch1);
3144+	retn(code);
3145+
3146+	opts->trap = code->cur;
3147+	push_r(code, opts->gen.scratch2);
3148+	//swap USP and SSP if not already in supervisor mode
3149+	check_user_mode_swap_ssp_usp(opts);
3150+	//save PC
3151+	subi_areg(opts, 4, 7);
3152+	areg_to_native(opts, 7, opts->gen.scratch2);
3153+	call(code, opts->write_32_lowfirst);
3154+	//save status register
3155+	subi_areg(opts, 2, 7);
3156+	call(code, opts->get_sr);
3157+	areg_to_native(opts, 7, opts->gen.scratch2);
3158+	call(code, opts->write_16);
3159+	//set supervisor bit
3160+	or_irdisp(code, 0x20, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3161+	//clear trace bit
3162+	and_irdisp(code, 0x7F, opts->gen.context_reg, offsetof(m68k_context, status), SZ_B);
3163+	mov_irdisp(code, 0, opts->gen.context_reg, offsetof(m68k_context, trace_pending), SZ_B);
3164+	//calculate vector address
3165+	pop_r(code, opts->gen.scratch1);
3166+	shl_ir(code, 2, opts->gen.scratch1, SZ_D);
3167+	call(code, opts->read_32);
3168+	call(code, opts->native_addr_and_sync);
3169+	cycles(&opts->gen, 18);
3170+	jmp_r(code, opts->gen.scratch1);
3171+	
3172+	opts->retrans_stub = code->cur;
3173+	call(code, opts->gen.save_context);
3174+	push_r(code, opts->gen.context_reg);
3175+	call_args(code,(code_ptr)m68k_retranslate_inst, 2, opts->gen.scratch1, opts->gen.context_reg);
3176+	pop_r(code, opts->gen.context_reg);
3177+	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR);
3178+	call(code, opts->gen.load_context);
3179+	jmp_r(code, opts->gen.scratch1);
3180+	
3181+	
3182+	check_code_prologue(code);
3183+	opts->bp_stub = code->cur;
3184+
3185+	tmp_stack_off = code->stack_off;
3186+	//Calculate length of prologue
3187+	check_cycles_int(&opts->gen, 0x1234);
3188+	int check_int_size = code->cur-opts->bp_stub;
3189+	code->cur = opts->bp_stub;
3190+	code->stack_off = tmp_stack_off;
3191+	opts->prologue_start = *opts->bp_stub;
3192+	//Calculate length of patch
3193+	mov_ir(code, 0x1234, opts->gen.scratch1, SZ_D);
3194+	call(code, opts->bp_stub);
3195+	int patch_size = code->cur - opts->bp_stub;
3196+	code->cur = opts->bp_stub;
3197+	code->stack_off = tmp_stack_off;
3198+
3199+	//Save context and call breakpoint handler
3200+	call(code, opts->gen.save_context);
3201+	push_r(code, opts->gen.scratch1);
3202+	call_args_abi(code, (code_ptr)m68k_bp_dispatcher, 2, opts->gen.context_reg, opts->gen.scratch1);
3203+	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
3204+	//Restore context
3205+	call(code, opts->gen.load_context);
3206+	pop_r(code, opts->gen.scratch1);
3207+	//do prologue stuff
3208+	cmp_rr(code, opts->gen.cycles, opts->gen.limit, SZ_D);
3209+	code_ptr jmp_off = code->cur + 1;
3210+	jcc(code, CC_NC, code->cur + 7);
3211+	call(code, opts->gen.handle_cycle_limit_int);
3212+	*jmp_off = code->cur - (jmp_off+1);
3213+	//jump back to body of translated instruction
3214+	pop_r(code, opts->gen.scratch1);
3215+	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3216+	jmp_r(code, opts->gen.scratch1);
3217+	code->stack_off = tmp_stack_off;
3218+	
3219+	retranslate_calc(&opts->gen);
3220+}
+115, -0
  1@@ -0,0 +1,115 @@
  2+/*
  3+ Copyright 2014 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef M68K_INTERNAL_H_
  8+#define M68K_INTERNAL_H_
  9+
 10+#include "68kinst.h"
 11+
 12+//functions implemented in host CPU specfic file
 13+void translate_out_of_bounds(m68k_options *opts, uint32_t address);
 14+void areg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 15+void dreg_to_native(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 16+void areg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 17+void dreg_to_native_sx(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 18+void native_to_areg(m68k_options *opts, uint8_t native_reg, uint8_t reg);
 19+void native_to_dreg(m68k_options *opts, uint8_t native_reg, uint8_t reg);
 20+void ldi_areg(m68k_options *opts, int32_t value, uint8_t reg);
 21+void ldi_native(m68k_options *opts, int32_t value, uint8_t reg);
 22+void addi_native(m68k_options *opts, int32_t value, uint8_t reg);
 23+void subi_native(m68k_options *opts, int32_t value, uint8_t reg);
 24+void push_native(m68k_options *opts, uint8_t reg);
 25+void pop_native(m68k_options *opts, uint8_t reg);
 26+void sign_extend16_native(m68k_options *opts, uint8_t reg);
 27+void addi_areg(m68k_options *opts, int32_t val, uint8_t reg);
 28+void subi_areg(m68k_options *opts, int32_t val, uint8_t reg);
 29+void add_areg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 30+void add_dreg_native(m68k_options *opts, uint8_t reg, uint8_t native_reg);
 31+void calc_areg_displace(m68k_options *opts, m68k_op_info *op, uint8_t native_reg);
 32+void calc_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg);
 33+void calc_areg_index_disp8(m68k_options *opts, m68k_op_info *op, uint8_t native_reg);
 34+void nop_fill_or_jmp_next(code_info *code, code_ptr old_end, code_ptr next_inst);
 35+void check_user_mode_swap_ssp_usp(m68k_options *opts);
 36+void m68k_set_last_prefetch(m68k_options *opts, uint32_t address);
 37+void translate_m68k_odd(m68k_options *opts, m68kinst *inst);
 38+void m68k_trap_if_not_supervisor(m68k_options *opts, m68kinst *inst);
 39+void m68k_breakpoint_patch(m68k_context *context, uint32_t address, m68k_debug_handler bp_handler, code_ptr native_addr);
 40+void m68k_check_cycles_int_latch(m68k_options *opts);
 41+uint8_t translate_m68k_op(m68kinst * inst, host_ea * ea, m68k_options * opts, uint8_t dst);
 42+
 43+//functions implemented in m68k_core.c
 44+int8_t native_reg(m68k_op_info * op, m68k_options * opts);
 45+size_t dreg_offset(uint8_t reg);
 46+size_t areg_offset(uint8_t reg);
 47+size_t reg_offset(m68k_op_info *op);
 48+void m68k_read_size(m68k_options *opts, uint8_t size);
 49+void m68k_write_size(m68k_options *opts, uint8_t size, uint8_t lowfirst);
 50+void m68k_save_result(m68kinst * inst, m68k_options * opts);
 51+void jump_m68k_abs(m68k_options * opts, uint32_t address);
 52+void swap_ssp_usp(m68k_options * opts);
 53+code_ptr get_native_address(m68k_options *opts, uint32_t address);
 54+uint8_t m68k_is_terminal(m68kinst * inst);
 55+code_ptr get_native_address_trans(m68k_context * context, uint32_t address);
 56+void * m68k_retranslate_inst(uint32_t address, m68k_context * context);
 57+m68k_context *m68k_bp_dispatcher(m68k_context *context, uint32_t address);
 58+
 59+//individual instructions
 60+void translate_m68k_bcc(m68k_options * opts, m68kinst * inst);
 61+void translate_m68k_scc(m68k_options * opts, m68kinst * inst);
 62+void translate_m68k_dbcc(m68k_options * opts, m68kinst * inst);
 63+void translate_m68k_trapv(m68k_options *opts, m68kinst *inst);
 64+void translate_m68k_move(m68k_options * opts, m68kinst * inst);
 65+void translate_m68k_movep(m68k_options * opts, m68kinst * inst);
 66+void translate_m68k_arith(m68k_options *opts, m68kinst * inst, uint32_t flag_mask, host_ea *src_op, host_ea *dst_op);
 67+void translate_m68k_unary(m68k_options *opts, m68kinst *inst, uint32_t flag_mask, host_ea *dst_op);
 68+void translate_m68k_cmp(m68k_options * opts, m68kinst * inst);
 69+void translate_m68k_tas(m68k_options * opts, m68kinst * inst);
 70+void translate_m68k_ext(m68k_options * opts, m68kinst * inst);
 71+void translate_m68k_abcd_sbcd(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 72+void translate_m68k_sl(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 73+void translate_m68k_asr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 74+void translate_m68k_lsr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 75+void translate_m68k_bit(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 76+void translate_m68k_chk(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 77+void translate_m68k_div(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 78+void translate_m68k_exg(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 79+void translate_m68k_mul(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 80+void translate_m68k_negx(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 81+void translate_m68k_rot(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 82+void translate_m68k_andi_ori_ccr_sr(m68k_options *opts, m68kinst *inst);
 83+void translate_m68k_eori_ccr_sr(m68k_options *opts, m68kinst *inst);
 84+void translate_m68k_move_ccr_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 85+void translate_m68k_stop(m68k_options *opts, m68kinst *inst);
 86+void translate_m68k_move_from_sr(m68k_options *opts, m68kinst *inst, host_ea *src_op, host_ea *dst_op);
 87+void translate_m68k_reset(m68k_options *opts, m68kinst *inst);
 88+
 89+//flag update bits
 90+#define X0  0x0001
 91+#define X1  0x0002
 92+#define X   0x0004
 93+#define N0  0x0008
 94+#define N1  0x0010
 95+#define N   0x0020
 96+#define Z0  0x0040
 97+#define Z1  0x0080
 98+#define Z   0x0100
 99+#define V0  0x0200
100+#define V1  0x0400
101+#define V   0x0800
102+#define C0  0x1000
103+#define C1  0x2000
104+#define C   0x4000
105+
106+#define BUS 4
107+#define PREDEC_PENALTY 2
108+extern char disasm_buf[1024];
109+
110+m68k_context * sync_components(m68k_context * context, uint32_t address);
111+
112+void m68k_invalid();
113+void bcd_add();
114+void bcd_sub();
115+
116+#endif //M68K_INTERNAL_H_
+22, -0
 1@@ -0,0 +1,22 @@
 2+#!/usr/bin/env python
 3+from glob import glob
 4+import subprocess
 5+from sys import exit
 6+
 7+sources = set()
 8+for path in glob('generated_tests/*/*.s68'):
 9+	sources.add(path)
10+
11+bins = set()
12+for path in glob('generated_tests/*/*.bin'):
13+	bins.add(path)
14+
15+for path in sources:
16+	binpath = path.replace('.s68', '.bin')
17+	if not binpath in bins:
18+		print binpath
19+		res = subprocess.call(['vasmm68k_mot', '-Fbin', '-m68000', '-no-opt', '-spaces', '-o', binpath, path])
20+		if res != 0:
21+			print 'vasmm68k_mot returned non-zero status code', res
22+			exit(1)
23+
+427, -0
  1@@ -0,0 +1,427 @@
  2+#include <stdlib.h>
  3+#include <stdint.h>
  4+#include <string.h>
  5+#include <sys/types.h>
  6+#include <sys/socket.h>
  7+#include <unistd.h>
  8+#include <netinet/in.h>
  9+#include <errno.h>
 10+#include <fcntl.h>
 11+#include "genesis.h"
 12+#include "net.h"
 13+
 14+enum {
 15+	TX_IDLE,
 16+	TX_LEN1,
 17+	TX_LEN2,
 18+	TX_PAYLOAD,
 19+	TX_WAIT_ETX
 20+};
 21+#define STX 0x7E
 22+#define ETX 0x7E
 23+#define MAX_RECV_SIZE 1440
 24+
 25+#define E(N) N
 26+enum {
 27+#include "mw_commands.c"
 28+	CMD_ERROR = 255
 29+};
 30+#undef E
 31+#define E(N) #N
 32+static const char *cmd_names[] = {
 33+#include "mw_commands.c"
 34+	[255] = "CMD_ERROR"
 35+};
 36+
 37+#ifndef MSG_NOSIGNAL
 38+#define MSG_NOSIGNAL 0
 39+#endif
 40+
 41+enum {
 42+	STATE_IDLE=1,
 43+	STATE_AP_JOIN,
 44+	STATE_SCAN,
 45+	STATE_READY,
 46+	STATE_TRANSPARENT
 47+};
 48+
 49+#define FLAG_ONLINE 
 50+
 51+typedef struct {
 52+	uint32_t transmit_bytes;
 53+	uint32_t expected_bytes;
 54+	uint32_t receive_bytes;
 55+	uint32_t receive_read;
 56+	int      sock_fds[15];
 57+	uint16_t channel_flags;
 58+	uint8_t  channel_state[15];
 59+	uint8_t  scratchpad;
 60+	uint8_t  transmit_channel;
 61+	uint8_t  transmit_state;
 62+	uint8_t  module_state;
 63+	uint8_t  flags;
 64+	uint8_t  transmit_buffer[4096];
 65+	uint8_t  receive_buffer[4096];
 66+} megawifi;
 67+
 68+static megawifi *get_megawifi(void *context)
 69+{
 70+	m68k_context *m68k = context;
 71+	genesis_context *gen = m68k->system;
 72+	if (!gen->extra) {
 73+		gen->extra = calloc(1, sizeof(megawifi));
 74+		megawifi *mw = gen->extra;
 75+		mw->module_state = STATE_IDLE;
 76+		for (int i = 0; i < 15; i++)
 77+		{
 78+			mw->sock_fds[i] = -1;
 79+		}
 80+	}
 81+	return gen->extra;
 82+}
 83+
 84+static void mw_putc(megawifi *mw, uint8_t v)
 85+{
 86+	if (mw->receive_bytes == sizeof(mw->receive_buffer)) {
 87+		return;
 88+	}
 89+	mw->receive_buffer[mw->receive_bytes++] = v;
 90+}
 91+
 92+static void mw_set(megawifi *mw, uint8_t val, uint32_t count)
 93+{
 94+	if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) {
 95+		count = sizeof(mw->receive_buffer) - mw->receive_bytes;
 96+	}
 97+	memset(mw->receive_buffer + mw->receive_bytes, val, count);
 98+	mw->receive_bytes += count;
 99+}
100+
101+static void mw_copy(megawifi *mw, const uint8_t *src, uint32_t count)
102+{
103+	if (count + mw->receive_bytes > sizeof(mw->receive_buffer)) {
104+		count = sizeof(mw->receive_buffer) - mw->receive_bytes;
105+	}
106+	memcpy(mw->receive_buffer + mw->receive_bytes, src, count);
107+	mw->receive_bytes += count;
108+}
109+
110+static void mw_puts(megawifi *mw, char *s)
111+{
112+	uint32_t len = strlen(s);
113+	if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) {
114+		return;
115+	}
116+	memcpy(mw->receive_buffer + mw->receive_bytes, s, len);
117+	mw->receive_bytes += len;
118+}
119+
120+static void poll_socket(megawifi *mw, uint8_t channel)
121+{
122+	if (mw->sock_fds[channel] < 0) {
123+		return;
124+	}
125+	if (mw->channel_state[channel] == 1) {
126+		int res = accept(mw->sock_fds[channel], NULL, NULL);
127+		if (res >= 0) {
128+			close(mw->sock_fds[channel]);
129+			fcntl(res, F_SETFL, O_NONBLOCK);
130+			mw->sock_fds[channel] = res;
131+			mw->channel_state[channel] = 2;
132+			mw->channel_flags |= 1 << (channel + 1);
133+		} else if (errno != EAGAIN && errno != EWOULDBLOCK) {
134+			close(mw->sock_fds[channel]);
135+			mw->channel_state[channel] = 0;
136+			mw->channel_flags |= 1 << (channel + 1);
137+		}
138+	} else if (mw->channel_state[channel] == 2 && mw->receive_bytes < sizeof(mw->receive_buffer) - 4) {
139+		size_t max = sizeof(mw->receive_buffer) - 4 - mw->receive_bytes;
140+		if (max > MAX_RECV_SIZE) {
141+			max = MAX_RECV_SIZE;
142+		}
143+		int bytes = recv(mw->sock_fds[channel], mw->receive_buffer + mw->receive_bytes + 3, max, 0);
144+		if (bytes > 0) {
145+			mw_putc(mw, STX);
146+			mw_putc(mw, bytes >> 8 | (channel+1) << 4);
147+			mw_putc(mw, bytes);
148+			mw->receive_bytes += bytes;
149+			mw_putc(mw, ETX);
150+			//should this set the channel flag?
151+		} else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
152+			close(mw->sock_fds[channel]);
153+			mw->channel_state[channel] = 0;
154+			mw->channel_flags |= 1 << (channel + 1);
155+		}
156+	}
157+}
158+
159+static void poll_all_sockets(megawifi *mw)
160+{
161+	for (int i = 0; i < 15; i++)
162+	{
163+		poll_socket(mw, i);
164+	}
165+}
166+
167+static void start_reply(megawifi *mw, uint8_t cmd)
168+{
169+	mw_putc(mw, STX);
170+	//reserve space for length
171+	mw->receive_bytes += 2;
172+	//cmd
173+	mw_putc(mw, 0);
174+	mw_putc(mw, cmd);
175+	//reserve space for length
176+	mw->receive_bytes += 2;
177+}
178+
179+static void end_reply(megawifi *mw)
180+{
181+	uint32_t len = mw->receive_bytes - 3;
182+	//LSD packet length
183+	mw->receive_buffer[1] = len >> 8;
184+	mw->receive_buffer[2] = len;
185+	//command length
186+	len -= 4;
187+	mw->receive_buffer[5] = len >> 8;
188+	mw->receive_buffer[6] = len;
189+	mw_putc(mw, ETX);
190+}
191+
192+static void process_packet(megawifi *mw)
193+{
194+	if (mw->transmit_channel == 0) {
195+		uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
196+		uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3];
197+		if (size > mw->transmit_bytes - 4) {
198+			size = mw->transmit_bytes - 4;
199+		}
200+		int orig_receive_bytes = mw->receive_bytes;
201+		switch (command)
202+		{
203+		case CMD_VERSION:
204+			start_reply(mw, CMD_OK);
205+			mw_putc(mw, 1);
206+			mw_putc(mw, 0);
207+			mw_puts(mw, "blastem");
208+			end_reply(mw);
209+			break;
210+		case CMD_ECHO:
211+			mw->receive_bytes = mw->transmit_bytes;
212+			memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
213+			break;
214+		case CMD_IP_CURRENT: {
215+			iface_info i;
216+			if (get_host_address(&i)) {
217+				start_reply(mw, CMD_OK);
218+				//config number and reserved bytes
219+				mw_set(mw, 0, 4);
220+				//ip
221+				mw_copy(mw, i.ip, sizeof(i.ip));
222+				//net mask
223+				mw_copy(mw, i.net_mask, sizeof(i.net_mask));
224+				//gateway guess
225+				mw_putc(mw, i.ip[0] & i.net_mask[0]);
226+				mw_putc(mw, i.ip[1] & i.net_mask[1]);
227+				mw_putc(mw, i.ip[2] & i.net_mask[2]);
228+				mw_putc(mw, (i.ip[3] & i.net_mask[3]) + 1);
229+				//dns
230+				static const uint8_t localhost[] = {127,0,0,1};
231+				mw_copy(mw, localhost, sizeof(localhost));
232+				mw_copy(mw, localhost, sizeof(localhost));
233+				
234+			} else {
235+				start_reply(mw, CMD_ERROR);
236+			}
237+			end_reply(mw);
238+			break;
239+		}
240+		case CMD_AP_JOIN:
241+			mw->module_state = STATE_READY;
242+			start_reply(mw, CMD_OK);
243+			end_reply(mw);
244+			break;
245+		case CMD_TCP_BIND:{
246+			if (size < 7){
247+				start_reply(mw, CMD_ERROR);
248+				end_reply(mw);
249+				break;
250+			}
251+			uint8_t channel = mw->transmit_buffer[10];
252+			if (!channel || channel > 15) {
253+				start_reply(mw, CMD_ERROR);
254+				end_reply(mw);
255+				break;
256+			}
257+			channel--;
258+			if (mw->sock_fds[channel] >= 0) {
259+				close(mw->sock_fds[channel]);
260+			}
261+			mw->sock_fds[channel] = socket(AF_INET, SOCK_STREAM, 0);
262+			if (mw->sock_fds[channel] < 0) {
263+				start_reply(mw, CMD_ERROR);
264+				end_reply(mw);
265+				break;
266+			}
267+			int value = 1;
268+			setsockopt(mw->sock_fds[channel], SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
269+			struct sockaddr_in bind_addr;
270+			memset(&bind_addr, 0, sizeof(bind_addr));
271+			bind_addr.sin_family = AF_INET;
272+			bind_addr.sin_port = htons(mw->transmit_buffer[8] << 8 | mw->transmit_buffer[9]);
273+			if (bind(mw->sock_fds[channel], (struct sockaddr *)&bind_addr, sizeof(bind_addr)) != 0) {
274+				close(mw->sock_fds[channel]);
275+				mw->sock_fds[channel] = -1;
276+				start_reply(mw, CMD_ERROR);
277+				end_reply(mw);
278+				break;
279+			}
280+			int res = listen(mw->sock_fds[channel], 2);
281+			start_reply(mw, res ? CMD_ERROR : CMD_OK);
282+			if (res) {
283+				close(mw->sock_fds[channel]);
284+				mw->sock_fds[channel] = -1;
285+			} else {
286+				mw->channel_flags |= 1 << (channel + 1);
287+				mw->channel_state[channel] = 1;
288+				fcntl(mw->sock_fds[channel], F_SETFL, O_NONBLOCK);
289+			}
290+			end_reply(mw);
291+			break;
292+		}
293+		case CMD_SOCK_STAT: {
294+			uint8_t channel = mw->transmit_buffer[4];
295+			if (!channel || channel > 15) {
296+				start_reply(mw, CMD_ERROR);
297+				end_reply(mw);
298+				break;
299+			}
300+			mw->channel_flags &= ~(1 << channel);
301+			channel--;
302+			poll_socket(mw, channel);
303+			start_reply(mw, CMD_OK);
304+			mw_putc(mw, mw->channel_state[channel]);
305+			end_reply(mw);
306+			break;
307+		}
308+		case CMD_SYS_STAT:
309+			poll_all_sockets(mw);
310+			start_reply(mw, CMD_OK);
311+			mw_putc(mw, mw->module_state);
312+			mw_putc(mw, mw->flags);
313+			mw_putc(mw, mw->channel_flags >> 8);
314+			mw_putc(mw, mw->channel_flags);
315+			end_reply(mw);
316+			break;
317+		default:
318+			printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
319+			break;
320+		}
321+	} else if (mw->sock_fds[mw->transmit_channel - 1] >= 0 && mw->channel_state[mw->transmit_channel - 1] == 2) {
322+		uint8_t channel = mw->transmit_channel - 1;
323+		int sent = send(mw->sock_fds[channel], mw->transmit_buffer, mw->transmit_bytes, MSG_NOSIGNAL);
324+		if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
325+			close(mw->sock_fds[channel]);
326+			mw->sock_fds[channel] = -1;
327+			mw->channel_state[channel] = 0;
328+			mw->channel_flags |= 1 << mw->transmit_channel;
329+		} else if (sent < mw->transmit_bytes) {
330+			//TODO: save this data somewhere so it can be sent in poll_socket
331+			printf("Sent %d bytes on channel %d, but %d were requested\n", sent, mw->transmit_channel, mw->transmit_bytes);
332+		}
333+	} else {
334+		printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
335+	}
336+	mw->transmit_bytes = mw->expected_bytes = 0;
337+}
338+
339+void *megawifi_write_b(uint32_t address, void *context, uint8_t value)
340+{
341+	if (!(address & 1)) {
342+		return context;
343+	}
344+	megawifi *mw = get_megawifi(context);
345+	address = address >> 1 & 7;
346+	switch (address)
347+	{
348+	case 0:
349+		switch (mw->transmit_state)
350+		{
351+		case TX_IDLE:
352+			if (value == STX) {
353+				mw->transmit_state = TX_LEN1;
354+			}
355+			break;
356+		case TX_LEN1:
357+			mw->transmit_channel = value >> 4;
358+			mw->expected_bytes = value << 8 & 0xF00;
359+			mw->transmit_state = TX_LEN2;
360+			break;
361+		case TX_LEN2:
362+			mw->expected_bytes |= value;
363+			mw->transmit_state = TX_PAYLOAD;
364+			break;
365+		case TX_PAYLOAD:
366+			mw->transmit_buffer[mw->transmit_bytes++] = value;
367+			if (mw->transmit_bytes == mw->expected_bytes) {
368+				mw->transmit_state = TX_WAIT_ETX;
369+			}
370+			break;
371+		case TX_WAIT_ETX:
372+			if (value == ETX) {
373+				mw->transmit_state = TX_IDLE;
374+				process_packet(mw);
375+			}
376+			break;
377+		}
378+		break;
379+	case 7:
380+		mw->scratchpad = value;
381+		break;
382+	default:
383+		printf("Unhandled write to MegaWiFi UART register %X: %X\n", address, value);
384+	}
385+	return context;
386+}
387+
388+void *megawifi_write_w(uint32_t address, void *context, uint16_t value)
389+{
390+	return megawifi_write_b(address | 1, context, value);
391+}
392+
393+uint8_t megawifi_read_b(uint32_t address, void *context)
394+{
395+	
396+	if (!(address & 1)) {
397+		return 0xFF;
398+	}
399+	megawifi *mw = get_megawifi(context);
400+	address = address >> 1 & 7;
401+	switch (address)
402+	{
403+	case 0:
404+		poll_all_sockets(mw);
405+		if (mw->receive_read < mw->receive_bytes) {
406+			uint8_t ret = mw->receive_buffer[mw->receive_read++];
407+			if (mw->receive_read == mw->receive_bytes) {
408+				mw->receive_read = mw->receive_bytes = 0;
409+			}
410+			return ret;
411+		}
412+		return 0xFF;
413+	case 5:
414+		poll_all_sockets(mw);
415+		//line status
416+		return 0x60 | (mw->receive_read < mw->receive_bytes);
417+	case 7:
418+		return mw->scratchpad;
419+	default:
420+		printf("Unhandled read from MegaWiFi UART register %X\n", address);
421+		return 0xFF;
422+	}
423+}
424+
425+uint16_t megawifi_read_w(uint32_t address, void *context)
426+{
427+	return 0xFF00 | megawifi_read_b(address | 1, context);
428+}
+9, -0
 1@@ -0,0 +1,9 @@
 2+#ifndef MEGAWIFI_H_
 3+#define MEGAWIFI_H_
 4+
 5+void *megawifi_write_w(uint32_t address, void *context, uint16_t value);
 6+void *megawifi_write_b(uint32_t address, void *context, uint8_t value);
 7+uint16_t megawifi_read_w(uint32_t address, void *context);
 8+uint8_t megawifi_read_b(uint32_t address, void *context);
 9+
10+#endif //MEGAWIFI_H_
A mem.c
+45, -0
 1@@ -0,0 +1,45 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include <sys/mman.h>
 8+#include <stddef.h>
 9+#include <stdint.h>
10+#include <stdlib.h>
11+#include <unistd.h>
12+#include <errno.h>
13+#include <stdio.h>
14+
15+#include "mem.h"
16+#include "arena.h"
17+#ifndef MAP_ANONYMOUS
18+#define MAP_ANONYMOUS MAP_ANON
19+#endif
20+
21+#ifndef MAP_32BIT
22+#define MAP_32BIT 0
23+#endif
24+
25+void * alloc_code(size_t *size)
26+{
27+	//start at the 1GB mark to allow plenty of room for sbrk based malloc implementations
28+	//while still keeping well within 32-bit displacement range for calling code compiled into the executable
29+	static uint8_t *next = (uint8_t *)0x40000000;
30+	uint8_t *ret = try_alloc_arena();
31+	if (ret) {
32+		return ret;
33+	}
34+	if (*size & (PAGE_SIZE -1)) {
35+		*size += PAGE_SIZE - (*size & (PAGE_SIZE - 1));
36+	}
37+	ret = mmap(next, *size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
38+	if (ret == MAP_FAILED) {
39+		perror("alloc_code");
40+		return NULL;
41+	}
42+	track_block(ret);
43+	next = ret + *size;
44+	return ret;
45+}
46+
A mem.h
+16, -0
 1@@ -0,0 +1,16 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm. 
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef MEM_H_
 8+#define MEM_H_
 9+
10+#include <stddef.h>
11+
12+#define PAGE_SIZE 4096
13+
14+void * alloc_code(size_t *size);
15+
16+#endif //MEM_H_
17+
+41, -0
 1@@ -0,0 +1,41 @@
 2+#ifndef MEMMAP_H_
 3+#define MEMMAP_H_
 4+
 5+typedef enum {
 6+	READ_16,
 7+	READ_8,
 8+	WRITE_16,
 9+	WRITE_8
10+} ftype;
11+
12+#define MMAP_READ      0x01
13+#define MMAP_WRITE     0x02
14+#define MMAP_CODE      0x04
15+#define MMAP_PTR_IDX   0x08
16+#define MMAP_ONLY_ODD  0x10
17+#define MMAP_ONLY_EVEN 0x20
18+#define MMAP_FUNC_NULL 0x40
19+#define MMAP_BYTESWAP  0x80
20+#define MMAP_AUX_BUFF  0x100
21+#define MMAP_READ_CODE 0x200
22+
23+typedef uint16_t (*read_16_fun)(uint32_t address, void * context);
24+typedef uint8_t (*read_8_fun)(uint32_t address, void * context);
25+typedef void * (*write_16_fun)(uint32_t address, void * context, uint16_t value);
26+typedef void * (*write_8_fun)(uint32_t address, void * context, uint8_t value);
27+
28+typedef struct {
29+	uint32_t     start;
30+	uint32_t     end;
31+	uint32_t     mask;
32+	uint32_t     aux_mask;
33+	uint16_t     ptr_index;
34+	uint16_t     flags;
35+	void *       buffer;
36+	read_16_fun  read_16;
37+	write_16_fun write_16;
38+	read_8_fun   read_8;
39+	write_8_fun  write_8;
40+} memmap_chunk;
41+
42+#endif //MEMMAP_H_
A menu.c
+260, -0
  1@@ -0,0 +1,260 @@
  2+#include <stdint.h>
  3+#include <stdlib.h>
  4+#include <string.h>
  5+#include <stdio.h>
  6+#include <errno.h>
  7+#include "genesis.h"
  8+#include "menu.h"
  9+#include "backend.h"
 10+#include "util.h"
 11+#include "gst.h"
 12+#include "paths.h"
 13+#include "saves.h"
 14+#include "config.h"
 15+
 16+static menu_context *get_menu(genesis_context *gen)
 17+{
 18+	menu_context *menu = gen->extra;
 19+	if (!menu) {
 20+		gen->extra = menu = calloc(1, sizeof(menu_context));
 21+		get_initial_browse_path(&menu->curpath);
 22+	}
 23+	return menu;
 24+}
 25+
 26+uint16_t menu_read_w(uint32_t address, void * vcontext)
 27+{
 28+	if ((address >> 1) == 14) {
 29+		m68k_context *context = vcontext;
 30+		menu_context *menu = get_menu(context->system);
 31+		uint16_t value = menu->external_game_load;
 32+		if (value) {
 33+			printf("Read: %X\n", value);
 34+		}
 35+		menu->external_game_load = 0;
 36+		return value;
 37+	} else {
 38+		//This should return the status of the last request with 0
 39+		//meaning either the request is complete or no request is pending
 40+		//in the current implementation, the operations happen instantly
 41+		//in emulated time so we can always return 0
 42+		return 0;
 43+	}
 44+}
 45+
 46+void copy_string_from_guest(m68k_context *m68k, uint32_t guest_addr, char *buf, size_t maxchars)
 47+{
 48+	char *cur;
 49+	char *src = NULL;
 50+	for (cur = buf; cur < buf+maxchars; cur+=2, guest_addr+=2, src+=2)
 51+	{
 52+		if (!src || !(guest_addr & 0xFFFF)) {
 53+			//we may have walked off the end of a memory block, get a fresh native pointer
 54+			src = get_native_pointer(guest_addr, (void **)m68k->mem_pointers, &m68k->options->gen);
 55+			if (!src) {
 56+				break;
 57+			}
 58+		}
 59+		*cur = src[1];
 60+		cur[1] = *src;
 61+		if (!*src || !src[1]) {
 62+			break;
 63+		}
 64+	}
 65+	//make sure we terminate the string even if we did not hit a null terminator in the source
 66+	buf[maxchars-1] = 0;
 67+}
 68+
 69+void copy_to_guest(m68k_context *m68k, uint32_t guest_addr, char *src, size_t tocopy)
 70+{
 71+	char *dst = NULL;
 72+	for (char *cur = src; cur < src+tocopy; cur+=2, guest_addr+=2, dst+=2)
 73+	{
 74+		if (!dst || !(guest_addr & 0xFFFF)) {
 75+			//we may have walked off the end of a memory block, get a fresh native pointer
 76+			dst = get_native_pointer(guest_addr, (void **)m68k->mem_pointers, &m68k->options->gen);
 77+			if (!dst) {
 78+				break;
 79+			}
 80+		}
 81+		dst[1] = *cur;
 82+		*dst = cur[1];
 83+	}
 84+}
 85+
 86+#define SAVE_INFO_BUFFER_SIZE (11*40)
 87+
 88+uint32_t copy_dir_entry_to_guest(uint32_t dst, m68k_context *m68k, char *name, uint8_t is_dir)
 89+{
 90+	uint8_t *dest = get_native_pointer(dst, (void **)m68k->mem_pointers, &m68k->options->gen);
 91+	if (!dest) {
 92+		return 0;
 93+	}
 94+	*(dest++) = is_dir;
 95+	*(dest++) = 1;
 96+	dst += 2;
 97+	uint8_t term = 0;
 98+	for (char *cpos = name; *cpos; cpos++)
 99+	{
100+		dest[1] = *cpos;
101+		dest[0] = cpos[1];
102+		if (cpos[1]) {
103+			cpos++;
104+		} else {
105+			term = 1;
106+		}
107+		dst += 2;
108+		if (!(dst & 0xFFFF)) {
109+			//we may have walked off the end of a memory block, get a fresh native pointer
110+			dest = get_native_pointer(dst, (void **)m68k->mem_pointers, &m68k->options->gen);
111+			if (!dest) {
112+				break;
113+			}
114+		} else {
115+			dest += 2;
116+		}
117+	}
118+	if (!term) {
119+		*(dest++) = 0;
120+		*dest = 0;
121+		dst += 2;
122+	}
123+	return dst;
124+}
125+void * menu_write_w(uint32_t address, void * context, uint16_t value)
126+{
127+	m68k_context *m68k = context;
128+	genesis_context *gen = m68k->system;
129+	menu_context *menu = get_menu(gen);
130+	if (menu->state) {
131+		uint32_t dst = menu->latch << 16 | value;
132+		switch (address >> 2)
133+		{
134+		case 0: {
135+			size_t num_entries;
136+			dir_entry *entries = get_dir_list(menu->curpath, &num_entries);
137+			if (entries) {
138+				sort_dir_list(entries, num_entries);
139+			} else {
140+				warning("Failed to open directory %s: %s\n", menu->curpath, strerror(errno));
141+				entries = malloc(sizeof(dir_entry));
142+				entries->name = strdup("..");
143+				entries->is_dir = 1;
144+				num_entries = 1;
145+			}
146+			uint32_t num_exts;
147+			char **ext_list = get_extension_list(config, &num_exts);
148+			for (size_t i = 0; dst && i < num_entries; i++)
149+			{
150+				if (num_exts && !entries[i].is_dir) {
151+					if (!path_matches_extensions(entries[i].name, ext_list, num_exts)) {
152+						continue;
153+					}
154+				}
155+				dst = copy_dir_entry_to_guest(dst,  m68k, entries[i].name, entries[i].is_dir);
156+			}
157+			free(ext_list);
158+			//terminate list
159+			uint8_t *dest = get_native_pointer(dst, (void **)m68k->mem_pointers, &m68k->options->gen);
160+			if (dest) {
161+				*dest = dest[1] = 0;
162+			}
163+			free_dir_list(entries, num_entries);
164+			break;
165+		}
166+		case 1: {
167+			char buf[4096];
168+			copy_string_from_guest(m68k, dst, buf, sizeof(buf));
169+			buf[sizeof(buf)-1] = 0;
170+			char *tmp = menu->curpath;
171+			menu->curpath = path_append(tmp, buf);
172+			free(tmp);
173+			break;
174+		}
175+		case 2:
176+		case 8: {
177+			char buf[4096];
178+			copy_string_from_guest(m68k, dst, buf, sizeof(buf));
179+			char const *pieces[] = {menu->curpath, PATH_SEP, buf};
180+			char *selected = alloc_concat_m(3, pieces);
181+			if ((address >> 2) == 2) {
182+				gen->header.next_rom = selected;
183+				m68k->should_return = 1;
184+			} else {
185+				lockon_media(selected);
186+				free(selected);
187+			}
188+			break;
189+		}
190+		case 3: {
191+			switch (dst)
192+			{
193+			case 1:
194+				m68k->should_return = 1;
195+				gen->header.should_exit = 1;
196+				break;
197+			case 2:
198+				m68k->should_return = 1;
199+				break;
200+			}
201+			
202+			break;
203+		}
204+		case 4: {
205+			char *buffer = malloc(SAVE_INFO_BUFFER_SIZE);
206+			char *cur = buffer;
207+			if (gen->header.next_context && gen->header.next_context->save_dir) {
208+				char *end = buffer + SAVE_INFO_BUFFER_SIZE;
209+				uint32_t num_slots;
210+				save_slot_info *slots = get_slot_info(gen->header.next_context, &num_slots);
211+				for (uint32_t i = 0; i < num_slots; i++)
212+				{
213+					size_t desc_len = strlen(slots[i].desc) + 1;//+1 for string terminator
214+					char *after = cur + desc_len + 1;//+1 for list terminator
215+					if (after > cur) {
216+						desc_len -= after - cur;
217+					}
218+					memcpy(cur, slots[i].desc, desc_len);
219+					cur = after;
220+				}
221+				*cur = 0;//terminate list
222+			} else {
223+				*(cur++) = 0;
224+				*(cur++) = 0;
225+			}
226+			copy_to_guest(m68k, dst, buffer, cur-buffer);
227+			break;
228+		}
229+		case 5:
230+			//save state
231+			if (gen->header.next_context) {
232+				gen->header.next_context->save_state = dst + 1;
233+			}
234+			m68k->should_return = 1;
235+			break;
236+		case 6:
237+			//load state
238+			if (gen->header.next_context && gen->header.next_context->save_dir) {
239+				if (!gen->header.next_context->load_state(gen->header.next_context, dst)) {
240+					break;
241+				}
242+			}
243+			m68k->should_return = 1;
244+			break;
245+		case 7: 
246+			//read only port
247+			break;
248+		default:
249+			fprintf(stderr, "WARNING: write to undefined menu port %X\n", address);
250+		}
251+		menu->state = 0;
252+	} else {
253+		menu->latch = value;
254+		menu->state = 1;
255+	}
256+	if (m68k->should_return) {
257+		m68k->target_cycle = m68k->current_cycle;
258+	}
259+
260+	return context;
261+}
A menu.h
+19, -0
 1@@ -0,0 +1,19 @@
 2+/*
 3+ Copyright 2015 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef MENU_H_
 8+#define MENU_H_
 9+typedef struct {
10+	char     *curpath;
11+	uint16_t latch;
12+	uint16_t state;
13+	uint8_t  external_game_load;
14+} menu_context;
15+
16+
17+uint16_t menu_read_w(uint32_t address, void * context);
18+void * menu_write_w(uint32_t address, void * context, uint16_t value);
19+
20+#endif // MENU_H_
+1440, -0
   1@@ -0,0 +1,1440 @@
   2+	dc.l $0, start
   3+	dc.l empty_handler
   4+	dc.l empty_handler
   5+	;$10
   6+	dc.l empty_handler
   7+	dc.l empty_handler
   8+	dc.l empty_handler
   9+	dc.l empty_handler
  10+	;$20
  11+	dc.l empty_handler
  12+	dc.l empty_handler
  13+	dc.l empty_handler
  14+	dc.l empty_handler
  15+	;$30
  16+	dc.l empty_handler
  17+	dc.l empty_handler
  18+	dc.l empty_handler
  19+	dc.l empty_handler
  20+	;$40
  21+	dc.l empty_handler
  22+	dc.l empty_handler
  23+	dc.l empty_handler
  24+	dc.l empty_handler
  25+	;$50
  26+	dc.l empty_handler
  27+	dc.l empty_handler
  28+	dc.l empty_handler
  29+	dc.l empty_handler
  30+	;$60
  31+	dc.l empty_handler
  32+	dc.l empty_handler
  33+	dc.l empty_handler
  34+	dc.l empty_handler
  35+	;$70
  36+	dc.l int_4
  37+	dc.l empty_handler
  38+	dc.l int_6
  39+	dc.l empty_handler
  40+	;$80
  41+	dc.l empty_handler
  42+	dc.l empty_handler
  43+	dc.l empty_handler
  44+	dc.l empty_handler
  45+	;$90
  46+	dc.l empty_handler
  47+	dc.l empty_handler
  48+	dc.l empty_handler
  49+	dc.l empty_handler
  50+	;$A0
  51+	dc.l empty_handler
  52+	dc.l empty_handler
  53+	dc.l empty_handler
  54+	dc.l empty_handler
  55+	;$B0
  56+	dc.l empty_handler
  57+	dc.l empty_handler
  58+	dc.l empty_handler
  59+	dc.l empty_handler
  60+	;$C0
  61+	dc.l empty_handler
  62+	dc.l empty_handler
  63+	dc.l empty_handler
  64+	dc.l empty_handler
  65+	;$D0
  66+	dc.l empty_handler
  67+	dc.l empty_handler
  68+	dc.l empty_handler
  69+	dc.l empty_handler
  70+	;$E0
  71+	dc.l empty_handler
  72+	dc.l empty_handler
  73+	dc.l empty_handler
  74+	dc.l empty_handler
  75+	;$F0
  76+	dc.l empty_handler
  77+	dc.l empty_handler
  78+	dc.l empty_handler
  79+	dc.l empty_handler
  80+	dc.b "SEGA GENESIS    "
  81+	dc.b "(c) 2015.JULY   "
  82+	dc.b "Menu            "
  83+	dc.b "                "
  84+	dc.b "                "
  85+	dc.b "Menu            "
  86+	dc.b "                "
  87+	dc.b "                "
  88+	dc.b "MP BlstMenu-00", 0, 0
  89+	dc.b "                "
  90+	dc.l $0, rom_end-1, $FF0000, $FFFFFF
  91+	dc.b "                "
  92+	dc.b "                "
  93+	dc.b "                "
  94+	dc.b "                "
  95+	dc.b "JU  "
  96+
  97+;register addresses
  98+VDP_DATA  equ $C00000
  99+VDP_CTRL  equ $C00004
 100+VDP_HV    equ $C00008
 101+Z80_RAM   equ $A00000
 102+IO_AREA   equ $A10000
 103+PAD1_DATA equ (IO_AREA + 3)
 104+PAD2_DATA equ (IO_AREA + 5)
 105+EXT_DATA  equ (IO_AREA + 7)
 106+PAD1_CTRL equ (IO_AREA + 9)
 107+PAD2_CTRL equ (IO_AREA + 11)
 108+EXT_CTRL  equ (IO_AREA + 13)
 109+
 110+MODE_1   equ 0
 111+MODE_2   equ 1
 112+SCROLL_A equ 2
 113+WINDOW   equ 3
 114+SCROLL_B equ 4
 115+SAT      equ 5
 116+BG_COLOR equ 7
 117+HINT     equ $A
 118+MODE_3   equ $B
 119+MODE_4   equ $C
 120+HSCROLL  equ $D
 121+AUTOINC  equ $F
 122+SCROLL   EQU $10
 123+WINDOW_H equ $11
 124+WINDOW_V equ $12
 125+DMALEN_L equ $13
 126+DMALEN_H equ $14
 127+DMASRC_L equ $15
 128+DMASRC_M equ $16
 129+DMASRC_H equ $17
 130+
 131+VDP_VRAM_WRITE equ $40000000
 132+VDP_CRAM_WRITE equ $C0000000
 133+VDP_VSRAM_WRITE equ $40000010
 134+VDP_DMA_FLAG equ $80
 135+
 136+vdpregset macro
 137+	move.w #(((\1) << 8) | $8000 | (\2)), (a1)
 138+	endm
 139+
 140+vdpreg macro
 141+	dc.w (((\1) << 8) | $8000 | (\2))
 142+	endm
 143+
 144+;Writes a normal VDP command to the control port
 145+;\1 - VDP address
 146+;\2 - Access type
 147+vdpaccess macro
 148+	ifeq NARG-2
 149+	move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), (a1)
 150+	else
 151+	move.l #((\2) | (\1) << 16 & $3FFF0000 | (\1) >> 14 & 3), \3
 152+	endif
 153+	endm
 154+
 155+;Writes a DMA command to the control port
 156+;\1 - Destination address
 157+;\2 - Destination type
 158+startdma macro
 159+	move.l #(\2 | VDP_DMA_FLAG | (\1 << 16) & $3FFF0000 | (\1 >> 14) & 3), (a1)
 160+	endm
 161+
 162+DMA_SRC_68K  equ 0
 163+DMA_SRC_VRAM equ $C0
 164+DMA_SRC_FILL equ $80
 165+
 166+dmasrc macro
 167+	move.l #($95009600 + (\1) << 15 & $FF0000 + (\1) >> 9 & $FF), (a1)
 168+	move.w #($9700 + (\1) >> 17 & $7F | (\2)), (a1)
 169+	endm
 170+
 171+dir_buffer equ $100000
 172+menu_port  equ $180000
 173+load_rom_port equ (menu_port+2*4)
 174+lock_on_port equ (menu_port+8*4)
 175+
 176+MAX_DISPLAY equ 24
 177+
 178+	rsset $FFFF8000
 179+x_pos           rs.w 1
 180+base_cmd        rs.l 1
 181+sprite_list     rs.l 160
 182+page_index      rs.l MAX_DISPLAY+1
 183+page_stack      rs.l 1
 184+page_pointers   rs.l 1024
 185+mouse_sprite    rs.l 1
 186+menu_functions  rs.l 1
 187+cursor_show_fun rs.l 1
 188+special_click   rs.l 1
 189+rom_load_addr   rs.l 1
 190+mouse_x         rs.w 1
 191+selection_top   rs.w 1
 192+selection_bot   rs.w 1
 193+selection_mask  rs.w 1
 194+num_sprites     rs.b 1
 195+last_pad1       rs.b 1
 196+last_pad2       rs.b 1
 197+selected        rs.b 1
 198+more_pages      rs.b 1
 199+mouse_buf       rs.b 3
 200+mouse_shown     rs.b 1
 201+last_mbuttons   rs.b 1
 202+num_menu        rs.b 1
 203+num_slots       rs.b 1
 204+port_off        rs.b 1
 205+
 206+
 207+int_6:
 208+	dmasrc sprite_list, DMA_SRC_68K
 209+	;set DMA length
 210+	move.l #$94009300, d0
 211+	moveq #0, d1
 212+	move.b num_sprites.w, d1
 213+	add.w d1, d1
 214+	add.w d1, d1
 215+	move.b d1, d0
 216+	swap d0
 217+	lsr.w #8, d1
 218+	move.b d1, d0
 219+	move.l d0, (a1)
 220+	startdma $C000, VDP_VRAM_WRITE
 221+	
 222+	move.w (menu_port+4*7), d0
 223+	btst #0, d0
 224+	bne show_pause_menu
 225+
 226+	;read gamepad/mouse in port 1
 227+	lea PAD1_DATA, a2
 228+
 229+	bsr io_read
 230+
 231+	cmp.b #3, d2
 232+	beq .mouse
 233+
 234+	move.b last_pad1.w, d1
 235+	eor.b d0, d1
 236+	and.b d0, d1
 237+	move.b d0, last_pad1.w
 238+
 239+	bsr handle_pad_buttons
 240+
 241+	bra pad2
 242+.mouse
 243+	bsr handle_mouse
 244+
 245+pad2:
 246+	;read gamepad/mouse in port 2
 247+	lea PAD2_DATA, a2
 248+
 249+	bsr io_read
 250+
 251+	cmp.b #3, d2
 252+	beq .mouse
 253+
 254+	move.b last_pad2.w, d1
 255+	eor.b d0, d1
 256+	and.b d0, d1
 257+	move.b d0, last_pad2.w
 258+
 259+	bsr handle_pad_buttons
 260+	rte
 261+.mouse
 262+	bsr handle_mouse
 263+	rte
 264+
 265+
 266+;d0 = SACBRLUD
 267+;d1 = newly pressed buttons
 268+handle_pad_buttons:
 269+	tst.b num_menu.w
 270+	bne handle_buttons_menu
 271+	tst.b num_slots.w
 272+	bne handle_buttons_save
 273+	moveq #16, d2
 274+
 275+
 276+	btst #3, d1
 277+	bne right
 278+	btst #2, d1
 279+	bne left
 280+buttons_no_leftright
 281+	btst #1, d1
 282+	bne down
 283+	btst #0, d1
 284+	bne up
 285+	btst #7, d1
 286+	bne select_entry
 287+	btst #5, d1
 288+	bne select_entry
 289+handle_done:
 290+	rts
 291+handle_buttons_menu
 292+	moveq #48, d2
 293+	bra buttons_no_leftright
 294+handle_buttons_save
 295+	moveq #32, d2
 296+	bra buttons_no_leftright
 297+
 298+down:
 299+	
 300+	;check if we are already at the bottom of the page
 301+	moveq #1, d0
 302+	add.b (selected).w, d0
 303+	tst.b num_menu.w
 304+	bne .menu
 305+	tst.b num_slots.w
 306+	bne .slots
 307+	move.w d0, d1
 308+	add.w d1, d1
 309+	add.w d1, d1
 310+	lea page_index.w, a2
 311+	tst.l (0, a2, d1.w)
 312+	beq handle_done
 313+.do_move
 314+	move.b d0, (selected).w
 315+
 316+	add.w d2, (sprite_list).w
 317+	add.w d2, (sprite_list+8).w
 318+	rts
 319+.menu:
 320+	cmp.b num_menu.w, d0
 321+	beq handle_done
 322+	bra .do_move
 323+.slots:
 324+	cmp.b num_slots.w, d0
 325+	beq handle_done
 326+	bra .do_move
 327+	
 328+up:
 329+	;check if we are already at the top of the page
 330+	move.b (selected).w, d0
 331+	beq handle_done
 332+	subq #1, d0
 333+	move.b d0, (selected).w
 334+
 335+	sub.w d2, (sprite_list).w
 336+	sub.w d2, (sprite_list+8).w
 337+	rts
 338+
 339+right:
 340+	;check that we have another page to go to
 341+	tst.b more_pages.w
 342+	beq handle_done
 343+	;switch to the next page
 344+	move.l page_stack.w, a6
 345+	move.l (-4, a6), a6
 346+
 347+	addq #6, a7
 348+	bra render_page
 349+
 350+left:
 351+	move.l page_stack.w, a5
 352+	;check if we're already on the first page
 353+	cmp.l #(page_pointers+8), a5
 354+	beq handle_done
 355+	;switch to previous page
 356+	lea (-12, a5), a5
 357+	move.l (a5)+, a6
 358+	move.l a5, page_stack.w
 359+
 360+	addq #6, a7
 361+	bra render_page
 362+
 363+select_entry:
 364+	moveq #0, d0
 365+	move.b (selected).w, d0
 366+	add.w d0, d0
 367+	add.w d0, d0
 368+	tst.b num_menu.w
 369+	bne .select_menu_button
 370+	tst.b num_slots.w
 371+	bne .select_save_slot
 372+	lea page_index.w, a2
 373+	move.l (0, a2, d0.w), a2
 374+	tst.b (-1, a2)
 375+	bne enter_dir
 376+	;regular file
 377+	move.l rom_load_addr.w, a3
 378+	move.l a2, (a3)
 379+	
 380+	addq #6, a7
 381+	bra show_pause_menu
 382+.select_menu_button:
 383+	movea.l menu_functions.w, a2
 384+	move.l (0, a2, d0.w), a2
 385+	addq #6, a7
 386+	jmp (a2)
 387+.select_save_slot:
 388+	lea menu_port, a3
 389+	moveq #0, d0
 390+	move.b port_off.w, d0
 391+	add.w d0, a3
 392+	move.b selected.w, d0
 393+	move.l d0, (a3)
 394+	addq #6, a7
 395+	jmp show_pause_menu
 396+	
 397+enter_dir:
 398+	lea menu_port+4, a3
 399+	move.l a2, (a3)
 400+.wait_complete
 401+	tst.w (a3)
 402+	bne .wait_complete
 403+	addq #6, a7
 404+	bra menu_start
 405+
 406+handle_mouse:
 407+	move.b last_mbuttons.w, d4
 408+	eor.b d3, d4
 409+	and.b d3, d4
 410+	move.b d3, last_mbuttons.w
 411+
 412+	move.b d0, d2
 413+	or.b d1, d2
 414+	beq .no_mouse_move
 415+
 416+
 417+	tst.b mouse_shown.w
 418+	bne .skip_show_check
 419+
 420+	moveq #0, d2
 421+	move.b num_sprites.w, d2
 422+	move.w d2, d4
 423+	lsl.w #3, d4
 424+	lea sprite_list.w, a2
 425+	move.b d2, (-5, a2, d4.w)
 426+	lea (0, a2, d4.w), a2
 427+	move.l a2, mouse_sprite.w
 428+	move.l #$00EA0500, (a2)+
 429+	move.w #$8083, (a2)
 430+	move.w #$100, mouse_x.w
 431+	addq #1, d2
 432+	move.b d2, num_sprites.w
 433+
 434+	move.b #1, mouse_shown.w
 435+	
 436+	move.l cursor_show_fun.w, d2
 437+	beq .skip_show_check
 438+	move.l d2, a2
 439+	jsr (a2)
 440+	
 441+
 442+.skip_show_check
 443+	neg.w d1
 444+	move.l mouse_sprite.w, a2
 445+	add.w d1, (a2)
 446+	add.w d0, mouse_x.w
 447+	move.w mouse_x.w, d0
 448+	asr.w #1, d0
 449+	move.w d0, (6, a2)
 450+	move.w (a2), d1
 451+	cmp.w selection_top.w, d1
 452+	blo .done
 453+	cmp.w selection_bot.w, d1
 454+	bhi .special_click
 455+	tst.b num_menu.w
 456+	bne .handle_menu
 457+	tst.b num_slots.w
 458+	bne .handle_slots
 459+	and.w #$FFF0, d1
 460+	subq #8, d1
 461+	move.w d1, (sprite_list).w
 462+	move.w d1, (sprite_list+8).w
 463+
 464+	sub.w #264, d1
 465+	lsr.w #4, d1
 466+	move.b d1, selected.w
 467+	bra .normal_click
 468+.handle_menu
 469+	;TODO: FIXME
 470+	and.w #$FFF0, d1
 471+	moveq #0, d0
 472+	move.w d1, d0
 473+	sub.w selection_top.w, d0
 474+	divu.w #48, d0
 475+	swap d0
 476+	tst.w d0
 477+	beq .no_adjust
 478+	
 479+	cmp.w #16, d0
 480+	bne .round_up
 481+	swap d0
 482+	sub.w #16, d1
 483+	bra .set_cursor_pos
 484+	
 485+.round_up
 486+	swap d0
 487+	addq #1, d0
 488+	add.w #16, d1
 489+	bra .set_cursor_pos
 490+	
 491+.no_adjust
 492+	swap d0
 493+.set_cursor_pos
 494+	move.w d1, (sprite_list).w
 495+	move.w d1, (sprite_list+8).w
 496+
 497+	move.b d0, selected.w
 498+	
 499+	bra .normal_click
 500+.handle_slots
 501+	and.w #$FFE0, d1
 502+	subq #8, d1
 503+	move.w d1, (sprite_list).w
 504+	move.w d1, (sprite_list+8).w
 505+
 506+	sub.w #264, d1
 507+	lsr.w #5, d1
 508+	move.b d1, selected.w
 509+.normal_click
 510+	btst #0, d4
 511+	bne select_entry
 512+.done
 513+	rts
 514+.no_mouse_move
 515+	tst.b mouse_shown
 516+	bne .skip_show_check
 517+	rts
 518+.special_click:
 519+	btst #0, d4
 520+	beq .done
 521+	move.l special_click.w, d2
 522+	beq .done
 523+	move.l d2, a2
 524+	jmp (a2)
 525+int_4:
 526+empty_handler:
 527+	rte
 528+
 529+id_lookup:
 530+	dc.b $0, $1, $4, $5
 531+	dc.b $2, $3, $6, $7
 532+	dc.b $8, $9, $C, $D
 533+	dc.b $A, $B, $E, $F
 534+
 535+io_read:
 536+	;read TH=1
 537+	move.b (a2), d0
 538+	;read TH=0
 539+	move.b #0, (a2)
 540+	nop
 541+	nop
 542+	move.b (a2), d1
 543+	;reset TH to 1
 544+	move.b #$40, (a2)
 545+
 546+	moveq #0, d2   ;4
 547+
 548+	;calculate Mega Drive peripheral ID
 549+	move.b d1, d2  ;4
 550+	lsr.b #1, d2   ;8, 12
 551+	or.b d1, d2    ;4, 16
 552+	and.b #5, d2   ;8, 24
 553+
 554+	move.b d0, d3  ;4
 555+	add.b d3, d3   ;4, 8
 556+	or.b d0, d3    ;4, 12
 557+	and.b #$A, d3  ;8, 20
 558+
 559+	or.b d3, d2    ;4
 560+	move.b (id_lookup, pc, d2.w), d2 ;14
 561+
 562+
 563+	cmp.b #$3, d2
 564+	beq .mouse
 565+
 566+	cmp.b #$D, d2
 567+	bne .not_pad
 568+
 569+	and.b #$3F, d0
 570+	and.b #$30, d1
 571+	add.b d1, d1
 572+	add.b d1, d1
 573+	or.b d1, d0
 574+	not.b d0
 575+	rts
 576+.not_pad:
 577+	moveq #0, d0
 578+	rts
 579+
 580+.mouse:
 581+
 582+	move.b #$60, (a2)
 583+	move.b #$60, (PAD1_CTRL-PAD1_DATA, a2)
 584+	move.b #$60, (a2)
 585+
 586+	moveq #$f, d4
 587+wait_hi_init:
 588+	btst #4, (a2)
 589+	beq wait_hi_init
 590+	nop
 591+	nop
 592+	move.b #$20, (a2)
 593+	nop
 594+	nop
 595+	moveq #$f, d4
 596+	move.b #0, (a2)
 597+.wait_lo
 598+	btst #4, (a2)
 599+	bne .wait_lo
 600+	moveq #$f, d4
 601+	move.b #$20, (a2)
 602+.wait_hi
 603+	btst #4, (a2)
 604+	beq .wait_hi
 605+
 606+	lea mouse_buf.w, a3
 607+	move.l a3, a4
 608+	moveq #2, d3
 609+	moveq #0, d0
 610+loop:
 611+	moveq #$f, d4
 612+	move.b #0, (a2)
 613+.wait_lo
 614+	btst #4, (a2)
 615+	bne .wait_lo
 616+	move.b (a2), d0
 617+	lsl.b #4, d0
 618+	moveq #$f, d4
 619+	move.b #$20, (a2)
 620+.wait_hi
 621+	btst #4, (a2)
 622+	beq .wait_hi
 623+	move.b (a2), d1
 624+	and.b #$f, d1
 625+	or.b d1, d0
 626+	move.b d0, (a3)+
 627+
 628+	dbra d3, loop
 629+
 630+	;end request
 631+	move.b #$60, (a2)
 632+
 633+
 634+	;massage data
 635+	moveq #0, d1
 636+	move.b d0, d1
 637+	move.b (a4)+, d3
 638+	move.b (a4), d0
 639+
 640+	btst #4, d3
 641+	beq xpos
 642+	or.w #$FF00, d0
 643+xpos
 644+	btst #5, d3
 645+	beq ypos
 646+	or.w #$FF00, d1
 647+ypos
 648+	;set port config back to normal controller mode
 649+	move.b #$40, (PAD1_CTRL-PAD1_DATA, a2)
 650+	rts
 651+
 652+topcorner equ (button-font)/64 + 32
 653+topmiddle equ topcorner+1
 654+botcorner equ topmiddle+1
 655+botmiddle equ botcorner+1
 656+horiz_flip equ $800
 657+vert_flip equ $1000
 658+
 659+; draws a button
 660+; d0.w - x in cells
 661+; d1.w - y in cells
 662+; d2.w - width in cells
 663+;
 664+; clobbers a6
 665+draw_button:
 666+	;multiply x by 2
 667+	add.w d0, d0
 668+	;multiply y by 128
 669+	lsl.w #7, d1
 670+	add.w d1, d0
 671+	add.w #$A000, d0
 672+	move.w d0, d1
 673+	and.w #$3FFF, d0
 674+	rol.w #2, d1
 675+	and.w #3, d1
 676+	ori.w #(VDP_VRAM_WRITE >> 16), d0
 677+	swap d0
 678+	move.w d1, d0
 679+	move.l d0, (a1)
 680+	move.w d2, d1
 681+	;top left corner
 682+	move.w #topcorner, (a0)
 683+	subq #3, d1
 684+	bmi .notopmiddle
 685+.toploop:
 686+	;top middle
 687+	move.w #topmiddle, (a0)
 688+	dbra d1, .toploop
 689+.notopmiddle
 690+	;top right corner
 691+	move.w #(topcorner | horiz_flip), (a0)
 692+	;go to next row in name table
 693+	add.l #((2*64) << 16), d0
 694+	move.l d0, (a1)
 695+	;bottom left corner
 696+	move.w #botcorner, (a0)
 697+	subq #3, d2
 698+	bmi .nomiddlebot
 699+.botloop:
 700+	;bottom middle
 701+	move.w #botmiddle, (a0)
 702+	dbra d2, .botloop
 703+.nomiddlebot
 704+	;bottom right corner
 705+	move.w #(botcorner | horiz_flip), (a0)
 706+	rts
 707+
 708+;a5 - menu pointer
 709+;d6 - initial Y position of menu
 710+draw_menu:
 711+	moveq #0, d7
 712+	moveq #0, d5
 713+	;clear out save slot state
 714+	move.b d5, num_slots.w
 715+	;clear out event handlers
 716+	move.l d5, cursor_show_fun.w
 717+	move.l d5, special_click.w
 718+	;select first item
 719+	move.b d7, selected.w
 720+	;save menu pointer for second pass
 721+	movea.l a5, a4
 722+	;adjust arrow mask
 723+	move.w #$FFE0, selection_mask.w
 724+.lenloop	
 725+	tst.b (a5)
 726+	beq .lendone
 727+	addq #1, d5
 728+	movea.l a5, a6
 729+	bsr strlen
 730+	cmp.w d7, d0
 731+	blo .nochange
 732+	move.w d0, d7
 733+.nochange
 734+	lea (1, a5, d0.w), a5
 735+	bra .lenloop
 736+.lendone
 737+	
 738+	addq #2, d7
 739+	move.b d5, num_menu.w
 740+	
 741+	;calculate X position
 742+	move.w d7, d4
 743+	lsr.w #1, d4
 744+	moveq #20, d5
 745+	sub.w d4, d5
 746+	;calculate left arrow X
 747+	move.w d5, d4
 748+	lsl.w #3, d4
 749+	add.w #(128-24), d4
 750+	move.w d4, (sprite_list+6).w
 751+	;calculate right arrow x
 752+	move.w d7, d3
 753+	lsl.w #3, d3
 754+	add.w d3, d4
 755+	add.w #32, d4
 756+	move.w d4, (sprite_list+6+8).w
 757+	;update left arrow Y
 758+	move.w d6, d4
 759+	lsl.w #4, d4
 760+	add.w #256, d4
 761+	move.w d4, (sprite_list).w
 762+	move.w d4, (sprite_list+8).w
 763+	;update mouse top limit
 764+	move.w d4, selection_top.w
 765+	;restore menu pointer
 766+	movea.l a4, a5
 767+.drawloop
 768+	tst.b (a5)
 769+	beq .done
 770+	;x pos
 771+	move.w d5, d0
 772+	;y pos
 773+	move.w d6, d1
 774+	;width
 775+	move.w d7, d2
 776+	bsr draw_button
 777+	
 778+	movea.l a5, a6
 779+	bsr strlen
 780+	movea.l a5, a6
 781+	lea (1, a5, d0.w), a5
 782+	;x pos
 783+	move.w d7, d1
 784+	lsr.w #1, d1
 785+	add.w d5, d1
 786+	lsr.w #1, d0
 787+	sub.w d0, d1
 788+	;y pos
 789+	move.w d6, d2
 790+	;base attribute
 791+	move.w #$206B, d0
 792+	bsr print_string_fixed
 793+	
 794+	addq #3, d6
 795+	bra .drawloop
 796+.done
 797+	;update mouse bottom limit
 798+	lsl.w #4, d6
 799+	add.w #224, d6
 800+	move.w d6, selection_bot.w
 801+	rts
 802+	
 803+clear_screen:
 804+	;clear name tables
 805+	vdpaccess $8000, VDP_VRAM_WRITE
 806+	moveq #32, d0
 807+	swap d0
 808+	move.b #32, d0
 809+	move.w #(64*64-1), d1
 810+ploop:
 811+	move.l d0, (a0)
 812+	dbra d1, ploop
 813+	rts
 814+
 815+initial_regs:
 816+	vdpreg MODE_2, $4    ;Mode 5, everything turned off
 817+	vdpreg MODE_1, $4
 818+	vdpreg SCROLL_A, $20 ;Scroll a table $8000
 819+	vdpreg SCROLL_B, $05 ;Scroll b table $A000
 820+	vdpreg SAT, $60      ;SAT table $C000
 821+	vdpreg BG_COLOR, 0
 822+	vdpreg HINT, $FF
 823+	vdpreg MODE_3, 0     ;full screen scroll
 824+	vdpreg MODE_4, $87   ;40 cell mode, double-res interlace
 825+	vdpreg HSCROLL, 0
 826+	vdpreg AUTOINC, 2
 827+	vdpreg SCROLL, 1     ;64x32 scroll size
 828+end_initial_regs
 829+
 830+start:
 831+	lea $FF0000, a0
 832+	moveq #0, d0
 833+	move.w #($10000/8 - 1), d1
 834+.clearloop:
 835+	move.l d0, (a0)+
 836+	move.l d0, (a0)+
 837+	dbra d1, .clearloop
 838+
 839+	lea $C00000, a0
 840+	lea $C00004, a1
 841+
 842+	moveq #(end_initial_regs-initial_regs-1), d0
 843+	lea initial_regs.w, a2
 844+.regloop
 845+	move.w (a2)+, (a1)
 846+	dbra d0, .regloop
 847+
 848+	vdpaccess $0, VDP_CRAM_WRITE
 849+	move.w #$400, (a0)
 850+	move.w #$EEE, (a0)
 851+	move.w #$222, (a0)
 852+
 853+	;init scroll table
 854+	vdpaccess $0, VDP_VRAM_WRITE
 855+	move.w #0, (a0)
 856+	move.w #0, (a0)
 857+	
 858+	
 859+	;load tiles
 860+	vdpaccess $800, VDP_VRAM_WRITE
 861+	lea font(pc), a2
 862+	move.w #((buttonend-font)/4 - 1), d0
 863+tloop:
 864+	move.l (a2)+, (a0)
 865+	dbra d0, tloop
 866+	move.w #((fontfixedend-fontfixed)/4 - 1), d0
 867+dtloop:
 868+	move.l (a2)+, d1
 869+	move.l d1, (a0)
 870+	move.l d1, (a0)
 871+	dbra d0, dtloop
 872+
 873+
 874+	;setup SAT
 875+	;;vdpaccess $C000, VDP_VRAM_WRITE
 876+
 877+	lea sprite_list.w, a2
 878+	;left arrow
 879+	move.l #$01080501, (a2)+
 880+	move.l #$807F0086, (a2)+
 881+
 882+	;right arrow
 883+	move.l #$01080500, (a2)+
 884+	move.l #$887F01AA, (a2)+
 885+	move.b #2, num_sprites.w
 886+	
 887+show_main_menu:
 888+	bsr clear_screen
 889+	;init vertical scroll RAM
 890+	vdpaccess $0, VDP_VSRAM_WRITE
 891+	move.w #-4, (a0)
 892+	move.w #0, (a0)
 893+	
 894+	moveq #8, d6
 895+	move.l #main_menu_func, menu_functions.w
 896+	lea main_menu(pc), a5
 897+	bsr draw_menu
 898+	bra gamepad_setup
 899+	
 900+show_pause_menu:
 901+	bsr clear_screen
 902+	;init vertical scroll RAM
 903+	vdpaccess $0, VDP_VSRAM_WRITE
 904+	move.w #-4, (a0)
 905+	move.w #0, (a0)
 906+	moveq #8, d6
 907+	move.l #pause_menu_func, menu_functions.w
 908+	lea pause_menu(pc), a5
 909+	bsr draw_menu
 910+	bra gamepad_setup
 911+	
 912+lock_on:
 913+	move.l #lock_on_port, rom_load_addr.w
 914+	bra menu_common
 915+menu_start:
 916+	move.l #load_rom_port, rom_load_addr.w
 917+menu_common:
 918+	moveq #0, d0
 919+	;init vertical scroll RAM
 920+	vdpaccess $0, VDP_VSRAM_WRITE
 921+	move.w d0, (a0)
 922+	move.w d0, (a0)
 923+	
 924+	;reset arrow position
 925+	move.w #$0108, sprite_list.w
 926+	move.w #$0108, (sprite_list + 8).w
 927+	move.w #$0086, (sprite_list + 6).w
 928+	move.w #$01AA, (sprite_list + 6 + 8).w
 929+	
 930+	;reset selection
 931+	move.b d0, selected.w
 932+	
 933+	;reset special click handler
 934+	move.l d0, special_click.w
 935+
 936+	
 937+	lea page_pointers.w, a5
 938+	lea dir_buffer, a6
 939+	move.l a6, (a5)+
 940+	move.l a5, page_stack.w
 941+	lea menu_port, a2
 942+	move.l a6, (a2)
 943+
 944+wait_complete:
 945+	tst.w (a2)
 946+	bne wait_complete
 947+
 948+render_page:
 949+	bsr clear_screen
 950+	
 951+	;clear menu state
 952+	move.b #0, num_menu.w
 953+	move.w #272, selection_top.w
 954+	move.w #655, selection_bot.w
 955+	move.w #$FFF0, selection_mask.w
 956+
 957+	;init scroll table
 958+	vdpaccess $0, VDP_VRAM_WRITE
 959+	move.w #0, (a0)
 960+	move.w #4, (a0)
 961+	
 962+	move.l #$40860002, d3
 963+	move.l d3, (a1)
 964+	move.l d3, base_cmd.w
 965+	
 966+	move.b #0, more_pages.w
 967+	lea page_index.w, a3
 968+	moveq #MAX_DISPLAY-1, d7
 969+file_loop:
 970+	tst.b (a6)+
 971+	beq done_files
 972+	addq #1, a6 ;TODO: Do something with directory flag
 973+
 974+	;skip over entries starting with a dot except ..
 975+	cmp.b #$2E, (a6)
 976+	bne normal
 977+	cmp.b #$2E, (1, a6)
 978+	beq normal
 979+	addq #1, a6
 980+.skip_loop:
 981+	tst.b (a6)+
 982+	bne .skip_loop
 983+	addq #1, d7
 984+	move.l a6, d6
 985+	bra skip
 986+normal:
 987+	;save entry pointer to page index
 988+	move.l a6, (a3)+
 989+	;print name on screen
 990+	moveq #0, d0
 991+	bsr print_string
 992+	move.l a6, d6
 993+
 994+	lea Newline(pc), a6
 995+	bsr print_string
 996+
 997+skip:
 998+	;word align pointer
 999+	addq #1, d6
1000+	and.w #$FFFE, d6
1001+	move.l d6, a6
1002+
1003+	dbra d7, file_loop
1004+	tst.b (a6)
1005+	beq done_files
1006+	move.b #1, more_pages.w
1007+done_files:
1008+	move.l page_stack.w, a5
1009+	move.l a6, (a5)+
1010+	move.l a5, page_stack.w
1011+
1012+	;null terminate page_index
1013+	moveq #0, d0
1014+	move.l d0, (a3)
1015+	
1016+	tst.b mouse_shown
1017+	beq .no_mouse
1018+	
1019+	tst.b more_pages.w
1020+	beq .no_next_page
1021+	
1022+	;draw Next button
1023+	moveq #30, d0
1024+	moveq #26, d1
1025+	moveq #6, d2
1026+	bsr draw_button
1027+	
1028+	;base attribute
1029+	move.w #$206B, d0
1030+	;x pos
1031+	moveq #32, d1
1032+	;y pos
1033+	moveq #26, d2
1034+	lea next_str(pc), a6
1035+	bsr print_string_fixed
1036+	
1037+.no_next_page
1038+
1039+	cmp.l #(page_pointers+8), a5
1040+	beq .no_prev_page
1041+	
1042+	;draw Prev button
1043+	moveq #3, d0
1044+	moveq #26, d1
1045+	moveq #6, d2
1046+	bsr draw_button
1047+	
1048+	;base attribute
1049+	move.w #$206B, d0
1050+	;x pos
1051+	moveq #5, d1
1052+	;y pos
1053+	moveq #26, d2
1054+	lea prev_str(pc), a6
1055+	bsr print_string_fixed
1056+	
1057+.no_prev_page
1058+
1059+	move.l #0, cursor_show_fun.w
1060+	
1061+	bra .done_page_buttons
1062+.no_mouse
1063+	move.l #show_prev_next_buttons, cursor_show_fun.w
1064+.done_page_buttons
1065+	move.l #handle_prev_next_click, special_click.w
1066+
1067+gamepad_setup:
1068+	;setup gamepads
1069+	move.b #$40, PAD1_CTRL
1070+	move.b #$40, PAD2_CTRL
1071+
1072+	move.w #$8174, (a1) ;enable display, vertical interrupts, DMA
1073+
1074+
1075+wait_forever
1076+	stop #2500
1077+	bra wait_forever
1078+	
1079+handle_prev_next_click:
1080+	;make sure we're actually low enough
1081+	cmp.w #663, d1
1082+	bls .no_prev_page
1083+
1084+
1085+	tst.b more_pages.w
1086+	beq .no_next_page
1087+	
1088+	cmp.w #373, d0
1089+	blo .no_next_page
1090+	
1091+	cmp.w #419, d0
1092+	bhi .no_next_page
1093+	
1094+	;switch to the next page
1095+	move.l page_stack.w, a6
1096+	move.l (-4, a6), a6
1097+
1098+	add.w #10, a7
1099+	bra render_page
1100+	
1101+.no_next_page
1102+	cmp.l #(page_pointers+8), a5
1103+	beq .no_prev_page
1104+	
1105+	cmp.w #157, d0
1106+	blo .no_prev_page
1107+	
1108+	cmp.w #203, d0
1109+	bhi .no_prev_page
1110+	
1111+	;switch to previous page
1112+	lea (-12, a5), a5
1113+	move.l (a5)+, a6
1114+	move.l a5, page_stack.w
1115+
1116+	add.w #10, a7
1117+	bra render_page
1118+	
1119+.no_prev_page
1120+	rts
1121+	
1122+show_prev_next_buttons:
1123+	movem.l d0-d2/a6, -(a7)
1124+	tst.b more_pages.w
1125+	beq .no_next_page
1126+	
1127+	;draw Next button
1128+	moveq #30, d0
1129+	moveq #26, d1
1130+	moveq #6, d2
1131+	bsr draw_button
1132+	
1133+	;base attribute
1134+	move.w #$206B, d0
1135+	;x pos
1136+	moveq #32, d1
1137+	;y pos
1138+	moveq #26, d2
1139+	lea next_str(pc), a6
1140+	bsr print_string_fixed
1141+	
1142+.no_next_page
1143+
1144+	cmp.l #(page_pointers+8), a5
1145+	beq .no_prev_page
1146+	
1147+	;draw Prev button
1148+	moveq #3, d0
1149+	moveq #26, d1
1150+	moveq #6, d2
1151+	bsr draw_button
1152+	
1153+	;base attribute
1154+	move.w #$206B, d0
1155+	;x pos
1156+	moveq #5, d1
1157+	;y pos
1158+	moveq #26, d2
1159+	lea prev_str(pc), a6
1160+	bsr print_string_fixed
1161+	
1162+.no_prev_page
1163+	move.l #0, cursor_show_fun.w
1164+	movem.l (a7)+, d0-d2/a6
1165+	rts
1166+	
1167+show_about:
1168+	bsr clear_screen
1169+	moveq #1, d7
1170+	lea about_text(pc), a6
1171+	;base attribute
1172+	move.w #$006B, d0
1173+.loop
1174+	tst.b (a6)
1175+	beq .done
1176+	;x pos
1177+	moveq #1, d1
1178+	;y pos
1179+	move.w d7, d2
1180+	bsr print_string_fixed
1181+	addq #1, d7
1182+	bra .loop
1183+.done
1184+	moveq #8, d6
1185+	move.l #about_menu_func, menu_functions.w
1186+	lea about_menu(pc), a5
1187+	bsr draw_menu
1188+.wait
1189+	stop #$2500
1190+	bra .wait
1191+	
1192+exit:
1193+	move.l #1, menu_port+12
1194+	bra exit
1195+	
1196+resume:
1197+	move.l #2, menu_port+12
1198+	bra show_pause_menu
1199+	
1200+show_save_slots:
1201+	move.w #(256+26), sprite_list.w
1202+	move.w #(256+26), (sprite_list+8).w
1203+	move.w #(128+8), (sprite_list+6).w
1204+	move.w #(128+320-24), (sprite_list+6+8).w
1205+	move.w #(256+32), selection_top.w
1206+	move.b #0, selected.w
1207+	move.b #0, num_menu.w
1208+	lea dir_buffer, a6
1209+	lea menu_port+16, a3
1210+	move.l a6, (a3)
1211+.waitdone:
1212+	tst.w (a3)
1213+	bne .waitdone
1214+	bsr clear_screen
1215+	moveq #0, d0
1216+	
1217+	moveq #0, d6
1218+	moveq #2, d7
1219+.slotloop
1220+	tst.b (a6)
1221+	beq .done
1222+	addq #1, d6
1223+	moveq #4, d1
1224+	move.w d7, d2
1225+	bsr print_string_fixed
1226+	addq #2, d7
1227+	bra .slotloop
1228+.done
1229+	lsl.w #4, d7
1230+	add.w #248, d7
1231+	move.w d7, selection_bot.w
1232+	move.b d6, num_slots.w
1233+	rts
1234+	
1235+save_state:
1236+	move.b #(5*4), port_off.w
1237+	bsr show_save_slots
1238+.wait
1239+	stop #$2500
1240+	bra .wait
1241+	
1242+load_state:
1243+	move.b #(6*4), port_off.w
1244+	bsr show_save_slots
1245+.wait
1246+	stop #$2500
1247+	bra .wait
1248+	
1249+next_str:
1250+	dc.b "Next", 0
1251+prev_str:
1252+	dc.b "Prev", 0
1253+	
1254+about_text:
1255+	dc.b "BlastEm v0.6.2", 0
1256+	dc.b "Copyright 2011-2019 Michael Pavone", 0
1257+	dc.b " ", 0
1258+	dc.b "BlastEm is a high performance, open", 0
1259+	dc.b "source (GPLv3) Genesis/Megadrive", 0
1260+	dc.b "emulator.",0
1261+	dc.b " ", 0
1262+	dc.b " ", 0
1263+	dc.b " ", 0
1264+	dc.b " ", 0
1265+	dc.b "       --- Special Thanks ---", 0
1266+	dc.b " ", 0
1267+	dc.b "Nemesis: Documentatino and test ROMs", 0
1268+	dc.b "Charles MacDonald: Documentation", 0
1269+	dc.b "Eke-Eke: Documentation", 0
1270+	dc.b "Bart Trzynadlowski: Documentation", 0
1271+	dc.b "KanedaFR: Hosting the best Sega forum", 0
1272+	dc.b "Titan: Awesome demos and documentation", 0
1273+	dc.b "flamewing: BCD info and test ROM", 0
1274+	dc.b "r57shell: Opcode size test ROM", 0
1275+	dc.b "micky: Testing", 0
1276+	dc.b "Sasha: Testing", 0
1277+	dc.b "lol-frank: Testing", 0
1278+	dc.b "Sik: Testing", 0
1279+	dc.b "Tim Lawrence : Testing", 0
1280+	dc.b "ComradeOj: Testing", 0
1281+	dc.b "Vladikcomper: Testing", 0
1282+	dc.b 0
1283+	
1284+
1285+Newline:
1286+	dc.b $A, 0
1287+
1288+	align 1
1289+
1290+;Prints a null terminated string
1291+;a6 - pointer to string
1292+;a0 - VDP data port
1293+;d0 - base tile attribute
1294+;
1295+;Clobbers: d1.w, d2.w, d3.l
1296+print_string:
1297+	lea widths(pc), a5
1298+	move.w x_pos.w, d2
1299+	move.l base_cmd.w, d3
1300+.loop
1301+	moveq #0, d1
1302+	move.b (a6)+, d1
1303+	beq .end
1304+	cmp.b #$A, d1
1305+	beq .newline
1306+	tst.b (-32, a5, d1.w)
1307+	beq .narrow
1308+	add.w d0, d1
1309+	move.w d1, (a0)
1310+	addq #2, d2
1311+	bra .loop
1312+.narrow
1313+	add.w d0, d1
1314+	move.w d1, (a0)
1315+	addq #1, d2
1316+	move.l d2, d1
1317+	;switch to other plane
1318+	and.w #$FFFE, d1
1319+	swap d1
1320+	eor.l #$20000000, d3
1321+	add.l d3, d1
1322+	move.l d1, (a1)
1323+	bra .loop
1324+.newline
1325+	moveq #0, d2
1326+	;switch back to plane A
1327+	and.l #$DFFFFFFF, d3
1328+	;skip to next row
1329+	add.l #$00800000, d3
1330+	move.l d3, (a1)
1331+	bra .loop
1332+.end
1333+	move.w d2, x_pos.w
1334+	move.l d3, base_cmd.w
1335+	rts
1336+	
1337+;Prints a null-terminated string with a fixed width font
1338+;a6 - pointer to string
1339+;a0 - VDP data port
1340+;d0 - base tile attribute
1341+;d1 - x col
1342+;d2 - y col
1343+;
1344+print_string_fixed:
1345+	;multiply x by 2
1346+	add.w d1, d1
1347+	;multiply y by 128
1348+	lsl.w #7, d2
1349+	add.w d2, d1
1350+	add.w #$8000, d1
1351+	move.w d1, d2
1352+	and.w #$3FFF, d1
1353+	rol.w #2, d2
1354+	and.w #3, d2
1355+	ori.w #(VDP_VRAM_WRITE >> 16), d1
1356+	swap d1
1357+	move.w d2, d1
1358+	move.l d1, (a1)
1359+.loop
1360+	moveq #0, d1
1361+	move.b (a6)+, d1
1362+	beq .end
1363+	add.w d0, d1
1364+	move.w d1, (a0)
1365+	bra .loop
1366+.end
1367+	rts
1368+	
1369+;Returns string length in d0
1370+;a6 - pointer to string
1371+strlen:
1372+	moveq #-1, d0
1373+.loop
1374+	addq #1, d0
1375+	tst.b (a6)+
1376+	bne .loop
1377+	rts
1378+
1379+	align 1
1380+font:
1381+	incbin font_interlace_variable.tiles
1382+fontend
1383+arrow:
1384+	incbin arrow.tiles
1385+arrowend:
1386+cursor:
1387+	incbin cursor.tiles
1388+cursorend:
1389+button:
1390+	incbin button.tiles
1391+buttonend:
1392+fontfixed:
1393+	incbin font.tiles
1394+fontfixedend:
1395+
1396+widths:
1397+	dc.b 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1
1398+	dc.b 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0
1399+	dc.b 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1
1400+	dc.b 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
1401+	dc.b 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1
1402+	
1403+main_menu:
1404+	dc.b "Load ROM", 0
1405+	dc.b "About", 0
1406+	dc.b "Exit", 0
1407+	dc.b 0
1408+	
1409+	align 1
1410+main_menu_func:
1411+	dc.l menu_start
1412+	dc.l show_about
1413+	dc.l exit
1414+	
1415+about_menu:
1416+	dc.b "Return", 0
1417+	dc.b 0
1418+	
1419+	align 1
1420+about_menu_func:
1421+	dc.l show_main_menu
1422+	
1423+pause_menu:
1424+	dc.b "Resume", 0
1425+	dc.b "Load ROM", 0
1426+	dc.b "Lock On", 0
1427+	dc.b "Save State", 0
1428+	dc.b "Load State", 0
1429+	dc.b "Exit", 0
1430+	dc.b 0
1431+	
1432+	align 1
1433+pause_menu_func
1434+	dc.l resume
1435+	dc.l menu_start
1436+	dc.l lock_on
1437+	dc.l save_state
1438+	dc.l load_state
1439+	dc.l exit
1440+
1441+rom_end:
+37, -0
 1@@ -0,0 +1,37 @@
 2+#include "genesis.h"
 3+
 4+void *write_multi_game_b(uint32_t address, void *vcontext, uint8_t value)
 5+{
 6+	m68k_context *context = vcontext;
 7+	genesis_context *gen = context->system;
 8+	gen->bank_regs[0] = address;
 9+	uint32_t base = (address & 0x3F) << 16, start = 0, end = 0x400000;
10+	//find the memmap chunk, so we can properly mask the base value
11+	for (int i = 0; i < context->options->gen.memmap_chunks; i++)
12+	{
13+		if (context->options->gen.memmap[i].flags & MMAP_PTR_IDX) {
14+			base &= context->options->gen.memmap[i].mask;
15+			start = context->options->gen.memmap[i].start;
16+			end = context->options->gen.memmap[i].end;
17+			break;
18+		}
19+	}
20+	context->mem_pointers[gen->mapper_start_index] = gen->cart + base/2;
21+	m68k_invalidate_code_range(context, start, end);
22+	return vcontext;
23+}
24+
25+void *write_multi_game_w(uint32_t address, void *context, uint16_t value)
26+{
27+	return write_multi_game_b(address, context, value);
28+}
29+
30+void multi_game_serialize(genesis_context *gen, serialize_buffer *buf)
31+{
32+	save_int8(buf, gen->bank_regs[0]);
33+}
34+
35+void multi_game_deserialize(deserialize_buffer *buf, genesis_context *gen)
36+{
37+	write_multi_game_b(load_int8(buf), gen->m68k, 0);
38+}
+9, -0
 1@@ -0,0 +1,9 @@
 2+#ifndef MULTI_GAME_H_
 3+#define MULTI_GAME_H_
 4+#include "serialize.h"
 5+
 6+void *write_multi_game_b(uint32_t address, void *context, uint8_t value);
 7+void *write_multi_game_w(uint32_t address, void *context, uint16_t value);
 8+void multi_game_serialize(genesis_context *gen, serialize_buffer *buf);
 9+void multi_game_deserialize(deserialize_buffer *buf, genesis_context *gen);
10+#endif //MULTI_GAME_H_
+33, -0
 1@@ -0,0 +1,33 @@
 2+	E(CMD_OK),
 3+	E(CMD_VERSION),
 4+	E(CMD_ECHO),
 5+	E(CMD_AP_SCAN),
 6+	E(CMD_AP_CFG),
 7+	E(CMD_AP_CFG_GET),
 8+	E(CMD_IP_CURRENT),
 9+	E(CMD_RESERVED),
10+	E(CMD_IP_CFG),
11+	E(CMD_IP_CFG_GET),
12+	E(CMD_DEF_AP_CFG),
13+	E(CMD_DEF_AP_CFG_GET),
14+	E(CMD_AP_JOIN),
15+	E(CMD_AP_LEAVE),
16+	E(CMD_TCP_CON),
17+	E(CMD_TCP_BIND),
18+	E(CMD_TCP_ACCEPT),
19+	E(CMD_TCP_DISC),
20+	E(CMD_UDP_SET),
21+	E(CMD_UDP_CLR),
22+	E(CMD_SOCK_STAT),
23+	E(CMD_PING),
24+	E(CMD_SNTP_CFG),
25+	E(CMD_SNTP_CFG_GET),
26+	E(CMD_DATETIME),
27+	E(CMD_DT_SET),
28+	E(CMD_FLASH_WRITE),
29+	E(CMD_FLASH_READ),
30+	E(CMD_FLASH_ERASE),
31+	E(CMD_FLASH_ID),
32+	E(CMD_SYS_STAT),
33+	E(CMD_DEF_CFG_SET),
34+	E(CMD_HRNG_GET),
A net.c
+49, -0
 1@@ -0,0 +1,49 @@
 2+#include <sys/types.h>
 3+#include <ifaddrs.h>
 4+#include <netinet/in.h>
 5+#include "net.h"
 6+
 7+static uint8_t is_loopback(struct sockaddr_in *addr)
 8+{
 9+	return (addr->sin_addr.s_addr & 0xFF) == 127;
10+}
11+
12+static void format_address(uint8_t *dst, struct sockaddr_in *addr)
13+{
14+	long ip = addr->sin_addr.s_addr;
15+	dst[0] = ip;
16+	dst[1] = ip >> 8;
17+	dst[2] = ip >> 16;
18+	dst[3] = ip >> 24;
19+}
20+
21+uint8_t get_host_address(iface_info *out)
22+{
23+	struct ifaddrs *entries, *current, *localhost;
24+	if (getifaddrs(&entries)) {
25+		return 0;
26+	}
27+	
28+	for (current = entries; current; current = current->ifa_next)
29+	{
30+		if (current->ifa_addr && current->ifa_addr->sa_family == AF_INET) {
31+			struct sockaddr_in *addr = (struct sockaddr_in *)current->ifa_addr;
32+			if (is_loopback(addr)) {
33+				localhost = current;
34+			} else {
35+				break;
36+			}
37+		}
38+	}
39+	if (!current && localhost) {
40+		current = localhost;
41+	}
42+	uint8_t ret = 0;
43+	if (current) {
44+		ret = 1;
45+		format_address(out->ip, (struct sockaddr_in *)current->ifa_addr);
46+		format_address(out->net_mask, (struct sockaddr_in *)current->ifa_netmask);
47+	}
48+	freeifaddrs(entries);
49+	return ret;
50+}
A net.h
+12, -0
 1@@ -0,0 +1,12 @@
 2+#ifndef NET_H_
 3+#define NET_H_
 4+#include <stdint.h>
 5+
 6+typedef struct {
 7+	uint8_t ip[4];
 8+	uint8_t net_mask[4];
 9+} iface_info;
10+
11+uint8_t get_host_address(iface_info *out);
12+
13+#endif //NET_H_
A nor.c
+217, -0
  1@@ -0,0 +1,217 @@
  2+#include "genesis.h"
  3+#include <stdlib.h>
  4+#include <string.h>
  5+#include "util.h"
  6+
  7+enum {
  8+	NOR_NORMAL,
  9+	NOR_PRODUCTID,
 10+	NOR_BOOTBLOCK
 11+};
 12+
 13+enum {
 14+	NOR_CMD_IDLE,
 15+	NOR_CMD_AA,
 16+	NOR_CMD_55
 17+};
 18+
 19+//Technically this value shoudl be slightly different between NTSC and PAL
 20+//as it's defined as 200 micro-seconds, not in clock cycles
 21+#define NOR_WRITE_PAUSE 10690 
 22+
 23+void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags)
 24+{
 25+	state->buffer = buffer;
 26+	state->page_buffer = malloc(page_size);
 27+	memset(state->page_buffer, 0xFF, page_size);
 28+	state->size = size;
 29+	state->page_size = page_size;
 30+	state->product_id = product_id;
 31+	state->last_write_cycle = 0xFFFFFFFF;
 32+	state->mode = NOR_NORMAL;
 33+	state->cmd_state = NOR_CMD_IDLE;
 34+	state->alt_cmd = 0;
 35+	state->bus_flags = bus_flags;
 36+	state->cmd_address1 = 0x5555;
 37+	state->cmd_address2 = 0x2AAA;
 38+}
 39+
 40+void nor_run(nor_state *state, m68k_context *m68k, uint32_t cycle)
 41+{
 42+	if (state->last_write_cycle == 0xFFFFFFFF) {
 43+		return;
 44+	}
 45+	if (cycle - state->last_write_cycle >= NOR_WRITE_PAUSE) {
 46+		state->last_write_cycle = 0xFFFFFFFF;
 47+		for (uint32_t i = 0; i < state->page_size; i++) {
 48+			state->buffer[state->current_page + i] = state->page_buffer[i];
 49+		}
 50+		memset(state->page_buffer, 0xFF, state->page_size);
 51+		if (state->bus_flags == RAM_FLAG_BOTH) {
 52+			//TODO: add base address of NOR device to start and end addresses
 53+			m68k_invalidate_code_range(m68k, state->current_page, state->current_page + state->page_size);
 54+		}
 55+	}
 56+}
 57+
 58+uint8_t nor_flash_read_b(uint32_t address, void *vcontext)
 59+{
 60+	m68k_context *m68k = vcontext;
 61+	genesis_context *gen = m68k->system;
 62+	nor_state *state = &gen->nor;
 63+	if (
 64+		((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
 65+		(!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
 66+	) {
 67+		return 0xFF;
 68+	}
 69+	if (state->bus_flags != RAM_FLAG_BOTH) {
 70+		address = address >> 1;
 71+	}
 72+	
 73+	nor_run(state, m68k, m68k->current_cycle);
 74+	switch (state->mode)
 75+	{
 76+	case NOR_NORMAL:
 77+		if (state->bus_flags == RAM_FLAG_BOTH) {
 78+			address ^= 1;
 79+		}
 80+		return state->buffer[address & (state->size-1)];
 81+		break;
 82+	case NOR_PRODUCTID:
 83+		switch (address & (state->size - 1))
 84+		{
 85+		case 0:
 86+			return state->product_id >> 8;
 87+		case 1:
 88+			return state->product_id;
 89+		case 2:
 90+			//TODO: Implement boot block protection
 91+			return 0xFE;
 92+		default:
 93+			return 0xFE;
 94+		}			//HERE
 95+		break;
 96+	case NOR_BOOTBLOCK:
 97+		break;
 98+	}
 99+	return 0xFF;
100+}
101+
102+uint16_t nor_flash_read_w(uint32_t address, void *context)
103+{
104+	uint16_t value = nor_flash_read_b(address, context) << 8;
105+	value |= nor_flash_read_b(address+1, context);
106+	return value;
107+}
108+
109+void nor_write_byte(nor_state *state, uint32_t address, uint8_t value, uint32_t cycle)
110+{
111+	switch(state->mode)
112+	{
113+	case NOR_NORMAL:
114+		if (state->last_write_cycle != 0xFFFFFFFF) {
115+			state->current_page = address & (state->size - 1) & ~(state->page_size - 1);
116+		}
117+		if (state->bus_flags == RAM_FLAG_BOTH) {
118+			address ^= 1;
119+		}
120+		state->page_buffer[address & (state->page_size - 1)] = value;
121+		break;
122+	case NOR_PRODUCTID:
123+		break;
124+	case NOR_BOOTBLOCK:
125+		//TODO: Implement boot block protection
126+		state->mode = NOR_NORMAL;
127+		break;
128+	}
129+}
130+
131+void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value)
132+{
133+	m68k_context *m68k = vcontext;
134+	genesis_context *gen = m68k->system;
135+	nor_state *state = &gen->nor;
136+	if (
137+		((address & 1) && state->bus_flags == RAM_FLAG_EVEN) ||
138+		(!(address & 1) && state->bus_flags == RAM_FLAG_ODD)
139+	) {
140+		return vcontext;
141+	}
142+	if (state->bus_flags != RAM_FLAG_BOTH) {
143+		address = address >> 1;
144+	}
145+	
146+	nor_run(state, m68k, m68k->current_cycle);
147+	switch (state->cmd_state)
148+	{
149+	case NOR_CMD_IDLE:
150+		if (value == 0xAA && (address & (state->size - 1)) == state->cmd_address1) {
151+			state->cmd_state = NOR_CMD_AA;
152+		} else {
153+			nor_write_byte(state, address, value, m68k->current_cycle);
154+			state->cmd_state = NOR_CMD_IDLE;
155+		}
156+		break;
157+	case NOR_CMD_AA:
158+		if (value == 0x55 && (address & (state->size - 1)) == state->cmd_address2) {
159+			state->cmd_state = NOR_CMD_55;
160+		} else {
161+			nor_write_byte(state, state->cmd_address1, 0xAA, m68k->current_cycle);
162+			nor_write_byte(state, address, value, m68k->current_cycle);
163+			state->cmd_state = NOR_CMD_IDLE;
164+		}
165+		break;
166+	case NOR_CMD_55:
167+		if ((address & (state->size - 1)) == state->cmd_address1) {
168+			if (state->alt_cmd) {
169+				switch(value)
170+				{
171+				case 0x10:
172+					puts("UNIMPLEMENTED: NOR flash erase");
173+					break;
174+				case 0x20:
175+					puts("UNIMPLEMENTED: NOR flash disable protection");
176+					break;
177+				case 0x40:
178+					state->mode = NOR_BOOTBLOCK;
179+					break;
180+				case 0x60:
181+					state->mode = NOR_PRODUCTID;
182+					break;
183+				}
184+			} else {
185+				switch(value)
186+				{
187+				case 0x80:
188+					state->alt_cmd = 1;
189+					break;
190+				case 0x90:
191+					state->mode = NOR_PRODUCTID;
192+					break;
193+				case 0xA0:
194+					puts("UNIMPLEMENTED: NOR flash enable protection");
195+					break;
196+				case 0xF0:
197+					state->mode = NOR_NORMAL;
198+					break;
199+				default:
200+					printf("Unrecognized unshifted NOR flash command %X\n", value);
201+				}
202+			}
203+		} else {
204+			nor_write_byte(state, state->cmd_address1, 0xAA, m68k->current_cycle);
205+			nor_write_byte(state, state->cmd_address2, 0x55, m68k->current_cycle);
206+			nor_write_byte(state, address, value, m68k->current_cycle);
207+		}
208+		state->cmd_state = NOR_CMD_IDLE;
209+		break;
210+	}
211+	return vcontext;
212+}
213+
214+void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value)
215+{
216+	nor_flash_write_b(address, vcontext, value >> 8);
217+	return nor_flash_write_b(address + 1, vcontext, value);
218+}
A nor.h
+10, -0
 1@@ -0,0 +1,10 @@
 2+#ifndef NOR_H_
 3+#define NOR_H_
 4+
 5+void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags);
 6+uint8_t nor_flash_read_b(uint32_t address, void *vcontext);
 7+uint16_t nor_flash_read_w(uint32_t address, void *context);
 8+void *nor_flash_write_b(uint32_t address, void *vcontext, uint8_t value);
 9+void *nor_flash_write_w(uint32_t address, void *vcontext, uint16_t value);
10+
11+#endif //NOR_H_
+76, -0
 1@@ -0,0 +1,76 @@
 2+cmp.w <ea>, Dn 4(1/0) + <ea> time
 3+cmp.l <ea>, Dn 6(1/0) + <ea> time
 4+cmp.w #num, Dn 4(1/0) + 4(1/0)
 5+cmp.l #num, Dn 6(1/0) + 8(2/0)
 6+
 7+cmpi.w #num, Dn 8(2/0)
 8+cmpi.l #num, Dn 14(3/0)
 9+
10+
11+movem
12+
13+subtype field (bits 9-11) = 110 or 100 depending on direction
14+bit 8 = 0
15+bit 7 = 1
16+bit 6 = size
17+
18+
19+
20+x86-64 registers in 68K core
21+
22+1. native stack pointer
23+2. current cycle count
24+3. target cycle count
25+4. cartridge address
26+5. work ram address
27+6. scratch register
28+7. context pointer (contains 68K registers and memory pointers not in registers)
29+8. status register (maybe, depends on how well I can abuse native x86 status stuff)
30+Rest of registers used for holding 68K registers
31+
32+rax = cycle counter
33+bl = N flag
34+bh = V flag
35+rcx = scratch register
36+dl = Z flag
37+dh = C flag
38+rbp = target cycle count
39+rsi = context pointer
40+rdi = scratch register
41+r8 = cartridge address
42+r9 = work ram address
43+r10 = d0
44+r11 = d1
45+r12 = d2
46+r13 = a0
47+r14 = a1
48+r15 = a7
49+rsp = native stack pointer
50+
51+68K context:
52+uint8_t flags[5];
53+uint8_t pad??[3]
54+uint32_t dregs[8]; //8 + 4 * reg
55+uint32_t aregs[8]; //40 + 4 * reg
56+.....
57+
58+x86-64 registers in Z80 core
59+
60+ax = HL
61+bx = BC
62+cx = DE
63+dx = IX
64+ebp = current cycle count
65+rsi = context pointer
66+edi = target cycle count
67+rsp = native stack pointer
68+r8 = IY
69+r9 = SP
70+r10 = A (maybe AF?)
71+r11 = z80 ram address
72+r12 = cartridge address if bank is pointed at ROM
73+r13 = scratch1
74+r14 = scratch2
75+r15 = ?maybe z80 bank register?
76+
77+
+89, -0
 1@@ -0,0 +1,89 @@
 2+#include <string.h>
 3+#include <stdlib.h>
 4+#include "blastem.h"
 5+#include "util.h"
 6+
 7+static char **current_path;
 8+
 9+static void persist_path(void)
10+{
11+	char *pathfname = alloc_concat(get_userdata_dir(), PATH_SEP "blastem" PATH_SEP "sticky_path");
12+	FILE *f = fopen(pathfname, "wb");
13+	if (f) {
14+		if (fwrite(*current_path, 1, strlen(*current_path), f) != strlen(*current_path)) {
15+			warning("Failed to save menu path");
16+		}
17+		fclose(f);
18+	} else {
19+		warning("Failed to save menu path: Could not open %s for writing\n", pathfname);
20+		
21+	}
22+	free(pathfname);
23+}
24+
25+void get_initial_browse_path(char **dst)
26+{
27+	*dst = NULL;
28+	char *remember_path = tern_find_path(config, "ui\0remember_path\0", TVAL_PTR).ptrval;
29+	if (!remember_path || !strcmp("on", remember_path)) {
30+		char *pathfname = alloc_concat(get_userdata_dir(), PATH_SEP "blastem" PATH_SEP "sticky_path");
31+		FILE *f = fopen(pathfname, "rb");
32+		if (f) {
33+			long pathsize = file_size(f);
34+			if (pathsize > 0) {
35+				*dst = malloc(pathsize + 1);
36+				if (fread(*dst, 1, pathsize, f) != pathsize) {
37+					warning("Error restoring saved file browser path");
38+					free(*dst);
39+					*dst = NULL;
40+				} else {
41+					(*dst)[pathsize] = 0;
42+				}
43+			}
44+			fclose(f);
45+		}
46+		free(pathfname);
47+		if (!current_path) {
48+			atexit(persist_path);
49+			current_path = dst;
50+		}
51+	}
52+	if (!*dst) {
53+		*dst = tern_find_path(config, "ui\0initial_path\0", TVAL_PTR).ptrval;
54+	}
55+	if (!*dst){
56+		*dst = "$HOME";
57+	}
58+	tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir());
59+	vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir());
60+	*dst = replace_vars(*dst, vars, 1);
61+	tern_free(vars);
62+}
63+
64+char *path_append(const char *base, const char *suffix)
65+{
66+	if (!strcmp(suffix, "..")) {
67+		size_t len = strlen(base);
68+		while (len > 0) {
69+			--len;
70+			if (is_path_sep(base[len])) {
71+				if (!len) {
72+					//special handling for /
73+					len++;
74+				}
75+				char *ret = malloc(len+1);
76+				memcpy(ret, base, len);
77+				ret[len] = 0;
78+				return ret;
79+			}
80+		}
81+		return strdup(PATH_SEP);
82+	} else {
83+		if (is_path_sep(base[strlen(base) - 1])) {
84+			return alloc_concat(base, suffix);
85+		} else {
86+			char const *pieces[] = {base, PATH_SEP, suffix};
87+			return alloc_concat_m(3, pieces);
88+		}
89+	}
90+}
+7, -0
1@@ -0,0 +1,7 @@
2+#ifndef PATHS_H_
3+#define PATHS_H_
4+
5+void get_initial_browse_path(char **dst);
6+char *path_append(const char *base, const char *suffix);
7+
8+#endif //PATHS_H_
A png.c
+447, -0
  1@@ -0,0 +1,447 @@
  2+#include <stdint.h>
  3+#include <stdlib.h>
  4+#include <stdio.h>
  5+#include <string.h>
  6+#include <zlib.h>
  7+
  8+static const char png_magic[] = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n'};
  9+static const char ihdr[] = {'I', 'H', 'D', 'R'};
 10+static const char plte[] = {'P', 'L', 'T', 'E'};
 11+static const char idat[] = {'I', 'D', 'A', 'T'};
 12+static const char iend[] = {'I', 'E', 'N', 'D'};
 13+
 14+enum {
 15+	COLOR_GRAY,
 16+	COLOR_TRUE = 2,
 17+	COLOR_INDEXED,
 18+	COLOR_GRAY_ALPHA,
 19+	COLOR_TRUE_ALPHA=6
 20+};
 21+
 22+static void write_chunk(FILE *f, const char*id, uint8_t *buffer, uint32_t size)
 23+{
 24+	uint8_t tmp[4] = {size >> 24, size >> 16, size >> 8, size};
 25+	uint8_t warn = 0;
 26+	warn = warn || (sizeof(tmp) != fwrite(tmp, 1, sizeof(tmp), f));
 27+	warn = warn || (4 != fwrite(id, 1, 4, f));
 28+	if (size) {
 29+		warn = warn || (size != fwrite(buffer, 1, size, f));
 30+	}
 31+	
 32+	uint32_t crc = crc32(0, NULL, 0);
 33+	crc = crc32(crc, id, 4);
 34+	if (size) {
 35+		crc = crc32(crc, buffer, size);
 36+	}
 37+	tmp[0] = crc >> 24;
 38+	tmp[1] = crc >> 16;
 39+	tmp[2] = crc >> 8;
 40+	tmp[3] = crc;
 41+	warn = warn || (sizeof(tmp) != fwrite(tmp, 1, sizeof(tmp), f));
 42+	if (warn) {
 43+		fprintf(stderr, "Failure during write of %c%c%c%c chunk\n", id[0], id[1], id[2], id[3]);
 44+	}
 45+}
 46+
 47+static void write_header(FILE *f, uint32_t width, uint32_t height, uint8_t color_type)
 48+{
 49+	uint8_t chunk[13] = {
 50+		width >> 24, width >> 16, width >> 8, width,
 51+		height >> 24, height >> 16, height >> 8, height,
 52+		8, color_type, 0, 0, 0
 53+	};
 54+	if (sizeof(png_magic) != fwrite(png_magic, 1, sizeof(png_magic), f)) {
 55+		fputs("Error writing PNG magic\n", stderr);
 56+	}
 57+	write_chunk(f, ihdr, chunk, sizeof(chunk));
 58+}
 59+
 60+void save_png24(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch)
 61+{
 62+	uint32_t idat_size = (1 + width*3) * height;
 63+	uint8_t *idat_buffer = malloc(idat_size);
 64+	uint32_t *pixel = buffer;
 65+	uint8_t *cur = idat_buffer;
 66+	for (uint32_t y = 0; y < height; y++)
 67+	{
 68+		//save filter type
 69+		*(cur++) = 0;
 70+		uint32_t *start = pixel;
 71+		for (uint32_t x = 0; x < width; x++, pixel++)
 72+		{
 73+			uint32_t value = *pixel;
 74+			*(cur++) = value >> 16;
 75+			*(cur++) = value >> 8;
 76+			*(cur++) = value;
 77+		}
 78+		pixel = start + pitch / sizeof(uint32_t);
 79+	}
 80+	write_header(f, width, height, COLOR_TRUE);
 81+	uLongf compress_buffer_size = idat_size + 5 * (idat_size/16383 + 1) + 3;
 82+	uint8_t *compressed = malloc(compress_buffer_size);
 83+	compress(compressed, &compress_buffer_size, idat_buffer, idat_size);
 84+	free(idat_buffer);
 85+	write_chunk(f, idat, compressed, compress_buffer_size);
 86+	write_chunk(f, iend, NULL, 0);
 87+	free(compressed);
 88+}
 89+
 90+void save_png(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch)
 91+{
 92+	uint32_t palette[256];
 93+	uint8_t pal_buffer[256*3];
 94+	uint32_t num_pal = 0;
 95+	uint32_t index_size = (1 + width) * height;
 96+	uint8_t *index_buffer = malloc(index_size);
 97+	uint8_t *cur = index_buffer;
 98+	uint32_t *pixel = buffer;
 99+	for (uint32_t y = 0; y < height; y++)
100+	{
101+		//save filter type
102+		*(cur++) = 0;
103+		uint32_t *start = pixel;
104+		for (uint32_t x = 0; x < width; x++, pixel++, cur++)
105+		{
106+			uint32_t value = (*pixel) & 0xFFFFFF;
107+			uint32_t i;
108+			for (i = 0; i < num_pal; i++)
109+			{
110+				if (palette[i] == value) {
111+					break;
112+				}
113+			}
114+			if (i == num_pal) {
115+				if (num_pal == 256) {
116+					free(index_buffer);
117+					save_png24(f, buffer, width, height, pitch);
118+					return;
119+				}
120+				palette[i] = value;
121+				num_pal++;
122+			}
123+			*cur = i;
124+		}
125+		pixel = start + pitch / sizeof(uint32_t);
126+	}
127+	write_header(f, width, height, COLOR_INDEXED);
128+	cur = pal_buffer;
129+	for (uint32_t i = 0; i < num_pal; i++)
130+	{
131+		*(cur++) = palette[i] >> 16;
132+		*(cur++) = palette[i] >> 8;
133+		*(cur++) = palette[i];
134+	}
135+	write_chunk(f, plte, pal_buffer, num_pal * 3);
136+	uLongf compress_buffer_size = index_size + 5 * (index_size/16383 + 1) + 3;
137+	uint8_t *compressed = malloc(compress_buffer_size);
138+	compress(compressed, &compress_buffer_size, index_buffer, index_size);
139+	free(index_buffer);
140+	write_chunk(f, idat, compressed, compress_buffer_size);
141+	write_chunk(f, iend, NULL, 0);
142+	free(compressed);
143+}
144+
145+typedef uint8_t (*filter_fun)(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x);
146+typedef uint32_t (*pixel_fun)(uint8_t **cur, uint8_t **last, uint8_t bpp, uint32_t x, filter_fun);
147+
148+static uint8_t filter_none(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x)
149+{
150+	return *cur;
151+}
152+
153+static uint8_t filter_sub(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x)
154+{
155+	if (x) {
156+		return *cur + *(cur - bpp);
157+	} else {
158+		return *cur;
159+	}
160+}
161+
162+static uint8_t filter_up(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x)
163+{
164+	if (last) {
165+		return *cur + *last;
166+	} else {
167+		return *cur;
168+	}
169+}
170+
171+static uint8_t filter_avg(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x)
172+{
173+	uint8_t prev = x ? *(cur - bpp) : 0;
174+	uint8_t prior = last ? *last : 0;
175+	return *cur + ((prev + prior) >> 1);
176+}
177+
178+static uint8_t paeth(uint8_t a, uint8_t b, uint8_t c)
179+{
180+	int32_t p = a + b - c;
181+	int32_t pa = abs(p - a);
182+	int32_t pb = abs(p - b);
183+	int32_t pc = abs(p - c);
184+	if (pa <= pb && pa <= pc) {
185+		return a;
186+	}
187+	if (pb <= pc) {
188+		return b;
189+	}
190+	return c;
191+}
192+
193+static uint8_t filter_paeth(uint8_t *cur, uint8_t *last, uint8_t bpp, uint32_t x)
194+{
195+	uint8_t prev, prev_prior;
196+	if (x) {
197+		prev = *(cur - bpp);
198+		prev_prior = *(last - bpp);
199+	} else {
200+		prev = prev_prior = 0;
201+	}
202+	uint8_t prior = last ? *last : 0;
203+	return *cur + paeth(prev, prior, prev_prior);
204+}
205+
206+static uint32_t pixel_gray(uint8_t **cur, uint8_t **last, uint8_t bpp, uint32_t x, filter_fun filter)
207+{
208+	uint8_t value = filter(*cur, *last, bpp, x);
209+	(*cur)++;
210+	if (*last) {
211+		(*last)++;
212+	}
213+	return 0xFF000000 | value << 16 | value << 8 | value;
214+}
215+
216+static uint32_t pixel_true(uint8_t **cur, uint8_t **last, uint8_t bpp, uint32_t x, filter_fun filter)
217+{
218+	uint8_t red = filter(*cur, *last, bpp, x);
219+	(*cur)++;
220+	if (*last) {
221+		(*last)++;
222+	}
223+	uint8_t green = filter(*cur, *last, bpp, x);
224+	(*cur)++;
225+	if (*last) {
226+		(*last)++;
227+	}
228+	uint8_t blue = filter(*cur, *last, bpp, x);
229+	(*cur)++;
230+	if (*last) {
231+		(*last)++;
232+	}
233+	return 0xFF000000 | red << 16 | green << 8 | blue;
234+}
235+
236+static uint32_t pixel_gray_alpha(uint8_t **cur, uint8_t **last, uint8_t bpp, uint32_t x, filter_fun filter)
237+{
238+	uint8_t value = filter(*cur, *last, bpp, x);
239+	(*cur)++;
240+	if (*last) {
241+		(*last)++;
242+	}
243+	uint8_t alpha = filter(*cur, *last, bpp, x);
244+	(*cur)++;
245+	if (*last) {
246+		(*last)++;
247+	}
248+	return alpha << 24 | value << 16 | value << 8 | value;
249+}
250+
251+static uint32_t pixel_true_alpha(uint8_t **cur, uint8_t **last, uint8_t bpp, uint32_t x, filter_fun filter)
252+{
253+	uint8_t red = filter(*cur, *last, bpp, x);
254+	(*cur)++;
255+	if (*last) {
256+		(*last)++;
257+	}
258+	uint8_t green = filter(*cur, *last, bpp, x);
259+	(*cur)++;
260+	if (*last) {
261+		(*last)++;
262+	}
263+	uint8_t blue = filter(*cur, *last, bpp, x);
264+	(*cur)++;
265+	if (*last) {
266+		(*last)++;
267+	}
268+	uint8_t alpha = filter(*cur, *last, bpp, x);
269+	(*cur)++;
270+	if (*last) {
271+		(*last)++;
272+	}
273+	return alpha << 24 | red << 16 | green << 8 | blue;
274+}
275+
276+static filter_fun filters[] = {filter_none, filter_sub, filter_up, filter_avg, filter_paeth};
277+
278+#define MIN_CHUNK_SIZE 12
279+#define MIN_IHDR_SIZE 0xD
280+#define MAX_SUPPORTED_DIM 32767 //chosen to avoid possibility of overflow when calculating uncompressed size
281+uint32_t *load_png(uint8_t *buffer, uint32_t buf_size, uint32_t *width, uint32_t *height)
282+{
283+	if (buf_size < sizeof(png_magic) || memcmp(buffer, png_magic, sizeof(png_magic))) {
284+		return NULL;
285+	}
286+	uint32_t cur = sizeof(png_magic);
287+	uint8_t has_header = 0;
288+	uint8_t bits, color_type, comp_type, filter_type, interlace;
289+	uint8_t *idat_buf = NULL;
290+	uint8_t idat_needs_free = 0;
291+	uint32_t idat_size;
292+	uint32_t *out = NULL;
293+	uint32_t *palette = NULL;
294+	while(cur + MIN_CHUNK_SIZE <= buf_size)
295+	{
296+		uint32_t chunk_size = buffer[cur++] << 24;
297+		chunk_size |=  buffer[cur++] << 16;
298+		chunk_size |=  buffer[cur++] << 8;
299+		chunk_size |=  buffer[cur++];
300+		if (!memcmp(ihdr, buffer + cur, sizeof(ihdr))) {
301+			if (chunk_size < MIN_IHDR_SIZE || cur + MIN_IHDR_SIZE > buf_size) {
302+				return NULL;
303+			}
304+			cur += sizeof(ihdr);
305+			*width = buffer[cur++] << 24;
306+			*width |=  buffer[cur++] << 16;
307+			*width |=  buffer[cur++] << 8;
308+			*width |=  buffer[cur++];
309+			*height = buffer[cur++] << 24;
310+			*height |=  buffer[cur++] << 16;
311+			*height |=  buffer[cur++] << 8;
312+			*height |=  buffer[cur++];
313+			if (*width > MAX_SUPPORTED_DIM || *height > MAX_SUPPORTED_DIM) {
314+				return NULL;
315+			}
316+			bits = buffer[cur++];
317+			if (bits != 8) {
318+				//only support 8-bits per element for now
319+				return NULL;
320+			}
321+			color_type = buffer[cur++];
322+			if (color_type > COLOR_TRUE_ALPHA || color_type == 1 || color_type == 5) {
323+				//reject invalid color type
324+				return NULL;
325+			}
326+			comp_type = buffer[cur++];
327+			if (comp_type) {
328+				//only compression type 0 is defined by the spec
329+				return NULL;
330+			}
331+			filter_type = buffer[cur++];
332+			interlace = buffer[cur++];
333+			if (interlace) {
334+				//interlacing not supported for now
335+				return NULL;
336+			}
337+			cur += chunk_size - MIN_IHDR_SIZE;
338+			has_header = 1;
339+		} else {
340+			if (!has_header) {
341+				//IHDR is required to be the first chunk, fail if it isn't
342+				break;
343+			}
344+			if (!memcmp(plte, buffer + cur, sizeof(plte))) {
345+				//TODO: implement paletted images
346+			} else if (!memcmp(idat, buffer + cur, sizeof(idat))) {
347+				cur += sizeof(idat);
348+				if (idat_buf) {
349+					if (idat_needs_free) {
350+						idat_buf = realloc(idat_buf, idat_size + chunk_size);
351+					} else {
352+						uint8_t *tmp = idat_buf;
353+						idat_buf = malloc(idat_size + chunk_size);
354+						memcpy(idat_buf, tmp, idat_size);
355+					}
356+					memcpy(idat_buf + idat_size, buffer + cur, chunk_size);
357+					idat_size += chunk_size;
358+				} else {
359+					idat_buf = buffer + cur;
360+					idat_size = chunk_size;
361+				}
362+				cur += chunk_size;
363+			} else if (!memcmp(iend, buffer + cur, sizeof(iend))) {
364+				if (!idat_buf) {
365+					break;
366+				}
367+				if (!palette && color_type == COLOR_INDEXED) {
368+					//indexed color, but no PLTE chunk found
369+					return NULL;
370+				}
371+				uLongf uncompressed_size = *width * *height;
372+				uint8_t bpp;
373+				pixel_fun pixel;
374+				switch (color_type)
375+				{
376+				case COLOR_GRAY:
377+					uncompressed_size *= bits / 8;
378+					bpp = bits/8;
379+					pixel = pixel_gray;
380+					break;
381+				case COLOR_TRUE:
382+					uncompressed_size *= 3 * bits / 8;
383+					bpp = 3 * bits/8;
384+					pixel = pixel_true;
385+					break;
386+				case COLOR_INDEXED: {
387+					uint32_t pixels_per_byte = 8 / bits;
388+					uncompressed_size = (*width / pixels_per_byte) * *height;
389+					if (*width % pixels_per_byte) {
390+						uncompressed_size += *height;
391+					}
392+					bpp = 1;
393+					break;
394+				}
395+				case COLOR_GRAY_ALPHA:
396+					uncompressed_size *= bits / 4;
397+					bpp = bits / 4;
398+					pixel = pixel_gray_alpha;
399+					break;
400+				case COLOR_TRUE_ALPHA:
401+					uncompressed_size *= bits / 2;
402+					bpp = bits / 2;
403+					pixel = pixel_true_alpha;
404+					break;
405+				}
406+				//add filter type byte
407+				uncompressed_size += *height;
408+				uint8_t *decomp_buffer = malloc(uncompressed_size);
409+				if (Z_OK != uncompress(decomp_buffer, &uncompressed_size, idat_buf, idat_size)) {
410+					free(decomp_buffer);
411+					break;
412+				}
413+				out = calloc(*width * *height, sizeof(uint32_t));
414+				uint32_t *cur_pixel = out;
415+				uint8_t *cur_byte = decomp_buffer;
416+				uint8_t *last_line = NULL;
417+				for (uint32_t y = 0; y < *height; y++)
418+				{
419+					uint8_t filter_type = *(cur_byte++);
420+					if (filter_type >= sizeof(filters)/sizeof(*filters)) {
421+						free(out);
422+						out = NULL;
423+						free(decomp_buffer);
424+						break;
425+					}
426+					filter_fun filter = filters[filter_type];
427+					uint8_t *line_start = cur_byte;
428+					for (uint32_t x = 0; x < *width; x++)
429+					{
430+						*(cur_pixel++) = pixel(&cur_byte, &last_line, bpp, x, filter);
431+					}
432+					last_line = line_start;
433+				}
434+				free(decomp_buffer);
435+			} else {
436+				//skip uncrecognized chunks
437+				cur += 4 + chunk_size;
438+			}
439+		}
440+		//skip CRC for now
441+		cur += sizeof(uint32_t);
442+	}
443+	if (idat_needs_free) {
444+		free(idat_buf);
445+	}
446+	free(palette);
447+	return out;
448+}
A png.h
+8, -0
1@@ -0,0 +1,8 @@
2+#ifndef PNG_H_
3+#define PNG_H_
4+
5+void save_png24(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch);
6+void save_png(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch);
7+uint32_t *load_png(uint8_t *buffer, uint32_t buf_size, uint32_t *width, uint32_t *height);
8+
9+#endif //PNG_H_
A ppm.c
+21, -0
 1@@ -0,0 +1,21 @@
 2+#include <stdint.h>
 3+#include <stdio.h>
 4+
 5+void save_ppm(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch)
 6+{
 7+	fprintf(f, "P6\n%d %d\n255\n", width, height);
 8+	for(uint32_t y = 0; y < height; y++)
 9+	{
10+		uint32_t *line = buffer;
11+		for (uint32_t x = 0; x < width; x++, line++)
12+		{
13+			uint8_t buf[3] = {
14+				*line >> 16, //red
15+				*line >> 8,  //green
16+				*line        //blue
17+			};
18+			fwrite(buf, 1, sizeof(buf), f);
19+		}
20+		buffer = buffer + pitch / sizeof(uint32_t);
21+	}
22+}
A ppm.h
+6, -0
1@@ -0,0 +1,6 @@
2+#ifndef PPM_H_
3+#define PPM_H_
4+
5+void save_ppm(FILE *f, uint32_t *buffer, uint32_t width, uint32_t height, uint32_t pitch);
6+
7+#endif //PPM_H_
A psg.c
+157, -0
  1@@ -0,0 +1,157 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "psg.h"
  8+#include "render.h"
  9+#include "blastem.h"
 10+#include <string.h>
 11+#include <stdlib.h>
 12+#include <stdio.h>
 13+#include <math.h>
 14+void psg_init(psg_context * context, uint32_t master_clock, uint32_t clock_div)
 15+{
 16+	memset(context, 0, sizeof(*context));
 17+	context->audio = render_audio_source(master_clock, clock_div, 1);
 18+	context->clock_inc = clock_div;
 19+	for (int i = 0; i < 4; i++) {
 20+		context->volume[i] = 0xF;
 21+	}
 22+}
 23+
 24+void psg_free(psg_context *context)
 25+{
 26+	render_free_source(context->audio);
 27+	free(context);
 28+}
 29+
 30+void psg_adjust_master_clock(psg_context * context, uint32_t master_clock)
 31+{
 32+	render_audio_adjust_clock(context->audio, master_clock, context->clock_inc);
 33+}
 34+
 35+void psg_write(psg_context * context, uint8_t value)
 36+{
 37+	if (value & 0x80) {
 38+		context->latch = value & 0x70;
 39+		uint8_t channel = value >> 5 & 0x3;
 40+		if (value & 0x10) {
 41+			context->volume[channel] = value & 0xF;
 42+		} else {
 43+			if (channel == 3) {
 44+				switch(value & 0x3)
 45+				{
 46+				case 0:
 47+				case 1:
 48+				case 2:
 49+					context->counter_load[3] = 0x10 << (value & 0x3);
 50+					context->noise_use_tone = 0;
 51+					break;
 52+				default:
 53+					context->counter_load[3] = context->counter_load[2];
 54+					context->noise_use_tone = 1;
 55+				}
 56+				context->noise_type = value & 0x4;
 57+				context->lsfr = 0x8000;
 58+			} else {
 59+				context->counter_load[channel] = (context->counter_load[channel] & 0x3F0) | (value & 0xF);
 60+				if (channel == 2 && context->noise_use_tone) {
 61+					context->counter_load[3] = context->counter_load[2];
 62+				}
 63+			}
 64+		}
 65+	} else {
 66+		if (!(context->latch & 0x10)) {
 67+			uint8_t channel = context->latch >> 5 & 0x3;
 68+			if (channel != 3) {
 69+				context->counter_load[channel] = (value << 4 & 0x3F0) | (context->counter_load[channel] & 0xF);
 70+				if (channel == 2 && context->noise_use_tone) {
 71+					context->counter_load[3] = context->counter_load[2];
 72+				}
 73+			}
 74+		}
 75+	}
 76+}
 77+
 78+#define PSG_VOL_DIV 14
 79+
 80+//table shamelessly swiped from PSG doc from smspower.org
 81+static int16_t volume_table[16] = {
 82+	32767/PSG_VOL_DIV, 26028/PSG_VOL_DIV, 20675/PSG_VOL_DIV, 16422/PSG_VOL_DIV, 13045/PSG_VOL_DIV, 10362/PSG_VOL_DIV,
 83+	8231/PSG_VOL_DIV, 6568/PSG_VOL_DIV, 5193/PSG_VOL_DIV, 4125/PSG_VOL_DIV, 3277/PSG_VOL_DIV, 2603/PSG_VOL_DIV,
 84+	2067/PSG_VOL_DIV, 1642/PSG_VOL_DIV, 1304/PSG_VOL_DIV, 0
 85+};
 86+
 87+void psg_run(psg_context * context, uint32_t cycles)
 88+{
 89+	while (context->cycles < cycles) {
 90+		for (int i = 0; i < 4; i++) {
 91+			if (context->counters[i]) {
 92+				context->counters[i] -= 1;
 93+			}
 94+			if (!context->counters[i]) {
 95+				context->counters[i] = context->counter_load[i];
 96+				context->output_state[i] = !context->output_state[i];
 97+				if (i == 3 && context->output_state[i]) {
 98+					context->noise_out = context->lsfr & 1;
 99+					context->lsfr = (context->lsfr >> 1) | (context->lsfr << 15);
100+					if (context->noise_type) {
101+						//white noise
102+						if (context->lsfr & 0x40) {
103+							context->lsfr ^= 0x8000;
104+						}
105+					}
106+				}
107+			}
108+		}
109+
110+		int16_t accum = 0;
111+		
112+		for (int i = 0; i < 3; i++) {
113+			if (context->output_state[i]) {
114+				accum += volume_table[context->volume[i]];
115+			}
116+		}
117+		if (context->noise_out) {
118+			accum += volume_table[context->volume[3]];
119+		}
120+		
121+		render_put_mono_sample(context->audio, accum);
122+
123+		context->cycles += context->clock_inc;
124+	}
125+}
126+
127+void psg_serialize(psg_context *context, serialize_buffer *buf)
128+{
129+	save_int16(buf, context->lsfr);
130+	save_buffer16(buf, context->counter_load, 4);
131+	save_buffer16(buf, context->counters, 4);
132+	save_buffer8(buf, context->volume, 4);
133+	uint8_t output_state = context->output_state[0] << 3 | context->output_state[1] << 2
134+		| context->output_state[2] << 1 | context->output_state[3]
135+		| context->noise_use_tone << 4;
136+	save_int8(buf, output_state);
137+	save_int8(buf, context->noise_type);
138+	save_int8(buf, context->latch);
139+	save_int32(buf, context->cycles);
140+}
141+
142+void psg_deserialize(deserialize_buffer *buf, void *vcontext)
143+{
144+	psg_context *context = vcontext;
145+	context->lsfr = load_int16(buf);
146+	load_buffer16(buf, context->counter_load, 4);
147+	load_buffer16(buf, context->counters, 4);
148+	load_buffer8(buf, context->volume, 4);
149+	uint8_t output_state = load_int8(buf);
150+	context->output_state[0] = output_state >> 3 & 1;
151+	context->output_state[1] = output_state >> 2 & 1;
152+	context->output_state[2] = output_state >> 1 & 1;
153+	context->output_state[3] = output_state & 1;
154+	context->noise_use_tone = output_state >> 4 & 1;
155+	context->noise_type = load_int8(buf);
156+	context->latch = load_int8(buf);
157+	context->cycles = load_int32(buf);
158+}
A psg.h
+38, -0
 1@@ -0,0 +1,38 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef PSG_CONTEXT_H_
 8+#define PSG_CONTEXT_H_
 9+
10+#include <stdint.h>
11+#include "serialize.h"
12+#include "render.h"
13+
14+typedef struct {
15+	audio_source *audio;
16+	uint32_t clock_inc;
17+	uint32_t cycles;
18+	uint16_t lsfr;
19+	uint16_t counter_load[4];
20+	uint16_t counters[4];
21+	uint8_t  volume[4];
22+	uint8_t  output_state[4];
23+	uint8_t  noise_out;
24+	uint8_t  noise_use_tone;
25+	uint8_t  noise_type;
26+	uint8_t  latch;
27+} psg_context;
28+
29+
30+void psg_init(psg_context * context, uint32_t master_clock, uint32_t clock_div);
31+void psg_free(psg_context *context);
32+void psg_adjust_master_clock(psg_context * context, uint32_t master_clock);
33+void psg_write(psg_context * context, uint8_t value);
34+void psg_run(psg_context * context, uint32_t cycles);
35+void psg_serialize(psg_context *context, serialize_buffer *buf);
36+void psg_deserialize(deserialize_buffer *buf, void *vcontext);
37+
38+#endif //PSG_CONTEXT_H_
39+
+151, -0
  1@@ -0,0 +1,151 @@
  2+#include <stdint.h>
  3+#include <stdlib.h>
  4+#include <string.h>
  5+#include "romdb.h"
  6+#include "genesis.h"
  7+#include "util.h"
  8+
  9+typedef struct {
 10+	uint8_t rom_space[512*1024];
 11+	uint8_t regs[3];
 12+} realtec;
 13+
 14+
 15+uint8_t realtec_detect(uint8_t *rom, uint32_t rom_size)
 16+{
 17+	//All Realtec mapper games are 512KB total
 18+	if (rom_size != 512*1024) {
 19+		return 0;
 20+	}
 21+	return memcmp(rom + 0x7E100, "SEGA", 4) == 0;
 22+}
 23+
 24+static realtec *get_realtec(genesis_context *gen)
 25+{
 26+	if (!gen->extra) {
 27+		gen->extra = gen->m68k->mem_pointers[0];
 28+	}
 29+	return gen->extra;
 30+}
 31+
 32+static void *realtec_write_b(uint32_t address, void *context, uint8_t value)
 33+{
 34+	if (address & 1) {
 35+		return context;
 36+	}
 37+	m68k_context *m68k = context;
 38+	genesis_context *gen = m68k->system;
 39+	realtec *r = get_realtec(gen);
 40+	uint32_t offset = address >> 13;
 41+	if (offset < 3 && r->regs[offset] != value) {
 42+		r->regs[offset] = value;
 43+		//other regs are only 3 bits, so assume 3 for this one too
 44+		uint32_t size = (r->regs[1] & 0x7) << 17;
 45+		uint32_t start = (r->regs[2] & 7) << 17 | (r->regs[0] & 6) << 19;
 46+		if (!size || size > 512*1024) {
 47+			size = 512*1024;
 48+		}
 49+		for(uint32_t cur = 0; cur < 512*1024; cur += size)
 50+		{
 51+			if (start + size > 512*1024) {
 52+				memcpy(r->rom_space + cur, gen->cart + start/2, 512*1024-start);
 53+				//assume it wraps
 54+				memcpy(r->rom_space + cur + 512*1024-start, gen->cart, size - (512*1024-start));
 55+			} else {
 56+				memcpy(r->rom_space + cur, gen->cart + start/2, size);
 57+			}
 58+		}
 59+		m68k_invalidate_code_range(gen->m68k, 0, 0x400000);
 60+	}
 61+	return context;
 62+}
 63+
 64+static void *realtec_write_w(uint32_t address, void *context, uint16_t value)
 65+{
 66+	return realtec_write_b(address, context, value >> 8);
 67+}
 68+
 69+void realtec_serialize(genesis_context *gen, serialize_buffer *buf)
 70+{
 71+	realtec *r = get_realtec(gen);
 72+	save_buffer8(buf, r->regs, sizeof(r->regs));
 73+}
 74+
 75+void realtec_deserialize(deserialize_buffer *buf, genesis_context *gen)
 76+{
 77+	realtec *r = get_realtec(gen);
 78+	for (int i = 0; i < sizeof(r->regs); i++)
 79+	{
 80+		realtec_write_b(i << 13, gen->m68k, load_int8(buf));
 81+	}
 82+}
 83+
 84+rom_info realtec_configure_rom(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
 85+{
 86+	rom_info info;
 87+	realtec *r = calloc(sizeof(realtec), 1);
 88+	for (uint32_t i = 0; i < 512*1024; i += 8*1024)
 89+	{
 90+		memcpy(r->rom_space + i, rom + 0x7E000, 8*1024);
 91+	}
 92+	byteswap_rom(512*1024, (uint16_t *)r->rom_space);
 93+	
 94+	uint8_t *name_start = NULL, *name_end = NULL;
 95+	for (int i = 0x94; i < 0xE0; i++)
 96+	{
 97+		if (name_start) {
 98+			if (rom[i] < ' ' || rom[i] > 0x80 || !memcmp(rom+i, "ARE", 3) || !memcmp(rom+i, "are", 3)) {
 99+				name_end = rom+i;
100+				break;
101+			}
102+		} else if (rom[i] > ' ' && rom[i] < 0x80 && rom[i] != ':') {
103+			name_start = rom + i;
104+		}
105+	}
106+	if (name_start && !name_end) {
107+		name_end = rom + 0xE0;
108+	}
109+	if (name_end) {
110+		while (name_end > name_start && name_end[-1] == ' ')
111+		{
112+			name_end--;
113+		}
114+		info.name = malloc(name_end-name_start+1);
115+		memcpy(info.name, name_start, name_end-name_start);
116+		info.name[name_end-name_start] = 0;
117+	} else {
118+		info.name = strdup("Realtec Game");
119+	}
120+	info.save_type = SAVE_NONE;
121+	info.save_size = 0;
122+	info.save_buffer = NULL;
123+	info.num_eeprom = 0;
124+	info.eeprom_map = NULL;
125+	info.rom = rom;
126+	info.rom_size = rom_size;
127+	info.mapper_type = MAPPER_REALTEC;
128+	info.is_save_lock_on = 0;
129+	info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
130+	info.map_chunks = base_chunks + 2;
131+	info.map = calloc(sizeof(memmap_chunk), info.map_chunks);
132+	info.map[0].mask = sizeof(r->rom_space)-1;
133+	info.map[0].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX;
134+	info.map[0].start = 0;
135+	info.map[0].end = 0x400000;
136+	info.map[0].buffer = r->rom_space;
137+	info.map[0].write_16 = NULL;
138+	info.map[0].read_16 = NULL;
139+	info.map[0].write_8 = NULL;
140+	info.map[0].read_8 = NULL;
141+	info.map[1].mask = 0x7FFF;
142+	info.map[1].flags = 0;
143+	info.map[1].start = 0x400000;
144+	info.map[1].end = 0x800000;
145+	info.map[1].write_16 = realtec_write_w;
146+	info.map[1].write_8 = realtec_write_b;
147+	info.map[1].read_16 = NULL;
148+	info.map[1].read_8 = NULL;
149+	memcpy(info.map + 2, base_map, base_chunks * sizeof(memmap_chunk));
150+	
151+	return info;
152+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+#ifndef REALTEC_H_
 3+#define REALTEC_H_
 4+#include "serialize.h"
 5+
 6+uint8_t realtec_detect(uint8_t *rom, uint32_t rom_size);
 7+rom_info realtec_configure_rom(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks);
 8+void realtec_serialize(genesis_context *gen, serialize_buffer *buf);
 9+void realtec_deserialize(deserialize_buffer *buf, genesis_context *gen);
10+
11+#endif //REALTEC_H_
+80, -0
 1@@ -0,0 +1,80 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef RENDER_H_
 8+#define RENDER_H_
 9+
10+#include "special_keys_evdev.h"
11+#define render_relative_mouse(V)
12+
13+#define MAX_JOYSTICKS 8
14+#define MAX_MICE 8
15+#define MAX_MOUSE_BUTTONS 8
16+
17+#define VIDEO_BUFFER_ODD 0
18+#define VIDEO_BUFFER_EVEN 1
19+#define VIDEO_BUFFER_USER_START 2
20+
21+#include "vdp.h"
22+
23+typedef enum {
24+	VID_NTSC,
25+	VID_PAL,
26+	NUM_VID_STD
27+} vid_std;
28+
29+#define RENDER_DPAD_BIT 0x40000000
30+#define RENDER_AXIS_BIT 0x20000000
31+#define RENDER_AXIS_POS 0x10000000
32+#define RENDER_INVALID_NAME -1
33+#define RENDER_NOT_MAPPED -2
34+#define RENDER_NOT_PLUGGED_IN -3
35+
36+typedef struct audio_source audio_source;
37+typedef void (*window_close_handler)(uint8_t which);
38+
39+uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b);
40+void render_save_screenshot(char *path);
41+uint8_t render_create_window(char *caption, uint32_t width, uint32_t height, window_close_handler close_handler);
42+void render_destroy_window(uint8_t which);
43+uint32_t *render_get_video_buffer(uint8_t which, int *pitch);
44+void render_video_buffer_updated(uint8_t which, int width);
45+//returns the video buffer index associated with the window that has focus
46+uint8_t render_get_active_video_buffer(void);
47+void render_init(int width, int height, char * title);
48+void render_set_video_standard(vid_std std);
49+void render_update_caption(char *title);
50+void render_wait_quit(vdp_context * context);
51+uint32_t render_audio_buffer();
52+uint32_t render_sample_rate();
53+void process_events();
54+int render_width();
55+int render_height();
56+void process_events();
57+int32_t render_translate_input_name(int32_t controller, char *name, uint8_t is_axis);
58+int32_t render_dpad_part(int32_t input);
59+int32_t render_axis_part(int32_t input);
60+uint8_t render_direction_part(int32_t input);
61+char* render_joystick_type_id(int index);
62+void render_errorbox(char *title, char *message);
63+void render_warnbox(char *title, char *message);
64+void render_infobox(char *title, char *message);
65+uint32_t render_emulated_width();
66+uint32_t render_emulated_height();
67+uint32_t render_overscan_top();
68+uint32_t render_overscan_left();
69+uint32_t render_elapsed_ms(void);
70+void render_sleep_ms(uint32_t delay);
71+audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels);
72+void render_audio_source_gaindb(audio_source *src, float gain);
73+void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider);
74+void render_put_mono_sample(audio_source *src, int16_t value);
75+void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right);
76+void render_pause_source(audio_source *src);
77+void render_resume_source(audio_source *src);
78+void render_free_source(audio_source *src);
79+void render_config_updated(void);
80+
81+#endif //RENDER_H_
+1800, -0
   1@@ -0,0 +1,1800 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include <stdlib.h>
   8+#include <stdio.h>
   9+#include <string.h>
  10+#include <stdint.h>
  11+#include <errno.h>
  12+#include <math.h>
  13+#include <linux/input.h>
  14+#include <linux/kd.h>
  15+#include <alsa/asoundlib.h>
  16+#include <sys/types.h>
  17+#include <sys/stat.h>
  18+#include <sys/ioctl.h>
  19+#include <sys/mman.h>
  20+#include <poll.h>
  21+#include <fcntl.h>
  22+#include <unistd.h>
  23+#include <pthread.h>
  24+#include <dirent.h>
  25+#include <wayland-client.h>
  26+#include "xdg-shell-client-protocol.h"
  27+#include <sys/syscall.h>
  28+#include <time.h>
  29+#include "render.h"
  30+#include "blastem.h"
  31+#include "genesis.h"
  32+#include "bindings.h"
  33+#include "util.h"
  34+#include "paths.h"
  35+#include "ppm.h"
  36+#include "png.h"
  37+#include "config.h"
  38+#include "controller_info.h"
  39+
  40+#define MAX_EVENT_POLL_PER_FRAME 2
  41+
  42+static int main_width, main_height;
  43+static snd_pcm_uframes_t buffer_samples;
  44+static unsigned int output_channels, sample_rate;
  45+
  46+
  47+struct audio_source {
  48+	int16_t  *front;
  49+	int16_t  *back;
  50+	double   dt;
  51+	uint64_t buffer_fraction;
  52+	uint64_t buffer_inc;
  53+	uint32_t buffer_pos;
  54+	uint32_t read_start;
  55+	uint32_t read_end;
  56+	uint32_t lowpass_alpha;
  57+	uint32_t mask;
  58+	float    gain_mult;
  59+	int16_t  last_left;
  60+	int16_t  last_right;
  61+	uint8_t  num_channels;
  62+	uint8_t  front_populated;
  63+};
  64+
  65+static audio_source *audio_sources[8];
  66+static audio_source *inactive_audio_sources[8];
  67+static uint8_t num_audio_sources;
  68+static uint8_t num_inactive_audio_sources;
  69+
  70+typedef int32_t (*mix_func)(audio_source *audio, void *vstream, int len);
  71+
  72+static int32_t mix_s16(audio_source *audio, void *vstream, int len)
  73+{
  74+	int samples = len/(sizeof(int16_t)*output_channels);
  75+	int16_t *stream = vstream;
  76+	int16_t *end = stream + output_channels*samples;
  77+	int16_t *src = audio->front;
  78+	uint32_t i = audio->read_start;
  79+	uint32_t i_end = audio->read_end;
  80+	int16_t *cur = stream;
  81+	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
  82+	if (audio->num_channels == 1) {
  83+		while (cur < end && i != i_end)
  84+		{
  85+			*cur += src[i];
  86+			cur += first_add;
  87+			*cur += src[i++];
  88+			cur += second_add;
  89+			i &= audio->mask;
  90+		}
  91+	} else {
  92+		while (cur < end && i != i_end)
  93+		{
  94+			*cur += src[i++];
  95+			cur += first_add;
  96+			*cur += src[i++];
  97+			cur += second_add;
  98+			i &= audio->mask;
  99+		}
 100+	}
 101+	
 102+	if (cur != end) {
 103+		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 104+	}
 105+	if (cur != end) {
 106+		//printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 107+		return (cur-end)/2;
 108+	} else {
 109+		return ((i_end - i) & audio->mask) / audio->num_channels;
 110+	}
 111+}
 112+
 113+static int32_t mix_f32(audio_source *audio, void *vstream, int len)
 114+{
 115+	int samples = len/(sizeof(float)*output_channels);
 116+	float *stream = vstream;
 117+	float *end = stream + output_channels*samples;
 118+	int16_t *src = audio->front;
 119+	uint32_t i = audio->read_start;
 120+	uint32_t i_end = audio->read_end;
 121+	float *cur = stream;
 122+	size_t first_add = output_channels > 1 ? 1 : 0, second_add = output_channels > 1 ? output_channels - 1 : 1;
 123+	if (audio->num_channels == 1) {
 124+		while (cur < end && i != i_end)
 125+		{
 126+			*cur += ((float)src[i]) / 0x7FFF;
 127+			cur += first_add;
 128+			*cur += ((float)src[i++]) / 0x7FFF;
 129+			cur += second_add;
 130+			i &= audio->mask;
 131+		}
 132+	} else {
 133+		while(cur < end && i != i_end)
 134+		{
 135+			*cur += ((float)src[i++]) / 0x7FFF;
 136+			cur += first_add;
 137+			*cur += ((float)src[i++]) / 0x7FFF;
 138+			cur += second_add;
 139+			i &= audio->mask;
 140+		}
 141+	}
 142+	if (cur != end) {
 143+		printf("Underflow of %d samples, read_start: %d, read_end: %d, mask: %X\n", (int)(end-cur)/2, audio->read_start, audio->read_end, audio->mask);
 144+		return (cur-end)/2;
 145+	} else {
 146+		return ((i_end - i) & audio->mask) / audio->num_channels;
 147+	}
 148+}
 149+
 150+static mix_func mix;
 151+
 152+static snd_pcm_t *audio_handle;
 153+static void render_close_audio()
 154+{
 155+	if (audio_handle) {
 156+		snd_pcm_close(audio_handle);
 157+		audio_handle = NULL;
 158+	}
 159+}
 160+
 161+static void destroy_wayland(void);
 162+
 163+#define BUFFER_INC_RES 0x40000000UL
 164+
 165+void render_audio_adjust_clock(audio_source *src, uint64_t master_clock, uint64_t sample_divider)
 166+{
 167+	src->buffer_inc = ((BUFFER_INC_RES * (uint64_t)sample_rate) / master_clock) * sample_divider;
 168+}
 169+
 170+audio_source *render_audio_source(uint64_t master_clock, uint64_t sample_divider, uint8_t channels)
 171+{
 172+	audio_source *ret = NULL;
 173+	uint32_t alloc_size = channels * buffer_samples;
 174+	if (num_audio_sources < 8) {
 175+		ret = malloc(sizeof(audio_source));
 176+		ret->back = malloc(alloc_size * sizeof(int16_t));
 177+		ret->front = malloc(alloc_size * sizeof(int16_t));
 178+		ret->front_populated = 0;
 179+		ret->num_channels = channels;
 180+		audio_sources[num_audio_sources++] = ret;
 181+	}
 182+	if (!ret) {
 183+		fatal_error("Too many audio sources!");
 184+	} else {
 185+		render_audio_adjust_clock(ret, master_clock, sample_divider);
 186+		double lowpass_cutoff = get_lowpass_cutoff(config);
 187+		double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
 188+		ret->dt = 1.0 / ((double)master_clock / (double)(sample_divider));
 189+		double alpha = ret->dt / (ret->dt + rc);
 190+		ret->lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
 191+		ret->buffer_pos = 0;
 192+		ret->buffer_fraction = 0;
 193+		ret->gain_mult = 1.0f;
 194+		ret->last_left = ret->last_right = 0;
 195+		ret->read_start = 0;
 196+		ret->read_end = buffer_samples * channels;
 197+		ret->mask = 0xFFFFFFFF;
 198+	}
 199+	return ret;
 200+}
 201+
 202+static float db_to_mult(float gain)
 203+{
 204+	return powf(10.0f, gain / 20.0f);
 205+}
 206+
 207+void render_audio_source_gaindb(audio_source *src, float gain)
 208+{
 209+	src->gain_mult = db_to_mult(gain);
 210+}
 211+
 212+void render_pause_source(audio_source *src)
 213+{
 214+	for (uint8_t i = 0; i < num_audio_sources; i++)
 215+	{
 216+		if (audio_sources[i] == src) {
 217+			audio_sources[i] = audio_sources[--num_audio_sources];
 218+			break;
 219+		}
 220+	}
 221+	inactive_audio_sources[num_inactive_audio_sources++] = src;
 222+}
 223+
 224+void render_resume_source(audio_source *src)
 225+{
 226+	if (num_audio_sources < 8) {
 227+		audio_sources[num_audio_sources++] = src;
 228+	}
 229+	for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
 230+	{
 231+		if (inactive_audio_sources[i] == src) {
 232+			inactive_audio_sources[i] = inactive_audio_sources[--num_inactive_audio_sources];
 233+		}
 234+	}
 235+}
 236+
 237+void render_free_source(audio_source *src)
 238+{
 239+	render_pause_source(src);
 240+	
 241+	free(src->front);
 242+	free(src->back);
 243+	free(src);
 244+}
 245+static void do_audio_ready(audio_source *src)
 246+{
 247+	if (src->front_populated) {
 248+		fatal_error("Audio source filled up a buffer a second time before other sources finished their first\n");
 249+	}
 250+	int16_t *tmp = src->front;
 251+	src->front = src->back;
 252+	src->back = tmp;
 253+	src->front_populated = 1;
 254+	src->buffer_pos = 0;
 255+	
 256+	for (uint8_t i = 0; i < num_audio_sources; i++)
 257+	{
 258+		if (!audio_sources[i]->front_populated) {
 259+			//at least one audio source is not ready yet.
 260+			return;
 261+		}
 262+	}
 263+	
 264+	size_t bytes = (mix == mix_s16 ? sizeof(int16_t) : sizeof(float)) * output_channels * buffer_samples;
 265+	void *buffer = calloc(1, bytes);
 266+	for (uint8_t i = 0; i < num_audio_sources; i++)
 267+	{
 268+		mix(audio_sources[i], buffer, bytes);
 269+		audio_sources[i]->front_populated = 0;
 270+	}
 271+	int frames = snd_pcm_writei(audio_handle, buffer, buffer_samples);
 272+	if (frames < 0) {
 273+		frames = snd_pcm_recover(audio_handle, frames, 0);
 274+	}
 275+	if (frames < 0) {
 276+		fprintf(stderr, "Failed to write samples: %s\n", snd_strerror(frames));
 277+	}
 278+	free(buffer);
 279+}
 280+
 281+static int16_t lowpass_sample(audio_source *src, int16_t last, int16_t current)
 282+{
 283+	int32_t tmp = current * src->lowpass_alpha + last * (0x10000 - src->lowpass_alpha);
 284+	current = tmp >> 16;
 285+	return current;
 286+}
 287+
 288+static void interp_sample(audio_source *src, int16_t last, int16_t current)
 289+{
 290+	int64_t tmp = last * ((src->buffer_fraction << 16) / src->buffer_inc);
 291+	tmp += current * (0x10000 - ((src->buffer_fraction << 16) / src->buffer_inc));
 292+	src->back[src->buffer_pos++] = tmp >> 16;
 293+}
 294+
 295+void render_put_mono_sample(audio_source *src, int16_t value)
 296+{
 297+	value = lowpass_sample(src, src->last_left, value);
 298+	src->buffer_fraction += src->buffer_inc;
 299+	uint32_t base = 0;
 300+	while (src->buffer_fraction > BUFFER_INC_RES)
 301+	{
 302+		src->buffer_fraction -= BUFFER_INC_RES;
 303+		interp_sample(src, src->last_left, value);
 304+		
 305+		if (((src->buffer_pos - base) & src->mask) >= buffer_samples) {
 306+			do_audio_ready(src);
 307+		}
 308+		src->buffer_pos &= src->mask;
 309+	}
 310+	src->last_left = value;
 311+}
 312+
 313+void render_put_stereo_sample(audio_source *src, int16_t left, int16_t right)
 314+{
 315+	left = lowpass_sample(src, src->last_left, left);
 316+	right = lowpass_sample(src, src->last_right, right);
 317+	src->buffer_fraction += src->buffer_inc;
 318+	uint32_t base = 0;
 319+	while (src->buffer_fraction > BUFFER_INC_RES)
 320+	{
 321+		src->buffer_fraction -= BUFFER_INC_RES;
 322+		
 323+		interp_sample(src, src->last_left, left);
 324+		interp_sample(src, src->last_right, right);
 325+		
 326+		if (((src->buffer_pos - base) & src->mask)/2 >= buffer_samples) {
 327+			do_audio_ready(src);
 328+		}
 329+		src->buffer_pos &= src->mask;
 330+	}
 331+	src->last_left = left;
 332+	src->last_right = right;
 333+}
 334+
 335+int render_width()
 336+{
 337+	return main_width;
 338+}
 339+
 340+int render_height()
 341+{
 342+	return main_height;
 343+}
 344+
 345+uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
 346+{
 347+	return 0xFF000000 | r << 16 | g << 8 | b;
 348+}
 349+
 350+#define MAX_VIDEO_BUFFER_LINES 590
 351+static uint32_t video_buffer[MAX_VIDEO_BUFFER_LINES * LINEBUF_SIZE * 2];
 352+
 353+static char * caption = NULL;
 354+static char * fps_caption = NULL;
 355+
 356+static void render_quit()
 357+{
 358+	render_close_audio();
 359+	destroy_wayland();
 360+}
 361+
 362+static float config_aspect()
 363+{
 364+	static float aspect = 0.0f;
 365+	if (aspect == 0.0f) {
 366+		char *config_aspect = tern_find_path_default(config, "video\0aspect\0", (tern_val){.ptrval = "4:3"}, TVAL_PTR).ptrval;
 367+		if (strcmp("stretch", config_aspect)) {
 368+			aspect = 4.0f/3.0f;
 369+			char *end;
 370+			float aspect_numerator = strtof(config_aspect, &end);
 371+			if (aspect_numerator > 0.0f && *end == ':') {
 372+				float aspect_denominator = strtof(end+1, &end);
 373+				if (aspect_denominator > 0.0f && !*end) {
 374+					aspect = aspect_numerator / aspect_denominator;
 375+				}
 376+			}
 377+		} else {
 378+			aspect = -1.0f;
 379+		}
 380+	}
 381+	return aspect;
 382+}
 383+
 384+static uint8_t scancode_map[128] = {
 385+	[KEY_A] = 0x1C,
 386+	[KEY_B] = 0x32,
 387+	[KEY_C] = 0x21,
 388+	[KEY_D] = 0x23,
 389+	[KEY_E] = 0x24,
 390+	[KEY_F] = 0x2B,
 391+	[KEY_G] = 0x34,
 392+	[KEY_H] = 0x33,
 393+	[KEY_I] = 0x43,
 394+	[KEY_J] = 0x3B,
 395+	[KEY_K] = 0x42,
 396+	[KEY_L] = 0x4B,
 397+	[KEY_M] = 0x3A,
 398+	[KEY_N] = 0x31,
 399+	[KEY_O] = 0x44,
 400+	[KEY_P] = 0x4D,
 401+	[KEY_Q] = 0x15,
 402+	[KEY_R] = 0x2D,
 403+	[KEY_S] = 0x1B,
 404+	[KEY_T] = 0x2C,
 405+	[KEY_U] = 0x3C,
 406+	[KEY_V] = 0x2A,
 407+	[KEY_W] = 0x1D,
 408+	[KEY_X] = 0x22,
 409+	[KEY_Y] = 0x35,
 410+	[KEY_Z] = 0x1A,
 411+	[KEY_1] = 0x16,
 412+	[KEY_2] = 0x1E,
 413+	[KEY_3] = 0x26,
 414+	[KEY_4] = 0x25,
 415+	[KEY_5] = 0x2E,
 416+	[KEY_6] = 0x36,
 417+	[KEY_7] = 0x3D,
 418+	[KEY_8] = 0x3E,
 419+	[KEY_9] = 0x46,
 420+	[KEY_0] = 0x45,
 421+	[KEY_ENTER] = 0x5A,
 422+	[KEY_ESC] = 0x76,
 423+	[KEY_SPACE] = 0x29,
 424+	[KEY_TAB] = 0x0D,
 425+	[KEY_BACKSPACE] = 0x66,
 426+	[KEY_MINUS] = 0x4E,
 427+	[KEY_EQUAL] = 0x55,
 428+	[KEY_LEFTBRACE] = 0x54,
 429+	[KEY_RIGHTBRACE] = 0x5B,
 430+	[KEY_BACKSLASH] = 0x5D,
 431+	[KEY_SEMICOLON] = 0x4C,
 432+	[KEY_APOSTROPHE] = 0x52,
 433+	[KEY_GRAVE] = 0x0E,
 434+	[KEY_COMMA] = 0x41,
 435+	[KEY_DOT] = 0x49,
 436+	[KEY_SLASH] = 0x4A,
 437+	[KEY_CAPSLOCK] = 0x58,
 438+	[KEY_F1] = 0x05,
 439+	[KEY_F2] = 0x06,
 440+	[KEY_F3] = 0x04,
 441+	[KEY_F4] = 0x0C,
 442+	[KEY_F5] = 0x03,
 443+	[KEY_F6] = 0x0B,
 444+	[KEY_F7] = 0x83,
 445+	[KEY_F8] = 0x0A,
 446+	[KEY_F9] = 0x01,
 447+	[KEY_F10] = 0x09,
 448+	[KEY_F11] = 0x78,
 449+	[KEY_F12] = 0x07,
 450+	[KEY_LEFTCTRL] = 0x14,
 451+	[KEY_LEFTSHIFT] = 0x12,
 452+	[KEY_LEFTALT] = 0x11,
 453+	[KEY_RIGHTCTRL] = 0x18,
 454+	[KEY_RIGHTSHIFT] = 0x59,
 455+	[KEY_RIGHTALT] = 0x17,
 456+	[KEY_INSERT] = 0x81,
 457+	[KEY_PAUSE] = 0x82,
 458+	[KEY_SYSRQ] = 0x84,
 459+	[KEY_SCROLLLOCK] = 0x7E,
 460+	[KEY_DELETE] = 0x85,
 461+	[KEY_LEFT] = 0x86,
 462+	[KEY_HOME] = 0x87,
 463+	[KEY_END] = 0x88,
 464+	[KEY_UP] = 0x89,
 465+	[KEY_DOWN] = 0x8A,
 466+	[KEY_PAGEUP] = 0x8B,
 467+	[KEY_PAGEDOWN] = 0x8C,
 468+	[KEY_RIGHT] = 0x8D,
 469+	[KEY_NUMLOCK] = 0x77,
 470+	[KEY_KPSLASH] = 0x80,
 471+	[KEY_KPASTERISK] = 0x7C,
 472+	[KEY_KPMINUS] = 0x7B,
 473+	[KEY_KPPLUS] = 0x79,
 474+	[KEY_KPENTER] = 0x19,
 475+	[KEY_KP1] = 0x69,
 476+	[KEY_KP2] = 0x72,
 477+	[KEY_KP3] = 0x7A,
 478+	[KEY_KP4] = 0x6B,
 479+	[KEY_KP5] = 0x73,
 480+	[KEY_KP6] = 0x74,
 481+	[KEY_KP7] = 0x6C,
 482+	[KEY_KP8] = 0x75,
 483+	[KEY_KP9] = 0x7D,
 484+	[KEY_KP0] = 0x70,
 485+	[KEY_KPDOT] = 0x71,
 486+};
 487+
 488+#include "special_keys_evdev.h"
 489+static uint8_t sym_map[128] = {
 490+	[KEY_A] = 'a',
 491+	[KEY_B] = 'b',
 492+	[KEY_C] = 'c',
 493+	[KEY_D] = 'd',
 494+	[KEY_E] = 'e',
 495+	[KEY_F] = 'f',
 496+	[KEY_G] = 'g',
 497+	[KEY_H] = 'h',
 498+	[KEY_I] = 'i',
 499+	[KEY_J] = 'j',
 500+	[KEY_K] = 'k',
 501+	[KEY_L] = 'l',
 502+	[KEY_M] = 'm',
 503+	[KEY_N] = 'n',
 504+	[KEY_O] = 'o',
 505+	[KEY_P] = 'p',
 506+	[KEY_Q] = 'q',
 507+	[KEY_R] = 'r',
 508+	[KEY_S] = 's',
 509+	[KEY_T] = 't',
 510+	[KEY_U] = 'u',
 511+	[KEY_V] = 'v',
 512+	[KEY_W] = 'w',
 513+	[KEY_X] = 'x',
 514+	[KEY_Y] = 'y',
 515+	[KEY_Z] = 'z',
 516+	[KEY_1] = '1',
 517+	[KEY_2] = '2',
 518+	[KEY_3] = '3',
 519+	[KEY_4] = '4',
 520+	[KEY_5] = '5',
 521+	[KEY_6] = '6',
 522+	[KEY_7] = '7',
 523+	[KEY_8] = '8',
 524+	[KEY_9] = '9',
 525+	[KEY_0] = '0',
 526+	[KEY_ENTER] = '\r',
 527+	[KEY_SPACE] = ' ',
 528+	[KEY_TAB] = '\t',
 529+	[KEY_BACKSPACE] = '\b',
 530+	[KEY_MINUS] = '-',
 531+	[KEY_EQUAL] = '=',
 532+	[KEY_LEFTBRACE] = '[',
 533+	[KEY_RIGHTBRACE] = ']',
 534+	[KEY_BACKSLASH] = '\\',
 535+	[KEY_SEMICOLON] = ';',
 536+	[KEY_APOSTROPHE] = '\'',
 537+	[KEY_GRAVE] = '`',
 538+	[KEY_COMMA] = ',',
 539+	[KEY_DOT] = '.',
 540+	[KEY_SLASH] = '/',
 541+	[KEY_ESC] = RENDERKEY_ESC,
 542+	[KEY_F1] = RENDERKEY_F1,
 543+	[KEY_F2] = RENDERKEY_F2,
 544+	[KEY_F3] = RENDERKEY_F3,
 545+	[KEY_F4] = RENDERKEY_F4,
 546+	[KEY_F5] = RENDERKEY_F5,
 547+	[KEY_F6] = RENDERKEY_F6,
 548+	[KEY_F7] = RENDERKEY_F7,
 549+	[KEY_F8] = RENDERKEY_F8,
 550+	[KEY_F9] = RENDERKEY_F9,
 551+	[KEY_F10] = RENDERKEY_F10,
 552+	[KEY_F11] = RENDERKEY_F11,
 553+	[KEY_F12] = RENDERKEY_F12,
 554+	[KEY_LEFTCTRL] = RENDERKEY_LCTRL,
 555+	[KEY_LEFTSHIFT] = RENDERKEY_LSHIFT,
 556+	[KEY_LEFTALT] = RENDERKEY_LALT,
 557+	[KEY_RIGHTCTRL] = RENDERKEY_RCTRL,
 558+	[KEY_RIGHTSHIFT] = RENDERKEY_RSHIFT,
 559+	[KEY_RIGHTALT] = RENDERKEY_RALT,
 560+	[KEY_DELETE] = RENDERKEY_DEL,
 561+	[KEY_LEFT] = RENDERKEY_LEFT,
 562+	[KEY_HOME] = RENDERKEY_HOME,
 563+	[KEY_END] = RENDERKEY_END,
 564+	[KEY_UP] = RENDERKEY_UP,
 565+	[KEY_DOWN] = RENDERKEY_DOWN,
 566+	[KEY_PAGEUP] = RENDERKEY_PAGEUP,
 567+	[KEY_PAGEDOWN] = RENDERKEY_PAGEDOWN,
 568+	[KEY_RIGHT] = RENDERKEY_RIGHT,
 569+	[KEY_KPSLASH] = 0x80,
 570+	[KEY_KPASTERISK] = 0x7C,
 571+	[KEY_KPMINUS] = 0x7B,
 572+	[KEY_KPPLUS] = 0x79,
 573+	[KEY_KPENTER] = 0x19,
 574+	[KEY_KP1] = 0x69,
 575+	[KEY_KP2] = 0x72,
 576+	[KEY_KP3] = 0x7A,
 577+	[KEY_KP4] = 0x6B,
 578+	[KEY_KP5] = 0x73,
 579+	[KEY_KP6] = 0x74,
 580+	[KEY_KP7] = 0x6C,
 581+	[KEY_KP8] = 0x75,
 582+	[KEY_KP9] = 0x7D,
 583+	[KEY_KP0] = 0x70,
 584+	[KEY_KPDOT] = 0x71,
 585+};
 586+
 587+char* render_joystick_type_id(int index)
 588+{
 589+	return strdup("");
 590+}
 591+
 592+static uint32_t overscan_top[NUM_VID_STD] = {2, 21};
 593+static uint32_t overscan_bot[NUM_VID_STD] = {1, 17};
 594+static uint32_t overscan_left[NUM_VID_STD] = {13, 13};
 595+static uint32_t overscan_right[NUM_VID_STD] = {14, 14};
 596+static vid_std video_standard = VID_NTSC;
 597+
 598+typedef enum {
 599+	DEV_NONE,
 600+	DEV_KEYBOARD,
 601+	DEV_MOUSE,
 602+	DEV_GAMEPAD
 603+} device_type;
 604+
 605+static int32_t mouse_x, mouse_y, mouse_accum_x, mouse_accum_y;
 606+static int32_t handle_event(device_type dtype, int device_index, struct input_event *event)
 607+{
 608+	switch (event->type) {
 609+	case EV_KEY:
 610+		//code is key, value is 1 for keydown, 0 for keyup
 611+		if (dtype == DEV_KEYBOARD && event->code < 128) {
 612+			//keyboard key that we might have a mapping for
 613+			if (event->value) {
 614+				handle_keydown(sym_map[event->code], scancode_map[event->code]);
 615+			} else {
 616+				handle_keyup(sym_map[event->code], scancode_map[event->code]);
 617+			}
 618+		} else if (dtype == DEV_MOUSE && event->code >= BTN_MOUSE && event->code < BTN_JOYSTICK) {
 619+			//mosue button
 620+			if (event->value) {
 621+				handle_mousedown(device_index, event->code - BTN_LEFT);
 622+			} else {
 623+				handle_mouseup(device_index, event->code - BTN_LEFT);
 624+			}
 625+		} else if (dtype == DEV_GAMEPAD && event->code >= BTN_GAMEPAD && event->code < BTN_DIGI) {
 626+			//gamepad button
 627+			if (event->value) {
 628+				handle_joydown(device_index, event->code - BTN_SOUTH);
 629+			} else {
 630+				handle_joyup(device_index, event->code - BTN_SOUTH);
 631+			}
 632+		}
 633+		break;
 634+	case EV_REL:
 635+		if (dtype == DEV_MOUSE) {
 636+			switch(event->code)
 637+			{
 638+			case REL_X:
 639+				mouse_accum_x += event->value;
 640+				break;
 641+			case REL_Y:
 642+				mouse_accum_y += event->value;
 643+				break;
 644+			}
 645+		}
 646+		break;
 647+	case EV_ABS:
 648+		//TODO: Handle joystick axis/hat motion, absolute mouse movement
 649+		break;
 650+	case EV_SYN:
 651+		if (dtype == DEV_MOUSE && (mouse_accum_x || mouse_accum_y)) {
 652+			mouse_x += mouse_accum_x;
 653+			mouse_y += mouse_accum_y;
 654+			if (mouse_x < 0) {
 655+				mouse_x = 0;
 656+			} else if (mouse_x >= main_width) {
 657+				mouse_x = main_width - 1;
 658+			}
 659+			if (mouse_y < 0) {
 660+				mouse_y = 0;
 661+			} else if (mouse_y >= main_height) {
 662+				mouse_y = main_height - 1;
 663+			}
 664+			handle_mouse_moved(device_index, mouse_x, mouse_y, mouse_accum_x, mouse_accum_y);
 665+			mouse_accum_x = mouse_accum_y = 0;
 666+		}
 667+		break;
 668+	}
 669+	return 0;
 670+}
 671+
 672+#define MAX_DEVICES 16
 673+static int device_fds[MAX_DEVICES];
 674+static device_type device_types[MAX_DEVICES];
 675+static int cur_devices;
 676+
 677+static void drain_events()
 678+{
 679+	struct input_event events[64];
 680+	int index_by_type[3] = {0,0,0};
 681+	for (int i = 0; i < cur_devices; i++)
 682+	{
 683+		int bytes = sizeof(events);
 684+		int device_index = index_by_type[device_types[i]-1]++;
 685+		while (bytes == sizeof(events))
 686+		{
 687+			bytes = read(device_fds[i], events, sizeof(events));
 688+			if (bytes > 0) {
 689+				int num_events = bytes / sizeof(events[0]);
 690+				for (int j = 0; j < num_events; j++)
 691+				{
 692+					handle_event(device_types[i], device_index, events + j);
 693+				}
 694+			} else if (bytes < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
 695+				perror("Failed to read evdev events");
 696+			}
 697+		}
 698+	}
 699+}
 700+
 701+static char *vid_std_names[NUM_VID_STD] = {"ntsc", "pal"};
 702+
 703+static void init_audio()
 704+{
 705+	char *device_name = tern_find_path_default(config, "audio\0alsa_device\0", (tern_val){.ptrval="default"}, TVAL_PTR).ptrval;
 706+	int res = snd_pcm_open(&audio_handle, device_name, SND_PCM_STREAM_PLAYBACK, 0);
 707+	if (res < 0) {
 708+		fatal_error("Failed to open ALSA device: %s\n", snd_strerror(res));
 709+	}
 710+	
 711+	snd_pcm_hw_params_t *params;
 712+	snd_pcm_hw_params_alloca(&params);
 713+	res = snd_pcm_hw_params_any(audio_handle, params);
 714+	if (res < 0) {
 715+		fatal_error("No playback configurations available: %s\n", snd_strerror(res));
 716+	}
 717+	res = snd_pcm_hw_params_set_access(audio_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
 718+	if (res < 0) {
 719+		fatal_error("Failed to set access type: %s\n", snd_strerror(res));
 720+	}
 721+	res = snd_pcm_hw_params_set_format(audio_handle, params, SND_PCM_FORMAT_S16_LE);
 722+	if (res < 0) {
 723+		//failed to set, signed 16-bit integer, try floating point
 724+		res = snd_pcm_hw_params_set_format(audio_handle, params, SND_PCM_FORMAT_FLOAT_LE);
 725+		if (res < 0) {
 726+			fatal_error("Failed to set an acceptable format: %s\n", snd_strerror(res));
 727+		}
 728+		mix = mix_f32;
 729+	} else {
 730+		mix = mix_s16;
 731+	}
 732+
 733+    char * rate_str = tern_find_path(config, "audio\0rate\0", TVAL_PTR).ptrval;
 734+   	sample_rate = rate_str ? atoi(rate_str) : 0;
 735+   	if (!sample_rate) {
 736+   		sample_rate = 48000;
 737+   	}
 738+    snd_pcm_hw_params_set_rate_near(audio_handle, params, &sample_rate, NULL);
 739+	output_channels = 2;
 740+	snd_pcm_hw_params_set_channels_near(audio_handle, params, &output_channels);
 741+
 742+    char * samples_str = tern_find_path(config, "audio\0buffer\0", TVAL_PTR).ptrval;
 743+   	buffer_samples = samples_str ? atoi(samples_str) : 0;
 744+   	if (!buffer_samples) {
 745+   		buffer_samples = 512;
 746+   	}
 747+	snd_pcm_hw_params_set_period_size_near(audio_handle, params, &buffer_samples, NULL);
 748+	
 749+	int dir = 1;
 750+	unsigned int periods = 2;
 751+	snd_pcm_hw_params_set_periods_near(audio_handle, params, &periods, &dir);
 752+
 753+	res = snd_pcm_hw_params(audio_handle, params);
 754+	if (res < 0) {
 755+		fatal_error("Failed to set ALSA hardware params: %s\n", snd_strerror(res));
 756+	}
 757+	
 758+	printf("Initialized audio at frequency %d with a %d sample buffer, ", (int)sample_rate, (int)buffer_samples);
 759+	if (mix == mix_s16) {
 760+		puts("signed 16-bit int format");
 761+	} else {
 762+		puts("32-bit float format");
 763+	}
 764+}
 765+
 766+struct wayland_buffer {
 767+	struct wl_buffer *buffer;
 768+	uint32_t *pixels;
 769+	uint8_t busy;
 770+};
 771+
 772+static struct wl_display *wl_display_handle;
 773+static struct wl_compositor *wl_compositor_handle;
 774+static struct wl_shm *wl_shm_handle;
 775+static struct wl_seat *wl_seat_handle;
 776+static struct wl_keyboard *wl_keyboard_handle;
 777+static struct wl_pointer *wl_pointer_handle;
 778+static struct xdg_wm_base *xdg_wm_base_handle;
 779+static struct wl_surface *wl_surface_handle;
 780+static struct xdg_surface *xdg_surface_handle;
 781+static struct xdg_toplevel *xdg_toplevel_handle;
 782+static struct wl_callback *frame_callback;
 783+static struct wayland_buffer wl_buffers[2];
 784+static uint8_t wl_cur_buffer;
 785+static uint8_t wl_configured;
 786+static uint8_t frame_pending;
 787+static uint32_t wl_stride;
 788+static int32_t wl_pointer_x, wl_pointer_y;
 789+static uint32_t *copy_buffer;
 790+static uint32_t last_width, last_width_scale, last_height, last_height_scale;
 791+static uint32_t max_multiple;
 792+
 793+static void wl_buffer_release(void *data, struct wl_buffer *buffer)
 794+{
 795+	((struct wayland_buffer *)data)->busy = 0;
 796+}
 797+
 798+static const struct wl_buffer_listener wl_buffer_listener = {
 799+	.release = wl_buffer_release
 800+};
 801+
 802+static void dispatch_wayland_pending(uint32_t timeout)
 803+{
 804+	if (!wl_display_handle) {
 805+		return;
 806+	}
 807+	while (wl_display_prepare_read(wl_display_handle) != 0)
 808+	{
 809+		wl_display_dispatch_pending(wl_display_handle);
 810+	}
 811+	wl_display_flush(wl_display_handle);
 812+	struct pollfd pfd = {
 813+		.fd = wl_display_get_fd(wl_display_handle),
 814+		.events = POLLIN
 815+	};
 816+	if (poll(&pfd, 1, timeout) > 0 && (pfd.revents & POLLIN)) {
 817+		wl_display_read_events(wl_display_handle);
 818+	} else {
 819+		wl_display_cancel_read(wl_display_handle);
 820+	}
 821+	wl_display_dispatch_pending(wl_display_handle);
 822+}
 823+
 824+static void frame_done(void *data, struct wl_callback *callback, uint32_t time)
 825+{
 826+	wl_callback_destroy(callback);
 827+	if (callback == frame_callback) {
 828+		frame_callback = NULL;
 829+		frame_pending = 0;
 830+	}
 831+}
 832+
 833+static const struct wl_callback_listener frame_listener = {
 834+	.done = frame_done
 835+};
 836+
 837+static int create_shm_file(size_t size)
 838+{
 839+#ifdef SYS_memfd_create
 840+	int fd = syscall(SYS_memfd_create, "blastem-wayland", 0);
 841+	if (fd >= 0) {
 842+		if (ftruncate(fd, size) == 0) {
 843+			return fd;
 844+		}
 845+		close(fd);
 846+	}
 847+#endif
 848+	char template[] = "/blastem-wayland-XXXXXX";
 849+	const char *runtime_dir = getenv("XDG_RUNTIME_DIR");
 850+	if (!runtime_dir) {
 851+		return -1;
 852+	}
 853+	char *name = alloc_concat(runtime_dir, template);
 854+	fd = mkostemp(name, O_CLOEXEC);
 855+	if (fd >= 0) {
 856+		unlink(name);
 857+		if (ftruncate(fd, size) == 0) {
 858+			free(name);
 859+			return fd;
 860+		}
 861+		close(fd);
 862+	}
 863+	free(name);
 864+	return -1;
 865+}
 866+
 867+static void create_wayland_buffer(struct wayland_buffer *buf);
 868+static void destroy_wayland_buffer(struct wayland_buffer *buf);
 869+
 870+static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
 871+{
 872+	xdg_wm_base_pong(xdg_wm_base, serial);
 873+}
 874+
 875+static const struct xdg_wm_base_listener xdg_wm_base_listener = {
 876+	.ping = xdg_wm_base_ping
 877+};
 878+
 879+static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial)
 880+{
 881+	xdg_surface_ack_configure(xdg_surface, serial);
 882+	wl_configured = 1;
 883+}
 884+
 885+static const struct xdg_surface_listener xdg_surface_listener = {
 886+	.configure = xdg_surface_configure
 887+};
 888+
 889+static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states)
 890+{
 891+	if (width > 0 && height > 0 && (width != main_width || height != main_height)) {
 892+		destroy_wayland_buffer(&wl_buffers[0]);
 893+		destroy_wayland_buffer(&wl_buffers[1]);
 894+		main_width = width;
 895+		main_height = height;
 896+		wl_stride = main_width * sizeof(uint32_t);
 897+		create_wayland_buffer(&wl_buffers[0]);
 898+		create_wayland_buffer(&wl_buffers[1]);
 899+	}
 900+}
 901+
 902+static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
 903+{
 904+	if (current_system) {
 905+		current_system->request_exit(current_system);
 906+	} else {
 907+		exit(0);
 908+	}
 909+}
 910+
 911+static const struct xdg_toplevel_listener xdg_toplevel_listener = {
 912+	.configure = xdg_toplevel_configure,
 913+	.close = xdg_toplevel_close
 914+};
 915+
 916+static void wl_keyboard_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
 917+{
 918+	close(fd);
 919+}
 920+
 921+static void wl_keyboard_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
 922+{
 923+}
 924+
 925+static void wl_keyboard_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
 926+{
 927+}
 928+
 929+static void wl_keyboard_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
 930+{
 931+	if (key >= 128) {
 932+		return;
 933+	}
 934+	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
 935+		handle_keydown(sym_map[key], scancode_map[key]);
 936+	} else {
 937+		handle_keyup(sym_map[key], scancode_map[key]);
 938+	}
 939+}
 940+
 941+static void wl_keyboard_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
 942+{
 943+}
 944+
 945+static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *keyboard, int32_t rate, int32_t delay)
 946+{
 947+}
 948+
 949+static const struct wl_keyboard_listener wl_keyboard_listener = {
 950+	.keymap = wl_keyboard_keymap,
 951+	.enter = wl_keyboard_enter,
 952+	.leave = wl_keyboard_leave,
 953+	.key = wl_keyboard_key,
 954+	.modifiers = wl_keyboard_modifiers,
 955+	.repeat_info = wl_keyboard_repeat_info
 956+};
 957+
 958+static void wl_pointer_enter(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
 959+{
 960+	wl_pointer_x = wl_fixed_to_int(surface_x);
 961+	wl_pointer_y = wl_fixed_to_int(surface_y);
 962+	handle_mouse_moved(0, wl_pointer_x, wl_pointer_y, 0, 0);
 963+}
 964+
 965+static void wl_pointer_leave(void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
 966+{
 967+}
 968+
 969+static void wl_pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
 970+{
 971+	int32_t x = wl_fixed_to_int(surface_x);
 972+	int32_t y = wl_fixed_to_int(surface_y);
 973+	handle_mouse_moved(0, x, y, x - wl_pointer_x, y - wl_pointer_y);
 974+	wl_pointer_x = x;
 975+	wl_pointer_y = y;
 976+}
 977+
 978+static void wl_pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
 979+{
 980+	if (button < BTN_MOUSE || button >= BTN_JOYSTICK) {
 981+		return;
 982+	}
 983+	if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
 984+		handle_mousedown(0, button - BTN_LEFT);
 985+	} else {
 986+		handle_mouseup(0, button - BTN_LEFT);
 987+	}
 988+}
 989+
 990+static void wl_pointer_axis(void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
 991+{
 992+}
 993+
 994+static const struct wl_pointer_listener wl_pointer_listener = {
 995+	.enter = wl_pointer_enter,
 996+	.leave = wl_pointer_leave,
 997+	.motion = wl_pointer_motion,
 998+	.button = wl_pointer_button,
 999+	.axis = wl_pointer_axis
1000+};
1001+
1002+static void seat_capabilities(void *data, struct wl_seat *seat, uint32_t capabilities)
1003+{
1004+	if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && !wl_keyboard_handle) {
1005+		wl_keyboard_handle = wl_seat_get_keyboard(seat);
1006+		wl_keyboard_add_listener(wl_keyboard_handle, &wl_keyboard_listener, NULL);
1007+	} else if (!(capabilities & WL_SEAT_CAPABILITY_KEYBOARD) && wl_keyboard_handle) {
1008+		wl_keyboard_destroy(wl_keyboard_handle);
1009+		wl_keyboard_handle = NULL;
1010+	}
1011+	if ((capabilities & WL_SEAT_CAPABILITY_POINTER) && !wl_pointer_handle) {
1012+		wl_pointer_handle = wl_seat_get_pointer(seat);
1013+		wl_pointer_add_listener(wl_pointer_handle, &wl_pointer_listener, NULL);
1014+	} else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) && wl_pointer_handle) {
1015+		wl_pointer_destroy(wl_pointer_handle);
1016+		wl_pointer_handle = NULL;
1017+	}
1018+}
1019+
1020+static void seat_name(void *data, struct wl_seat *seat, const char *name)
1021+{
1022+}
1023+
1024+static const struct wl_seat_listener wl_seat_listener = {
1025+	.capabilities = seat_capabilities,
1026+	.name = seat_name
1027+};
1028+
1029+static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
1030+{
1031+	if (!strcmp(interface, wl_compositor_interface.name)) {
1032+		wl_compositor_handle = wl_registry_bind(registry, name, &wl_compositor_interface, version < 4 ? version : 4);
1033+	} else if (!strcmp(interface, wl_shm_interface.name)) {
1034+		wl_shm_handle = wl_registry_bind(registry, name, &wl_shm_interface, 1);
1035+	} else if (!strcmp(interface, wl_seat_interface.name)) {
1036+		wl_seat_handle = wl_registry_bind(registry, name, &wl_seat_interface, 1);
1037+		wl_seat_add_listener(wl_seat_handle, &wl_seat_listener, NULL);
1038+	} else if (!strcmp(interface, xdg_wm_base_interface.name)) {
1039+		xdg_wm_base_handle = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
1040+		xdg_wm_base_add_listener(xdg_wm_base_handle, &xdg_wm_base_listener, NULL);
1041+	}
1042+}
1043+
1044+static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name)
1045+{
1046+}
1047+
1048+static const struct wl_registry_listener registry_listener = {
1049+	.global = registry_global,
1050+	.global_remove = registry_global_remove
1051+};
1052+
1053+static void create_wayland_buffer(struct wayland_buffer *buf)
1054+{
1055+	size_t size = wl_stride * main_height;
1056+	int fd = create_shm_file(size);
1057+	if (fd < 0) {
1058+		fatal_error("Failed to create Wayland shared memory file\n");
1059+	}
1060+	buf->pixels = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1061+	if (buf->pixels == MAP_FAILED) {
1062+		close(fd);
1063+		fatal_error("Failed to mmap Wayland shared memory buffer\n");
1064+	}
1065+	struct wl_shm_pool *pool = wl_shm_create_pool(wl_shm_handle, fd, size);
1066+	buf->buffer = wl_shm_pool_create_buffer(pool, 0, main_width, main_height, wl_stride, WL_SHM_FORMAT_XRGB8888);
1067+	wl_buffer_add_listener(buf->buffer, &wl_buffer_listener, buf);
1068+	wl_shm_pool_destroy(pool);
1069+	close(fd);
1070+}
1071+
1072+static void destroy_wayland_buffer(struct wayland_buffer *buf)
1073+{
1074+	size_t size = wl_stride * main_height;
1075+	if (buf->buffer) {
1076+		wl_buffer_destroy(buf->buffer);
1077+		buf->buffer = NULL;
1078+	}
1079+	if (buf->pixels) {
1080+		munmap(buf->pixels, size);
1081+		buf->pixels = NULL;
1082+	}
1083+	buf->busy = 0;
1084+}
1085+
1086+static void destroy_wayland(void)
1087+{
1088+	destroy_wayland_buffer(&wl_buffers[0]);
1089+	destroy_wayland_buffer(&wl_buffers[1]);
1090+	if (xdg_toplevel_handle) {
1091+		xdg_toplevel_destroy(xdg_toplevel_handle);
1092+		xdg_toplevel_handle = NULL;
1093+	}
1094+	if (xdg_surface_handle) {
1095+		xdg_surface_destroy(xdg_surface_handle);
1096+		xdg_surface_handle = NULL;
1097+	}
1098+	if (frame_callback) {
1099+		wl_callback_destroy(frame_callback);
1100+		frame_callback = NULL;
1101+		frame_pending = 0;
1102+	}
1103+	if (wl_surface_handle) {
1104+		wl_surface_destroy(wl_surface_handle);
1105+		wl_surface_handle = NULL;
1106+	}
1107+	if (wl_keyboard_handle) {
1108+		wl_keyboard_destroy(wl_keyboard_handle);
1109+		wl_keyboard_handle = NULL;
1110+	}
1111+	if (wl_pointer_handle) {
1112+		wl_pointer_destroy(wl_pointer_handle);
1113+		wl_pointer_handle = NULL;
1114+	}
1115+	if (wl_seat_handle) {
1116+		wl_seat_destroy(wl_seat_handle);
1117+		wl_seat_handle = NULL;
1118+	}
1119+	if (xdg_wm_base_handle) {
1120+		xdg_wm_base_destroy(xdg_wm_base_handle);
1121+		xdg_wm_base_handle = NULL;
1122+	}
1123+	if (wl_shm_handle) {
1124+		wl_shm_destroy(wl_shm_handle);
1125+		wl_shm_handle = NULL;
1126+	}
1127+	if (wl_compositor_handle) {
1128+		wl_compositor_destroy(wl_compositor_handle);
1129+		wl_compositor_handle = NULL;
1130+	}
1131+	if (wl_display_handle) {
1132+		wl_display_disconnect(wl_display_handle);
1133+		wl_display_handle = NULL;
1134+	}
1135+	wl_configured = 0;
1136+}
1137+
1138+static uint32_t mix_pixel(uint32_t last, uint32_t cur, float ratio)
1139+{
1140+	float a,b,c,d;
1141+	a = (last & 255) * ratio;
1142+	b = (last >> 8 & 255) * ratio;
1143+	c = (last >> 16 & 255) * ratio;
1144+	d = (last >> 24 & 255) * ratio;
1145+	ratio = 1.0f - ratio;
1146+	a += (cur & 255) * ratio;
1147+	b += (cur >> 8 & 255) * ratio;
1148+	c += (cur >> 16 & 255) * ratio;
1149+	d += (cur >> 24 & 255) * ratio;
1150+	return ((int)d) << 24 | ((int)c) << 16 | ((int)b) << 8 | ((int)a);
1151+}
1152+static void do_buffer_copy(void)
1153+{
1154+	while (frame_pending && wl_display_handle)
1155+	{
1156+		wl_display_dispatch(wl_display_handle);
1157+	}
1158+	struct wayland_buffer *target = &wl_buffers[wl_cur_buffer];
1159+	if (target->busy) {
1160+		target = &wl_buffers[wl_cur_buffer ^ 1];
1161+		while (target->busy && wl_display_handle)
1162+		{
1163+			wl_display_dispatch(wl_display_handle);
1164+		}
1165+	}
1166+	wl_cur_buffer = target == &wl_buffers[0] ? 1 : 0;
1167+	uint32_t *pixels = target->pixels;
1168+	uint32_t width_multiple = main_width / last_width_scale;
1169+	uint32_t height_multiple = main_height / last_height_scale;
1170+	uint32_t multiple = width_multiple < height_multiple ? width_multiple : height_multiple;
1171+	if (max_multiple && multiple > max_multiple) {
1172+		multiple = max_multiple;
1173+	}
1174+	height_multiple = last_height_scale * multiple / last_height;
1175+	uint32_t *cur_line = pixels + (main_width - last_width_scale * multiple)/2;
1176+	cur_line += wl_stride * (main_height - last_height_scale * multiple) / (2 * sizeof(uint32_t));
1177+	uint32_t *src_line = copy_buffer;
1178+	memset(pixels, 0, wl_stride * main_height);
1179+	if (height_multiple * last_height == multiple * last_height_scale) {
1180+		if (last_width == last_width_scale) {
1181+			for (uint32_t y = 0; y < last_height; y++)
1182+			{
1183+				for (uint32_t i = 0; i < height_multiple; i++)
1184+				{
1185+					uint32_t *cur = cur_line;
1186+					uint32_t *src = src_line;
1187+					for (uint32_t x = 0; x < last_width	; x++)
1188+					{
1189+						uint32_t pixel = *(src++);
1190+						for (uint32_t j = 0; j < multiple; j++)
1191+						{
1192+							*(cur++) = pixel;
1193+						}
1194+					}
1195+					
1196+					cur_line += wl_stride / sizeof(uint32_t);
1197+				}
1198+				src_line += LINEBUF_SIZE;
1199+			}
1200+		} else {
1201+			float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width;
1202+			float remaining = 0.0f;
1203+			uint32_t last_pixel = 0;
1204+			for (uint32_t y = 0; y < last_height; y++)
1205+			{
1206+				for (uint32_t i = 0; i < height_multiple; i++)
1207+				{
1208+					uint32_t *cur = cur_line;
1209+					uint32_t *src = src_line;
1210+					for (uint32_t x = 0; x < last_width	; x++)
1211+					{
1212+						uint32_t pixel = *(src++);
1213+						float count = scale_multiple;
1214+						if (remaining > 0.0f) {
1215+							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1216+							count -= 1.0f - remaining;
1217+						}
1218+						for (; count >= 1; count -= 1.0f)
1219+						{
1220+							*(cur++) = pixel;
1221+						}
1222+						remaining = count;
1223+						last_pixel = pixel;
1224+					}
1225+					
1226+					cur_line += wl_stride / sizeof(uint32_t);
1227+				}
1228+				src_line += LINEBUF_SIZE;
1229+			}
1230+		}
1231+	} else {
1232+		float height_scale = ((float)(last_height_scale * multiple)) / (float)last_height;
1233+		float height_remaining = 0.0f;
1234+		uint32_t *last_line;
1235+		if (last_width == last_width_scale) {
1236+			for (uint32_t y = 0; y < last_height; y++)
1237+			{
1238+				float hcount = height_scale;
1239+				if (height_remaining > 0.0f) {
1240+					uint32_t *cur = cur_line;
1241+					uint32_t *src = src_line;
1242+					uint32_t *last = last_line;
1243+					for (uint32_t x = 0; x < last_width	; x++)
1244+					{
1245+						uint32_t mixed = mix_pixel(*(last++), *(src++), height_remaining);
1246+						for (uint32_t j = 0; j < multiple; j++)
1247+						{
1248+							*(cur++) = mixed;
1249+						}
1250+					}
1251+					hcount -= 1.0f - height_remaining;
1252+					cur_line += wl_stride / sizeof(uint32_t);
1253+				}
1254+				for(; hcount >= 1; hcount -= 1.0f)
1255+				{
1256+					uint32_t *cur = cur_line;
1257+					uint32_t *src = src_line;
1258+					for (uint32_t x = 0; x < last_width	; x++)
1259+					{
1260+						uint32_t pixel = *(src++);
1261+						for (uint32_t j = 0; j < multiple; j++)
1262+						{
1263+							*(cur++) = pixel;
1264+						}
1265+					}
1266+					
1267+					cur_line += wl_stride / sizeof(uint32_t);
1268+				}
1269+				height_remaining = hcount;
1270+				last_line = src_line;
1271+				src_line += LINEBUF_SIZE;
1272+			}
1273+		} else {
1274+			float scale_multiple = ((float)(last_width_scale * multiple)) / (float)last_width;
1275+			float remaining = 0.0f;
1276+			uint32_t last_pixel = 0;
1277+			for (uint32_t y = 0; y < last_height; y++)
1278+			{
1279+				float hcount = height_scale;
1280+				if (height_remaining > 0.0f) {
1281+					uint32_t *cur = cur_line;
1282+					uint32_t *src = src_line;
1283+					uint32_t *last = last_line;
1284+					
1285+					for (uint32_t x = 0; x < last_width; x++)
1286+					{
1287+						uint32_t pixel = mix_pixel(*(last++), *(src++), height_remaining);
1288+						float count = scale_multiple;
1289+						if (remaining > 0.0f) {
1290+							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1291+							count -= 1.0f - remaining;
1292+						}
1293+						for (; count >= 1.0f; count -= 1.0f)
1294+						{
1295+							*(cur++) = pixel;
1296+						}
1297+						remaining = count;
1298+						last_pixel = pixel;
1299+					}
1300+					hcount -= 1.0f - height_remaining;
1301+					cur_line += wl_stride / sizeof(uint32_t);
1302+				}
1303+				
1304+				for (; hcount >= 1.0f; hcount -= 1.0f)
1305+				{
1306+					uint32_t *cur = cur_line;
1307+					uint32_t *src = src_line;
1308+					for (uint32_t x = 0; x < last_width	; x++)
1309+					{
1310+						uint32_t pixel = *(src++);
1311+						float count = scale_multiple;
1312+						if (remaining > 0.0f) {
1313+							*(cur++) = mix_pixel(last_pixel, pixel, remaining);
1314+							count -= 1.0f - remaining;
1315+						}
1316+						for (; count >= 1; count -= 1.0f)
1317+						{
1318+							*(cur++) = pixel;
1319+						}
1320+						remaining = count;
1321+						last_pixel = pixel;
1322+					}
1323+					
1324+					cur_line += wl_stride / sizeof(uint32_t);
1325+				}
1326+				height_remaining = hcount;
1327+				last_line = src_line;
1328+				src_line += LINEBUF_SIZE;
1329+			}
1330+		}
1331+	}
1332+	wl_surface_attach(wl_surface_handle, target->buffer, 0, 0);
1333+	wl_surface_damage(wl_surface_handle, 0, 0, main_width, main_height);
1334+	frame_callback = wl_surface_frame(wl_surface_handle);
1335+	wl_callback_add_listener(frame_callback, &frame_listener, NULL);
1336+	frame_pending = 1;
1337+	wl_surface_commit(wl_surface_handle);
1338+	target->busy = 1;
1339+	wl_display_flush(wl_display_handle);
1340+}
1341+
1342+void window_setup(void)
1343+{
1344+	tern_val def = {.ptrval = "audio"};
1345+	tern_node *video = tern_find_node(config, "video");
1346+	if (video)
1347+	{
1348+		for (int i = 0; i < NUM_VID_STD; i++)
1349+		{
1350+			tern_node *std_settings = tern_find_node(video, vid_std_names[i]);
1351+			if (std_settings) {
1352+				char *val = tern_find_path_default(std_settings, "overscan\0top\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1353+				if (val) {
1354+					overscan_top[i] = atoi(val);
1355+				}
1356+				val = tern_find_path_default(std_settings, "overscan\0bottom\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1357+				if (val) {
1358+					overscan_bot[i] = atoi(val);
1359+				}
1360+				val = tern_find_path_default(std_settings, "overscan\0left\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1361+				if (val) {
1362+					overscan_left[i] = atoi(val);
1363+				}
1364+				val = tern_find_path_default(std_settings, "overscan\0right\0", (tern_val){.ptrval = NULL}, TVAL_PTR).ptrval;
1365+				if (val) {
1366+					overscan_right[i] = atoi(val);
1367+				}
1368+			}
1369+		}
1370+	}
1371+	wl_display_handle = wl_display_connect(NULL);
1372+	if (!wl_display_handle) {
1373+		fatal_error("Failed to connect to Wayland display\n");
1374+	}
1375+	struct wl_registry *registry = wl_display_get_registry(wl_display_handle);
1376+	wl_registry_add_listener(registry, &registry_listener, NULL);
1377+	wl_display_roundtrip(wl_display_handle);
1378+	if (!wl_compositor_handle || !wl_shm_handle || !xdg_wm_base_handle) {
1379+		fatal_error("Wayland compositor is missing wl_compositor, wl_shm or xdg_wm_base support\n");
1380+	}
1381+	wl_display_roundtrip(wl_display_handle);
1382+	wl_surface_handle = wl_compositor_create_surface(wl_compositor_handle);
1383+	xdg_surface_handle = xdg_wm_base_get_xdg_surface(xdg_wm_base_handle, wl_surface_handle);
1384+	xdg_surface_add_listener(xdg_surface_handle, &xdg_surface_listener, NULL);
1385+	xdg_toplevel_handle = xdg_surface_get_toplevel(xdg_surface_handle);
1386+	xdg_toplevel_add_listener(xdg_toplevel_handle, &xdg_toplevel_listener, NULL);
1387+	if (caption) {
1388+		xdg_toplevel_set_title(xdg_toplevel_handle, caption);
1389+	}
1390+	wl_surface_commit(wl_surface_handle);
1391+	while (!wl_configured && wl_display_dispatch(wl_display_handle) != -1)
1392+	{
1393+	}
1394+	wl_stride = main_width * sizeof(uint32_t);
1395+	create_wayland_buffer(&wl_buffers[0]);
1396+	create_wayland_buffer(&wl_buffers[1]);
1397+	printf("Wayland shm window: %d x %d\n", main_width, main_height);
1398+
1399+	def.ptrval = "0";
1400+	max_multiple = atoi(tern_find_path_default(config, "video\0wayland\0max_multiple\0", def, TVAL_PTR).ptrval);
1401+	
1402+}
1403+
1404+void restore_tty(void)
1405+{
1406+	ioctl(STDIN_FILENO, KDSETMODE, KD_TEXT);
1407+	for (int i = 0; i < cur_devices; i++)
1408+	{
1409+		if (device_types[i] == DEV_KEYBOARD) {
1410+			ioctl(device_fds[i], EVIOCGRAB, 0);
1411+		}
1412+	}
1413+}
1414+
1415+static void init_evdev(void)
1416+{
1417+	tern_val def = {.ptrval = "off"};
1418+	if (strcmp(tern_find_path_default(config, "video\0wayland\0evdev\0", def, TVAL_PTR).ptrval, "on")) {
1419+		return;
1420+	}
1421+	DIR *d = opendir("/dev/input");
1422+	if (!d) {
1423+		warning("Failed to open /dev/input for reading: %s\n", strerror(errno));
1424+		return;
1425+	}
1426+	struct dirent* entry;
1427+	int joystick_counter = 0;
1428+	while ((entry = readdir(d)) && cur_devices < MAX_DEVICES)
1429+	{
1430+		if (!strncmp("event", entry->d_name, strlen("event"))) {
1431+			char *filename = alloc_concat("/dev/input/", entry->d_name);
1432+			int fd = open(filename, O_RDONLY);
1433+			if (fd == -1) {
1434+				int errnum = errno;
1435+				warning("Failed to open evdev device %s for reading: %s\n", filename, strerror(errnum));
1436+				free(filename);
1437+				continue;
1438+			}
1439+			
1440+			unsigned long bits;
1441+			if (-1 == ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits)) {
1442+				int errnum = errno;
1443+				warning("Failed get capability bits from evdev device %s: %s\n", filename, strerror(errnum));
1444+				free(filename);
1445+				close(fd);
1446+				continue;
1447+			}
1448+			if (!(1 & bits >> EV_KEY)) {
1449+				free(filename);
1450+				close(fd);
1451+				continue;
1452+			}
1453+			unsigned long button_bits[(BTN_THUMBR+8*sizeof(long))/(8*sizeof(long))];
1454+			int res = ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(button_bits)), button_bits);
1455+			if (-1 == res) {
1456+				int errnum = errno;
1457+				warning("Failed get capability bits from evdev device %s: %s\n", filename, strerror(errnum));
1458+				free(filename);
1459+				close(fd);
1460+				continue;
1461+			}
1462+			int to_check[] = {KEY_ENTER, BTN_MOUSE, BTN_GAMEPAD};
1463+			device_type dtype = DEV_NONE;
1464+			for (int i = 0; i < 3; i++)
1465+			{
1466+				if (1 & button_bits[to_check[i]/(8*sizeof(button_bits[0]))] >> to_check[i]%(8*sizeof(button_bits[0]))) {
1467+					dtype = i + 1;
1468+				}
1469+			}
1470+			if (dtype == DEV_NONE) {
1471+				close(fd);
1472+			} else {
1473+				device_fds[cur_devices] = fd;
1474+				device_types[cur_devices] = dtype;
1475+				char name[1024];
1476+				char *names[] = {"Keyboard", "Mouse", "Gamepad"};
1477+				ioctl(fd, EVIOCGNAME(sizeof(name)), name);
1478+				printf("%s is a %s\n%s\n", filename, names[dtype - 1], name);
1479+				
1480+				if (dtype == DEV_GAMEPAD) {
1481+					handle_joy_added(joystick_counter++);
1482+				} else if (dtype == DEV_KEYBOARD && isatty(STDIN_FILENO)) {
1483+					ioctl(fd, EVIOCGRAB, 1);
1484+				}
1485+				
1486+				fcntl(fd, F_SETFL, O_NONBLOCK);
1487+				cur_devices++;
1488+			}
1489+			free(filename);
1490+		}
1491+	}
1492+	closedir(d);
1493+}
1494+
1495+void render_init(int width, int height, char * title)
1496+{
1497+	if (height <= 0) {
1498+		float aspect = config_aspect() > 0.0f ? config_aspect() : 4.0f/3.0f;
1499+		height = ((float)width / aspect) + 0.5f;
1500+	}
1501+	printf("width: %d, height: %d\n", width, height);
1502+	main_width = width;
1503+	main_height = height;
1504+	
1505+	caption = title;
1506+	
1507+	if (isatty(STDIN_FILENO)) {
1508+		ioctl(STDIN_FILENO, KDSETMODE, KD_GRAPHICS);
1509+		atexit(restore_tty);
1510+	}
1511+	
1512+	window_setup();
1513+	
1514+	init_audio();
1515+	
1516+	render_set_video_standard(VID_NTSC);
1517+	init_evdev();
1518+
1519+	atexit(render_quit);
1520+}
1521+static void update_source(audio_source *src, double rc, uint8_t sync_changed)
1522+{
1523+	double alpha = src->dt / (src->dt + rc);
1524+	int32_t lowpass_alpha = (int32_t)(((double)0x10000) * alpha);
1525+	src->lowpass_alpha = lowpass_alpha;
1526+}
1527+
1528+void render_config_updated(void)
1529+{
1530+	
1531+	destroy_wayland();
1532+	drain_events();
1533+	
1534+	window_setup();
1535+
1536+	render_close_audio();
1537+	init_audio();
1538+	render_set_video_standard(video_standard);
1539+	
1540+	double lowpass_cutoff = get_lowpass_cutoff(config);
1541+	double rc = (1.0 / lowpass_cutoff) / (2.0 * M_PI);
1542+	for (uint8_t i = 0; i < num_audio_sources; i++)
1543+	{
1544+		update_source(audio_sources[i], rc, 0);
1545+	}
1546+	for (uint8_t i = 0; i < num_inactive_audio_sources; i++)
1547+	{
1548+		update_source(inactive_audio_sources[i], rc, 0);
1549+	}
1550+	drain_events();
1551+}
1552+
1553+void render_set_video_standard(vid_std std)
1554+{
1555+	video_standard = std;
1556+}
1557+
1558+void render_update_caption(char *title)
1559+{
1560+	caption = title;
1561+	if (xdg_toplevel_handle) {
1562+		xdg_toplevel_set_title(xdg_toplevel_handle, title);
1563+	}
1564+	free(fps_caption);
1565+	fps_caption = NULL;
1566+}
1567+
1568+static char *screenshot_path;
1569+void render_save_screenshot(char *path)
1570+{
1571+	if (screenshot_path) {
1572+		free(screenshot_path);
1573+	}
1574+	screenshot_path = path;
1575+}
1576+
1577+uint8_t render_create_window(char *caption, uint32_t width, uint32_t height, window_close_handler close_handler)
1578+{
1579+	//no op
1580+	return 0;
1581+}
1582+
1583+void render_destroy_window(uint8_t which)
1584+{
1585+	//no op
1586+}
1587+
1588+static uint8_t last_video_buffer;
1589+static uint32_t video_buffer_offset;
1590+uint32_t *render_get_video_buffer(uint8_t which, int *pitch)
1591+{
1592+	if (last_video_buffer != which) {
1593+		*pitch = LINEBUF_SIZE * sizeof(uint32_t) * 2;
1594+		return video_buffer + video_buffer_offset + (which == VIDEO_BUFFER_EVEN ? LINEBUF_SIZE : 0);
1595+	}
1596+	*pitch = LINEBUF_SIZE * sizeof(uint32_t);
1597+	return video_buffer + video_buffer_offset;
1598+}
1599+
1600+uint8_t events_processed;
1601+#define FPS_INTERVAL 1000
1602+
1603+void render_video_buffer_updated(uint8_t which, int width)
1604+{
1605+	uint32_t height = which <= VIDEO_BUFFER_EVEN 
1606+		? (video_standard == VID_NTSC ? 243 : 294) - (overscan_top[video_standard] + overscan_bot[video_standard])
1607+		: 240;
1608+	width -= overscan_left[video_standard] + overscan_right[video_standard];
1609+	last_width = width;
1610+	last_width_scale = LINEBUF_SIZE - (overscan_left[video_standard] + overscan_right[video_standard]);
1611+	last_height = last_height_scale = height;
1612+	copy_buffer = video_buffer + video_buffer_offset + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard];
1613+	if (which != last_video_buffer) {
1614+		last_height *= 2;
1615+		copy_buffer += LINEBUF_SIZE * overscan_top[video_standard];
1616+		uint32_t *src = video_buffer + (video_buffer_offset ? 0 : LINEBUF_SIZE * MAX_VIDEO_BUFFER_LINES) + overscan_left[video_standard] + LINEBUF_SIZE * overscan_top[video_standard] + LINEBUF_SIZE * overscan_top[video_standard];
1617+		uint32_t *dst = copy_buffer;
1618+		if (which == VIDEO_BUFFER_ODD) {
1619+			src += LINEBUF_SIZE;
1620+			dst += LINEBUF_SIZE;
1621+		}
1622+		for (int i = 0; i < height; i++)
1623+		{
1624+			memcpy(dst, src, width * sizeof(uint32_t));
1625+			src += LINEBUF_SIZE * 2;
1626+			dst += LINEBUF_SIZE * 2;
1627+		}
1628+		video_buffer_offset = video_buffer_offset ? 0 : LINEBUF_SIZE * MAX_VIDEO_BUFFER_LINES;
1629+	}
1630+	do_buffer_copy();
1631+	last_video_buffer = which;
1632+	if (!events_processed) {
1633+		process_events();
1634+	}
1635+	events_processed = 0;
1636+}
1637+
1638+uint32_t render_emulated_width()
1639+{
1640+	return last_width - overscan_left[video_standard] - overscan_right[video_standard];
1641+}
1642+
1643+uint32_t render_emulated_height()
1644+{
1645+	return (video_standard == VID_NTSC ? 243 : 294) - overscan_top[video_standard] - overscan_bot[video_standard];
1646+}
1647+
1648+uint32_t render_overscan_left()
1649+{
1650+	return overscan_left[video_standard];
1651+}
1652+
1653+uint32_t render_overscan_top()
1654+{
1655+	return overscan_top[video_standard];
1656+}
1657+
1658+void render_wait_quit(vdp_context * context)
1659+{
1660+	for(;;)
1661+	{
1662+		drain_events();
1663+		sleep(1);
1664+	}
1665+}
1666+
1667+int render_lookup_button(char *name)
1668+{
1669+	static tern_node *button_lookup;
1670+	if (!button_lookup) {
1671+		//xbox names
1672+		button_lookup = tern_insert_int(button_lookup, "a", BTN_SOUTH);
1673+		button_lookup = tern_insert_int(button_lookup, "b", BTN_EAST);
1674+		button_lookup = tern_insert_int(button_lookup, "x", BTN_WEST);
1675+		button_lookup = tern_insert_int(button_lookup, "y", BTN_NORTH);
1676+		button_lookup = tern_insert_int(button_lookup, "back", BTN_SELECT);
1677+		button_lookup = tern_insert_int(button_lookup, "start", BTN_START);
1678+		button_lookup = tern_insert_int(button_lookup, "guid", BTN_MODE);
1679+		button_lookup = tern_insert_int(button_lookup, "leftshoulder", BTN_TL);
1680+		button_lookup = tern_insert_int(button_lookup, "rightshoulder", BTN_TR);
1681+		button_lookup = tern_insert_int(button_lookup, "leftstick", BTN_THUMBL);
1682+		button_lookup = tern_insert_int(button_lookup, "rightstick", BTN_THUMBR);
1683+		//ps names
1684+		button_lookup = tern_insert_int(button_lookup, "cross", BTN_SOUTH);
1685+		button_lookup = tern_insert_int(button_lookup, "circle", BTN_EAST);
1686+		button_lookup = tern_insert_int(button_lookup, "square", BTN_WEST);
1687+		button_lookup = tern_insert_int(button_lookup, "triangle", BTN_NORTH);
1688+		button_lookup = tern_insert_int(button_lookup, "share", BTN_SELECT);
1689+		button_lookup = tern_insert_int(button_lookup, "select", BTN_SELECT);
1690+		button_lookup = tern_insert_int(button_lookup, "options", BTN_START);
1691+		button_lookup = tern_insert_int(button_lookup, "l1", BTN_TL);
1692+		button_lookup = tern_insert_int(button_lookup, "r1", BTN_TR);
1693+		button_lookup = tern_insert_int(button_lookup, "l3", BTN_THUMBL);
1694+		button_lookup = tern_insert_int(button_lookup, "r3", BTN_THUMBR);
1695+	}
1696+	return (int)tern_find_int(button_lookup, name, KEY_CNT);
1697+}
1698+
1699+int render_lookup_axis(char *name)
1700+{
1701+	static tern_node *axis_lookup;
1702+	if (!axis_lookup) {
1703+		//xbox names
1704+		axis_lookup = tern_insert_int(axis_lookup, "leftx", ABS_X);
1705+		axis_lookup = tern_insert_int(axis_lookup, "lefty", ABS_Y);
1706+		axis_lookup = tern_insert_int(axis_lookup, "lefttrigger", ABS_Z);
1707+		axis_lookup = tern_insert_int(axis_lookup, "rightx", ABS_RX);
1708+		axis_lookup = tern_insert_int(axis_lookup, "righty", ABS_RY);
1709+		axis_lookup = tern_insert_int(axis_lookup, "righttrigger", ABS_RZ);
1710+		//ps names
1711+		axis_lookup = tern_insert_int(axis_lookup, "l2", ABS_Z);
1712+		axis_lookup = tern_insert_int(axis_lookup, "r2", ABS_RZ);
1713+	}
1714+	return (int)tern_find_int(axis_lookup, name, ABS_CNT);
1715+}
1716+
1717+int32_t render_translate_input_name(int32_t controller, char *name, uint8_t is_axis)
1718+{
1719+	if (is_axis) {
1720+		int axis = render_lookup_axis(name);
1721+		if (axis == ABS_CNT) {
1722+			return RENDER_INVALID_NAME;
1723+		}
1724+		return RENDER_AXIS_BIT | axis;
1725+	} else {
1726+		int button = render_lookup_button(name);
1727+		if (button != KEY_CNT) {
1728+			return button;
1729+		}
1730+		if (!strcmp("dpup", name)) {
1731+			return RENDER_DPAD_BIT | 1;
1732+		}
1733+		if (!strcmp("dpdown", name)) {
1734+			return RENDER_DPAD_BIT | 4;
1735+		}
1736+		if (!strcmp("dpdleft", name)) {
1737+			return RENDER_DPAD_BIT | 8;
1738+		}
1739+		if (!strcmp("dpright", name)) {
1740+			return RENDER_DPAD_BIT | 2;
1741+		}
1742+		return RENDER_INVALID_NAME;
1743+	}
1744+}
1745+
1746+int32_t render_dpad_part(int32_t input)
1747+{
1748+	return input >> 4 & 0xFFFFFF;
1749+}
1750+
1751+uint8_t render_direction_part(int32_t input)
1752+{
1753+	return input & 0xF;
1754+}
1755+
1756+int32_t render_axis_part(int32_t input)
1757+{
1758+	return input & 0xFFFFFFF;
1759+}
1760+
1761+void process_events()
1762+{
1763+	if (events_processed > MAX_EVENT_POLL_PER_FRAME) {
1764+		return;
1765+	}
1766+	if (wl_display_handle) {
1767+		dispatch_wayland_pending(0);
1768+	}
1769+	drain_events();
1770+	events_processed++;
1771+}
1772+
1773+uint32_t render_audio_buffer()
1774+{
1775+	return buffer_samples;
1776+}
1777+
1778+uint32_t render_sample_rate()
1779+{
1780+	return sample_rate;
1781+}
1782+
1783+void render_errorbox(char *title, char *message)
1784+{
1785+	
1786+}
1787+
1788+void render_warnbox(char *title, char *message)
1789+{
1790+	
1791+}
1792+
1793+void render_infobox(char *title, char *message)
1794+{
1795+	
1796+}
1797+
1798+uint8_t render_get_active_video_buffer(void)
1799+{
1800+	return VIDEO_BUFFER_ODD;
1801+}
A rom.db
+1379, -0
   1@@ -0,0 +1,1379 @@
   2+T-081326 {
   3+	name NBA Jam
   4+	EEPROM {
   5+		type i2c
   6+		size 256
   7+	}
   8+	map {
   9+		0 {
  10+			device ROM
  11+			last 1FFFFF
  12+		}
  13+		200000 {
  14+			device EEPROM
  15+			last 3FFFFF
  16+			bits_read {
  17+				1 sda
  18+			}
  19+			bits_write {
  20+				0 sda
  21+				1 scl
  22+			}
  23+		}
  24+	}
  25+}
  26+T-81033 {
  27+	name NBA Jam
  28+	EEPROM {
  29+		type i2c
  30+		size 256
  31+	}
  32+	map {
  33+		0 {
  34+			device ROM
  35+			last 1FFFFF
  36+		}
  37+		200000 {
  38+			device EEPROM
  39+			last 3FFFFF
  40+			bits_read {
  41+				1 sda
  42+			}
  43+			bits_write {
  44+				0 sda
  45+				1 scl
  46+			}
  47+		}
  48+	}
  49+}
  50+T-081276 {
  51+	name NFL Quarterback Club
  52+	EEPROM {
  53+		type i2c
  54+		size 256
  55+	}
  56+	map {
  57+		0 {
  58+			device ROM
  59+			last 1FFFFF
  60+		}
  61+		200000 {
  62+			device EEPROM
  63+			#This is almost certainly not correct based on the address pins
  64+			#available to the Acclaim mapper. It's probably available up to
  65+			#2FFFFF at least and just fights with D0 from the mask ROM
  66+			last 200001
  67+			bits_read {
  68+				0 sda
  69+			}
  70+			bits_write {
  71+				0 sda
  72+				8 scl
  73+			}
  74+		}
  75+		200002 {
  76+			device ROM
  77+			offset 200000
  78+			last 2FFFFF
  79+		}
  80+	}
  81+}
  82+T-81406 {
  83+	name NBA Jam TE
  84+	EEPROM {
  85+		type i2c
  86+		size 512
  87+	}
  88+	map {
  89+		0 {
  90+			device ROM
  91+			last 1FFFFF
  92+		}
  93+		200000 {
  94+			device EEPROM
  95+			#This is almost certainly not correct based on the address pins
  96+			#available to the Acclaim mapper. It's probably available up to
  97+			#2FFFFF at least and just fights with D0 from the mask ROM
  98+			last 200001
  99+			bits_read {
 100+				0 sda
 101+			}
 102+			bits_write {
 103+				0 sda
 104+				8 scl
 105+			}
 106+		}
 107+		200002 {
 108+			device ROM
 109+			offset 200000
 110+			last 2FFFFF
 111+		}
 112+	}
 113+}
 114+T-081586 {
 115+	name NFL Quarterback Club '96
 116+	EEPROM {
 117+		type i2c
 118+		size 2048
 119+	}
 120+	map {
 121+		0 {
 122+			device ROM
 123+			last 1FFFFF
 124+		}
 125+		200000 {
 126+			device EEPROM
 127+			#This is almost certainly not correct based on the address pins
 128+			#available to the Acclaim mapper. It's probably available up to
 129+			#2FFFFF at least and just fights with D0 from the mask ROM
 130+			last 200001
 131+			bits_read {
 132+				0 sda
 133+			}
 134+			bits_write {
 135+				0 sda
 136+				8 scl
 137+			}
 138+		}
 139+		200002 {
 140+			device ROM
 141+			last 3FFFFF
 142+			offset 200000
 143+		}
 144+	}
 145+}
 146+T-81576 {
 147+	name College Slam
 148+	EEPROM {
 149+		type i2c
 150+		size 8192
 151+	}
 152+	map {
 153+		0 {
 154+			device ROM
 155+			last 1FFFFF
 156+		}
 157+		200000 {
 158+			device EEPROM
 159+			#This is almost certainly not correct based on the address pins
 160+			#available to the Acclaim mapper. It's probably available up to
 161+			#2FFFFF at least and just fights with D0 from the mask ROM
 162+			last 200001
 163+			bits_read {
 164+				0 sda
 165+			}
 166+			bits_write {
 167+				0 sda
 168+				8 scl
 169+			}
 170+		}
 171+		200002 {
 172+			device ROM
 173+			offset 200000
 174+			last 2FFFFF
 175+		}
 176+	}
 177+}
 178+T-81476 {
 179+	name Frank Thomas Big Hurt Baseball
 180+	EEPROM {
 181+		type i2c
 182+		size 8192
 183+	}
 184+	map {
 185+		0 {
 186+			device ROM
 187+			last 1FFFFF
 188+		}
 189+		200000 {
 190+			device EEPROM
 191+			#This is almost certainly not correct based on the address pins
 192+			#available to the Acclaim mapper. It's probably available up to
 193+			#2FFFFF at least and just fights with D0 from the mask ROM
 194+			last 200001
 195+			bits_read {
 196+				0 sda
 197+			}
 198+			bits_write {
 199+				0 sda
 200+				8 scl
 201+			}
 202+		}
 203+		200002 {
 204+			device ROM
 205+			last 3FFFFF
 206+			offset 200000
 207+		}
 208+	}
 209+}
 210+T-50176 {
 211+	name Rings of Power
 212+	EEPROM {
 213+		type i2c
 214+		size 128
 215+	}
 216+	map {
 217+		0 {
 218+			device ROM
 219+			last FFFFF
 220+		}
 221+		200000 {
 222+			device EEPROM
 223+			last 3FFFFF
 224+			bits_read {
 225+				7 sda
 226+			}
 227+			bits_write {
 228+				6 scl
 229+				7 sda
 230+			}
 231+		}
 232+	}
 233+}
 234+T-50396 {
 235+	name NHLPA Hockey '93
 236+	EEPROM {
 237+		type i2c
 238+		size 128
 239+	}
 240+	map {
 241+		0 {
 242+			device ROM
 243+			last 7FFFF
 244+		}
 245+		200000 {
 246+			device EEPROM
 247+			last 3FFFFF
 248+			bits_read {
 249+				7 sda
 250+			}
 251+			bits_write {
 252+				6 scl
 253+				7 sda
 254+			}
 255+		}
 256+	}
 257+}
 258+T-50446 {
 259+	name John Madden Football '93
 260+	EEPROM {
 261+		type i2c
 262+		size 128
 263+	}
 264+	map {
 265+		0 {
 266+			device ROM
 267+			last FFFFF
 268+		}
 269+		200000 {
 270+			device EEPROM
 271+			last 3FFFFF
 272+			bits_read {
 273+				7 sda
 274+			}
 275+			bits_write {
 276+				6 scl
 277+				7 sda
 278+			}
 279+		}
 280+	}
 281+}
 282+T-50516 {
 283+	name John Madden Football '93: Championship Edition
 284+	EEPROM {
 285+		type i2c
 286+		size 128
 287+	}
 288+	map {
 289+		0 {
 290+			device ROM
 291+			last FFFFF
 292+		}
 293+		200000 {
 294+			device EEPROM
 295+			last 3FFFFF
 296+			bits_read {
 297+				7 sda
 298+			}
 299+			bits_write {
 300+				6 scl
 301+				7 sda
 302+			}
 303+		}
 304+	}
 305+}
 306+T-172196 {
 307+	name Madden NFL 98
 308+	SRAM {
 309+		size 16318
 310+		bus odd
 311+	}
 312+	map {
 313+		0 {
 314+			device ROM
 315+			last 1FFFFF
 316+		}
 317+		200000 {
 318+			device SRAM
 319+			last 3FFFFF
 320+		}
 321+	}
 322+}
 323+T-50606 {
 324+	name Bill Walsh College Football
 325+	EEPROM {
 326+		type i2c
 327+		size 128
 328+	}
 329+	map {
 330+		0 {
 331+			device ROM
 332+			last FFFFF
 333+		}
 334+		200000 {
 335+			device EEPROM
 336+			last 3FFFFF
 337+			bits_read {
 338+				7 sda
 339+			}
 340+			bits_write {
 341+				6 scl
 342+				7 sda
 343+			}
 344+		}
 345+	}
 346+}
 347+MK-1228 {
 348+	name Greatest Heavyweights of the Ring
 349+	EEPROM {
 350+		type i2c
 351+		size 128
 352+	}
 353+	map {
 354+		0 {
 355+			device ROM
 356+			last 1FFFFF
 357+		}
 358+		200000 {
 359+			device EEPROM
 360+			last 3FFFFF
 361+			bits_read {
 362+				0 sda
 363+			}
 364+			bits_write {
 365+				0 sda
 366+				1 scl
 367+			}
 368+		}
 369+	}
 370+}
 371+G-5538 {
 372+	name Greatest Heavyweights of the Ring
 373+	EEPROM {
 374+		type i2c
 375+		size 128
 376+	}
 377+	map {
 378+		0 {
 379+			device ROM
 380+			last 1FFFFF
 381+		}
 382+		200000 {
 383+			device EEPROM
 384+			last 3FFFFF
 385+			bits_read {
 386+				0 sda
 387+			}
 388+			bits_write {
 389+				0 sda
 390+				1 scl
 391+			}
 392+		}
 393+	}
 394+}
 395+PR-1993 {
 396+	name Greatest Heavyweights of the Ring (Prototype)
 397+	EEPROM {
 398+		type i2c
 399+		size 128
 400+	}
 401+	map {
 402+		0 {
 403+			device ROM
 404+			last 1FFFFF
 405+		}
 406+		200000 {
 407+			device EEPROM
 408+			last 3FFFFF
 409+			bits_read {
 410+				0 sda
 411+			}
 412+			bits_write {
 413+				0 sda
 414+				1 scl
 415+			}
 416+		}
 417+	}
 418+}
 419+00001211 {
 420+	name Sports Talk Baseball
 421+	EEPROM {
 422+		type i2c
 423+		size 128
 424+	}
 425+	map {
 426+		0 {
 427+			device ROM
 428+			last 1FFFFF
 429+		}
 430+		200000 {
 431+			device EEPROM
 432+			last 3FFFFF
 433+			bits_read {
 434+				0 sda
 435+			}
 436+			bits_write {
 437+				0 sda
 438+				1 scl
 439+			}
 440+		}
 441+	}
 442+}
 443+00004076 {
 444+	name Honoo no Toukyuuji Dodge Danpei
 445+	EEPROM {
 446+		type i2c
 447+		size 128
 448+	}
 449+	map {
 450+		0 {
 451+			device ROM
 452+			last 1FFFFF
 453+		}
 454+		200000 {
 455+			device EEPROM
 456+			last 3FFFFF
 457+			bits_read {
 458+				0 sda
 459+			}
 460+			bits_write {
 461+				0 sda
 462+				1 scl
 463+			}
 464+		}
 465+	}
 466+}
 467+00054503 {
 468+	name Game Toshokan
 469+	EEPROM {
 470+		type i2c
 471+		size 128
 472+	}
 473+	map {
 474+		0 {
 475+			device ROM
 476+			last 1FFFFF
 477+		}
 478+		200000 {
 479+			device EEPROM
 480+			last 3FFFFF
 481+			bits_read {
 482+				0 sda
 483+			}
 484+			bits_write {
 485+				0 sda
 486+				1 scl
 487+			}
 488+		}
 489+	}
 490+}
 491+T-120106 {
 492+	name Brian Lara Cricket
 493+	EEPROM {
 494+		type i2c
 495+		size 1024
 496+	}
 497+	map {
 498+		0 {
 499+			device ROM
 500+			last 2FFFFF
 501+		}
 502+		300000 {
 503+			device EEPROM
 504+			last 37FFFF
 505+			bits_write {
 506+				0 sda
 507+				1 scl
 508+			}
 509+		}
 510+		380000 {
 511+			device EEPROM
 512+			last 3FFFFF
 513+			bits_read {
 514+				7 sda
 515+			}
 516+		}
 517+	}
 518+}
 519+T-120146 {
 520+	name Brian Lara Cricket 96
 521+	EEPROM {
 522+		type i2c
 523+		size 8192
 524+	}
 525+	map {
 526+		0 {
 527+			device ROM
 528+			last 2FFFFF
 529+		}
 530+		300000 {
 531+			device EEPROM
 532+			last 37FFFF
 533+			bits_write {
 534+				0 sda
 535+				1 scl
 536+			}
 537+		}
 538+		380000 {
 539+			device EEPROM
 540+			last 3FFFFF
 541+			bits_read {
 542+				7 sda
 543+			}
 544+		}
 545+	}
 546+}
 547+e8ff759679a0df2b3f9ece37ef686f248d3cf37b {
 548+	name Micro Machines: Turbo Tournament '96
 549+	EEPROM {
 550+		type i2c
 551+		size 2048
 552+	}
 553+	#TODO: J-Cart
 554+	map {
 555+		0 {
 556+			device ROM
 557+			last 2FFFFF
 558+		}
 559+		300000 {
 560+			device EEPROM
 561+			last 37FFFF
 562+			bits_write {
 563+				0 sda
 564+				1 scl
 565+			}
 566+		}
 567+		380000 {
 568+			device EEPROM
 569+			last 387FFF
 570+			bits_read {
 571+				7 sda
 572+			}
 573+		}
 574+		388000 {
 575+			device jcart
 576+			last 38FFFF
 577+		}
 578+	}
 579+}
 580+9f47fcc7bb2f5921cb1c3beb06b668ffb292cb08 {
 581+	name Micro Machines: Turbo Tournament '96
 582+	EEPROM {
 583+		type i2c
 584+		size 2048
 585+	}
 586+	#TODO: J-Cart
 587+	map {
 588+		0 {
 589+			device ROM
 590+			last 2FFFFF
 591+		}
 592+		300000 {
 593+			device EEPROM
 594+			last 37FFFF
 595+			bits_write {
 596+				0 sda
 597+				1 scl
 598+			}
 599+		}
 600+		380000 {
 601+			device EEPROM
 602+			last 3FFFFF
 603+			bits_read {
 604+				7 sda
 605+			}
 606+		}
 607+	}
 608+}
 609+6d3df64ab8bb0b559f216adca62d1cdd74704a26 {
 610+	name Micro Machines: Military
 611+	EEPROM {
 612+		type i2c
 613+		size 1024
 614+	}
 615+	#TODO: J-Cart
 616+	map {
 617+		0 {
 618+			device ROM
 619+			last 2FFFFF
 620+		}
 621+		300000 {
 622+			device EEPROM
 623+			last 37FFFF
 624+			bits_write {
 625+				0 sda
 626+				1 scl
 627+			}
 628+		}
 629+		380000 {
 630+			device EEPROM
 631+			last 387FFF
 632+			bits_read {
 633+				7 sda
 634+			}
 635+		}
 636+		388000 {
 637+			device jcart
 638+			last 38FFFF
 639+		}
 640+	}
 641+}
 642+T-120096 {
 643+	name Micro Machines 2: Turbo Tournament
 644+	EEPROM {
 645+		type i2c
 646+		size 2048
 647+	}
 648+	#TODO: J-Cart
 649+	map {
 650+		0 {
 651+			device ROM
 652+			last 2FFFFF
 653+		}
 654+		300000 {
 655+			device EEPROM
 656+			last 37FFFF
 657+			bits_write {
 658+				0 sda
 659+				1 scl
 660+			}
 661+		}
 662+		380000 {
 663+			device EEPROM
 664+			last 387FFF
 665+			bits_read {
 666+				7 sda
 667+			}
 668+		}
 669+		388000 {
 670+			device jcart
 671+			last 38FFFF
 672+		}
 673+	}
 674+}
 675+MK-12056 {
 676+	name Super Street Fighter 2: The New Challengers
 677+	map {
 678+		0 {
 679+			device ROM
 680+			last 7FFFF
 681+		}
 682+		80000 {
 683+			device Sega mapper
 684+			last 3FFFFF
 685+			offset 80000
 686+		}
 687+	}
 688+}
 689+T-12056 {
 690+	name Super Street Fighter 2: The New Challengers
 691+	map {
 692+		0 {
 693+			device ROM
 694+			last 7FFFF
 695+		}
 696+		80000 {
 697+			device Sega mapper
 698+			last 3FFFFF
 699+			offset 80000
 700+		}
 701+	}
 702+}
 703+T-12043 {
 704+	name Super Street Fighter 2: The New Challengers
 705+	map {
 706+		0 {
 707+			device ROM
 708+			last 7FFFF
 709+		}
 710+		80000 {
 711+			device Sega mapper
 712+			last 3FFFFF
 713+			offset 80000
 714+		}
 715+	}
 716+}
 717+T-12046 {
 718+	name Mega Man - The Wily Wars
 719+	EEPROM {
 720+		type i2c
 721+		size 128
 722+	}
 723+	map {
 724+		0 {
 725+			device ROM
 726+			last 1FFFFF
 727+		}
 728+		200000 {
 729+			device EEPROM
 730+			last 3FFFFF
 731+			bits_read {
 732+				0 sda
 733+			}
 734+			bits_write {
 735+				0 sda
 736+				1 scl
 737+			}
 738+		}
 739+	}
 740+}
 741+T-12053 {
 742+	name Rockman Mega World
 743+	EEPROM {
 744+		type i2c
 745+		size 128
 746+	}
 747+	map {
 748+		0 {
 749+			device ROM
 750+			last 1FFFFF
 751+		}
 752+		200000 {
 753+			device EEPROM
 754+			last 3FFFFF
 755+			bits_read {
 756+				0 sda
 757+			}
 758+			bits_write {
 759+				0 sda
 760+				1 scl
 761+			}
 762+		}
 763+	}
 764+}
 765+MK-1079 {
 766+	#This entry is needed only to make this play nicely with
 767+	#S&K lock-on support. Normal 2MB cartridges with SRAM won't
 768+	#work right, but Sonic 3 has the limited SRAM-only variant
 769+	#of Sega's mapper commonly found on 4MB carts with SRAM
 770+	name Sonic the Hedgehog 3
 771+	map {
 772+		0 {
 773+			device ROM
 774+			last 1FFFFF
 775+		}
 776+		200000 {
 777+			device Sega mapper
 778+			variant save-only
 779+			offset 200000
 780+			last 3FFFFF
 781+		}
 782+	}
 783+	
 784+}
 785+MK-1563 {
 786+	name Sonic & Knuckles
 787+	map {
 788+		0 {
 789+			device ROM
 790+			last 1FFFFF
 791+		}
 792+		200000 {
 793+			device LOCK-ON
 794+			last 3FFFFF
 795+			offset 200000
 796+		}
 797+	}
 798+}
 799+G-4060 {
 800+	name Wonder Boy in Monster World
 801+	EEPROM {
 802+		type i2c
 803+		size 128
 804+	}
 805+	map {
 806+		0 {
 807+			device ROM
 808+			last 1FFFFF
 809+		}
 810+		200000 {
 811+			device EEPROM
 812+			last 3FFFFF
 813+			bits_read {
 814+				0 sda
 815+			}
 816+			bits_write {
 817+				0 sda
 818+				1 scl
 819+			}
 820+		}
 821+	}
 822+}
 823+G-4524 {
 824+	name Ninja Burai Densetsu
 825+	EEPROM {
 826+		type i2c
 827+		size 128
 828+	}
 829+	map {
 830+		0 {
 831+			device ROM
 832+			last 1FFFFF
 833+		}
 834+		200000 {
 835+			device EEPROM
 836+			last 3FFFFF
 837+			bits_read {
 838+				0 sda
 839+			}
 840+			bits_write {
 841+				0 sda
 842+				1 scl
 843+			}
 844+		}
 845+	}
 846+}
 847+T-70106- {
 848+	name Another World
 849+	#European version of this game has EUROPE in the region field rather than just E
 850+	regions E
 851+}
 852+G-004130 {
 853+	name Alien Soldier
 854+	#Japanese version of this game seems to indicate support for European consoles in
 855+	#the header. While the game does indeed run, most people probably expect 60Hz
 856+	#if they are running the Japanese version rather than the European one
 857+	regions J
 858+}
 859+G-005545 {
 860+	name Light Crusader
 861+	#Japanese version of this game seems to indicate support for European consoles in
 862+	#the header. While the game does indeed run, most people probably expect 60Hz
 863+	#if they are running the Japanese version rather than the European one
 864+	regions J
 865+}
 866+
 867+00004042 {
 868+	name Castle of Illusion: Fushigi no Oshiro Daibouken
 869+	#Has JAPAN in header rather than J, A gets interpreted as a "new-style" code
 870+	regions J
 871+}
 872+T-48036 {
 873+	name Ms. Pac-Man
 874+	#Ms. Pac-Man doesn't like 6-button controllers
 875+	device_overrides {
 876+		1 gamepad3.1
 877+		2 gamepad3.2
 878+	}
 879+}
 880+T-103026 {
 881+	name King of the Monsters
 882+	#This game won't work at all with a properly emualted 6-button controller
 883+	device_overrides {
 884+		1 gamepad3.1
 885+		2 gamepad3.2
 886+	}
 887+}
 888+T-119106 {
 889+	name Combat Cars
 890+	#Routine in the main game seems to work fine with 6-button controllers,
 891+	#but options menu has problems.
 892+	device_overrides {
 893+		1 gamepad3.1
 894+		2 gamepad3.2
 895+	}
 896+}
 897+T-113106 {
 898+	name Second Samurai
 899+	#Pause doesn't work right with a 6-button controller
 900+	device_overrides {
 901+		1 gamepad3.1
 902+		2 gamepad3.2
 903+	}
 904+}
 905+MK-1304 {
 906+	name Dungeons & Dragons - Warriors of the Eternal Sun
 907+	#Switching characters cycles too fast with a 6-button controller
 908+	device_overrides {
 909+		1 gamepad3.1
 910+		2 gamepad3.2
 911+	}
 912+}
 913+#Automatically hook up the mouse in the appropriate port for the games I've tested
 914+T-76076 {
 915+	name Nobunaga's Ambition
 916+	device_overrides {
 917+		2 mouse.1
 918+	}
 919+}
 920+T-97056 {
 921+	name Fun 'N' Games
 922+	device_overrides {
 923+		2 mouse.1
 924+	}
 925+}
 926+MK-1552 {
 927+	name Richard Scarry's Busytown
 928+	device_overrides {
 929+		1 mouse.1
 930+	}
 931+}
 932+MK-1713 {
 933+	name Wacky Worlds
 934+	device_overrides {
 935+		2 mouse.1
 936+	}
 937+}
 938+T-97056- {
 939+	name Fun 'n' Games
 940+	device_overrides {
 941+		2 mouse.1
 942+	}
 943+}
 944+T-130016 {
 945+	name Shanghai II: Dragon's Eye
 946+	device_overrides {
 947+		1 mouse.1
 948+	}
 949+}
 950+T-50286 {
 951+	name Buck Rogers: Countdown to Doomsday
 952+	SRAM {
 953+		size 8192
 954+		bus odd
 955+	}
 956+	map {
 957+		0 {
 958+			device ROM
 959+			last 1FFFFF
 960+		}
 961+		200000 {
 962+			device SRAM
 963+			last 3FFFFF
 964+		}
 965+	}
 966+}
 967+MK-1215 {
 968+	name Evander 'Real Deal' Holyfield's Boxing
 969+	EEPROM {
 970+		type i2c
 971+		size 128
 972+	}
 973+	map {
 974+		0 {
 975+			device ROM
 976+			last 1FFFFF
 977+		}
 978+		200000 {
 979+			device EEPROM
 980+			last 3FFFFF
 981+			bits_read {
 982+				0 sda
 983+			}
 984+			bits_write {
 985+				0 sda
 986+				1 scl
 987+			}
 988+		}
 989+	}
 990+}
 991+ACLD012 {
 992+	name Hardball III
 993+	SRAM {
 994+		size 32768
 995+		bus odd
 996+	}
 997+	map {
 998+		0 {
 999+			device ROM
1000+			last 1FFFFF
1001+		}
1002+		200000 {
1003+			device SRAM
1004+			last 3FFFFF
1005+		}
1006+	}
1007+}
1008+T-50166 {
1009+	name Might and Magic - Gates to Another World
1010+	SRAM {
1011+		size 32768
1012+		bus odd
1013+	}
1014+	map {
1015+		0 {
1016+			device ROM
1017+			last 1FFFFF
1018+		}
1019+		200000 {
1020+			device SRAM
1021+			last 3FFFFF
1022+		}
1023+	}
1024+}
1025+9bed099693c27a6575b394bdd150efb7cc53c5c6 {
1026+	name Atomic Robo-Kid
1027+	regions J
1028+}
1029+d366d05644eb59a14baf3c2e7281c1584630c021 {
1030+	name Might and Magic III - Isles of Terra
1031+	SRAM {
1032+		size 32768
1033+		bus odd
1034+	}
1035+	map {
1036+		0 {
1037+			device ROM
1038+			last 1FFFFF
1039+		}
1040+		200000 {
1041+			device SRAM
1042+			last 3FFFFF
1043+		}
1044+	}
1045+}
1046+8fe0806427e123717ba20478ab1410c25fa942e6 {
1047+	name Ya Se Chuan Shuo
1048+	map {
1049+		0 {
1050+			device ROM
1051+			last 3FFFFF
1052+		}
1053+		400000 {
1054+			device fixed
1055+			value 6300
1056+			last 400001
1057+		}
1058+		400002 {
1059+			device fixed
1060+			value 9800
1061+			last 400003
1062+		}
1063+		400004 {
1064+			device fixed
1065+			value C900
1066+			last 400005
1067+		}
1068+		400006 {
1069+			device fixed
1070+			value 1800
1071+			last 400007
1072+		}
1073+	}
1074+}
1075+7857c797245b52641a3d1d4512089bccb0ed5359 {
1076+	name 16 Zhang Ma Jiang
1077+	map {
1078+		0 {
1079+			device ROM
1080+			last 3FFFFF
1081+		}
1082+		400002 {
1083+			device fixed
1084+			value AA00
1085+			last 400003
1086+		}
1087+		400006 {
1088+			device fixed
1089+			value F000
1090+			last 400007
1091+		}
1092+	}
1093+}
1094+5fc4591fbb1acc64e184466c7b6287c7f64e0b7a {
1095+	name Elf Wor
1096+	map {
1097+		0 {
1098+			device ROM
1099+			last 3FFFFF
1100+		}
1101+		400000 {
1102+			device fixed
1103+			value 5500
1104+			last 400001
1105+		}
1106+		400002 {
1107+			device fixed
1108+			value 0F00
1109+			last 400003
1110+		}
1111+		400004 {
1112+			device fixed
1113+			value C900
1114+			last 400005
1115+		}
1116+		400006 {
1117+			device fixed
1118+			value 1800
1119+			last 400007
1120+		}
1121+	}
1122+}
1123+df7a2527875317406b466175f0614d343dd32117 {
1124+	name Huan Le Tao Qi Shu: Smart Mouse
1125+	map {
1126+		0 {
1127+			device ROM
1128+			last 3FFFFF
1129+		}
1130+		400000 {
1131+			device fixed
1132+			value 5500
1133+			last 400001
1134+		}
1135+		400002 {
1136+			device fixed
1137+			value 0F00
1138+			last 400003
1139+		}
1140+		400004 {
1141+			device fixed
1142+			value AA00
1143+			last 400005
1144+		}
1145+		400006 {
1146+			device fixed
1147+			value F000
1148+			last 400007
1149+		}
1150+	}
1151+}
1152+25d2d6a5ab20e16b8b42b67e5fb338421b64b29b {
1153+	name Mighty Morphin' Power Rangers: The Fighting Edition
1154+	map {
1155+		0 {
1156+			device ROM
1157+			last 3FFFFF
1158+		}
1159+		400000 {
1160+			device fixed
1161+			value 5500
1162+			last 400001
1163+		}
1164+		400002 {
1165+			device fixed
1166+			value 0F00
1167+			last 400003
1168+		}
1169+		400004 {
1170+			device fixed
1171+			value C900
1172+			last 400005
1173+		}
1174+		400006 {
1175+			device fixed
1176+			value 1800
1177+			last 400007
1178+		}
1179+	}
1180+}
1181+03f40c14624f1522d6e3105997d14e8eaba12257 {
1182+	name Super Bubble Bobble MD
1183+	map {
1184+		0 {
1185+			device ROM
1186+			last 3FFFFF
1187+		}
1188+		400000 {
1189+			device fixed
1190+			value 5500
1191+			last 400001
1192+		}
1193+		400002 {
1194+			device fixed
1195+			value 0F00
1196+			last 400003
1197+		}
1198+	}
1199+}
1200+3dca68795b6c9a16cafa5e71218d5ce83aa465fc {
1201+	name Thunderbolt II
1202+	map {
1203+		0 {
1204+			device ROM
1205+			last 3FFFFF
1206+		}
1207+		400000 {
1208+			device fixed
1209+			value 5500
1210+			last 400001
1211+		}
1212+		400006 {
1213+			device fixed
1214+			value F000
1215+			last 400007
1216+		}
1217+	}
1218+}
1219+2a561b6e47c93272fe5947084837d9f6f514ed38 {
1220+	name Squirrel King
1221+	map {
1222+		0 {
1223+			device ROM
1224+			last 3FFFFF
1225+		}
1226+		400000 {
1227+			device RAM
1228+			size 2
1229+			bus both
1230+			last 7FFFFF
1231+		}
1232+	}
1233+}
1234+
1235+#This entry is used by the GUI ROM
1236+BlstMenu {
1237+	map {
1238+		0 {
1239+			device ROM
1240+			last FFFFF
1241+		}
1242+		100000 {
1243+			device RAM
1244+			size 80000
1245+			last 17FFFF
1246+		}
1247+		180000 {
1248+			device MENU
1249+			last 1FFFFF
1250+		}
1251+	}
1252+	device_overrides {
1253+		1 gamepad3.1
1254+		2 mouse.1
1255+		ext none
1256+	}
1257+	mouse_mode absolute
1258+}
1259+
1260+6568b3a4e096159776ef8687a80d43589741fd60 {
1261+	name Magistr 16 BIOS
1262+	NOR {
1263+		size 262144
1264+		page_size 128
1265+		product_id DA45
1266+		bus even
1267+	}
1268+	map {
1269+		0 {
1270+			device ROM
1271+			last 3FFFFF
1272+		}
1273+		400000 {
1274+			device NOR
1275+			last 5FFFFF
1276+		}
1277+#		600000 {
1278+#			device Super IO
1279+#			last 7FFFFF
1280+#		}
1281+		E00000 {
1282+			device RAM
1283+			size 40000
1284+			last FFFFFF
1285+			bus both
1286+		}
1287+	}
1288+}
1289+
1290+7313c20071de0ab1cd84ac1352cb0ed1c4a4afa8 {
1291+	#This appears to be an underdump, but it seems to be the only copy floating around 
1292+	name 12-in-1
1293+	map {
1294+		0 {
1295+			device multi-game
1296+			last 3FFFFF
1297+		}
1298+	}
1299+}
1300+6b2a6de2622735f6d56c6c9c01f74daa90e355cb {
1301+	name Super 15-in-1
1302+	map {
1303+		0 {
1304+			device multi-game
1305+			last 3FFFFF
1306+		}
1307+	}
1308+}
1309+e1c041ba69da087c428dcda16850159f3caebd4b {
1310+	name Super 19-in-1
1311+	map {
1312+		0 {
1313+			device multi-game
1314+			last 3FFFFF
1315+		}
1316+	}
1317+}
1318+31c66bd13abf4ae8271c09ec5286a0ee0289dbbc {
1319+	#Designed to run on Sega Channel hardware which is RAM-based
1320+	#writes to the this RAM qutie a bit to select games
1321+	name Game no Kanzume Otokuyou
1322+	map {
1323+		0 {
1324+			device ROM
1325+			last 3FFFFF
1326+			writeable yes
1327+		}
1328+	}
1329+}
1330+cda73e4caf53cbc8f0750b69e5e7f394ad3735d1 {
1331+	name MegaWiFi Bootloader
1332+	NOR {
1333+		size 4194304
1334+		page_size 128
1335+		product_id DA45
1336+		bus both
1337+		init ROM
1338+		cmd_address1 AAB
1339+		cmd_address2 555
1340+	}
1341+	map {
1342+		0 {
1343+			device NOR
1344+			last 3FFFFF
1345+		}
1346+		A130C0 {
1347+			device megawifi
1348+			last A130CF
1349+		}
1350+	}
1351+}
1352+222a66cdb8865a7f89e5a72418413888bb400176 {
1353+	#I've personally confirmed this version had a J-Cart
1354+	#release, but unlike the other revision it runs without it
1355+	name Pete Sampras Tennis
1356+	map {
1357+		0 {
1358+			device ROM
1359+			last 1FFFFF
1360+		}
1361+		200000 {
1362+			device jcart
1363+			last 3FFFFF
1364+		}
1365+	}
1366+}
1367+4c830ace4590294bb374b4cab71ebebf44d9a07a {
1368+	#This version will not accept input if J-Cart hardware is missing
1369+	name Pete Sampras Tennis
1370+	map {
1371+		0 {
1372+			device ROM
1373+			last 1FFFFF
1374+		}
1375+		200000 {
1376+			device jcart
1377+			last 3FFFFF
1378+		}
1379+	}
1380+}
+981, -0
  1@@ -0,0 +1,981 @@
  2+#include <stdlib.h>
  3+#include <string.h>
  4+#include "config.h"
  5+#include "romdb.h"
  6+#include "util.h"
  7+#include "hash.h"
  8+#include "genesis.h"
  9+#include "menu.h"
 10+#include "xband.h"
 11+#include "realtec.h"
 12+#include "nor.h"
 13+#include "sega_mapper.h"
 14+#include "multi_game.h"
 15+#include "megawifi.h"
 16+#include "jcart.h"
 17+#include "blastem.h"
 18+
 19+#define DOM_TITLE_START 0x120
 20+#define DOM_TITLE_END 0x150
 21+#define TITLE_START DOM_TITLE_END
 22+#define TITLE_END (TITLE_START+48)
 23+#define ROM_END   0x1A4
 24+#define RAM_ID    0x1B0
 25+#define RAM_FLAGS 0x1B2
 26+#define RAM_START 0x1B4
 27+#define RAM_END   0x1B8
 28+#define REGION_START 0x1F0
 29+
 30+char const *save_type_name(uint8_t save_type)
 31+{
 32+	if (save_type == SAVE_I2C) {
 33+		return "EEPROM";
 34+	} else if(save_type == SAVE_NOR) {
 35+		return "NOR Flash";
 36+	}
 37+	return "SRAM";
 38+}
 39+
 40+tern_node *load_rom_db()
 41+{
 42+	tern_node *db = parse_bundled_config("rom.db");
 43+	if (!db) {
 44+		fatal_error("Failed to load ROM DB\n");
 45+	}
 46+	return db;
 47+}
 48+
 49+void free_rom_info(rom_info *info)
 50+{
 51+	free(info->name);
 52+	if (info->save_type != SAVE_NONE) {
 53+		free(info->save_buffer);
 54+		if (info->save_type == SAVE_I2C) {
 55+			free(info->eeprom_map);
 56+		} else if (info->save_type == SAVE_NOR) {
 57+			free(info->nor);
 58+		}
 59+	}
 60+	free(info->map);
 61+	free(info->port1_override);
 62+	free(info->port2_override);
 63+	free(info->ext_override);
 64+	free(info->mouse_mode);
 65+}
 66+
 67+void cart_serialize(system_header *sys, serialize_buffer *buf)
 68+{
 69+	if (sys->type != SYSTEM_GENESIS) {
 70+		return;
 71+	}
 72+	genesis_context *gen = (genesis_context *)sys;
 73+	if (gen->mapper_type == MAPPER_NONE) {
 74+		return;
 75+	}
 76+	start_section(buf, SECTION_MAPPER);
 77+	save_int8(buf, gen->mapper_type);
 78+	switch(gen->mapper_type)
 79+	{
 80+	case MAPPER_SEGA:
 81+		sega_mapper_serialize(gen, buf);
 82+		break;
 83+	case MAPPER_REALTEC:
 84+		realtec_serialize(gen, buf);
 85+		break;
 86+	case MAPPER_XBAND:
 87+		xband_serialize(gen, buf);
 88+		break;
 89+	case MAPPER_MULTI_GAME:
 90+		multi_game_serialize(gen, buf);
 91+		break;
 92+	}
 93+	end_section(buf);
 94+}
 95+
 96+void cart_deserialize(deserialize_buffer *buf, void *vcontext)
 97+{
 98+	genesis_context *gen = vcontext;
 99+	uint8_t mapper_type = load_int8(buf);
100+	if (mapper_type != gen->mapper_type) {
101+		warning("Mapper type mismatch, skipping load of mapper state");
102+		return;
103+	}
104+	switch(gen->mapper_type)
105+	{
106+	case MAPPER_SEGA:
107+		sega_mapper_deserialize(buf, gen);
108+		break;
109+	case MAPPER_REALTEC:
110+		realtec_deserialize(buf, gen);
111+		break;
112+	case MAPPER_XBAND:
113+		xband_deserialize(buf, gen);
114+		break;
115+	case MAPPER_MULTI_GAME:
116+		multi_game_deserialize(buf, gen);
117+		break;
118+	}
119+}
120+
121+char *get_header_name(uint8_t *rom)
122+{
123+	//TODO: Should probably prefer the title field that corresponds to the user's region preference
124+	uint8_t *last = rom + TITLE_END - 1;
125+	uint8_t *src = rom + TITLE_START;
126+	
127+	for (;;)
128+	{
129+		while (last > src && (*last <=  0x20 || *last >= 0x80))
130+		{
131+			last--;
132+		}
133+		if (last == src) {
134+			if (src == rom + TITLE_START) {
135+				src = rom + DOM_TITLE_START;
136+				last = rom + DOM_TITLE_END - 1;
137+			} else {
138+				return strdup("UNKNOWN");
139+			}
140+		} else {
141+			last++;
142+			char *ret = malloc(last - src + 1);
143+			uint8_t *dst;
144+			uint8_t last_was_space = 1;
145+			for (dst = ret; src < last; src++)
146+			{
147+				if (*src >= 0x20 && *src < 0x80) {
148+					if (*src == ' ') {
149+						if (last_was_space) {
150+							continue;
151+						}
152+						last_was_space = 1;
153+					} else {
154+						last_was_space = 0;
155+					}
156+					*(dst++) = *src;
157+				}
158+			}
159+			*dst = 0;
160+			return ret;
161+		}
162+	}
163+}
164+
165+char *region_chars = "JUEW";
166+uint8_t region_bits[] = {REGION_J, REGION_U, REGION_E, REGION_J|REGION_U|REGION_E};
167+
168+uint8_t translate_region_char(uint8_t c)
169+{	
170+	for (int i = 0; i < sizeof(region_bits); i++)
171+	{
172+		if (c == region_chars[i]) {
173+			return region_bits[i];
174+		}
175+	}
176+	uint8_t bin_region = 0;
177+	if (c >= '0' && c <= '9') {
178+		bin_region = c - '0';
179+	} else if (c >= 'A' && c <= 'F') {
180+		bin_region = c - 'A' + 0xA;
181+	} else if (c >= 'a' && c <= 'f') {
182+		bin_region = c - 'a' + 0xA;
183+	}
184+	uint8_t ret = 0;
185+	if (bin_region & 8) {
186+		ret |= REGION_E;
187+	}
188+	if (bin_region & 4) {
189+		ret |= REGION_U;
190+	}
191+	if (bin_region & 1) {
192+		ret |= REGION_J;
193+	}
194+	return ret;
195+}
196+
197+uint8_t get_header_regions(uint8_t *rom)
198+{
199+	uint8_t regions = 0;
200+	for (int i = 0; i < 3; i++)
201+	{
202+		regions |= translate_region_char(rom[REGION_START + i]);
203+	}
204+	return regions;
205+}
206+
207+uint32_t get_u32be(uint8_t *data)
208+{
209+	return *data << 24 | data[1] << 16 | data[2] << 8 | data[3];
210+}
211+
212+uint32_t calc_mask(uint32_t src_size, uint32_t start, uint32_t end)
213+{
214+	uint32_t map_size = end-start+1;
215+	if (src_size < map_size) {
216+		return nearest_pow2(src_size)-1;
217+	} else if (!start) {
218+		return 0xFFFFFF;
219+	} else {
220+		return nearest_pow2(map_size)-1;
221+	}
222+}
223+
224+uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size)
225+{
226+	return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; 
227+}
228+
229+uint32_t read_ram_header(rom_info *info, uint8_t *rom)
230+{
231+	uint32_t ram_start = get_u32be(rom + RAM_START);
232+	uint32_t ram_end = get_u32be(rom + RAM_END);
233+	uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK;
234+	ram_start &= 0xFFFFFE;
235+	ram_end |= 1;
236+	if (ram_start >= 0x800000) {
237+		info->save_buffer = NULL;
238+		return ram_start;
239+	}
240+	info->save_mask = ram_end - ram_start;
241+	uint32_t save_size = info->save_mask + 1;
242+	if (ram_flags != RAM_FLAG_BOTH) {
243+		save_size /= 2;
244+	}
245+	info->save_size = save_size;
246+	info->save_buffer = malloc(save_size);
247+	return ram_start;
248+}
249+
250+void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks)
251+{
252+	uint32_t rom_end = get_u32be(rom + ROM_END) + 1;
253+	if (size > rom_end) {
254+		rom_end = size;
255+	} else if (rom_end > nearest_pow2(size)) {
256+		rom_end = nearest_pow2(size);
257+	}
258+	if (size >= 0x80000 && !memcmp("SEGA SSF", rom + 0x100, 8)) {
259+		info->mapper_start_index = 0;
260+		info->mapper_type = MAPPER_SEGA;
261+		info->map_chunks = base_chunks + 9;
262+		info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
263+		memset(info->map, 0, sizeof(memmap_chunk)*9);
264+		memcpy(info->map+9, base_map, sizeof(memmap_chunk) * base_chunks);
265+		
266+		info->map[0].start = 0;
267+		info->map[0].end = 0x80000;
268+		info->map[0].mask = 0xFFFFFF;
269+		info->map[0].flags = MMAP_READ;
270+		info->map[0].buffer = rom;
271+		
272+		if (has_ram_header(rom, size)){
273+			read_ram_header(info, rom);
274+		}
275+		
276+		for (int i = 1; i < 8; i++)
277+		{
278+			info->map[i].start = i * 0x80000;
279+			info->map[i].end = (i + 1) * 0x80000;
280+			info->map[i].mask = 0x7FFFF;
281+			info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom;
282+			info->map[i].ptr_index = i;
283+			info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
284+			
285+			info->map[i].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL
286+			info->map[i].read_8 = (read_8_fun)read_sram_b;
287+			info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
288+			info->map[i].write_8 = (write_8_fun)write_sram_area_b;
289+			
290+		}
291+		info->map[8].start = 0xA13000;
292+		info->map[8].end = 0xA13100;
293+		info->map[8].mask = 0xFF;
294+		info->map[8].write_16 = (write_16_fun)write_bank_reg_w;
295+		info->map[8].write_8 = (write_8_fun)write_bank_reg_b;
296+		return;
297+	} else if(!memcmp("SEGA MEGAWIFI", rom + 0x100, strlen("SEGA MEGAWIFI"))) {
298+		info->mapper_type = MAPPER_NONE;
299+		info->map_chunks = base_chunks + 2;
300+		info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
301+		memset(info->map, 0, sizeof(memmap_chunk)*2);
302+		memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks);
303+		info->save_size = 0x400000;
304+		info->save_bus = RAM_FLAG_BOTH;
305+		info->save_type = SAVE_NOR;
306+		info->map[0].start = 0;
307+		info->map[0].end = 0x400000;
308+		info->map[0].mask = 0xFFFFFF;
309+		info->map[0].write_16 = nor_flash_write_w;
310+		info->map[0].write_8 = nor_flash_write_b;
311+		info->map[0].read_16 = nor_flash_read_w;
312+		info->map[0].read_8 = nor_flash_read_b;
313+		info->map[0].flags = MMAP_READ_CODE | MMAP_CODE;
314+		info->map[0].buffer = info->save_buffer = malloc(info->save_size);
315+		uint32_t init_size = size < info->save_size ? size : info->save_size;
316+		memcpy(info->save_buffer, rom, init_size);
317+		byteswap_rom(info->save_size, (uint16_t *)info->save_buffer);
318+		info->nor = calloc(1, sizeof(nor_state));
319+		nor_flash_init(info->nor, info->save_buffer, info->save_size, 128, 0xDA45, RAM_FLAG_BOTH);
320+		info->nor->cmd_address1 = 0xAAB;
321+		info->nor->cmd_address2 = 0x555;
322+		info->map[1].start = 0xA130C0;
323+		info->map[1].end = 0xA130D0;
324+		info->map[1].mask = 0xFFFFFF;
325+		if (!strcmp(
326+			"on", 
327+			tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
328+		) {
329+			info->map[1].write_16 = megawifi_write_w;
330+			info->map[1].write_8 = megawifi_write_b;
331+			info->map[1].read_16 = megawifi_read_w;
332+			info->map[1].read_8 = megawifi_read_b;
333+		} else {
334+			warning("ROM uses MegaWiFi, but it is disabled\n");
335+		}
336+		return;
337+	} else if (has_ram_header(rom, size)) {
338+		uint32_t ram_start = read_ram_header(info, rom);
339+
340+		if (info->save_buffer) {
341+			info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3);
342+			info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
343+			memset(info->map, 0, sizeof(memmap_chunk)*2);
344+			memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks);
345+
346+			if (ram_start >= rom_end) {
347+				info->map[0].end = rom_end < 0x400000 ? nearest_pow2(rom_end) - 1 : 0xFFFFFF;
348+				if (info->map[0].end > ram_start) {
349+					info->map[0].end = ram_start;
350+				}
351+				//TODO: ROM mirroring
352+				info->map[0].mask = 0xFFFFFF;
353+				info->map[0].flags = MMAP_READ;
354+				info->map[0].buffer = rom;
355+
356+				info->map[1].start = ram_start;
357+				info->map[1].mask = info->save_mask;
358+				info->map[1].end = ram_start + info->save_mask + 1;
359+				info->map[1].flags = MMAP_READ | MMAP_WRITE;
360+
361+				if (info->save_type == RAM_FLAG_ODD) {
362+					info->map[1].flags |= MMAP_ONLY_ODD;
363+				} else if (info->save_type == RAM_FLAG_EVEN) {
364+					info->map[1].flags |= MMAP_ONLY_EVEN;
365+				}
366+				info->map[1].buffer = info->save_buffer;
367+			} else {
368+				//Assume the standard Sega mapper
369+				info->mapper_type = MAPPER_SEGA;
370+				info->map[0].end = 0x200000;
371+				info->map[0].mask = 0xFFFFFF;
372+				info->map[0].flags = MMAP_READ;
373+				info->map[0].buffer = rom;
374+
375+				info->map[1].start = 0x200000;
376+				info->map[1].end = 0x400000;
377+				info->map[1].mask = 0x1FFFFF;
378+				info->map[1].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL;
379+				info->map[1].ptr_index = info->mapper_start_index = 0;
380+				info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
381+				info->map[1].read_8 = (read_8_fun)read_sram_b;
382+				info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
383+				info->map[1].write_8 = (write_8_fun)write_sram_area_b;
384+				info->map[1].buffer = rom + 0x200000;
385+
386+				memmap_chunk *last = info->map + info->map_chunks - 1;
387+				memset(last, 0, sizeof(memmap_chunk));
388+				last->start = 0xA13000;
389+				last->end = 0xA13100;
390+				last->mask = 0xFF;
391+				last->write_16 = (write_16_fun)write_bank_reg_w;
392+				last->write_8 = (write_8_fun)write_bank_reg_b;
393+			}
394+			return;
395+		}
396+	}
397+	
398+	info->map_chunks = base_chunks + 1;
399+	info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
400+	memset(info->map, 0, sizeof(memmap_chunk));
401+	memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks);
402+
403+	info->map[0].end = rom_end > 0x400000 ? rom_end : 0x400000;
404+	info->map[0].mask = rom_end < 0x400000 ? nearest_pow2(rom_end) - 1 : 0xFFFFFF;
405+	info->map[0].flags = MMAP_READ;
406+	info->map[0].buffer = rom;
407+	info->save_type = SAVE_NONE;
408+}
409+
410+rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
411+{
412+	rom_info info;
413+	info.mapper_type = MAPPER_NONE;
414+	info.name = get_header_name(rom);
415+	info.regions = get_header_regions(rom);
416+	info.is_save_lock_on = 0;
417+	info.rom = rom;
418+	info.rom_size = rom_size;
419+	add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
420+	info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
421+	return info;
422+}
423+
424+typedef struct {
425+	rom_info     *info;
426+	uint8_t      *rom;
427+	uint8_t      *lock_on;
428+	tern_node    *root;
429+	tern_node    *rom_db;
430+	uint32_t     rom_size;
431+	uint32_t     lock_on_size;
432+	int          index;
433+	int          num_els;
434+	uint16_t     ptr_index;
435+} map_iter_state;
436+
437+void eeprom_read_fun(char *key, tern_val val, uint8_t valtype, void *data)
438+{
439+	int bit = atoi(key);
440+	if (bit < 0 || bit > 15) {
441+		fprintf(stderr, "bit %s is out of range", key);
442+		return;
443+	}
444+	if (valtype != TVAL_PTR) {
445+		fprintf(stderr, "bit %s has a non-scalar value", key);
446+		return;
447+	}
448+	char *pin = val.ptrval;
449+	if (strcmp(pin, "sda")) {
450+		fprintf(stderr, "bit %s is connected to unrecognized read pin %s", key, pin);
451+		return;
452+	}
453+	eeprom_map *map = data;
454+	map->sda_read_bit = bit;
455+}
456+
457+void eeprom_write_fun(char *key, tern_val val, uint8_t valtype, void *data)
458+{
459+	int bit = atoi(key);
460+	if (bit < 0 || bit > 15) {
461+		fprintf(stderr, "bit %s is out of range", key);
462+		return;
463+	}
464+	if (valtype != TVAL_PTR) {
465+		fprintf(stderr, "bit %s has a non-scalar value", key);
466+		return;
467+	}
468+	char *pin = val.ptrval;
469+	eeprom_map *map = data;
470+	if (!strcmp(pin, "sda")) {
471+		map->sda_write_mask = 1 << bit;
472+		return;
473+	}
474+	if (!strcmp(pin, "scl")) {
475+		map->scl_mask = 1 << bit;
476+		return;
477+	}
478+	fprintf(stderr, "bit %s is connected to unrecognized write pin %s", key, pin);
479+}
480+
481+void process_sram_def(char *key, map_iter_state *state)
482+{
483+	if (!state->info->save_size) {
484+		char * size = tern_find_path(state->root, "SRAM\0size\0", TVAL_PTR).ptrval;
485+		if (!size) {
486+			fatal_error("ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key);
487+		}
488+		state->info->save_size = atoi(size);
489+		if (!state->info->save_size) {
490+			fatal_error("SRAM size %s is invalid\n", size);
491+		}
492+		state->info->save_mask = nearest_pow2(state->info->save_size)-1;
493+		state->info->save_buffer = malloc(state->info->save_size);
494+		memset(state->info->save_buffer, 0, state->info->save_size);
495+		char *bus = tern_find_path(state->root, "SRAM\0bus\0", TVAL_PTR).ptrval;
496+		if (!strcmp(bus, "odd")) {
497+			state->info->save_type = RAM_FLAG_ODD;
498+		} else if(!strcmp(bus, "even")) {
499+			state->info->save_type = RAM_FLAG_EVEN;
500+		} else {
501+			state->info->save_type = RAM_FLAG_BOTH;
502+		}
503+	}
504+}
505+
506+void process_eeprom_def(char * key, map_iter_state *state)
507+{
508+	if (!state->info->save_size) {
509+		char * size = tern_find_path(state->root, "EEPROM\0size\0", TVAL_PTR).ptrval;
510+		if (!size) {
511+			fatal_error("ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key);
512+		}
513+		state->info->save_size = atoi(size);
514+		if (!state->info->save_size) {
515+			fatal_error("EEPROM size %s is invalid\n", size);
516+		}
517+		char *etype = tern_find_path(state->root, "EEPROM\0type\0", TVAL_PTR).ptrval;
518+		if (!etype) {
519+			etype = "i2c";
520+		}
521+		if (!strcmp(etype, "i2c")) {
522+			state->info->save_type = SAVE_I2C;
523+		} else {
524+			fatal_error("EEPROM type %s is invalid\n", etype);
525+		}
526+		state->info->save_buffer = malloc(state->info->save_size);
527+		memset(state->info->save_buffer, 0xFF, state->info->save_size);
528+		state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els);
529+		memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els);
530+	}
531+}
532+
533+void process_nor_def(char *key, map_iter_state *state)
534+{
535+	if (!state->info->save_size) {
536+		char *size = tern_find_path(state->root, "NOR\0size\0", TVAL_PTR).ptrval;
537+		if (!size) {
538+			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR size is not defined\n", state->index, key);
539+		}
540+		state->info->save_size = atoi(size);
541+		if (!state->info->save_size) {
542+			fatal_error("NOR size %s is invalid\n", size);
543+		}
544+		char *page_size = tern_find_path(state->root, "NOR\0page_size\0", TVAL_PTR).ptrval;
545+		if (!page_size) {
546+			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR page size is not defined\n", state->index, key);
547+		}
548+		uint32_t save_page_size = atoi(page_size);
549+		if (!save_page_size) {
550+			fatal_error("NOR page size %s is invalid\n", page_size);
551+		}
552+		char *product_id = tern_find_path(state->root, "NOR\0product_id\0", TVAL_PTR).ptrval;
553+		if (!product_id) {
554+			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR product ID is not defined\n", state->index, key);
555+		}
556+		uint16_t save_product_id = strtol(product_id, NULL, 16);
557+		char *bus = tern_find_path(state->root, "NOR\0bus\0", TVAL_PTR).ptrval;
558+		if (!strcmp(bus, "odd")) {
559+			state->info->save_bus = RAM_FLAG_ODD;
560+		} else if(!strcmp(bus, "even")) {
561+			state->info->save_bus = RAM_FLAG_EVEN;
562+		} else {
563+			state->info->save_bus = RAM_FLAG_BOTH;
564+		}
565+		state->info->save_type = SAVE_NOR;
566+		state->info->save_buffer = malloc(state->info->save_size);
567+		char *init = tern_find_path_default(state->root, "NOR\0init\0", (tern_val){.ptrval="FF"}, TVAL_PTR).ptrval;
568+		if (!strcmp(init, "ROM")) {
569+			uint32_t init_size = state->rom_size > state->info->save_size ? state->info->save_size : state->rom_size;
570+			memcpy(state->info->save_buffer, state->rom, init_size);
571+			if (state->info->save_bus == RAM_FLAG_BOTH) {
572+				byteswap_rom(state->info->save_size, (uint16_t *)state->info->save_buffer);
573+			}
574+		} else {
575+			memset(state->info->save_buffer, strtol(init, NULL, 16), state->info->save_size);
576+		}
577+		state->info->nor = calloc(1, sizeof(nor_state));
578+		nor_flash_init(state->info->nor, state->info->save_buffer, state->info->save_size, save_page_size, save_product_id, state->info->save_bus);
579+		char *cmd1 = tern_find_path(state->root, "NOR\0cmd_address1\0", TVAL_PTR).ptrval;
580+		if (cmd1) {
581+			state->info->nor->cmd_address1 = strtol(cmd1, NULL, 16);
582+		}
583+		char *cmd2 = tern_find_path(state->root, "NOR\0cmd_address2\0", TVAL_PTR).ptrval;
584+		if (cmd2) {
585+			state->info->nor->cmd_address2 = strtol(cmd2, NULL, 16);
586+		}
587+	}
588+}
589+
590+void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_state *state)
591+{
592+	eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom;
593+	eep_map->start = start;
594+	eep_map->end = end;
595+	eep_map->sda_read_bit = 0xFF;
596+	tern_node * bits_read = tern_find_node(node, "bits_read");
597+	if (bits_read) {
598+		tern_foreach(bits_read, eeprom_read_fun, eep_map);
599+	}
600+	tern_node * bits_write = tern_find_node(node, "bits_write");
601+	if (bits_write) {
602+		tern_foreach(bits_write, eeprom_write_fun, eep_map);
603+	}
604+	debug_message("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask);
605+	state->info->num_eeprom++;
606+}
607+
608+void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
609+{
610+	map_iter_state *state = data;
611+	if (valtype != TVAL_NODE) {
612+		fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key);
613+	}
614+	tern_node *node = val.ptrval;
615+	uint32_t start = strtol(key, NULL, 16);
616+	uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16);
617+	if (!end || end < start) {
618+		fatal_error("'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key);
619+	}
620+	char * dtype = tern_find_ptr_default(node, "device", "ROM");
621+	uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16);
622+	memmap_chunk *map = state->info->map + state->index;
623+	map->start = start;
624+	map->end = end + 1;
625+	if (!strcmp(dtype, "ROM")) {
626+		map->buffer = state->rom + offset;
627+		map->mask = calc_mask(state->rom_size - offset, start, end);
628+		if (strcmp(tern_find_ptr_default(node, "writeable", "no"), "yes")) {
629+			map->flags = MMAP_READ;
630+		} else {
631+			map->flags = MMAP_READ | MMAP_WRITE | MMAP_CODE;
632+		}
633+	} else if (!strcmp(dtype, "LOCK-ON")) {
634+		rom_info lock_info;
635+		if (state->lock_on) {
636+			lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0);
637+		} else if (state->rom_size > start) {
638+			//This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks
639+			lock_info = configure_rom(state->rom_db, state->rom + start, state->rom_size - start, NULL, 0, NULL, 0);
640+		} else {
641+			//skip this entry if there is no lock on cartridge attached
642+			return;
643+		}
644+		uint32_t matching_chunks = 0;
645+		for (int i = 0; i < lock_info.map_chunks; i++)
646+		{
647+			if (lock_info.map[i].start < 0xC00000 && lock_info.map[i].end > 0x200000) {
648+				matching_chunks++;
649+			}
650+		}
651+		if (matching_chunks == 0) {
652+			//Nothing mapped in the relevant range for the lock-on cart, ignore this mapping
653+			free_rom_info(&lock_info);
654+			return;
655+		} else if (matching_chunks > 1) {
656+			state->info->map_chunks += matching_chunks - 1;
657+			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
658+			memset(state->info->map + state->info->map_chunks - (matching_chunks - 1), 0, sizeof(memmap_chunk) * (matching_chunks - 1));
659+			map = state->info->map + state->index;
660+		}
661+		for (int i = 0; i < lock_info.map_chunks; i++)
662+		{
663+			if (lock_info.map[i].start >= 0xC00000 || lock_info.map[i].end <= 0x200000) {
664+				continue;
665+			}
666+			*map = lock_info.map[i];
667+			if (map->start < 0x200000) {
668+				if (map->buffer) {
669+					map->buffer += (0x200000 - map->start) & ((map->flags & MMAP_AUX_BUFF) ? map->aux_mask : map->mask);
670+				}
671+				map->start = 0x200000;
672+			}
673+			map++;
674+			state->index++;
675+		}
676+		if (state->info->save_type == SAVE_NONE && lock_info.save_type != SAVE_NONE) {
677+			//main cart has no save device, but lock-on cart does
678+			if (state->lock_on) {
679+				state->info->is_save_lock_on = 1;
680+			}
681+			state->info->save_buffer = lock_info.save_buffer;
682+			state->info->save_size = lock_info.save_size;
683+			state->info->save_mask = lock_info.save_mask;
684+			state->info->nor = lock_info.nor;
685+			state->info->save_type = lock_info.save_type;
686+			state->info->save_bus = lock_info.save_bus;
687+			lock_info.save_buffer = NULL;
688+			lock_info.save_type = SAVE_NONE;
689+		}
690+		free_rom_info(&lock_info);
691+		return;
692+	} else if (!strcmp(dtype, "EEPROM")) {
693+		process_eeprom_def(key, state);
694+		add_eeprom_map(node, start, end, state);
695+
696+		map->write_16 = write_eeprom_i2c_w;
697+		map->write_8 = write_eeprom_i2c_b;
698+		map->read_16 = read_eeprom_i2c_w;
699+		map->read_8 = read_eeprom_i2c_b;
700+		map->mask = 0xFFFFFF;
701+	} else if (!strcmp(dtype, "SRAM")) {
702+		process_sram_def(key, state);
703+		map->buffer = state->info->save_buffer + offset;
704+		map->flags = MMAP_READ | MMAP_WRITE;
705+		if (state->info->save_type == RAM_FLAG_ODD) {
706+			map->flags |= MMAP_ONLY_ODD;
707+		} else if(state->info->save_type == RAM_FLAG_EVEN) {
708+			map->flags |= MMAP_ONLY_EVEN;
709+		}
710+		map->mask = calc_mask(state->info->save_size, start, end);
711+	} else if (!strcmp(dtype, "RAM")) {
712+		uint32_t size = strtol(tern_find_ptr_default(node, "size", "0"), NULL, 16);
713+		if (!size || size > map->end - map->start) {
714+			size = map->end - map->start;
715+		}
716+		map->buffer = malloc(size);
717+		map->mask = calc_mask(size, start, end);
718+		map->flags = MMAP_READ | MMAP_WRITE;
719+		char *bus = tern_find_ptr_default(node, "bus", "both");
720+		if (!strcmp(bus, "odd")) {
721+			map->flags |= MMAP_ONLY_ODD;
722+		} else if (!strcmp(bus, "even")) {
723+			map->flags |= MMAP_ONLY_EVEN;
724+		} else {
725+			map->flags |= MMAP_CODE;
726+		}
727+	} else if (!strcmp(dtype, "NOR")) {
728+		process_nor_def(key, state);
729+		
730+		map->write_16 = nor_flash_write_w;
731+		map->write_8 = nor_flash_write_b;
732+		map->read_16 = nor_flash_read_w;
733+		map->read_8 = nor_flash_read_b;
734+		if (state->info->save_bus == RAM_FLAG_BOTH) {
735+			map->flags |= MMAP_READ_CODE | MMAP_CODE;
736+			map->buffer = state->info->save_buffer;
737+		}
738+		map->mask = 0xFFFFFF;
739+	} else if (!strcmp(dtype, "Sega mapper")) {
740+		state->info->mapper_type = MAPPER_SEGA;
741+		state->info->mapper_start_index = state->ptr_index++;
742+		char *variant = tern_find_ptr_default(node, "variant", "full");
743+		char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
744+		if (save_device && !strcmp(save_device, "EEPROM")) {
745+			process_eeprom_def(key, state);
746+			add_eeprom_map(node, start & map->mask, end & map->mask, state);
747+		} else if (save_device && !strcmp(save_device, "SRAM")) {
748+			process_sram_def(key, state);
749+		} else if(has_ram_header(state->rom, state->rom_size)) {
750+			//no save definition in ROM DB entry, but there is an SRAM header
751+			//this support is mostly to handle homebrew that uses the SSF2 product ID
752+			//in an attempt to signal desire for the full Sega/SSF2 mapper, but also uses SRAM unlike SSF2
753+			read_ram_header(state->info, state->rom);
754+		}
755+		if (!strcmp(variant, "save-only")) {
756+			state->info->map_chunks+=1;
757+			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
758+			memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
759+			map = state->info->map + state->index;
760+			map->start = start;
761+			map->end = end;
762+			offset &= nearest_pow2(state->rom_size) - 1;
763+			map->buffer = state->rom + offset;
764+			map->mask = calc_mask(state->rom_size - offset, start, end);
765+			map->ptr_index = state->info->mapper_start_index;
766+			map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
767+			if (save_device && !strcmp(save_device, "EEPROM")) {
768+				map->write_16 = write_eeprom_i2c_w;
769+				map->write_8 = write_eeprom_i2c_b;
770+				map->read_16 = read_eeprom_i2c_w;
771+				map->read_8 = read_eeprom_i2c_b;
772+			} else {
773+				map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[ptr_idx] == NULL
774+				map->read_8 = (read_8_fun)read_sram_b;
775+				map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
776+				map->write_8 = (write_8_fun)write_sram_area_b;
777+			}
778+			state->index++;
779+			map++;
780+		} else {
781+			state->info->map_chunks+=7;
782+			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
783+			memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7);
784+			map = state->info->map + state->index;
785+			for (int i = 0; i < 7; i++, state->index++, map++)
786+			{
787+				map->start = start + i * 0x80000;
788+				map->end = start + (i + 1) * 0x80000;
789+				map->mask = 0x7FFFF;
790+				map->buffer = state->rom + offset + i * 0x80000;
791+				map->ptr_index = state->ptr_index++;
792+				if (i < 3) {
793+					map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
794+				} else {
795+					map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
796+					if (save_device && !strcmp(save_device, "EEPROM")) {
797+						map->write_16 = write_eeprom_i2c_w;
798+						map->write_8 = write_eeprom_i2c_b;
799+						map->read_16 = read_eeprom_i2c_w;
800+						map->read_8 = read_eeprom_i2c_b;
801+					} else {
802+						map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
803+						map->read_8 = (read_8_fun)read_sram_b;
804+						map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
805+						map->write_8 = (write_8_fun)write_sram_area_b;
806+					}
807+				}
808+			}
809+		}
810+		map->start = 0xA13000;
811+		map->end = 0xA13100;
812+		map->mask = 0xFF;
813+		map->write_16 = (write_16_fun)write_bank_reg_w;
814+		map->write_8 = (write_8_fun)write_bank_reg_b;
815+	} else if (!strcmp(dtype, "MENU")) {
816+		//fake hardware for supporting menu
817+		map->buffer = NULL;
818+		map->mask = 0xFF;
819+		map->write_16 = menu_write_w;
820+		map->read_16 = menu_read_w;
821+	} else if (!strcmp(dtype, "fixed")) {
822+		uint16_t *value =  malloc(2);
823+		map->buffer = value;
824+		map->mask = 0;
825+		map->flags = MMAP_READ;
826+		*value = strtol(tern_find_ptr_default(node, "value", "0"), NULL, 16);
827+	} else if (!strcmp(dtype, "multi-game")) {
828+		state->info->mapper_type = MAPPER_MULTI_GAME;
829+		state->info->mapper_start_index = state->ptr_index++;
830+		//make a mirror copy of the ROM so we can efficiently support arbitrary start offsets
831+		state->rom = realloc(state->rom, state->rom_size * 2);
832+		memcpy(state->rom + state->rom_size, state->rom, state->rom_size);
833+		state->rom_size *= 2;
834+		//make room for an extra map entry
835+		state->info->map_chunks+=1;
836+		state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
837+		memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
838+		map = state->info->map + state->index;
839+		map->buffer = state->rom;
840+		map->mask = calc_mask(state->rom_size, start, end);
841+		map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
842+		map->ptr_index = state->info->mapper_start_index;
843+		map++;
844+		state->index++;
845+		map->start = 0xA13000;
846+		map->end = 0xA13100;
847+		map->mask = 0xFF;
848+		map->write_16 = write_multi_game_w;
849+		map->write_8 = write_multi_game_b;
850+	} else if (!strcmp(dtype, "megawifi")) {
851+		if (!strcmp(
852+			"on", 
853+			tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
854+		) {
855+			map->write_16 = megawifi_write_w;
856+			map->write_8 = megawifi_write_b;
857+			map->read_16 = megawifi_read_w;
858+			map->read_8 = megawifi_read_b;
859+			map->mask = 0xFFFFFF;
860+		} else {
861+			warning("ROM uses MegaWiFi, but it is disabled\n");
862+			return;
863+		}
864+	} else if (!strcmp(dtype, "jcart")) {
865+		state->info->mapper_type = MAPPER_JCART;
866+		map->write_16 = jcart_write_w;
867+		map->write_8 = jcart_write_b;
868+		map->read_16 = jcart_read_w;
869+		map->read_8 = jcart_read_b;
870+		map->mask = 0xFFFFFF;
871+	} else {
872+		fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
873+	}
874+	state->index++;
875+}
876+
877+rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks)
878+{
879+	uint8_t product_id[GAME_ID_LEN+1];
880+	uint8_t *rom = vrom;
881+	product_id[GAME_ID_LEN] = 0;
882+	for (int i = 0; i < GAME_ID_LEN; i++)
883+	{
884+		if (rom[GAME_ID_OFF + i] <= ' ') {
885+			product_id[i] = 0;
886+			break;
887+		}
888+		product_id[i] = rom[GAME_ID_OFF + i];
889+
890+	}
891+	debug_message("Product ID: %s\n", product_id);
892+	uint8_t raw_hash[20];
893+	sha1(vrom, rom_size, raw_hash);
894+	uint8_t hex_hash[41];
895+	bin_to_hex(hex_hash, raw_hash, 20);
896+	debug_message("SHA1: %s\n", hex_hash);
897+	tern_node * entry = tern_find_node(rom_db, hex_hash);
898+	if (!entry) {
899+		entry = tern_find_node(rom_db, product_id);
900+	}
901+	if (!entry) {
902+		debug_message("Not found in ROM DB, examining header\n\n");
903+		if (xband_detect(rom, rom_size)) {
904+			return xband_configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks);
905+		}
906+		if (realtec_detect(rom, rom_size)) {
907+			return realtec_configure_rom(rom, rom_size, base_map, base_chunks);
908+		}
909+		return configure_rom_heuristics(rom, rom_size, base_map, base_chunks);
910+	}
911+	rom_info info;
912+	info.mapper_type = MAPPER_NONE;
913+	info.name = tern_find_ptr(entry, "name");
914+	if (info.name) {
915+		debug_message("Found name: %s\n\n", info.name);
916+		info.name = strdup(info.name);
917+	} else {
918+		info.name = get_header_name(rom);
919+	}
920+
921+	char *dbreg = tern_find_ptr(entry, "regions");
922+	info.regions = 0;
923+	if (dbreg) {
924+		while (*dbreg != 0)
925+		{
926+			info.regions |= translate_region_char(*(dbreg++));
927+		}
928+	}
929+	if (!info.regions) {
930+		info.regions = get_header_regions(rom);
931+	}
932+
933+	info.is_save_lock_on = 0;
934+	info.rom = vrom;
935+	info.rom_size = rom_size;
936+	tern_node *map = tern_find_node(entry, "map");
937+	if (map) {
938+		info.save_type = SAVE_NONE;
939+		info.map_chunks = tern_count(map);
940+		if (info.map_chunks) {
941+			info.map_chunks += base_chunks;
942+			info.save_buffer = NULL;
943+			info.save_size = 0;
944+			info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
945+			info.eeprom_map = NULL;
946+			info.num_eeprom = 0;
947+			memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks);
948+			map_iter_state state = {
949+				.info = &info, 
950+				.rom = rom, 
951+				.lock_on = lock_on,
952+				.root = entry,
953+				.rom_db = rom_db,
954+				.rom_size = rom_size, 
955+				.lock_on_size = lock_on_size,
956+				.index = 0, 
957+				.num_els = info.map_chunks - base_chunks,
958+				.ptr_index = 0
959+			};
960+			tern_foreach(map, map_iter_fun, &state);
961+			memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);
962+			info.rom = state.rom;
963+			info.rom_size = state.rom_size;
964+		} else {
965+			add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
966+		}
967+	} else {
968+		add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
969+	}
970+
971+	tern_node *device_overrides = tern_find_node(entry, "device_overrides");
972+	if (device_overrides) {
973+		info.port1_override = tern_find_ptr(device_overrides, "1");
974+		info.port2_override = tern_find_ptr(device_overrides, "2");
975+		info.ext_override = tern_find_ptr(device_overrides, "ext");
976+	} else {
977+		info.port1_override = info.port2_override = info.ext_override = NULL;
978+	}
979+	info.mouse_mode = tern_find_ptr(entry, "mouse_mode");
980+
981+	return info;
982+}
+96, -0
 1@@ -0,0 +1,96 @@
 2+#ifndef ROMDB_H_
 3+#define ROMDB_H_
 4+
 5+#define REGION_J 1
 6+#define REGION_U 2
 7+#define REGION_E 4
 8+
 9+#define RAM_FLAG_ODD  0x18
10+#define RAM_FLAG_EVEN 0x10
11+#define RAM_FLAG_BOTH 0x00
12+#define RAM_FLAG_MASK RAM_FLAG_ODD
13+#define SAVE_I2C      0x01
14+#define SAVE_NOR      0x02
15+#define SAVE_NONE     0xFF
16+
17+#include "tern.h"
18+#include "serialize.h"
19+
20+typedef struct {
21+	uint32_t     start;
22+	uint32_t     end;
23+	uint16_t     sda_write_mask;
24+	uint16_t     scl_mask;
25+	uint8_t      sda_read_bit;
26+} eeprom_map;
27+
28+typedef struct {
29+	uint8_t     *buffer;
30+	uint8_t     *page_buffer;
31+	uint32_t    size;
32+	uint32_t    page_size;
33+	uint32_t    current_page;
34+	uint32_t    last_write_cycle;
35+	uint32_t    cmd_address1;
36+	uint32_t    cmd_address2;
37+	uint16_t    product_id;
38+	uint8_t     mode;
39+	uint8_t     cmd_state;
40+	uint8_t     alt_cmd;
41+	uint8_t     bus_flags;
42+} nor_state;
43+
44+enum {
45+	MAPPER_NONE,
46+	MAPPER_SEGA,
47+	MAPPER_REALTEC,
48+	MAPPER_XBAND,
49+	MAPPER_MULTI_GAME,
50+	MAPPER_JCART
51+};
52+
53+
54+typedef struct rom_info rom_info;
55+
56+#include "memmap.h"
57+
58+struct rom_info {
59+	char          *name;
60+	memmap_chunk  *map;
61+	uint8_t       *save_buffer;
62+	void          *rom;
63+	eeprom_map    *eeprom_map;
64+	char          *port1_override;
65+	char          *port2_override;
66+	char          *ext_override;
67+	char          *mouse_mode;
68+	nor_state     *nor;
69+	uint32_t      num_eeprom;
70+	uint32_t      map_chunks;
71+	uint32_t      rom_size;
72+	uint32_t      save_size;
73+	uint32_t      save_mask;
74+	uint16_t      mapper_start_index;
75+	uint8_t       save_type;
76+	uint8_t       save_bus; //only used for NOR currently
77+	uint8_t       mapper_type;
78+	uint8_t       regions;
79+	uint8_t       is_save_lock_on; //Does the save buffer actually belong to a lock-on cart?
80+};
81+
82+#define GAME_ID_OFF 0x183
83+#define GAME_ID_LEN 8
84+
85+tern_node *load_rom_db();
86+rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks);
87+rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks);
88+uint8_t translate_region_char(uint8_t c);
89+char const *save_type_name(uint8_t save_type);
90+//Note: free_rom_info only frees things pointed to by a rom_info struct, not the struct itself
91+//this is because rom_info structs are typically stack allocated
92+void free_rom_info(rom_info *info);
93+typedef struct system_header system_header;
94+void cart_serialize(system_header *sys, serialize_buffer *buf);
95+void cart_deserialize(deserialize_buffer *buf, void *vcontext);
96+
97+#endif //ROMDB_H_
+73, -0
 1@@ -0,0 +1,73 @@
 2+#include <string.h>
 3+#include <stdlib.h>
 4+#include "saves.h"
 5+#include "util.h"
 6+
 7+//0123456789012345678901234678
 8+//Slot N - December 31st, XXXX
 9+#define MAX_DESC_SIZE 40
10+
11+char *get_slot_name(system_header *system, uint32_t slot_index, char *ext)
12+{
13+	if (!system->save_dir) {
14+		return NULL;
15+	}
16+	char *fname;
17+	if (slot_index < 10) {
18+		size_t name_len = strlen("slot_N.") + strlen(ext) + 1;
19+		fname = malloc(name_len);
20+		snprintf(fname, name_len, "slot_%d.%s", slot_index, ext);
21+	} else {
22+		size_t name_len = strlen("quicksave.") + strlen(ext) + 1;
23+		fname = malloc(name_len);
24+		snprintf(fname, name_len, "quicksave.%s", ext);
25+	}
26+	char const *parts[] = {system->save_dir, PATH_SEP, fname};
27+	char *ret = alloc_concat_m(3, parts);
28+	free(fname);
29+	return ret;
30+}
31+
32+save_slot_info *get_slot_info(system_header *system, uint32_t *num_out)
33+{
34+	save_slot_info *dst = calloc(11, sizeof(save_slot_info));
35+	time_t modtime;
36+	struct tm ltime;
37+	for (uint32_t i = 0; i <= QUICK_SAVE_SLOT; i++)
38+	{
39+		char * cur = dst[i].desc = malloc(MAX_DESC_SIZE);
40+		char * fname = get_slot_name(system, i, "state");
41+		modtime = get_modification_time(fname);
42+		free(fname);
43+		if (!modtime && system->type == SYSTEM_GENESIS) {
44+			fname = get_slot_name(system, i, "gst");
45+			modtime = get_modification_time(fname);
46+			free(fname);
47+		}
48+		if (i == QUICK_SAVE_SLOT) {
49+			cur += snprintf(cur, MAX_DESC_SIZE, "Quick - ");
50+		} else {
51+			cur += snprintf(cur, MAX_DESC_SIZE, "Slot %d - ", i);
52+		}
53+		if (modtime) {
54+			strftime(cur, MAX_DESC_SIZE - (cur - dst->desc), "%c", localtime_r(&modtime, &ltime));
55+		} else {
56+			strcpy(cur, "EMPTY");
57+		}
58+		dst[i].modification_time = modtime;
59+	}
60+	*num_out = QUICK_SAVE_SLOT + 1;
61+	return dst;
62+}
63+
64+void free_slot_info(save_slot_info *slots)
65+{
66+	if (!slots) {
67+		return;
68+	}
69+	for (uint32_t i = 0; i <= QUICK_SAVE_SLOT; i++)
70+	{
71+		free(slots[i].desc);
72+	}
73+	free(slots);
74+}
+20, -0
 1@@ -0,0 +1,20 @@
 2+#ifndef SAVES_H_
 3+#define SAVES_H_
 4+
 5+#include <time.h>
 6+#include <stdint.h>
 7+#include "system.h"
 8+
 9+#define QUICK_SAVE_SLOT 10
10+#define SERIALIZE_SLOT 11
11+
12+typedef struct {
13+	char   *desc;
14+	time_t modification_time;
15+} save_slot_info;
16+
17+char *get_slot_name(system_header *system, uint32_t slot_index, char *ext);
18+save_slot_info *get_slot_info(system_header *system, uint32_t *num_out);
19+void free_slot_info(save_slot_info *slots);
20+
21+#endif //SAVES_H_
+148, -0
  1@@ -0,0 +1,148 @@
  2+#include "genesis.h"
  3+
  4+uint16_t read_sram_w(uint32_t address, m68k_context * context)
  5+{
  6+	genesis_context * gen = context->system;
  7+	address &= gen->save_ram_mask;
  8+	switch(gen->save_type)
  9+	{
 10+	case RAM_FLAG_BOTH:
 11+		return gen->save_storage[address] << 8 | gen->save_storage[address+1];
 12+	case RAM_FLAG_EVEN:
 13+		return gen->save_storage[address >> 1] << 8 | 0xFF;
 14+	case RAM_FLAG_ODD:
 15+		return gen->save_storage[address >> 1] | 0xFF00;
 16+	}
 17+	return 0xFFFF;//We should never get here
 18+}
 19+
 20+uint8_t read_sram_b(uint32_t address, m68k_context * context)
 21+{
 22+	genesis_context * gen = context->system;
 23+	address &= gen->save_ram_mask;
 24+	switch(gen->save_type)
 25+	{
 26+	case RAM_FLAG_BOTH:
 27+		return gen->save_storage[address];
 28+	case RAM_FLAG_EVEN:
 29+		if (address & 1) {
 30+			return 0xFF;
 31+		} else {
 32+			return gen->save_storage[address >> 1];
 33+		}
 34+	case RAM_FLAG_ODD:
 35+		if (address & 1) {
 36+			return gen->save_storage[address >> 1];
 37+		} else {
 38+			return 0xFF;
 39+		}
 40+	}
 41+	return 0xFF;//We should never get here
 42+}
 43+
 44+m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value)
 45+{
 46+	genesis_context * gen = context->system;
 47+	if ((gen->bank_regs[0] & 0x3) == 1) {
 48+		address &= gen->save_ram_mask;
 49+		switch(gen->save_type)
 50+		{
 51+		case RAM_FLAG_BOTH:
 52+			gen->save_storage[address] = value >> 8;
 53+			gen->save_storage[address+1] = value;
 54+			break;
 55+		case RAM_FLAG_EVEN:
 56+			gen->save_storage[address >> 1] = value >> 8;
 57+			break;
 58+		case RAM_FLAG_ODD:
 59+			gen->save_storage[address >> 1] = value;
 60+			break;
 61+		}
 62+	}
 63+	return context;
 64+}
 65+
 66+m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8_t value)
 67+{
 68+	genesis_context * gen = context->system;
 69+	if ((gen->bank_regs[0] & 0x3) == 1) {
 70+		address &= gen->save_ram_mask;
 71+		switch(gen->save_type)
 72+		{
 73+		case RAM_FLAG_BOTH:
 74+			gen->save_storage[address] = value;
 75+			break;
 76+		case RAM_FLAG_EVEN:
 77+			if (!(address & 1)) {
 78+				gen->save_storage[address >> 1] = value;
 79+			}
 80+			break;
 81+		case RAM_FLAG_ODD:
 82+			if (address & 1) {
 83+				gen->save_storage[address >> 1] = value;
 84+			}
 85+			break;
 86+		}
 87+	}
 88+	return context;
 89+}
 90+
 91+m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value)
 92+{
 93+	genesis_context * gen = context->system;
 94+	address &= 0xE;
 95+	address >>= 1;
 96+	gen->bank_regs[address] = value;
 97+	if (!address) {
 98+		if (value & 1) {
 99+			//Used for games that only use the mapper for SRAM
100+			if (context->mem_pointers[gen->mapper_start_index]) {
101+				gen->mapper_temp = context->mem_pointers[gen->mapper_start_index];
102+			}
103+			context->mem_pointers[gen->mapper_start_index] = NULL;
104+			//For games that need more than 4MB
105+			for (int i = 4; i < 8; i++)
106+			{
107+				context->mem_pointers[gen->mapper_start_index + i] = NULL;
108+			}
109+		} else {
110+			//Used for games that only use the mapper for SRAM
111+			if (!context->mem_pointers[gen->mapper_start_index]) {
112+				context->mem_pointers[gen->mapper_start_index] = gen->mapper_temp;
113+			}
114+			//For games that need more than 4MB
115+			for (int i = 4; i < 8; i++)
116+			{
117+				context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i];
118+			}
119+		}
120+	} else {
121+		void *new_ptr = gen->cart + 0x40000*value;
122+		if (context->mem_pointers[gen->mapper_start_index + address] != new_ptr) {
123+			m68k_invalidate_code_range(gen->m68k, address * 0x80000, (address + 1) * 0x80000);
124+			context->mem_pointers[gen->mapper_start_index + address] = new_ptr;
125+		}
126+	}
127+	return context;
128+}
129+
130+m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value)
131+{
132+	if (address & 1) {
133+		write_bank_reg_w(address, context, value);
134+	}
135+	return context;
136+}
137+
138+void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf)
139+{
140+	save_buffer8(buf, gen->bank_regs, sizeof(gen->bank_regs));
141+}
142+
143+void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen)
144+{
145+	for (int i = 0; i < sizeof(gen->bank_regs); i++)
146+	{
147+		write_bank_reg_w(i * 2, gen->m68k, load_int8(buf));
148+	}
149+}
+14, -0
 1@@ -0,0 +1,14 @@
 2+#ifndef SEGA_MAPPER_H_
 3+#define SEGA_MAPPER_H_
 4+#include "serialize.h"
 5+
 6+uint16_t read_sram_w(uint32_t address, m68k_context * context);
 7+uint8_t read_sram_b(uint32_t address, m68k_context * context);
 8+m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value);
 9+m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8_t value);
10+m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value);
11+m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value);
12+void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf);
13+void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen);
14+
15+#endif //SEGA_MAPPER_H_
+277, -0
  1@@ -0,0 +1,277 @@
  2+#include <string.h>
  3+#include <stdlib.h>
  4+#include <stdio.h>
  5+#include "serialize.h"
  6+#include "util.h"
  7+
  8+#ifndef SERIALIZE_DEFAULT_SIZE
  9+#define SERIALIZE_DEFAULT_SIZE (256*1024) //default to enough for a Genesis save state
 10+#endif
 11+
 12+
 13+void init_serialize(serialize_buffer *buf)
 14+{
 15+	buf->storage = SERIALIZE_DEFAULT_SIZE;
 16+	buf->size = 0;
 17+	buf->current_section_start = 0;
 18+	buf->data = malloc(SERIALIZE_DEFAULT_SIZE);
 19+}
 20+
 21+static void reserve(serialize_buffer *buf, size_t amount)
 22+{
 23+	if (amount > (buf->storage - buf->size)) {
 24+		buf->storage *= 2;
 25+		buf = realloc(buf, buf->storage + sizeof(*buf));
 26+	}
 27+}
 28+
 29+void save_int32(serialize_buffer *buf, uint32_t val)
 30+{
 31+	reserve(buf, sizeof(val));
 32+	buf->data[buf->size++] = val >> 24;
 33+	buf->data[buf->size++] = val >> 16;
 34+	buf->data[buf->size++] = val >> 8;
 35+	buf->data[buf->size++] = val;
 36+}
 37+
 38+void save_int16(serialize_buffer *buf, uint16_t val)
 39+{
 40+	reserve(buf, sizeof(val));
 41+	buf->data[buf->size++] = val >> 8;
 42+	buf->data[buf->size++] = val;
 43+}
 44+
 45+void save_int8(serialize_buffer *buf, uint8_t val)
 46+{
 47+	reserve(buf, sizeof(val));
 48+	buf->data[buf->size++] = val;
 49+}
 50+
 51+void save_string(serialize_buffer *buf, char *val)
 52+{
 53+	size_t len = strlen(val);
 54+	save_buffer8(buf, val, len);
 55+}
 56+
 57+void save_buffer8(serialize_buffer *buf, void *val, size_t len)
 58+{
 59+	reserve(buf, len);
 60+	memcpy(&buf->data[buf->size], val, len);
 61+	buf->size += len;
 62+}
 63+
 64+void save_buffer16(serialize_buffer *buf, uint16_t *val, size_t len)
 65+{
 66+	reserve(buf, len * sizeof(*val));
 67+	for(; len != 0; len--, val++) {
 68+		buf->data[buf->size++] = *val >> 8;
 69+		buf->data[buf->size++] = *val;
 70+	}
 71+}
 72+
 73+void save_buffer32(serialize_buffer *buf, uint32_t *val, size_t len)
 74+{
 75+	reserve(buf, len * sizeof(*val));
 76+	for(; len != 0; len--, val++) {
 77+		buf->data[buf->size++] = *val >> 24;
 78+		buf->data[buf->size++] = *val >> 16;
 79+		buf->data[buf->size++] = *val >> 8;
 80+		buf->data[buf->size++] = *val;
 81+	}
 82+}
 83+
 84+void start_section(serialize_buffer *buf, uint16_t section_id)
 85+{
 86+	save_int16(buf, section_id);
 87+	//reserve some space for size once we end this section
 88+	reserve(buf, sizeof(uint32_t));
 89+	buf->size += sizeof(uint32_t);
 90+	//save start point for use in end_device
 91+	buf->current_section_start = buf->size;
 92+}
 93+
 94+void end_section(serialize_buffer *buf)
 95+{
 96+	size_t section_size = buf->size - buf->current_section_start;
 97+	if (section_size > 0xFFFFFFFFU) {
 98+		fatal_error("Sections larger than 4GB are not supported");
 99+	}
100+	uint32_t size = section_size;
101+	uint8_t *field = buf->data + buf->current_section_start - sizeof(uint32_t);
102+	*(field++) = size >> 24;
103+	*(field++) = size >> 16;
104+	*(field++) = size >> 8;
105+	*(field++) = size;
106+	buf->current_section_start = 0;
107+}
108+
109+void register_section_handler(deserialize_buffer *buf, section_handler handler, uint16_t section_id)
110+{
111+	if (section_id > buf->max_handler) {
112+		uint16_t old_max = buf->max_handler;
113+		if (buf->max_handler < 0x8000) {
114+			buf->max_handler *= 2;
115+		} else {
116+			buf->max_handler = 0xFFFF;
117+		}
118+		buf->handlers = realloc(buf->handlers, (buf->max_handler+1) * sizeof(handler));
119+		memset(buf->handlers + old_max + 1, 0, (buf->max_handler - old_max) * sizeof(handler));
120+	}
121+	if (!buf->handlers) {
122+		buf->handlers = calloc(buf->max_handler + 1, sizeof(handler));
123+	}
124+	buf->handlers[section_id] = handler;
125+}
126+
127+void init_deserialize(deserialize_buffer *buf, uint8_t *data, size_t size)
128+{
129+	buf->size = size;
130+	buf->cur_pos = 0;
131+	buf->data = data;
132+	buf->handlers = NULL;
133+	buf->max_handler = 8;
134+}
135+
136+uint32_t load_int32(deserialize_buffer *buf)
137+{
138+	uint32_t val;
139+	if ((buf->size - buf->cur_pos) < sizeof(val)) {
140+		fatal_error("Failed to load required int32 field");
141+	}
142+	val = buf->data[buf->cur_pos++] << 24;
143+	val |= buf->data[buf->cur_pos++] << 16;
144+	val |= buf->data[buf->cur_pos++] << 8;
145+	val |= buf->data[buf->cur_pos++];
146+	return val;
147+}
148+
149+uint16_t load_int16(deserialize_buffer *buf)
150+{
151+	uint16_t val;
152+	if ((buf->size - buf->cur_pos) < sizeof(val)) {
153+		fatal_error("Failed to load required int16 field");
154+	}
155+	val = buf->data[buf->cur_pos++] << 8;
156+	val |= buf->data[buf->cur_pos++];
157+	return val;
158+}
159+
160+uint8_t load_int8(deserialize_buffer *buf)
161+{
162+	uint8_t val;
163+	if ((buf->size - buf->cur_pos) < sizeof(val)) {
164+		fatal_error("Failed to load required int8 field");
165+	}
166+	val = buf->data[buf->cur_pos++];
167+	return val;
168+}
169+
170+void load_buffer8(deserialize_buffer *buf, void *dst, size_t len)
171+{
172+	if ((buf->size - buf->cur_pos) < len) {
173+		fatal_error("Failed to load required buffer of size %d", len);
174+	}
175+	memcpy(dst, buf->data + buf->cur_pos, len);
176+	buf->cur_pos += len;
177+}
178+
179+void load_buffer16(deserialize_buffer *buf, uint16_t *dst, size_t len)
180+{
181+	if ((buf->size - buf->cur_pos) < len * sizeof(uint16_t)) {
182+		fatal_error("Failed to load required buffer of size %d\n", len);
183+	}
184+	for(; len != 0; len--, dst++) {
185+		uint16_t value = buf->data[buf->cur_pos++] << 8;
186+		value |= buf->data[buf->cur_pos++];
187+		*dst = value;
188+	}
189+}
190+void load_buffer32(deserialize_buffer *buf, uint32_t *dst, size_t len)
191+{
192+	if ((buf->size - buf->cur_pos) < len * sizeof(uint32_t)) {
193+		fatal_error("Failed to load required buffer of size %d\n", len);
194+	}
195+	for(; len != 0; len--, dst++) {
196+		uint32_t value = buf->data[buf->cur_pos++] << 24;
197+		value |= buf->data[buf->cur_pos++] << 16;
198+		value |= buf->data[buf->cur_pos++] << 8;
199+		value |= buf->data[buf->cur_pos++];
200+		*dst = value;
201+	}
202+}
203+
204+void load_section(deserialize_buffer *buf)
205+{
206+	if (!buf->handlers) {
207+		fatal_error("load_section called on a deserialize_buffer with no handlers registered\n");
208+	}
209+	uint16_t section_id = load_int16(buf);
210+	uint32_t size = load_int32(buf);
211+	if (size > (buf->size - buf->cur_pos)) {
212+		fatal_error("Section is bigger than remaining space in file");
213+	}
214+	if (section_id > buf->max_handler || !buf->handlers[section_id].fun) {
215+		warning("No handler for section ID %d, save state may be from a newer version\n", section_id);
216+		buf->cur_pos += size;
217+		return;
218+	}
219+	deserialize_buffer section;
220+	init_deserialize(&section, buf->data + buf->cur_pos, size);
221+	buf->handlers[section_id].fun(&section, buf->handlers[section_id].data);
222+	buf->cur_pos += size;
223+}
224+
225+static const char sz_ident[] = "BLSTSZ\x01\x07";
226+
227+uint8_t save_to_file(serialize_buffer *buf, char *path)
228+{
229+	FILE *f = fopen(path, "wb");
230+	if (!f) {
231+		return 0;
232+	}
233+	if (fwrite(sz_ident, 1, sizeof(sz_ident)-1, f) != sizeof(sz_ident)-1) {
234+		fclose(f);
235+		return 0;
236+	}
237+	if (fwrite(buf->data, 1, buf->size, f) != buf->size) {
238+		fclose(f);
239+		return 0;
240+	}
241+	fclose(f);
242+	return 1;
243+}
244+
245+uint8_t load_from_file(deserialize_buffer *buf, char *path)
246+{
247+	FILE *f = fopen(path, "rb");
248+	if (!f) {
249+		return 0;
250+	}
251+	char ident[sizeof(sz_ident)-1];
252+	long size = file_size(f);
253+	if (size < sizeof(ident)) {
254+		fclose(f);
255+		return 0;
256+	}
257+	if (fread(ident, 1, sizeof(ident), f) != sizeof(ident)) {
258+		fclose(f);
259+		return 0;
260+	}
261+	if (memcmp(ident, sz_ident, sizeof(ident))) {
262+		return 0;
263+	}
264+	buf->size = size - sizeof(ident);
265+	buf->cur_pos = 0;
266+	buf->data = malloc(buf->size);
267+	buf->handlers = NULL;
268+	buf->max_handler = 8;
269+	if (fread(buf->data, 1, buf->size, f) != buf->size) {
270+		fclose(f);
271+		free(buf->data);
272+		buf->data = NULL;
273+		buf->size = 0;
274+		return 0;
275+	}
276+	fclose(f);
277+	return 1;
278+}
+69, -0
 1@@ -0,0 +1,69 @@
 2+#ifndef SERIALIZE_H_
 3+#define SERIALIZE_H_
 4+
 5+#include <stdint.h>
 6+#include <stddef.h>
 7+
 8+typedef struct {
 9+	size_t  size;
10+	size_t  storage;
11+	size_t  current_section_start;
12+	uint8_t *data;
13+} serialize_buffer;
14+
15+typedef struct deserialize_buffer deserialize_buffer;
16+typedef void (*section_fun)(deserialize_buffer *buf, void *data);
17+
18+typedef struct  {
19+	section_fun fun;
20+	void        *data;
21+} section_handler;
22+
23+struct deserialize_buffer {
24+	size_t          size;
25+	size_t          cur_pos;
26+	uint8_t         *data;
27+	section_handler *handlers;
28+	uint16_t        max_handler;
29+};
30+
31+enum {
32+	SECTION_HEADER,
33+	SECTION_68000,
34+	SECTION_Z80,
35+	SECTION_VDP,
36+	SECTION_YM2612,
37+	SECTION_PSG,
38+	SECTION_GEN_BUS_ARBITER,
39+	SECTION_SEGA_IO_1,
40+	SECTION_SEGA_IO_2,
41+	SECTION_SEGA_IO_EXT,
42+	SECTION_MAIN_RAM,
43+	SECTION_SOUND_RAM,
44+	SECTION_MAPPER,
45+	SECTION_EEPROM,
46+	SECTION_CART_RAM
47+};
48+
49+void init_serialize(serialize_buffer *buf);
50+void save_int32(serialize_buffer *buf, uint32_t val);
51+void save_int16(serialize_buffer *buf, uint16_t val);
52+void save_int8(serialize_buffer *buf, uint8_t val);
53+void save_string(serialize_buffer *buf, char *val);
54+void save_buffer8(serialize_buffer *buf, void *val, size_t len);
55+void save_buffer16(serialize_buffer *buf, uint16_t *val, size_t len);
56+void save_buffer32(serialize_buffer *buf, uint32_t *val, size_t len);
57+void start_section(serialize_buffer *buf, uint16_t section_id);
58+void end_section(serialize_buffer *buf);
59+void register_section_handler(deserialize_buffer *buf, section_handler handler, uint16_t section_id);
60+void init_deserialize(deserialize_buffer *buf, uint8_t *data, size_t size);
61+uint32_t load_int32(deserialize_buffer *buf);
62+uint16_t load_int16(deserialize_buffer *buf);
63+uint8_t load_int8(deserialize_buffer *buf);
64+void load_buffer8(deserialize_buffer *buf, void *dst, size_t len);
65+void load_buffer16(deserialize_buffer *buf, uint16_t *dst, size_t len);
66+void load_buffer32(deserialize_buffer *buf, uint32_t *dst, size_t len);
67+void load_section(deserialize_buffer *buf);
68+uint8_t save_to_file(serialize_buffer *buf, char *path);
69+uint8_t load_from_file(deserialize_buffer *buf, char *path);
70+#endif //SERIALIZE_H
+173, -0
  1@@ -0,0 +1,173 @@
  2+HSYNC End
  3+Plane A: D13C
  4+??slot??
  5+tile
  6+tile
  7+Plane B: F29C
  8+?sprite tile slot?
  9+tile
 10+tile
 11+Plane A: D100
 12+68K Slot
 13+tile
 14+tile
 15+Plane B: F2A0
 16+?sprite table slot?
 17+tile
 18+tile
 19+Plane A: D104
 20+68K slot
 21+tile
 22+tile
 23+Plane B: F2A4
 24+?sprite table slot?
 25+tile
 26+tile
 27+Plane A: D108
 28+68K slot
 29+?tile?
 30+?tile?
 31+Plane B: F2A8
 32+?sprite table slot?
 33+tile
 34+tile
 35+Plane A: D10C
 36+refresh
 37+?tile?
 38+?tile?
 39+Plane B: F22C
 40+?sprite table slot?
 41+tile
 42+tile
 43+Plane A: D110
 44+68K slot
 45+?tile?
 46+?tile?
 47+Plane B: F230
 48+?sprite table slot?
 49+tile
 50+tile
 51+Plane A: D114
 52+68K slot
 53+?tile?
 54+?tile?
 55+Plane B: F2F4
 56+?sprite table slot?
 57+tile
 58+tile
 59+Plane A: D118
 60+68K slot
 61+?tile?
 62+?tile?
 63+Plane B: F238
 64+?sprite table slot?
 65+ttile tile
 66+Plane A: D11C
 67+refresh
 68+?tile?
 69+?tile?
 70+Plane B: F23C
 71+?sprite table slot?
 72+tile
 73+tile
 74+Plane A: D120
 75+68K slot
 76+?tile?
 77+?tile?
 78+Plane B: F240
 79+?sprite table slot?
 80+tile
 81+tile
 82+Plane A: D124
 83+68K Slot
 84+?tile?
 85+?tile?
 86+Plane B: F244
 87+?sprite table slot?
 88+tile
 89+tile
 90+Plane A: D128
 91+68K Slot
 92+?tile?
 93+?tile?
 94+Plane B: F3C8
 95+?sprite table slot?
 96+tile
 97+tile
 98+Plane A: D12C
 99+refresh
100+?tile?
101+?tile?
102+Plane B: F24C
103+?sprite table slot?
104+tile
105+tile
106+Plane A: D130
107+68K slot
108+?tile?
109+?tile?
110+Plane B: F250
111+?sprite table slot?
112+tile
113+tile
114+Plane A: D134
115+68K Slot
116+?tile?
117+?tile?
118+Plane B: F254
119+?sprite table slot?
120+tile
121+tile
122+Plane A: D138
123+68K slot
124+?tile?
125+?tile?
126+Plane B: F3D8
127+?sprite table slot?
128+tile
129+tile
130+Plane A: D13C
131+refresh
132+tile
133+tile
134+Plane B: F3DC
135+?sprite table slot?
136+tile
137+tile
138+---------------
139+68K Slot
140+68K Slot
141+sprite tile slot
142+sprite tile slot
143+sprite tile slot
144+sprite tile slot
145+?sprite tile slot?
146+?sprite tile slot?
147+?sprite tile slot?
148+?sprite tile slot?
149+?sprite tile slot?
150+?sprite tile slot?
151+?sprite tile slot?
152+?sprite tile slot?
153+?sprite tile slot?
154+?sprite tile slot?
155+68K Slot
156+?sprite tile slot?
157+?sprite tile slot?
158+?sprite tile slot?
159+?sprite tile slot?
160+?sprite tile slot?
161+HSYNC Start
162+?sprite tile slot?
163+?sprite tile slot?
164+?sprite tile slot?
165+?sprite tile slot?
166+?sprite tile slot?
167+?sprite tile slot?
168+?unkown tile slot?
169+68K Slot
170+Horizontal Scroll
171+?sprite tile slot?
172+?sprite tile slot?
173+?sprite tile slot?
174+?unkown tile slot?
+64, -0
 1@@ -0,0 +1,64 @@
 2+0000: single color blocks
 3+0200: Random symbols????
 4+0400-0C00: Font
 5+0C00-0E??: Score font
 6+0E??: Player name displays
 7+
 8+2000-3000: floor (mostly, some garbage around 2800 and 2A00)
 9+3000-6C00: background
10+6C00-8000: not graphics
11+8000-~8A00: bat/bird sprites, special attack text
12+8A00-9000: ?????
13+9000-9200: More special attack text
14+9200-9600: another font
15+9800-AA00: special attack effects?
16+AC00-B000: ????
17+B000-B500: character sprite
18+????
19+C000-C500: chracter sprite
20+D000-DA00: window name table
21+DA00-DC00: Sprite attribute table
22+DC00-E000: horizontal scroll data
23+E000-????: plane A&B name table
24+C500-FFFF: not graphics
25+
26+VDP Registers:
27+Mode
28+00 - 14
29+01 - 64
30+Scroll A Name Table Address: E000
31+02 - 38
32+Window Name Table Address: D000
33+03 - 34
34+Scroll B Name Table Address: E000
35+04 - 07
36+Sprite Attribute Table Address: DA00
37+05 - 6D
38+06 - 00
39+Backdrop color - 0
40+07 - 00
41+08 - 00
42+09 - 00
43+HINT Counter
44+0A - AF
45+Mode - Full screen vertical scroll, line horizontal scroll, external ints disabled, 32 cell display, no interlacing
46+0B - 03
47+0C - 00
48+H Scroll Data Address: DC00
49+0D - 37
50+0E - 00
51+Auto increment
52+0F - 02
53+Scroll Size
54+10 - 11
55+Window H Pos
56+11 - 00
57+Window V Pos
58+12 - 05
59+DMA transfer length
60+13 - 00
61+14 - 00
62+DMA source address and mode
63+15 - DB
64+16 - CF
65+17 - 7F
A sms.c
+641, -0
  1@@ -0,0 +1,641 @@
  2+#include <string.h>
  3+#include <stdlib.h>
  4+#include <stddef.h>
  5+#include "sms.h"
  6+#include "blastem.h"
  7+#include "render.h"
  8+#include "util.h"
  9+#include "debug.h"
 10+#include "saves.h"
 11+#include "bindings.h"
 12+
 13+#define Z80_CYCLE current_cycle
 14+#define Z80_OPTS options
 15+
 16+static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value)
 17+{
 18+	z80_context *z80 = vcontext;
 19+	sms_context *sms = z80->system;
 20+	if (location & 1) {
 21+		uint8_t fuzzy_ctrl_0 = sms->io.ports[0].control, fuzzy_ctrl_1 = sms->io.ports[1].control;
 22+		io_control_write(sms->io.ports, (~value) << 5 & 0x60, z80->Z80_CYCLE);
 23+		fuzzy_ctrl_0 |= sms->io.ports[0].control;
 24+		io_control_write(sms->io.ports+1, (~value) << 3 & 0x60, z80->Z80_CYCLE);
 25+		fuzzy_ctrl_1 |= sms->io.ports[1].control;
 26+		if (
 27+			(fuzzy_ctrl_0 & 0x40 & (sms->io.ports[0].output ^ (value << 1)) & (value << 1))
 28+			|| (fuzzy_ctrl_0 & 0x40 & (sms->io.ports[1].output ^ (value >> 1)) & (value >> 1))
 29+		) {
 30+			//TH is an output and it went from 0 -> 1
 31+			vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 32+			vdp_latch_hv(sms->vdp);
 33+		}
 34+		io_data_write(sms->io.ports, value << 1, z80->Z80_CYCLE);
 35+		io_data_write(sms->io.ports + 1, value >> 1, z80->Z80_CYCLE);
 36+	} else {
 37+		//TODO: memory control write
 38+	}
 39+	return vcontext;
 40+}
 41+
 42+static uint8_t hv_read(uint32_t location, void *vcontext)
 43+{
 44+	z80_context *z80 = vcontext;
 45+	sms_context *sms = z80->system;
 46+	vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 47+	uint16_t hv = vdp_hv_counter_read(sms->vdp);
 48+	if (location & 1) {
 49+		return hv;
 50+	} else {
 51+		return hv >> 8;
 52+	}
 53+}
 54+
 55+static void *sms_psg_write(uint32_t location, void *vcontext, uint8_t value)
 56+{
 57+	z80_context *z80 = vcontext;
 58+	sms_context *sms = z80->system;
 59+	psg_run(sms->psg, z80->Z80_CYCLE);
 60+	psg_write(sms->psg, value);
 61+	return vcontext;
 62+}
 63+
 64+static void update_interrupts(sms_context *sms)
 65+{
 66+	uint32_t vint = vdp_next_vint(sms->vdp);
 67+	uint32_t hint = vdp_next_hint(sms->vdp);
 68+	sms->z80->int_pulse_start = vint < hint ? vint : hint;
 69+}
 70+
 71+static uint8_t vdp_read(uint32_t location, void *vcontext)
 72+{
 73+	z80_context *z80 = vcontext;
 74+	sms_context *sms = z80->system;
 75+	vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 76+	if (location & 1) {
 77+		uint8_t ret = vdp_control_port_read(sms->vdp);
 78+		sms->vdp->flags2 &= ~(FLAG2_VINT_PENDING|FLAG2_HINT_PENDING);
 79+		update_interrupts(sms);
 80+		return ret;
 81+	} else {
 82+		return vdp_data_port_read_pbc(sms->vdp);
 83+	}
 84+}
 85+
 86+static void *vdp_write(uint32_t location, void *vcontext, uint8_t value)
 87+{
 88+	z80_context *z80 = vcontext;
 89+	sms_context *sms = z80->system;
 90+	if (location & 1) {
 91+		vdp_run_context_full(sms->vdp, z80->Z80_CYCLE);
 92+		vdp_control_port_write_pbc(sms->vdp, value);
 93+		update_interrupts(sms);
 94+	} else {
 95+		vdp_run_context(sms->vdp, z80->Z80_CYCLE);
 96+		vdp_data_port_write_pbc(sms->vdp, value);
 97+	}
 98+	return vcontext;
 99+}
100+
101+static uint8_t io_read(uint32_t location, void *vcontext)
102+{
103+	z80_context *z80 = vcontext;
104+	sms_context *sms = z80->system;
105+	if (location == 0xC0 || location == 0xDC) {
106+		uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
107+		uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
108+		return (port_a & 0x3F) | (port_b << 6);
109+	}
110+	if (location == 0xC1 || location == 0xDD) {
111+		uint8_t port_a = io_data_read(sms->io.ports, z80->Z80_CYCLE);
112+		uint8_t port_b = io_data_read(sms->io.ports+1, z80->Z80_CYCLE);
113+		return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10;
114+	}
115+	return 0xFF;
116+}
117+
118+static void update_mem_map(uint32_t location, sms_context *sms, uint8_t value)
119+{
120+	z80_context *z80 = sms->z80;
121+	void *old_value;
122+	if (location) {
123+		uint32_t idx = location - 1;
124+		old_value = z80->mem_pointers[idx];
125+		z80->mem_pointers[idx] = sms->rom + (value << 14 & (sms->rom_size-1));
126+		if (old_value != z80->mem_pointers[idx]) {
127+			//invalidate any code we translated for the relevant bank
128+			z80_invalidate_code_range(z80, idx ? idx * 0x4000 : 0x400, idx * 0x4000 + 0x4000);
129+		}
130+	} else {
131+		old_value = z80->mem_pointers[2];
132+		if (value & 8) {
133+			//cartridge RAM is enabled
134+			z80->mem_pointers[2] = sms->cart_ram + (value & 4 ? (SMS_CART_RAM_SIZE/2) : 0);
135+		} else {
136+			//cartridge RAM is disabled
137+			z80->mem_pointers[2] = sms->rom + (sms->bank_regs[3] << 14 & (sms->rom_size-1));
138+		}
139+		if (old_value != z80->mem_pointers[2]) {
140+			//invalidate any code we translated for the relevant bank
141+			z80_invalidate_code_range(z80, 0x8000, 0xC000);
142+		}
143+	}
144+}
145+
146+static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
147+{
148+	z80_context *z80 = vcontext;
149+	sms_context *sms = z80->system;
150+	location &= 3;
151+	sms->ram[0x1FFC + location] = value;
152+	sms->bank_regs[location] = value;
153+	update_mem_map(location, sms, value);
154+	return vcontext;
155+}
156+
157+static void *cart_ram_write(uint32_t location, void *vcontext, uint8_t value)
158+{
159+	z80_context *z80 = vcontext;
160+	sms_context *sms = z80->system;
161+	if (sms->bank_regs[0] & 8) {
162+		//cartridge RAM is enabled
163+		location &= 0x3FFF;
164+		z80->mem_pointers[2][location] = value;
165+		z80_handle_code_write(0x8000 + location, z80);
166+	}
167+	return vcontext;
168+}
169+
170+uint8_t debug_commands(system_header *system, char *input_buf)
171+{
172+	sms_context *sms = (sms_context *)system;
173+	switch(input_buf[0])
174+	{
175+	case 'v':
176+		if (input_buf[1] == 'r') {
177+			vdp_print_reg_explain(sms->vdp);
178+		} else if (input_buf[1] == 's') {
179+			vdp_print_sprite_table(sms->vdp);
180+		} else {
181+			return 0;
182+		}
183+		break;
184+	}
185+	return 1;
186+}
187+
188+static memmap_chunk io_map[] = {
189+	{0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL,     memory_io_write},
190+	{0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read,  sms_psg_write},
191+	{0x80, 0xC0, 0xFF, 0, 0, 0, NULL, NULL, NULL, vdp_read, vdp_write},
192+	{0xC0, 0x100,0xFF, 0, 0, 0, NULL, NULL, NULL, io_read,  NULL}
193+};
194+
195+static void set_speed_percent(system_header * system, uint32_t percent)
196+{
197+	sms_context *context = (sms_context *)system;
198+	uint32_t old_clock = context->master_clock;
199+	context->master_clock = ((uint64_t)context->normal_clock * (uint64_t)percent) / 100;
200+
201+	psg_adjust_master_clock(context->psg, context->master_clock);
202+}
203+
204+void sms_serialize(sms_context *sms, serialize_buffer *buf)
205+{
206+	start_section(buf, SECTION_Z80);
207+	z80_serialize(sms->z80, buf);
208+	end_section(buf);
209+	
210+	start_section(buf, SECTION_VDP);
211+	vdp_serialize(sms->vdp, buf);
212+	end_section(buf);
213+	
214+	start_section(buf, SECTION_PSG);
215+	psg_serialize(sms->psg, buf);
216+	end_section(buf);
217+	
218+	start_section(buf, SECTION_SEGA_IO_1);
219+	io_serialize(sms->io.ports, buf);
220+	end_section(buf);
221+	
222+	start_section(buf, SECTION_SEGA_IO_2);
223+	io_serialize(sms->io.ports + 1, buf);
224+	end_section(buf);
225+	
226+	start_section(buf, SECTION_MAIN_RAM);
227+	save_int8(buf, sizeof(sms->ram) / 1024);
228+	save_buffer8(buf, sms->ram, sizeof(sms->ram));
229+	end_section(buf);
230+	
231+	start_section(buf, SECTION_MAPPER);
232+	save_int8(buf, 1);//mapper type, 1 for Sega mapper
233+	save_buffer8(buf, sms->bank_regs, sizeof(sms->bank_regs));
234+	end_section(buf);
235+	
236+	start_section(buf, SECTION_CART_RAM);
237+	save_int8(buf, SMS_CART_RAM_SIZE / 1024);
238+	save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE);
239+	end_section(buf);
240+}
241+
242+static uint8_t *serialize(system_header *sys, size_t *size_out)
243+{
244+	sms_context *sms = (sms_context *)sys;
245+	serialize_buffer state;
246+	init_serialize(&state);
247+	sms_serialize(sms, &state);
248+	if (size_out) {
249+		*size_out = state.size;
250+	}
251+	return state.data;
252+}
253+
254+static void ram_deserialize(deserialize_buffer *buf, void *vsms)
255+{
256+	sms_context *sms = vsms;
257+	uint32_t ram_size = load_int8(buf) * 1024;
258+	if (ram_size > sizeof(sms->ram)) {
259+		fatal_error("State has a RAM size of %d bytes", ram_size);
260+	}
261+	load_buffer8(buf, sms->ram, ram_size);
262+}
263+
264+static void cart_ram_deserialize(deserialize_buffer *buf, void *vsms)
265+{
266+	sms_context *sms = vsms;
267+	uint32_t ram_size = load_int8(buf) * 1024;
268+	if (ram_size > SMS_CART_RAM_SIZE) {
269+		fatal_error("State has a cart RAM size of %d bytes", ram_size);
270+	}
271+	load_buffer8(buf, sms->cart_ram, ram_size);
272+}
273+
274+static void mapper_deserialize(deserialize_buffer *buf, void *vsms)
275+{
276+	sms_context *sms = vsms;
277+	uint8_t mapper_type = load_int8(buf);
278+	if (mapper_type != 1) {
279+		warning("State contains an unrecognized mapper type %d, it may be from a newer version of BlastEm\n", mapper_type);
280+		return;
281+	}
282+	for (int i = 0; i < sizeof(sms->bank_regs); i++)
283+	{
284+		sms->bank_regs[i] = load_int8(buf);
285+		update_mem_map(i, sms, sms->bank_regs[i]);
286+	}
287+}
288+
289+void sms_deserialize(deserialize_buffer *buf, sms_context *sms)
290+{
291+	register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = sms->z80}, SECTION_Z80);
292+	register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = sms->vdp}, SECTION_VDP);
293+	register_section_handler(buf, (section_handler){.fun = psg_deserialize, .data = sms->psg}, SECTION_PSG);
294+	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = sms->io.ports}, SECTION_SEGA_IO_1);
295+	register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = sms->io.ports + 1}, SECTION_SEGA_IO_2);
296+	register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = sms}, SECTION_MAIN_RAM);
297+	register_section_handler(buf, (section_handler){.fun = mapper_deserialize, .data = sms}, SECTION_MAPPER);
298+	register_section_handler(buf, (section_handler){.fun = cart_ram_deserialize, .data = sms}, SECTION_CART_RAM);
299+	//TODO: cart RAM
300+	while (buf->cur_pos < buf->size)
301+	{
302+		load_section(buf);
303+	}
304+	z80_invalidate_code_range(sms->z80, 0xC000, 0x10000);
305+	if (sms->bank_regs[0] & 8) {
306+		//cart RAM is enabled, invalidate the region in case there is any code there
307+		z80_invalidate_code_range(sms->z80, 0x8000, 0xC000);
308+	}
309+	free(buf->handlers);
310+	buf->handlers = NULL;
311+}
312+
313+static void deserialize(system_header *sys, uint8_t *data, size_t size)
314+{
315+	sms_context *sms = (sms_context *)sys;
316+	deserialize_buffer buffer;
317+	init_deserialize(&buffer, data, size);
318+	sms_deserialize(&buffer, sms);
319+}
320+
321+static void save_state(sms_context *sms, uint8_t slot)
322+{
323+	char *save_path = get_slot_name(&sms->header, slot, "state");
324+	serialize_buffer state;
325+	init_serialize(&state);
326+	sms_serialize(sms, &state);
327+	save_to_file(&state, save_path);
328+	printf("Saved state to %s\n", save_path);
329+	free(save_path);
330+	free(state.data);
331+}
332+
333+static uint8_t load_state_path(sms_context *sms, char *path)
334+{
335+	deserialize_buffer state;
336+	uint8_t ret;
337+	if ((ret = load_from_file(&state, path))) {
338+		sms_deserialize(&state, sms);
339+		free(state.data);
340+		printf("Loaded %s\n", path);
341+	}
342+	return ret;
343+}
344+
345+static uint8_t load_state(system_header *system, uint8_t slot)
346+{
347+	sms_context *sms = (sms_context *)system;
348+	char *statepath = get_slot_name(system, slot, "state");
349+	uint8_t ret;
350+	if (!sms->z80->native_pc) {
351+		ret = get_modification_time(statepath) != 0;
352+		if (ret) {
353+			system->delayed_load_slot = slot + 1;
354+		}
355+		goto done;
356+		
357+	}
358+	ret = load_state_path(sms, statepath);
359+done:
360+	free(statepath);
361+	return ret;
362+}
363+
364+static void run_sms(system_header *system)
365+{
366+	sms_context *sms = (sms_context *)system;
367+	uint32_t target_cycle = sms->z80->Z80_CYCLE + 3420*16;
368+	//TODO: PAL support
369+	render_set_video_standard(VID_NTSC);
370+	while (!sms->should_return)
371+	{
372+		if (system->delayed_load_slot) {
373+			load_state(system, system->delayed_load_slot - 1);
374+			system->delayed_load_slot = 0;
375+			
376+		}
377+		if (system->enter_debugger && sms->z80->pc) {
378+			system->enter_debugger = 0;
379+			zdebugger(sms->z80, sms->z80->pc);
380+		}
381+		if (sms->z80->nmi_start == CYCLE_NEVER) {
382+			uint32_t nmi = vdp_next_nmi(sms->vdp);
383+			if (nmi != CYCLE_NEVER) {
384+				z80_assert_nmi(sms->z80, nmi);
385+			}
386+		}
387+		z80_run(sms->z80, target_cycle);
388+		if (sms->z80->reset) {
389+			z80_clear_reset(sms->z80, sms->z80->Z80_CYCLE + 128*15);
390+		}
391+		target_cycle = sms->z80->Z80_CYCLE;
392+		vdp_run_context(sms->vdp, target_cycle);
393+		psg_run(sms->psg, target_cycle);
394+		
395+		if (system->save_state) {
396+			while (!sms->z80->pc) {
397+				//advance Z80 to an instruction boundary
398+				z80_run(sms->z80, sms->z80->Z80_CYCLE + 1);
399+			}
400+			save_state(sms, system->save_state - 1);
401+			system->save_state = 0;
402+		}
403+		
404+		target_cycle += 3420*16;
405+		if (target_cycle > 0x10000000) {
406+			uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2;
407+			io_adjust_cycles(sms->io.ports, sms->z80->Z80_CYCLE, adjust);
408+			io_adjust_cycles(sms->io.ports+1, sms->z80->Z80_CYCLE, adjust);
409+			z80_adjust_cycles(sms->z80, adjust);
410+			vdp_adjust_cycles(sms->vdp, adjust);
411+			sms->psg->cycles -= adjust;
412+			target_cycle -= adjust;
413+		}
414+	}
415+	bindings_release_capture();
416+	vdp_release_framebuffer(sms->vdp);
417+	render_pause_source(sms->psg->audio);
418+	sms->should_return = 0;
419+}
420+
421+static void resume_sms(system_header *system)
422+{
423+	sms_context *sms = (sms_context *)system;
424+	bindings_reacquire_capture();
425+	vdp_reacquire_framebuffer(sms->vdp);
426+	render_resume_source(sms->psg->audio);
427+	run_sms(system);
428+}
429+
430+static void start_sms(system_header *system, char *statefile)
431+{
432+	sms_context *sms = (sms_context *)system;
433+	
434+	z80_assert_reset(sms->z80, 0);
435+	z80_clear_reset(sms->z80, 128*15);
436+	
437+	if (statefile) {
438+		load_state_path(sms, statefile);
439+	}
440+	
441+	if (system->enter_debugger) {
442+		system->enter_debugger = 0;
443+		zinsert_breakpoint(sms->z80, sms->z80->pc, (uint8_t *)zdebugger);
444+	}
445+	
446+	run_sms(system);
447+}
448+
449+static void soft_reset(system_header *system)
450+{
451+	sms_context *sms = (sms_context *)system;
452+	z80_assert_reset(sms->z80, sms->z80->Z80_CYCLE);
453+	sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
454+}
455+
456+static void free_sms(system_header *system)
457+{
458+	sms_context *sms = (sms_context *)system;
459+	vdp_free(sms->vdp);
460+	z80_options_free(sms->z80->Z80_OPTS);
461+	free(sms->z80);
462+	psg_free(sms->psg);
463+	free(sms);
464+}
465+
466+static uint16_t get_open_bus_value(system_header *system)
467+{
468+	return 0xFFFF;
469+}
470+
471+static void request_exit(system_header *system)
472+{
473+	sms_context *sms = (sms_context *)system;
474+	sms->should_return = 1;
475+	sms->z80->target_cycle = sms->z80->sync_cycle = sms->z80->Z80_CYCLE;
476+}
477+
478+static void inc_debug_mode(system_header *system)
479+{
480+	sms_context *sms = (sms_context *)system;
481+	vdp_inc_debug_mode(sms->vdp);
482+}
483+
484+static void load_save(system_header *system)
485+{
486+	//TODO: Implement me
487+}
488+
489+static void persist_save(system_header *system)
490+{
491+	//TODO: Implement me
492+}
493+
494+static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
495+{
496+	sms_context *sms = (sms_context *)system;
497+	if (gamepad_num == GAMEPAD_MAIN_UNIT) {
498+		if (button == MAIN_UNIT_PAUSE) {
499+			vdp_pbc_pause(sms->vdp);
500+		}
501+	} else {
502+		io_gamepad_down(&sms->io, gamepad_num, button);
503+	}
504+}
505+
506+static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button)
507+{
508+	sms_context *sms = (sms_context *)system;
509+	io_gamepad_up(&sms->io, gamepad_num, button);
510+}
511+
512+static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button)
513+{
514+	sms_context *sms = (sms_context *)system;
515+	io_mouse_down(&sms->io, mouse_num, button);
516+}
517+
518+static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button)
519+{
520+	sms_context *sms = (sms_context *)system;
521+	io_mouse_up(&sms->io, mouse_num, button);
522+}
523+
524+static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y)
525+{
526+	sms_context *sms = (sms_context *)system;
527+	io_mouse_motion_absolute(&sms->io, mouse_num, x, y);
528+}
529+
530+static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y)
531+{
532+	sms_context *sms = (sms_context *)system;
533+	io_mouse_motion_relative(&sms->io, mouse_num, x, y);
534+}
535+
536+static void keyboard_down(system_header *system, uint8_t scancode)
537+{
538+	sms_context *sms = (sms_context *)system;
539+	io_keyboard_down(&sms->io, scancode);
540+}
541+
542+static void keyboard_up(system_header *system, uint8_t scancode)
543+{
544+	sms_context *sms = (sms_context *)system;
545+	io_keyboard_up(&sms->io, scancode);
546+}
547+
548+static void set_gain_config(sms_context *sms)
549+{
550+	char *config_gain;
551+	config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
552+	render_audio_source_gaindb(sms->psg->audio, config_gain ? atof(config_gain) : 0.0f);
553+}
554+
555+static void config_updated(system_header *system)
556+{
557+	sms_context *sms = (sms_context *)system;
558+	setup_io_devices(config, &system->info, &sms->io);
559+}
560+
561+
562+sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region)
563+{
564+	sms_context *sms = calloc(1, sizeof(sms_context));
565+	uint32_t rom_size = nearest_pow2(media->size);
566+	memmap_chunk memory_map[6];
567+	if (media->size > 0xC000)  {
568+		sms->header.info.map_chunks = 6;
569+		uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
570+		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF,             0, 0, MMAP_READ,                        media->buffer, NULL, NULL, NULL, NULL};
571+		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
572+		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
573+		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, cart_ram_write};
574+		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE,   sms->ram, NULL, NULL, NULL, NULL};
575+		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003,             0, 0, MMAP_READ,                        ram_reg_overlap, NULL, NULL, NULL, mapper_write};
576+	} else {
577+		sms->header.info.map_chunks = 2;
578+		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      media->buffer,  NULL, NULL, NULL, NULL};
579+		memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
580+	};
581+	sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks);
582+	memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
583+	z80_options *zopts = malloc(sizeof(z80_options));
584+	init_z80_opts(zopts, sms->header.info.map, sms->header.info.map_chunks, io_map, 4, 15, 0xFF);
585+	sms->z80 = init_z80_context(zopts);
586+	sms->z80->system = sms;
587+	sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands;
588+	
589+	sms->rom = media->buffer;
590+	sms->rom_size = rom_size;
591+	if (sms->header.info.map_chunks > 2) {
592+		sms->z80->mem_pointers[0] = sms->rom;
593+		sms->z80->mem_pointers[1] = sms->rom + 0x4000;
594+		sms->z80->mem_pointers[2] = sms->rom + 0x8000;
595+		sms->bank_regs[1] = 0;
596+		sms->bank_regs[2] = 0x4000 >> 14;
597+		sms->bank_regs[3] = 0x8000 >> 14;
598+	}
599+	
600+	//TODO: Detect region and pick master clock based off of that
601+	sms->normal_clock = sms->master_clock = 53693175;
602+	
603+	sms->psg = malloc(sizeof(psg_context));
604+	psg_init(sms->psg, sms->master_clock, 15*16);
605+	
606+	set_gain_config(sms);
607+	
608+	sms->vdp = init_vdp_context(0);
609+	sms->vdp->system = &sms->header;
610+	
611+	sms->header.info.save_type = SAVE_NONE;
612+	sms->header.info.name = strdup(media->name);
613+	
614+	setup_io_devices(config, &sms->header.info, &sms->io);
615+	sms->header.has_keyboard = io_has_keyboard(&sms->io);
616+	
617+	sms->header.set_speed_percent = set_speed_percent;
618+	sms->header.start_context = start_sms;
619+	sms->header.resume_context = resume_sms;
620+	sms->header.load_save = load_save;
621+	sms->header.persist_save = persist_save;
622+	sms->header.load_state = load_state;
623+	sms->header.free_context = free_sms;
624+	sms->header.get_open_bus_value = get_open_bus_value;
625+	sms->header.request_exit = request_exit;
626+	sms->header.soft_reset = soft_reset;
627+	sms->header.inc_debug_mode = inc_debug_mode;
628+	sms->header.gamepad_down = gamepad_down;
629+	sms->header.gamepad_up = gamepad_up;
630+	sms->header.mouse_down = mouse_down;
631+	sms->header.mouse_up = mouse_up;
632+	sms->header.mouse_motion_absolute = mouse_motion_absolute;
633+	sms->header.mouse_motion_relative = mouse_motion_relative;
634+	sms->header.keyboard_down = keyboard_down;
635+	sms->header.keyboard_up = keyboard_up;
636+	sms->header.config_updated = config_updated;
637+	sms->header.serialize = serialize;
638+	sms->header.deserialize = deserialize;
639+	sms->header.type = SYSTEM_SMS;
640+	
641+	return sms;
642+}
A sms.h
+31, -0
 1@@ -0,0 +1,31 @@
 2+#ifndef SMS_H_
 3+#define SMS_H_
 4+
 5+#include "system.h"
 6+#include "vdp.h"
 7+#include "psg.h"
 8+#include "z80_to_x86.h"
 9+#include "io.h"
10+
11+#define SMS_RAM_SIZE (8*1024)
12+#define SMS_CART_RAM_SIZE (32*1024)
13+
14+typedef struct {
15+	system_header header;
16+	z80_context   *z80;
17+	vdp_context   *vdp;
18+	psg_context   *psg;
19+	sega_io       io;
20+	uint8_t       *rom;
21+	uint32_t      rom_size;
22+	uint32_t      master_clock;
23+	uint32_t      normal_clock;
24+	uint8_t       should_return;
25+	uint8_t       ram[SMS_RAM_SIZE];
26+	uint8_t       bank_regs[4];
27+	uint8_t       cart_ram[SMS_CART_RAM_SIZE];
28+} sms_context;
29+
30+sms_context *alloc_configure_sms(system_media *media, uint32_t opts, uint8_t force_region);
31+
32+#endif //SMS_H_
+59, -0
 1@@ -0,0 +1,59 @@
 2+#ifndef SPECIAL_KEYS_EVDEV_H_
 3+#define SPECIAL_KEYS_EVDEV_H_
 4+
 5+enum {
 6+	RENDERKEY_DOWN = 128,
 7+	RENDERKEY_UP,
 8+	RENDERKEY_LEFT,
 9+	RENDERKEY_RIGHT,
10+	RENDERKEY_ESC,
11+	RENDERKEY_DEL,  
12+	RENDERKEY_LSHIFT, 
13+	RENDERKEY_RSHIFT,
14+	RENDERKEY_LCTRL,
15+	RENDERKEY_RCTRL,
16+	RENDERKEY_LALT,
17+	RENDERKEY_RALT,
18+	RENDERKEY_HOME,
19+	RENDERKEY_END,
20+	RENDERKEY_PAGEUP,
21+	RENDERKEY_PAGEDOWN,
22+	RENDERKEY_F1,
23+	RENDERKEY_F2,
24+	RENDERKEY_F3,
25+	RENDERKEY_F4,
26+	RENDERKEY_F5,
27+	RENDERKEY_F6,
28+	RENDERKEY_F7,
29+	RENDERKEY_F8,
30+	RENDERKEY_F9,
31+	RENDERKEY_F10,
32+	RENDERKEY_F11,
33+	RENDERKEY_F12,
34+	RENDERKEY_SELECT,
35+	RENDERKEY_PLAY,
36+	RENDERKEY_SEARCH,
37+	RENDERKEY_BACK,
38+	RENDERKEY_NP0,
39+	RENDERKEY_NP1,
40+	RENDERKEY_NP2,
41+	RENDERKEY_NP3,
42+	RENDERKEY_NP4,
43+	RENDERKEY_NP5,
44+	RENDERKEY_NP6,
45+	RENDERKEY_NP7,
46+	RENDERKEY_NP8,
47+	RENDERKEY_NP9,
48+	RENDERKEY_NP_DIV,
49+	RENDERKEY_NP_MUL,
50+	RENDERKEY_NP_MIN,
51+	RENDERKEY_NP_PLUS,
52+	RENDERKEY_NP_ENTER,
53+	RENDERKEY_NP_STOP,
54+	RENDER_DPAD_UP,
55+	RENDER_DPAD_DOWN,
56+	RENDER_DPAD_LEFT,
57+	RENDER_DPAD_RIGHT
58+};
59+
60+#endif //SPECIAL_KEYS_EVDEV_H_
+127, -0
  1@@ -0,0 +1,127 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm. 
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include <stdlib.h>
  8+#include <stdio.h>
  9+#include "vdp.h"
 10+#include "render.h"
 11+#include "util.h"
 12+#include "genesis.h"
 13+#include "config.h"
 14+
 15+
 16+uint16_t read_dma_value(uint32_t address)
 17+{
 18+	return 0;
 19+}
 20+
 21+m68k_context *m68k_handle_code_write(uint32_t address, m68k_context *context)
 22+{
 23+	return NULL;
 24+}
 25+
 26+z80_context *z80_handle_code_write(uint32_t address, z80_context *context)
 27+{
 28+	return NULL;
 29+}
 30+
 31+void ym_data_write(ym2612_context * context, uint8_t value)
 32+{
 33+}
 34+
 35+void ym_address_write_part1(ym2612_context * context, uint8_t address)
 36+{
 37+}
 38+
 39+void ym_address_write_part2(ym2612_context * context, uint8_t address)
 40+{
 41+}
 42+
 43+void handle_keydown(int keycode, uint8_t scancode)
 44+{
 45+}
 46+
 47+void handle_keyup(int keycode, uint8_t scancode)
 48+{
 49+}
 50+
 51+void handle_joydown(int joystick, int button)
 52+{
 53+}
 54+
 55+void handle_joyup(int joystick, int button)
 56+{
 57+}
 58+
 59+void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
 60+{
 61+}
 62+
 63+void handle_joy_axis(int joystick, int axis, int16_t value)
 64+{
 65+}
 66+
 67+void handle_joy_added(int joystick)
 68+{
 69+}
 70+
 71+void handle_mousedown(int mouse, int button)
 72+{
 73+}
 74+
 75+void handle_mouseup(int mouse, int button)
 76+{
 77+}
 78+
 79+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay)
 80+{
 81+}
 82+
 83+tern_node * config;
 84+int headless = 0;
 85+
 86+int main(int argc, char ** argv)
 87+{
 88+	if (argc < 2) {
 89+		fatal_error("Usage: stateview FILENAME\n");
 90+	}
 91+	FILE * state_file = fopen(argv[1], "rb");
 92+	if (!state_file) {
 93+		fatal_error("Failed to open %s\n", argv[1]);
 94+	}
 95+	set_exe_str(argv[0]);
 96+	config = load_config(argv[0]);
 97+	int width = -1;
 98+	int height = -1;
 99+	if (argc > 2) {
100+		width = atoi(argv[2]);
101+		if (argc > 3) {
102+			height = atoi(argv[3]);
103+		}
104+	}
105+	int def_width = 0;
106+	char *config_width = tern_find_ptr(config, "videowidth");
107+	if (config_width) {
108+		def_width = atoi(config_width);
109+	}
110+	if (!def_width) {
111+		def_width = 640;
112+	}
113+	width = width < 320 ? def_width : width;
114+	height = height < 240 ? (width/320) * 240 : height;
115+
116+	render_init(width, height, "GST State Viewer", 0);
117+	vdp_context *context = init_vdp_context(0);
118+	vdp_load_gst(context, state_file);
119+	vdp_run_to_vblank(context);
120+	vdp_print_sprite_table(context);
121+	printf("Display %s\n", (context->regs[REG_MODE_2] & DISPLAY_ENABLE) ? "enabled" : "disabled");
122+	if (!(context->regs[REG_MODE_2] & DISPLAY_ENABLE)) {
123+		puts("Forcing display on");
124+		vdp_control_port_write(context, 0x8000 | REG_MODE_2 << 8 | context->regs[REG_MODE_2] | DISPLAY_ENABLE);
125+	}
126+    render_wait_quit(context);
127+    return 0;
128+}
+7383, -0
   1@@ -0,0 +1,7383 @@
   2+;Size: 7375
   3+;Rate: 100000000
   4+;Channels: 16
   5+;EnabledChannels: 65535
   6+;TriggerPosition: 119
   7+;Compressed: true
   8+;AbsoluteLength: 12287
   9+;CursorEnabled: true
  10+000077f6@0
  11+0000f7f6@2
  12+0000fd1a@4
  13+0000b91a@5
  14+0000b99a@6
  15+0000399a@10
  16+0000a99a@11
  17+0000a91a@12
  18+0000adf2@13
  19+0000a5f2@14
  20+00002572@19
  21+00002570@20
  22+0000a5f0@21
  23+0000a5f4@22
  24+0000e7f4@23
  25+0000e5f4@25
  26+0000e774@26
  27+000067f4@28
  28+000065f0@29
  29+0000e7f4@30
  30+0000e5f0@32
  31+0000f7f4@33
  32+0000f774@34
  33+0000f770@35
  34+0000f7f4@36
  35+000077f4@37
  36+000075f6@38
  37+0000f7f6@39
  38+0000fd3e@41
  39+0000b93a@42
  40+0000b9ba@43
  41+000039ba@47
  42+000029ba@48
  43+0000a93a@49
  44+0000adfa@50
  45+0000a5f2@51
  46+00002572@56
  47+00002570@57
  48+0000a5f0@58
  49+0000e5f4@60
  50+0000e7f4@61
  51+0000e5f4@62
  52+0000e7f4@63
  53+0000e774@64
  54+000067f4@65
  55+000065f0@66
  56+0000e5f4@67
  57+0000e7f4@68
  58+0000e5f4@69
  59+0000f7f4@70
  60+0000f774@71
  61+0000f570@72
  62+0000f7f4@73
  63+000077f6@75
  64+0000f7f6@77
  65+0000fffe@78
  66+0000fb1a@79
  67+0000bb9a@80
  68+00003b9a@84
  69+0000ab1a@86
  70+0000ab9a@87
  71+0000a5f2@88
  72+00002572@93
  73+00002570@94
  74+0000a570@95
  75+0000a5f0@96
  76+0000e7f4@98
  77+0000e774@101
  78+000065f4@103
  79+0000e7f4@104
  80+0000f7f4@107
  81+0000f774@108
  82+0000f7f4@110
  83+000077f6@112
  84+0000f7f6@114
  85+0000f81a@116
  86+0000b81a@117
  87+0000b89a@118
  88+0000389a@121
  89+0000a81a@123
  90+0000a4f2@125
  91+00002470@131
  92+0000a470@132
  93+0000a674@134
  94+0000e6f0@135
  95+0000e6f4@136
  96+00006674@140
  97+00006474@141
  98+0000e674@142
  99+0000f6f4@144
 100+000076f6@149
 101+00007676@150
 102+0000f676@151
 103+0000f83a@153
 104+0000b8ba@154
 105+0000383a@159
 106+0000a83a@160
 107+0000acf2@162
 108+0000a4f2@163
 109+00002472@168
 110+00002470@169
 111+0000a470@170
 112+0000a474@171
 113+0000e6f4@172
 114+000066f4@177
 115+00006470@178
 116+0000e674@179
 117+0000f474@181
 118+0000f6f4@182
 119+000076f6@186
 120+00007476@187
 121+0000f676@188
 122+0000fe3e@190
 123+0000ba9a@191
 124+00003a1a@196
 125+0000aa1a@198
 126+0000ae7a@199
 127+0000a4f2@200
 128+000024f2@205
 129+00002470@206
 130+0000a470@207
 131+0000e4f4@209
 132+0000e6f4@210
 133+000066f4@214
 134+00006470@215
 135+0000e474@216
 136+0000e674@217
 137+0000e474@218
 138+0000f6f4@219
 139+00007676@224
 140+0000f676@226
 141+0000f67e@227
 142+0000f21a@228
 143+0000b29a@229
 144+0000329a@233
 145+0000321a@234
 146+0000a21a@235
 147+0000a4f2@237
 148+000024f2@242
 149+00002470@243
 150+0000a470@244
 151+0000e6f4@247
 152+00006474@252
 153+0000e474@253
 154+0000e674@254
 155+0000f6f4@256
 156+00007676@261
 157+0000f676@263
 158+0000f21a@265
 159+0000b29a@266
 160+0000329a@270
 161+0000321a@271
 162+0000a29a@272
 163+0000a4f2@274
 164+0000a472@278
 165+0000a4f2@279
 166+000024f0@280
 167+0000a4f0@281
 168+0000a6f4@283
 169+0000e6f4@284
 170+0000e674@285
 171+000066f4@289
 172+000064f4@290
 173+0000e6f4@291
 174+0000f6f4@293
 175+0000f674@295
 176+00007676@298
 177+000076f6@299
 178+0000f6f6@300
 179+0000f69a@302
 180+0000b21a@303
 181+0000329a@308
 182+0000a29a@309
 183+0000a6f2@311
 184+0000a4f2@312
 185+0000a472@314
 186+00002472@317
 187+000024f0@318
 188+0000a4f0@319
 189+0000a6f4@320
 190+0000e6f4@321
 191+0000e674@323
 192+00006674@326
 193+000064f0@327
 194+0000e6f4@328
 195+0000e4f0@330
 196+0000f6f4@331
 197+0000f674@332
 198+00007676@335
 199+000076f6@336
 200+0000f6f6@337
 201+0000f6be@339
 202+0000b2ae@340
 203+0000b22e@341
 204+000032ae@345
 205+0000a2ae@347
 206+0000a082@349
 207+0000a002@351
 208+00002082@354
 209+00002080@355
 210+0000a080@356
 211+0000e0a4@358
 212+0000e284@359
 213+0000e004@360
 214+0000e204@362
 215+00006224@363
 216+00006084@364
 217+0000e0a4@365
 218+0000e2a4@366
 219+0000e284@367
 220+0000f2a4@368
 221+0000f224@369
 222+0000f204@370
 223+000070a6@373
 224+000072a6@374
 225+0000f2a6@375
 226+0000f2ae@376
 227+0000f22e@379
 228+0000722e@382
 229+000072ae@383
 230+0000e2ae@384
 231+0000e082@386
 232+0000e002@388
 233+00006082@391
 234+00006080@392
 235+0000e080@393
 236+0000e2a4@395
 237+0000a2a4@396
 238+0000a60c@398
 239+0000268c@401
 240+0000a68c@402
 241+0000b68c@405
 242+0000b60c@407
 243+0000360e@410
 244+0000768e@411
 245+0000f68e@412
 246+0000f49a@414
 247+0000b49a@415
 248+0000b41a@416
 249+0000349a@419
 250+0000a49a@421
 251+0000aef2@423
 252+0000aaf2@424
 253+0000aa72@425
 254+0000aaf2@426
 255+00002af0@429
 256+0000aaf0@430
 257+0000aa74@432
 258+0000ea70@433
 259+0000eaf4@434
 260+00006af4@438
 261+0000ea74@440
 262+0000fa74@442
 263+0000faf4@444
 264+00007af6@447
 265+0000faf6@449
 266+0000fa76@450
 267+0000fe26@451
 268+0000b426@452
 269+0000b4a6@453
 270+000034a6@457
 271+0000a4a6@458
 272+0000a426@459
 273+0000a472@460
 274+0000a4f2@462
 275+000024f2@466
 276+000024f0@467
 277+0000a470@468
 278+0000a674@469
 279+0000e674@470
 280+0000e6f4@472
 281+000066f4@475
 282+000064f4@476
 283+0000e674@477
 284+0000f474@479
 285+0000f674@480
 286+0000f6f4@481
 287+000076f6@484
 288+000074f6@485
 289+0000f4f6@486
 290+0000f676@487
 291+0000f606@488
 292+0000b606@489
 293+0000b686@490
 294+00003686@494
 295+0000a606@496
 296+0000a676@497
 297+0000a472@498
 298+0000a4f2@500
 299+000024f2@503
 300+000024f0@504
 301+0000a470@505
 302+0000e474@507
 303+0000e674@508
 304+0000e6f4@509
 305+000066f4@512
 306+000064f4@513
 307+0000e4f4@514
 308+0000e674@515
 309+0000e474@516
 310+0000f674@517
 311+0000f6f4@519
 312+000074f6@522
 313+000076f6@523
 314+0000f676@524
 315+0000f626@526
 316+0000b6a6@527
 317+000036a6@531
 318+0000a626@533
 319+0000a472@535
 320+0000a4f2@537
 321+000024f2@540
 322+000024f0@541
 323+0000a470@542
 324+0000e674@545
 325+0000e6f4@546
 326+000064f4@550
 327+0000e4f4@551
 328+0000e674@552
 329+0000f674@554
 330+0000f6f4@556
 331+000076f6@559
 332+0000f676@561
 333+0000f226@563
 334+0000b226@564
 335+0000b2a6@565
 336+000032a6@568
 337+0000a2a6@570
 338+0000a226@571
 339+0000a002@572
 340+0000a082@574
 341+00002080@578
 342+0000a080@579
 343+0000a000@580
 344+0000a2a4@581
 345+0000e2a0@582
 346+0000e2a4@583
 347+00006224@587
 348+00006000@588
 349+0000e2a4@589
 350+0000f2a4@591
 351+0000f224@594
 352+00007226@596
 353+00007206@597
 354+0000f2a6@598
 355+0000f8be@600
 356+0000f9be@601
 357+0000b9be@602
 358+0000b93e@604
 359+0000393e@605
 360+0000a93e@607
 361+0000a9be@608
 362+0000abc2@609
 363+0000ab42@613
 364+00002b42@615
 365+00002b40@616
 366+0000abc0@617
 367+0000abe4@618
 368+0000ebe0@619
 369+0000ebe4@620
 370+0000eb64@623
 371+00006b64@624
 372+00006b44@625
 373+0000ebe4@626
 374+0000fbe4@629
 375+0000fb64@632
 376+00007b46@633
 377+0000fb66@635
 378+0000fbe6@636
 379+0000f3a6@638
 380+0000b3a6@639
 381+0000b326@641
 382+00003326@643
 383+00002326@644
 384+0000a3a6@645
 385+0000a182@647
 386+0000a102@651
 387+00002102@652
 388+00002100@653
 389+0000a180@654
 390+0000e1a4@656
 391+0000e3a4@657
 392+0000e1a4@658
 393+0000e3a4@659
 394+0000e324@660
 395+00006324@661
 396+00006104@662
 397+0000e124@663
 398+0000e3a4@664
 399+0000f3a4@666
 400+0000f324@669
 401+0000f304@670
 402+00007326@671
 403+0000f3a6@673
 404+0000f3be@674
 405+0000f19a@675
 406+0000b19a@676
 407+0000b11a@679
 408+0000311a@680
 409+0000a19a@682
 410+0000a182@684
 411+0000a102@688
 412+00002102@689
 413+00002100@690
 414+0000a100@691
 415+0000a180@692
 416+0000e3a4@694
 417+0000e324@697
 418+00006104@699
 419+0000e104@700
 420+0000e3a4@701
 421+0000e1a4@702
 422+0000f3a4@703
 423+0000f184@705
 424+0000f3a4@706
 425+0000f304@707
 426+00007326@708
 427+00007306@709
 428+0000f3a6@710
 429+0000f19a@712
 430+0000b19a@714
 431+0000b11a@716
 432+0000311a@717
 433+0000a11a@719
 434+0000a19a@720
 435+0000a182@721
 436+0000a102@725
 437+00002100@727
 438+0000a100@728
 439+0000a180@729
 440+0000a3a4@730
 441+0000e3a4@731
 442+0000e384@733
 443+0000e324@734
 444+0000e104@735
 445+000061a4@736
 446+000063a4@737
 447+0000e3a4@738
 448+0000f384@740
 449+0000f3a4@741
 450+0000f304@742
 451+0000f3a4@743
 452+000073a6@745
 453+0000f3a6@747
 454+0000f17e@749
 455+0000f15e@750
 456+0000b1de@751
 457+000031de@754
 458+0000a15e@756
 459+0000afc2@758
 460+00002f42@764
 461+00002f40@765
 462+0000afc0@766
 463+0000afe4@767
 464+0000efe0@768
 465+0000efe4@769
 466+0000efc4@770
 467+0000ef64@771
 468+0000ef44@772
 469+00006fe4@773
 470+00006fc4@774
 471+0000efe4@775
 472+0000efc4@777
 473+0000ffe4@778
 474+0000ff64@779
 475+0000ff44@780
 476+0000ffe4@781
 477+00007fe6@782
 478+0000ffe6@784
 479+0000fb56@786
 480+0000b356@787
 481+0000b3d6@788
 482+000033d6@792
 483+00002356@793
 484+0000a356@794
 485+0000a7f6@795
 486+0000a7f2@796
 487+00002772@801
 488+00002770@802
 489+0000a7f0@803
 490+0000e7f4@805
 491+0000e774@809
 492+000067f4@810
 493+0000e7f4@812
 494+0000f7f4@815
 495+0000f774@816
 496+0000f7f4@818
 497+000077f6@820
 498+0000f7f6@822
 499+0000f7fe@823
 500+0000f53a@824
 501+0000b5ba@825
 502+000035ba@829
 503+0000a53a@831
 504+0000a5ba@832
 505+0000ab02@833
 506+0000ab82@834
 507+00002b82@838
 508+00002b00@839
 509+0000ab80@840
 510+0000aba4@842
 511+0000eba4@843
 512+0000eb24@846
 513+00006ba4@848
 514+0000eba4@849
 515+0000fba4@852
 516+0000fb24@853
 517+0000fb04@854
 518+0000fba4@855
 519+00007ba6@857
 520+0000fba6@859
 521+0000f71a@861
 522+0000b79a@863
 523+0000379a@866
 524+0000a71a@868
 525+0000ab82@870
 526+00002b00@876
 527+0000ab80@877
 528+0000aba4@879
 529+0000eba4@880
 530+0000eb84@882
 531+0000eb24@883
 532+0000eb04@884
 533+00006ba4@885
 534+0000eba4@887
 535+0000fb84@889
 536+0000fba4@890
 537+0000fb24@891
 538+0000fba4@892
 539+00007ba6@894
 540+0000fba6@896
 541+0000f902@898
 542+0000b902@899
 543+0000b982@900
 544+00003982@904
 545+0000a902@905
 546+0000abc2@907
 547+00002b42@913
 548+00002b40@914
 549+0000abc0@915
 550+0000abe4@916
 551+0000ebe0@917
 552+0000ebe4@918
 553+0000ebc4@919
 554+0000eb64@920
 555+0000eb44@921
 556+00006be4@922
 557+00006bc4@923
 558+0000ebe4@924
 559+0000ebc0@926
 560+0000fbe4@927
 561+0000fb64@928
 562+0000fbc4@929
 563+0000fbe4@930
 564+00007be6@931
 565+0000fbe6@933
 566+0000fb02@935
 567+0000f902@936
 568+0000f982@937
 569+00007982@941
 570+00006982@942
 571+0000e902@943
 572+0000ebc2@944
 573+00006b42@950
 574+00006b40@951
 575+0000ebc0@952
 576+0000ebe4@954
 577+0000abc0@956
 578+0000a100@957
 579+00002180@959
 580+0000a180@961
 581+0000b180@963
 582+0000b100@965
 583+0000b180@967
 584+00007182@969
 585+0000f182@971
 586+0000f11a@972
 587+0000b19a@974
 588+0000319a@978
 589+0000a11a@980
 590+0000a182@982
 591+00002182@987
 592+00002100@988
 593+0000a180@989
 594+0000e3a4@992
 595+0000e3a0@993
 596+0000e384@994
 597+0000e324@995
 598+0000e304@996
 599+00006184@997
 600+0000e3a4@998
 601+0000f3a4@1001
 602+0000f304@1002
 603+0000f104@1003
 604+0000f3a4@1004
 605+000073a6@1006
 606+0000f3a6@1008
 607+0000f11a@1010
 608+0000b11a@1011
 609+0000b19a@1012
 610+0000319a@1015
 611+0000a11a@1017
 612+0000a182@1019
 613+00002100@1025
 614+0000a100@1026
 615+0000a180@1027
 616+0000a3a4@1028
 617+0000e3a4@1029
 618+0000e384@1031
 619+0000e324@1032
 620+0000e104@1033
 621+000063a4@1034
 622+000061a4@1035
 623+0000e3a4@1036
 624+0000f184@1038
 625+0000f3a4@1039
 626+0000f304@1040
 627+0000f3a4@1041
 628+000073a6@1043
 629+0000f3a6@1045
 630+0000f162@1047
 631+0000b1e2@1049
 632+000031e2@1052
 633+0000a162@1054
 634+0000af42@1056
 635+0000afc2@1057
 636+00002f42@1062
 637+00002fc0@1063
 638+0000afc0@1064
 639+0000afe4@1065
 640+0000efe0@1066
 641+0000efe4@1067
 642+0000efc4@1068
 643+0000ef64@1069
 644+0000ef40@1070
 645+00006fe4@1071
 646+00006fc0@1072
 647+0000efe4@1073
 648+0000efc0@1075
 649+0000ffe4@1076
 650+0000ff64@1077
 651+0000ff40@1078
 652+0000ffe4@1079
 653+00007fe6@1080
 654+0000ffe6@1082
 655+0000fb46@1084
 656+0000b346@1085
 657+0000b3c6@1086
 658+000033c6@1090
 659+00002346@1091
 660+0000a346@1092
 661+0000abe6@1093
 662+0000abe2@1094
 663+00002b62@1099
 664+00002b60@1100
 665+0000abe0@1101
 666+0000ebe4@1103
 667+0000eb64@1107
 668+00006be4@1108
 669+0000ebe4@1110
 670+0000fbe4@1113
 671+0000fb64@1114
 672+0000fbe4@1116
 673+00007be6@1118
 674+0000fbe6@1120
 675+0000ff7e@1121
 676+0000f73a@1122
 677+0000b7ba@1123
 678+000037ba@1127
 679+0000a73a@1129
 680+0000a7ba@1130
 681+0000ab02@1131
 682+0000ab82@1132
 683+00002b82@1136
 684+00002b00@1137
 685+0000ab80@1138
 686+0000aba4@1140
 687+0000eba4@1141
 688+0000eb24@1144
 689+00006ba4@1146
 690+0000eba4@1147
 691+0000fba4@1150
 692+0000fb24@1151
 693+0000fba4@1153
 694+00007ba6@1155
 695+0000fba6@1157
 696+0000f91a@1159
 697+0000b91a@1160
 698+0000b99a@1161
 699+0000399a@1164
 700+0000a91a@1166
 701+0000ab82@1168
 702+00002b00@1174
 703+0000ab80@1175
 704+0000aba4@1177
 705+0000eba4@1178
 706+0000eb84@1180
 707+0000eb24@1181
 708+0000eb04@1182
 709+00006ba4@1183
 710+0000eba4@1185
 711+0000fb84@1187
 712+0000fba4@1188
 713+0000fb04@1189
 714+0000fba4@1190
 715+00007ba6@1192
 716+0000fba6@1194
 717+0000f906@1196
 718+0000b906@1197
 719+0000b986@1198
 720+00003986@1202
 721+0000a906@1203
 722+0000abc2@1205
 723+00002b42@1211
 724+00002b40@1212
 725+0000abc0@1213
 726+0000abe4@1214
 727+0000ebe0@1215
 728+0000ebe4@1216
 729+0000ebc4@1217
 730+0000eb64@1218
 731+0000eb44@1219
 732+00006be4@1220
 733+00006bc4@1221
 734+0000ebe4@1222
 735+0000fbc4@1224
 736+0000fbe4@1225
 737+0000fb64@1226
 738+0000fb44@1227
 739+0000fbe4@1228
 740+00007be6@1229
 741+0000fbe6@1231
 742+0000fb06@1233
 743+0000f906@1234
 744+0000f986@1235
 745+00007986@1239
 746+00006986@1240
 747+0000e906@1241
 748+0000ebc6@1242
 749+0000ebc2@1243
 750+00006b42@1248
 751+00006b40@1249
 752+0000ebc0@1250
 753+0000ebe4@1252
 754+0000abc4@1254
 755+0000a100@1255
 756+00002180@1257
 757+0000a180@1259
 758+0000b180@1262
 759+0000b100@1263
 760+0000b180@1265
 761+00007182@1267
 762+0000f182@1269
 763+0000f11a@1270
 764+0000b19a@1272
 765+0000319a@1276
 766+0000a11a@1278
 767+0000a19a@1279
 768+0000a182@1280
 769+00002182@1285
 770+00002100@1286
 771+0000a100@1287
 772+0000a180@1288
 773+0000e3a4@1290
 774+0000e184@1292
 775+0000e324@1293
 776+0000e304@1294
 777+000061a4@1295
 778+0000e1a4@1296
 779+0000e3a4@1297
 780+0000f3a4@1299
 781+0000f324@1300
 782+0000f104@1301
 783+0000f3a4@1302
 784+000073a6@1304
 785+0000f3a6@1306
 786+0000f97a@1308
 787+0000f9fa@1309
 788+0000b9fa@1310
 789+000039fa@1313
 790+0000a97a@1315
 791+0000a982@1317
 792+0000a182@1318
 793+00002100@1323
 794+0000a180@1324
 795+0000a3a4@1326
 796+0000e3a4@1327
 797+0000e384@1329
 798+0000e324@1330
 799+0000e104@1331
 800+000061a4@1332
 801+0000e3a4@1334
 802+0000f180@1336
 803+0000f3a4@1337
 804+0000f104@1338
 805+0000f3a4@1339
 806+000073a6@1341
 807+0000f3a6@1343
 808+0000f166@1345
 809+0000b1e6@1347
 810+000031e6@1351
 811+0000a166@1352
 812+0000afc2@1354
 813+00002f42@1360
 814+00002f40@1361
 815+0000afc0@1362
 816+0000afe4@1363
 817+0000efe0@1364
 818+0000efe4@1365
 819+0000efc4@1366
 820+0000ef64@1367
 821+00006fe4@1369
 822+00006fc4@1370
 823+0000efe4@1371
 824+0000efc4@1373
 825+0000ffe4@1374
 826+0000ff64@1375
 827+0000ffe4@1377
 828+00007fe6@1378
 829+0000ffe6@1380
 830+0000fb46@1382
 831+0000b346@1383
 832+0000b3c6@1384
 833+000033c6@1388
 834+000023c6@1389
 835+0000a346@1390
 836+0000abe6@1391
 837+0000abe2@1392
 838+00002b62@1397
 839+00002b60@1398
 840+0000abe0@1399
 841+0000ebe4@1401
 842+0000eb64@1405
 843+00006be4@1406
 844+0000ebe4@1408
 845+0000fbe4@1411
 846+0000fb64@1412
 847+0000fbe4@1414
 848+00007be6@1416
 849+0000fbe6@1418
 850+0000fb7e@1419
 851+0000f93a@1420
 852+0000b9ba@1421
 853+000039ba@1425
 854+0000a93a@1427
 855+0000a9ba@1428
 856+0000ab02@1429
 857+0000ab82@1430
 858+00002b82@1434
 859+00002b00@1435
 860+0000ab80@1436
 861+0000aba4@1438
 862+0000eba4@1439
 863+0000eb24@1442
 864+00006ba4@1444
 865+0000eba4@1445
 866+0000fba4@1448
 867+0000fb24@1449
 868+0000fb04@1450
 869+0000fba4@1451
 870+00007ba6@1453
 871+0000fba6@1455
 872+0000f31a@1457
 873+0000b31a@1458
 874+0000b39a@1459
 875+0000339a@1462
 876+0000a31a@1464
 877+0000af22@1466
 878+0000ada2@1467
 879+00002d20@1472
 880+0000ada0@1473
 881+0000afa4@1475
 882+0000efa4@1476
 883+0000ef24@1479
 884+00006fa4@1481
 885+0000efa4@1483
 886+0000ffa4@1485
 887+0000ff24@1487
 888+0000ffa4@1488
 889+00007fa6@1490
 890+0000ffa6@1492
 891+0000f90a@1494
 892+0000b90a@1495
 893+0000b98a@1496
 894+0000398a@1500
 895+0000a90a@1501
 896+0000abc2@1503
 897+00002b42@1509
 898+00002b40@1510
 899+0000abc0@1511
 900+0000abe4@1512
 901+0000ebe0@1513
 902+0000ebe4@1514
 903+0000ebc4@1515
 904+0000eb64@1516
 905+0000eb44@1517
 906+00006be4@1518
 907+00006bc4@1519
 908+0000ebe4@1520
 909+0000fbc0@1522
 910+0000fbe4@1523
 911+0000fb44@1524
 912+0000fbe4@1526
 913+00007be6@1527
 914+0000fbe6@1529
 915+0000fb0e@1531
 916+0000f90a@1532
 917+0000f98a@1533
 918+0000798a@1537
 919+0000698a@1538
 920+0000e90a@1539
 921+0000ebca@1540
 922+0000ebc2@1541
 923+00006b42@1546
 924+00006b40@1547
 925+0000ebc0@1548
 926+0000ebe4@1550
 927+0000afe0@1552
 928+0000a5e0@1553
 929+0000a560@1554
 930+000025e0@1555
 931+0000a5e0@1557
 932+0000b5e0@1559
 933+0000b560@1561
 934+0000b5e0@1563
 935+000075e2@1565
 936+0000f5e2@1567
 937+0000fd7a@1568
 938+0000f91a@1569
 939+0000b99a@1570
 940+0000399a@1574
 941+0000a91a@1576
 942+0000a99a@1577
 943+0000abd2@1578
 944+00002bd2@1583
 945+00002b50@1584
 946+0000abd0@1585
 947+0000abf4@1587
 948+0000ebf4@1588
 949+0000ebd4@1590
 950+0000eb74@1591
 951+00006bf4@1593
 952+0000ebf4@1594
 953+0000fbf4@1597
 954+0000fb74@1598
 955+0000fb54@1599
 956+0000fbf4@1600
 957+00007bf6@1602
 958+0000fbf6@1604
 959+0000f91a@1606
 960+0000b91a@1607
 961+0000b99a@1608
 962+0000399a@1611
 963+0000a91a@1613
 964+0000a99a@1614
 965+0000abd2@1615
 966+00002b50@1621
 967+0000ab50@1622
 968+0000abd0@1623
 969+0000abf4@1624
 970+0000ebf4@1625
 971+0000ebd4@1627
 972+0000eb74@1628
 973+0000eb54@1629
 974+00006bf4@1630
 975+0000ebf4@1632
 976+0000fbf4@1634
 977+0000fb54@1636
 978+0000fbf4@1637
 979+00007bf6@1639
 980+00007bd6@1640
 981+0000fbf6@1641
 982+0000f17a@1643
 983+0000b16a@1644
 984+0000b1ea@1645
 985+000031ea@1649
 986+0000a1ea@1650
 987+0000a16a@1651
 988+0000afc2@1652
 989+00002f42@1658
 990+00002f40@1659
 991+0000afc0@1660
 992+0000afe4@1661
 993+0000efe0@1662
 994+0000efe4@1663
 995+0000efc4@1664
 996+0000ef64@1665
 997+0000ef44@1666
 998+00006fe4@1667
 999+0000efe4@1669
1000+0000efc0@1671
1001+0000ffe4@1672
1002+0000ff64@1673
1003+0000ff44@1674
1004+0000ffe4@1675
1005+00007fe6@1676
1006+0000ffe6@1678
1007+0000fb46@1680
1008+0000b346@1681
1009+0000b3c6@1682
1010+000033c6@1686
1011+00002346@1687
1012+0000a346@1688
1013+0000abe6@1689
1014+0000abe2@1690
1015+00002b62@1695
1016+00002b60@1696
1017+0000abe0@1697
1018+0000ebe4@1699
1019+0000eb64@1703
1020+00006be4@1704
1021+0000ebe4@1706
1022+0000fbe4@1709
1023+0000fb64@1710
1024+0000fbe4@1712
1025+00007be6@1714
1026+0000fbe6@1715
1027+0000fb7e@1717
1028+0000f33a@1718
1029+0000b3ba@1719
1030+000033ba@1723
1031+0000a33a@1725
1032+0000a3ba@1726
1033+0000ada2@1727
1034+00002da2@1732
1035+00002d20@1733
1036+0000ada0@1734
1037+0000efa4@1737
1038+0000efa0@1738
1039+0000efa4@1739
1040+0000ef24@1740
1041+00006da4@1742
1042+0000efa4@1743
1043+0000ffa4@1746
1044+0000ff24@1747
1045+0000ffa4@1749
1046+00007fa6@1751
1047+0000ffa6@1753
1048+0000f51a@1755
1049+0000b51a@1756
1050+0000b59a@1757
1051+0000359a@1760
1052+0000a51a@1762
1053+0000ad22@1764
1054+0000ada2@1765
1055+00002d20@1770
1056+0000ada0@1771
1057+0000afa4@1773
1058+0000efa4@1774
1059+0000ef24@1777
1060+00006da4@1779
1061+0000efa4@1781
1062+0000ffa0@1783
1063+0000ffa4@1784
1064+0000ff24@1785
1065+0000ffa4@1786
1066+00007fa6@1788
1067+0000ffa6@1790
1068+0000f90e@1792
1069+0000b98e@1794
1070+0000398e@1798
1071+0000a90e@1799
1072+0000abc2@1801
1073+00002b42@1807
1074+00002b40@1808
1075+0000abc0@1809
1076+0000abe4@1810
1077+0000ebe0@1811
1078+0000ebe4@1812
1079+0000ebc4@1813
1080+0000eb64@1814
1081+0000eb44@1815
1082+00006be4@1816
1083+00006bc4@1817
1084+0000ebe4@1818
1085+0000ebc4@1820
1086+0000fbe4@1821
1087+0000fb64@1822
1088+0000fbc4@1823
1089+0000fbe4@1824
1090+00007be6@1825
1091+0000fbe6@1827
1092+0000fb0e@1829
1093+0000f90e@1830
1094+0000f98e@1831
1095+0000798e@1835
1096+0000798c@1836
1097+0000f90c@1837
1098+0000fbcc@1838
1099+0000fbc0@1839
1100+0000ebc0@1841
1101+00006b40@1844
1102+0000ebc0@1846
1103+0000ebe4@1848
1104+0000eb44@1852
1105+00006be4@1853
1106+00006bc4@1854
1107+0000ebe4@1855
1108+0000ebc4@1857
1109+0000fbe4@1858
1110+0000fb64@1859
1111+0000fb44@1860
1112+0000fbe4@1861
1113+00007be6@1863
1114+0000fbe6@1864
1115+0000fb7e@1866
1116+0000f91a@1867
1117+0000b99a@1868
1118+0000399a@1872
1119+0000a91a@1874
1120+0000a99a@1875
1121+0000abd2@1876
1122+00002bd2@1881
1123+00002b50@1882
1124+0000abd0@1883
1125+0000abf4@1885
1126+0000ebf4@1886
1127+0000eb74@1889
1128+00006bf4@1891
1129+0000ebf4@1892
1130+0000fbf4@1895
1131+0000fb74@1896
1132+0000fb54@1897
1133+0000fbf4@1898
1134+00007bf6@1900
1135+0000fbf6@1902
1136+0000f91a@1904
1137+0000b91a@1905
1138+0000b99a@1906
1139+0000399a@1909
1140+0000a91a@1911
1141+0000abd2@1913
1142+00002b50@1919
1143+0000ab50@1920
1144+0000abd0@1921
1145+0000abf4@1922
1146+0000ebf4@1923
1147+0000ebd4@1925
1148+0000eb74@1926
1149+0000eb54@1927
1150+00006bf4@1928
1151+0000ebf4@1930
1152+0000fbd4@1932
1153+0000fbf4@1933
1154+0000fb54@1934
1155+0000fbf4@1935
1156+00007bf6@1937
1157+0000fbf6@1939
1158+0000f17e@1941
1159+0000b16e@1942
1160+0000b1ee@1943
1161+000031ee@1946
1162+0000a16e@1948
1163+0000afc2@1950
1164+00002f42@1956
1165+00002f40@1957
1166+0000afc0@1958
1167+0000afe4@1959
1168+0000efe0@1960
1169+0000efe4@1961
1170+0000efc4@1962
1171+0000ef64@1963
1172+0000ef44@1964
1173+00006fe4@1965
1174+0000efe4@1967
1175+0000efc0@1969
1176+0000ffe4@1970
1177+0000ff64@1971
1178+0000ff44@1972
1179+0000ffe4@1973
1180+00007fe6@1974
1181+0000ffe6@1976
1182+0000fb46@1978
1183+0000b346@1979
1184+0000b3c6@1980
1185+000033c6@1984
1186+00002346@1985
1187+0000a346@1986
1188+0000abe6@1987
1189+0000abe2@1988
1190+00002b62@1993
1191+00002b60@1994
1192+0000abe0@1995
1193+0000ebe4@1997
1194+0000eb64@2001
1195+00006be4@2002
1196+0000ebe4@2004
1197+0000fbe4@2007
1198+0000fb64@2008
1199+0000fbe4@2010
1200+00007be6@2012
1201+0000fbe6@2013
1202+0000ff7e@2015
1203+0000f53a@2016
1204+0000b5ba@2017
1205+000035ba@2021
1206+0000a53a@2023
1207+0000a5ba@2024
1208+0000ad22@2025
1209+0000ada2@2026
1210+00002da2@2030
1211+00002d20@2031
1212+0000ada0@2032
1213+0000efa4@2035
1214+0000eda4@2037
1215+0000ef24@2038
1216+0000efa4@2039
1217+00006da4@2040
1218+0000efa4@2041
1219+0000ffa4@2044
1220+0000ff24@2045
1221+0000ffa4@2047
1222+00007fa6@2049
1223+0000ffa6@2051
1224+0000f71a@2053
1225+0000b71a@2054
1226+0000b79a@2055
1227+0000379a@2058
1228+0000a71a@2060
1229+0000ada2@2062
1230+00002d20@2068
1231+0000ada0@2069
1232+0000afa4@2071
1233+0000efa4@2072
1234+0000ef24@2075
1235+00006fa4@2077
1236+0000efa4@2079
1237+0000ffa4@2081
1238+0000ff24@2083
1239+0000ffa4@2084
1240+00007fa6@2086
1241+0000ffa6@2088
1242+0000f932@2090
1243+0000b912@2091
1244+0000b992@2092
1245+00003992@2096
1246+0000a912@2097
1247+0000abc2@2099
1248+00002b42@2105
1249+00002b40@2106
1250+0000abc0@2107
1251+0000abe4@2108
1252+0000ebe0@2109
1253+0000ebe4@2110
1254+0000ebc4@2111
1255+0000eb64@2112
1256+0000eb44@2113
1257+00006be4@2114
1258+00006bc4@2115
1259+0000ebe4@2116
1260+0000fbc0@2118
1261+0000fbe4@2119
1262+0000fb64@2120
1263+0000fbc4@2121
1264+0000fbe4@2122
1265+00007be6@2123
1266+0000fbe6@2125
1267+0000fb12@2127
1268+0000f912@2128
1269+0000f992@2129
1270+00007992@2133
1271+00006992@2134
1272+0000e912@2135
1273+0000ebd2@2136
1274+0000ebc2@2137
1275+00006b42@2142
1276+00006b40@2143
1277+0000ebc0@2144
1278+0000ebe4@2146
1279+0000afe0@2148
1280+0000a5e0@2149
1281+0000a560@2150
1282+000025e0@2151
1283+0000a5e0@2153
1284+0000b5e0@2156
1285+0000b560@2157
1286+0000b5e0@2159
1287+000075e2@2161
1288+0000f5e2@2162
1289+0000fd7a@2164
1290+0000f91a@2165
1291+0000b99a@2166
1292+0000399a@2170
1293+0000a91a@2172
1294+0000a99a@2173
1295+0000abd2@2174
1296+00002bd2@2179
1297+00002b50@2180
1298+0000abd0@2181
1299+0000abf4@2183
1300+0000ebf4@2184
1301+0000eb74@2187
1302+00006bf4@2189
1303+0000ebf4@2190
1304+0000fbf4@2193
1305+0000fb74@2194
1306+0000fb54@2195
1307+0000fbf4@2196
1308+00007bf6@2198
1309+0000fbf6@2200
1310+0000f91a@2202
1311+0000b91a@2203
1312+0000b99a@2204
1313+0000399a@2207
1314+0000a91a@2209
1315+0000a99a@2210
1316+0000abd2@2211
1317+00002b50@2217
1318+0000ab50@2218
1319+0000abd0@2219
1320+0000abf4@2220
1321+0000ebf4@2221
1322+0000ebd4@2223
1323+0000eb74@2224
1324+0000eb54@2225
1325+00006bf4@2226
1326+0000ebf4@2228
1327+0000fbd4@2230
1328+0000fbf4@2231
1329+0000fb54@2232
1330+0000fbf4@2233
1331+00007bf6@2235
1332+0000fbf6@2237
1333+0000f172@2239
1334+0000b172@2240
1335+0000b1f2@2241
1336+000031f2@2244
1337+0000a172@2246
1338+0000afc2@2248
1339+00002f42@2254
1340+00002f40@2255
1341+0000afc0@2256
1342+0000afe4@2257
1343+0000efe0@2258
1344+0000efe4@2259
1345+0000ef64@2261
1346+00006fe4@2263
1347+0000efe4@2265
1348+0000ffc0@2267
1349+0000ffe4@2268
1350+0000ff64@2269
1351+0000ffe4@2271
1352+00007fe6@2272
1353+0000ffe6@2274
1354+0000f346@2276
1355+0000b346@2277
1356+0000b3c6@2278
1357+000033c6@2282
1358+00002346@2283
1359+0000a346@2284
1360+0000abe6@2285
1361+0000abe2@2286
1362+00002b62@2291
1363+00002b60@2292
1364+0000abe0@2293
1365+0000ebe4@2295
1366+0000eb64@2299
1367+00006be4@2300
1368+0000ebe4@2302
1369+0000fbe4@2304
1370+0000fb64@2306
1371+0000fbe4@2308
1372+00007be6@2310
1373+0000fbe6@2311
1374+0000fb7e@2313
1375+0000fb1a@2314
1376+0000bb9a@2315
1377+00003b9a@2319
1378+0000ab1a@2321
1379+0000ab9a@2322
1380+0000ab82@2323
1381+00002b82@2328
1382+00002b00@2329
1383+0000ab80@2330
1384+0000aba4@2332
1385+0000eba4@2333
1386+0000eb24@2336
1387+00006ba4@2338
1388+0000eba4@2339
1389+0000fba4@2342
1390+0000fb24@2343
1391+0000fb04@2344
1392+0000fba4@2345
1393+00007ba6@2347
1394+0000fba6@2349
1395+0000fb3a@2351
1396+0000bbba@2353
1397+00003bba@2356
1398+0000ab3a@2358
1399+0000ab82@2360
1400+00002b00@2366
1401+0000ab80@2367
1402+0000aba4@2369
1403+0000eba4@2370
1404+0000eb24@2373
1405+00006ba4@2375
1406+0000eba4@2377
1407+0000fba4@2379
1408+0000fb24@2381
1409+0000fba4@2382
1410+00007ba6@2384
1411+0000fba6@2386
1412+0000f916@2388
1413+0000b996@2390
1414+00003996@2393
1415+0000a916@2395
1416+0000abc2@2397
1417+00002b42@2403
1418+00002b40@2404
1419+0000abc0@2405
1420+0000abe4@2406
1421+0000ebe0@2407
1422+0000ebe4@2408
1423+0000ebc4@2409
1424+0000eb64@2410
1425+0000eb44@2411
1426+00006be4@2412
1427+00006bc4@2413
1428+0000ebe4@2414
1429+0000fbc0@2416
1430+0000fbe4@2417
1431+0000fb64@2418
1432+0000fb44@2419
1433+0000fbe4@2420
1434+00007be6@2421
1435+0000fbe6@2423
1436+0000fb16@2425
1437+0000f916@2426
1438+0000f996@2427
1439+00007996@2431
1440+0000e996@2432
1441+0000e916@2433
1442+0000ebd6@2434
1443+0000ebc2@2435
1444+00006b42@2440
1445+00006b40@2441
1446+0000ebc0@2442
1447+0000ebe4@2444
1448+0000afe0@2446
1449+0000a5e0@2447
1450+0000a560@2448
1451+000025e0@2449
1452+0000a5e0@2451
1453+0000b5e0@2454
1454+0000b560@2455
1455+0000b5e0@2457
1456+000075e2@2459
1457+0000f5e2@2460
1458+0000fd7a@2462
1459+0000f91a@2463
1460+0000b99a@2464
1461+0000399a@2468
1462+0000a91a@2470
1463+0000a99a@2471
1464+0000abd2@2472
1465+00002bd2@2477
1466+00002b50@2478
1467+0000abd0@2479
1468+0000abf4@2481
1469+0000ebf4@2482
1470+0000eb74@2485
1471+00006bf4@2487
1472+0000ebf4@2488
1473+0000fbf4@2491
1474+0000fb74@2492
1475+0000fb54@2493
1476+0000fbf4@2494
1477+00007bf6@2496
1478+0000fbf6@2498
1479+0000f91a@2500
1480+0000b91a@2501
1481+0000b99a@2502
1482+0000399a@2505
1483+0000a91a@2507
1484+0000a99a@2508
1485+0000abd2@2509
1486+00002b50@2515
1487+0000ab50@2516
1488+0000abd0@2517
1489+0000abf4@2518
1490+0000ebf4@2519
1491+0000ebd4@2521
1492+0000eb74@2522
1493+00006bf4@2524
1494+0000ebf4@2526
1495+0000fbd4@2528
1496+0000fbf4@2529
1497+0000fb54@2530
1498+0000fbf4@2531
1499+00007bf6@2533
1500+0000fbf6@2535
1501+0000f176@2537
1502+0000b1f6@2539
1503+000031f6@2542
1504+0000a176@2544
1505+0000afc2@2546
1506+00002f42@2552
1507+00002f40@2553
1508+0000afc0@2554
1509+0000afe4@2555
1510+0000efe0@2556
1511+0000efe4@2557
1512+0000efc4@2558
1513+0000ef64@2559
1514+00006fe4@2561
1515+00006fc4@2562
1516+0000efe4@2563
1517+0000ffc4@2565
1518+0000ffe4@2566
1519+0000ff64@2567
1520+0000ffe4@2569
1521+00007fe6@2570
1522+0000ffe6@2572
1523+0000f346@2574
1524+0000b346@2575
1525+0000b3c6@2576
1526+000033c6@2580
1527+0000a3c6@2581
1528+0000a346@2582
1529+0000abe6@2583
1530+0000abe2@2584
1531+00002b62@2589
1532+00002b60@2590
1533+0000abe0@2591
1534+0000ebe4@2593
1535+0000eb64@2597
1536+00006be4@2598
1537+0000ebe4@2600
1538+0000fbe4@2603
1539+0000fb64@2604
1540+0000fbe4@2606
1541+00007be6@2608
1542+0000fbe6@2609
1543+0000ff7e@2611
1544+0000fd1a@2612
1545+0000bd9a@2613
1546+00003d9a@2617
1547+0000ad1a@2619
1548+0000ad9a@2620
1549+0000ab82@2621
1550+00002b82@2626
1551+00002b00@2627
1552+0000ab80@2628
1553+0000aba4@2630
1554+0000eba4@2631
1555+0000eb04@2634
1556+0000eb24@2635
1557+00006ba4@2636
1558+0000eba4@2637
1559+0000fba4@2640
1560+0000fb24@2641
1561+0000fb04@2642
1562+0000fba4@2643
1563+00007ba6@2645
1564+0000fba6@2647
1565+0000fd3a@2649
1566+0000bdba@2651
1567+00003dba@2654
1568+0000ad3a@2656
1569+0000af82@2658
1570+0000ab82@2659
1571+00002b00@2664
1572+0000ab80@2665
1573+0000aba4@2667
1574+0000eba4@2668
1575+0000eb84@2670
1576+0000eb24@2671
1577+00006ba4@2673
1578+0000eba4@2675
1579+0000fba4@2677
1580+0000fb24@2679
1581+0000fba4@2680
1582+00007ba6@2682
1583+0000fba6@2684
1584+0000f91a@2686
1585+0000b99a@2688
1586+0000399a@2691
1587+0000a91a@2693
1588+0000abc2@2695
1589+00002b42@2701
1590+00002b40@2702
1591+0000abc0@2703
1592+0000abe4@2704
1593+0000ebe0@2705
1594+0000ebe4@2706
1595+0000ebc4@2707
1596+0000eb64@2708
1597+0000eb44@2709
1598+00006be4@2710
1599+0000ebe4@2712
1600+0000fbc0@2714
1601+0000fbe4@2715
1602+0000fb64@2716
1603+0000fb44@2717
1604+0000fbe4@2718
1605+00007be6@2719
1606+0000fbe6@2721
1607+0000fb1e@2723
1608+0000f91a@2724
1609+0000f99a@2725
1610+0000799a@2729
1611+0000f99a@2730
1612+0000e91a@2731
1613+0000ebda@2732
1614+0000ebc2@2733
1615+00006b42@2738
1616+00006b40@2739
1617+0000ebc0@2740
1618+0000ebe4@2742
1619+0000afe0@2744
1620+0000a5e0@2745
1621+0000a560@2746
1622+000025e0@2747
1623+0000a5e0@2749
1624+0000b5e0@2752
1625+0000b560@2753
1626+0000b5e0@2755
1627+000075e2@2757
1628+0000f5e2@2758
1629+0000fd7a@2760
1630+0000f91a@2761
1631+0000b99a@2762
1632+0000399a@2766
1633+0000a91a@2768
1634+0000a99a@2769
1635+0000abd2@2770
1636+00002bd2@2775
1637+00002b50@2776
1638+0000abd0@2777
1639+0000abf4@2779
1640+0000ebf4@2780
1641+0000eb54@2783
1642+0000ebf4@2784
1643+00006bf4@2785
1644+0000ebf4@2786
1645+0000fbf4@2789
1646+0000fb74@2790
1647+0000fb54@2791
1648+0000fbf4@2792
1649+00007bf6@2794
1650+0000fbf6@2796
1651+0000f91a@2798
1652+0000b91a@2799
1653+0000b99a@2800
1654+0000399a@2803
1655+0000a91a@2805
1656+0000a99a@2806
1657+0000abd2@2807
1658+00002b50@2813
1659+0000abd0@2814
1660+0000abf4@2816
1661+0000ebf4@2817
1662+0000ebd4@2819
1663+0000eb74@2820
1664+0000eb54@2821
1665+00006bf4@2822
1666+0000ebf4@2824
1667+0000fbf4@2826
1668+0000fb54@2828
1669+0000fbf4@2829
1670+00007bf6@2831
1671+0000fbf6@2833
1672+0000f17a@2835
1673+0000b1fa@2837
1674+000031fa@2840
1675+0000a17a@2842
1676+0000afc2@2844
1677+00002f42@2850
1678+00002f40@2851
1679+0000afc0@2852
1680+0000afe4@2853
1681+0000efe0@2854
1682+0000efe4@2855
1683+0000efc4@2856
1684+0000ef64@2857
1685+0000ef44@2858
1686+00006fe4@2859
1687+0000efe4@2861
1688+0000ffc0@2863
1689+0000ffe4@2864
1690+0000ff64@2865
1691+0000ffc4@2866
1692+0000ffe4@2867
1693+00007fe6@2868
1694+0000ffe6@2870
1695+0000f346@2872
1696+0000b346@2873
1697+0000b3c6@2874
1698+000033c6@2878
1699+0000a346@2879
1700+0000abe6@2881
1701+0000abe2@2882
1702+00002b62@2887
1703+00002b60@2888
1704+0000abe0@2889
1705+0000ebe4@2891
1706+0000eb64@2895
1707+00006be4@2896
1708+0000ebe4@2898
1709+0000fbe4@2900
1710+0000fb64@2902
1711+0000fbe4@2904
1712+00007be6@2906
1713+0000fbe6@2907
1714+0000ff7e@2909
1715+0000ff1a@2910
1716+0000bf9a@2911
1717+00003f9a@2915
1718+0000af1a@2917
1719+0000af9a@2918
1720+0000ab82@2919
1721+00002b82@2924
1722+00002b00@2925
1723+0000ab80@2926
1724+0000aba4@2928
1725+0000eba4@2929
1726+0000eb24@2932
1727+00006ba4@2934
1728+0000eba4@2935
1729+0000fba4@2938
1730+0000fb24@2939
1731+0000fb04@2940
1732+0000fba4@2941
1733+00007ba6@2943
1734+0000fba6@2945
1735+0000ff3a@2947
1736+0000bfba@2949
1737+00003fba@2952
1738+0000af3a@2954
1739+0000ab82@2956
1740+00002b00@2962
1741+0000ab80@2963
1742+0000aba4@2965
1743+0000eba4@2966
1744+0000eb84@2968
1745+0000eb24@2969
1746+00006ba4@2971
1747+0000eba4@2973
1748+0000fba4@2975
1749+0000fb24@2977
1750+0000fba4@2978
1751+00007ba6@2980
1752+0000fba6@2982
1753+0000f91e@2984
1754+0000b99e@2986
1755+0000399e@2989
1756+0000a91e@2991
1757+0000abc2@2993
1758+00002b42@2999
1759+00002b40@3000
1760+0000abc0@3001
1761+0000abe4@3002
1762+0000ebe0@3003
1763+0000ebe4@3004
1764+0000ebc4@3005
1765+0000eb64@3006
1766+0000eb44@3007
1767+00006be4@3008
1768+0000ebe4@3010
1769+0000fbc4@3012
1770+0000fbe4@3013
1771+0000fb64@3014
1772+0000fb44@3015
1773+0000fbe4@3016
1774+00007be6@3017
1775+0000fbe6@3019
1776+0000fb1e@3021
1777+0000f91e@3022
1778+0000f99e@3023
1779+0000799e@3027
1780+0000f99c@3028
1781+0000f91c@3029
1782+0000fbdc@3030
1783+0000fbc0@3031
1784+0000ebc0@3032
1785+00006b40@3036
1786+0000ebc0@3038
1787+0000ebe4@3040
1788+0000eb44@3044
1789+00006be4@3045
1790+00006bc4@3046
1791+0000ebe4@3047
1792+0000ebc4@3049
1793+0000fbe4@3050
1794+0000fb64@3051
1795+0000fb44@3052
1796+0000fbe4@3053
1797+00007be6@3055
1798+0000fbe6@3056
1799+0000fb7e@3058
1800+0000f91a@3059
1801+0000b99a@3060
1802+0000399a@3064
1803+0000a91a@3066
1804+0000a99a@3067
1805+0000abd2@3068
1806+00002bd2@3073
1807+00002b50@3074
1808+0000abd0@3075
1809+0000abf4@3077
1810+0000ebf4@3078
1811+0000eb74@3081
1812+00006bf4@3083
1813+0000ebf4@3084
1814+0000fbf4@3087
1815+0000fb74@3088
1816+0000fb54@3089
1817+0000fbf4@3090
1818+00007bf6@3092
1819+0000fbf6@3094
1820+0000fb1a@3096
1821+0000bb1a@3097
1822+0000bb9a@3098
1823+00003b9a@3101
1824+0000ab1a@3103
1825+0000ab9a@3104
1826+0000abe2@3105
1827+00002b60@3111
1828+0000ab60@3112
1829+0000abe0@3113
1830+0000abe4@3114
1831+0000ebe4@3115
1832+0000eb64@3118
1833+00006be4@3120
1834+0000ebe4@3122
1835+0000fbe4@3124
1836+0000fb64@3126
1837+0000fbe4@3127
1838+00007be6@3129
1839+0000fbe6@3131
1840+0000f17e@3133
1841+0000b1fe@3135
1842+000031fe@3138
1843+0000a17e@3140
1844+0000afc2@3142
1845+00002f42@3148
1846+00002f40@3149
1847+0000afc0@3150
1848+0000afe4@3151
1849+0000efe0@3152
1850+0000efe4@3153
1851+0000ef64@3155
1852+0000ef44@3156
1853+00006fe4@3157
1854+0000efe4@3159
1855+0000ffc4@3161
1856+0000ffe4@3162
1857+0000ff64@3163
1858+0000ffc4@3164
1859+0000ffe4@3165
1860+00007fe6@3166
1861+0000ffe6@3168
1862+0000f346@3170
1863+0000b346@3171
1864+0000b3c6@3172
1865+000033c6@3176
1866+0000a346@3177
1867+0000abe6@3179
1868+0000abe2@3180
1869+00002b62@3185
1870+00002b60@3186
1871+0000abe0@3187
1872+0000ebe4@3189
1873+0000eb64@3193
1874+00006be4@3194
1875+0000ebe4@3196
1876+0000fbe4@3199
1877+0000fb64@3200
1878+0000fbe4@3202
1879+00007be6@3204
1880+0000fbe6@3205
1881+0000ff7e@3207
1882+0000f71a@3208
1883+0000b79a@3209
1884+0000379a@3213
1885+0000a71a@3215
1886+0000a79a@3216
1887+0000a992@3217
1888+00002992@3222
1889+00002910@3223
1890+0000a990@3224
1891+0000e994@3226
1892+0000ebb4@3227
1893+0000eb90@3228
1894+0000e9b4@3229
1895+0000eb14@3230
1896+000069b4@3232
1897+0000ebb4@3233
1898+0000fbb4@3236
1899+0000fb34@3237
1900+0000fb14@3238
1901+0000fbb4@3239
1902+00007bb6@3241
1903+0000fbb6@3243
1904+0000ffb6@3244
1905+0000f73a@3245
1906+0000b7ba@3247
1907+000037ba@3250
1908+0000a73a@3252
1909+0000a992@3254
1910+00002910@3260
1911+0000a990@3261
1912+0000abb4@3263
1913+0000ebb4@3264
1914+0000eb34@3267
1915+0000e914@3268
1916+00006bb4@3269
1917+000069b4@3270
1918+0000ebb4@3271
1919+0000fb90@3273
1920+0000fbb4@3274
1921+0000fb14@3275
1922+0000fbb4@3276
1923+00007bb6@3278
1924+0000fbb6@3280
1925+0000f922@3282
1926+0000b922@3283
1927+0000b9a2@3284
1928+000039a2@3287
1929+0000a922@3289
1930+0000abc2@3291
1931+00002b42@3297
1932+00002b40@3298
1933+0000abc0@3299
1934+0000abe4@3300
1935+0000ebe0@3301
1936+0000ebe4@3302
1937+0000eb64@3304
1938+0000eb44@3305
1939+00006be4@3306
1940+0000ebe4@3308
1941+0000fbc0@3310
1942+0000fbe4@3311
1943+0000fb64@3312
1944+0000fbe4@3313
1945+00007be6@3315
1946+0000fbe6@3317
1947+0000fb62@3319
1948+0000f922@3320
1949+0000f9a2@3321
1950+000079a2@3325
1951+0000e9a2@3326
1952+0000e922@3327
1953+0000ebe2@3328
1954+0000ebc2@3329
1955+00006b42@3334
1956+00006b40@3335
1957+0000ebc0@3336
1958+0000ebe4@3338
1959+0000abec@3340
1960+0000a9ec@3341
1961+0000a96c@3342
1962+000029ec@3343
1963+0000a9ec@3345
1964+0000b9ec@3348
1965+0000b96c@3349
1966+0000b9ec@3351
1967+000079ee@3353
1968+0000f9ee@3354
1969+0000fb7e@3356
1970+0000fb3a@3357
1971+0000bbba@3358
1972+00003bba@3362
1973+0000ab3a@3364
1974+0000abba@3365
1975+0000abe2@3366
1976+00002be2@3371
1977+00002b60@3372
1978+0000abe0@3373
1979+0000ebe4@3376
1980+0000eb64@3379
1981+00006be4@3381
1982+0000ebe4@3382
1983+0000fbe4@3385
1984+0000fb64@3386
1985+0000fbe4@3388
1986+00007be6@3390
1987+0000fbe6@3392
1988+0000fbee@3393
1989+0000f91a@3394
1990+0000b91a@3395
1991+0000b99a@3396
1992+0000399a@3399
1993+0000a91a@3401
1994+0000a99a@3402
1995+0000abd2@3403
1996+00002bd2@3408
1997+00002b50@3409
1998+0000ab50@3410
1999+0000abd0@3411
2000+0000abf4@3412
2001+0000ebf4@3413
2002+0000ebd4@3415
2003+0000eb74@3416
2004+0000eb54@3417
2005+00006bf4@3418
2006+0000ebf4@3420
2007+0000fbf4@3422
2008+0000fb54@3424
2009+0000fbf4@3425
2010+00007bf6@3427
2011+0000fbf6@3429
2012+0000fb42@3431
2013+0000b342@3432
2014+0000b3c2@3433
2015+000033c2@3436
2016+0000a342@3438
2017+0000af42@3440
2018+0000afc2@3441
2019+00002f42@3446
2020+00002f40@3447
2021+0000afc0@3448
2022+0000afe4@3449
2023+0000efc0@3450
2024+0000efe4@3451
2025+0000efc4@3452
2026+0000ef64@3453
2027+0000ef44@3454
2028+00006fe4@3455
2029+00006fc4@3456
2030+0000efe4@3457
2031+0000ffc0@3459
2032+0000ffe4@3460
2033+0000ff64@3461
2034+0000ff44@3462
2035+0000ffe4@3463
2036+00007fe6@3464
2037+0000ffe6@3466
2038+0000f346@3468
2039+0000b346@3469
2040+0000b3c6@3470
2041+000033c6@3474
2042+0000a3c6@3475
2043+0000a346@3476
2044+0000abe6@3477
2045+0000abe2@3478
2046+00002b62@3483
2047+00002b60@3484
2048+0000abe0@3485
2049+0000ebe4@3487
2050+0000eb64@3491
2051+00006be4@3492
2052+0000ebe4@3494
2053+0000fbe4@3497
2054+0000fb64@3498
2055+0000fbe4@3500
2056+00007be6@3502
2057+0000fbe6@3503
2058+0000ff7e@3505
2059+0000ff1a@3506
2060+0000bf9a@3507
2061+00003f9a@3511
2062+0000af1a@3513
2063+0000af9a@3514
2064+0000aba2@3515
2065+00002ba2@3520
2066+00002b20@3521
2067+0000aba0@3522
2068+0000aba4@3524
2069+0000eba4@3525
2070+0000eb24@3528
2071+00006ba4@3530
2072+0000eba4@3531
2073+0000fba4@3534
2074+0000fb24@3535
2075+0000fba4@3537
2076+00007ba6@3539
2077+0000fba6@3541
2078+0000fbae@3542
2079+0000f53a@3543
2080+0000b5ba@3545
2081+000035ba@3548
2082+0000a53a@3550
2083+0000a182@3552
2084+00002100@3558
2085+0000a180@3559
2086+0000a3a4@3561
2087+0000e3a4@3562
2088+0000e384@3564
2089+0000e324@3565
2090+000061a4@3567
2091+0000e3a4@3569
2092+0000f184@3571
2093+0000f3a4@3572
2094+0000f304@3573
2095+0000f3a4@3574
2096+000073a6@3576
2097+0000f3a6@3578
2098+0000f926@3580
2099+0000b9a6@3582
2100+000039a6@3585
2101+0000a926@3587
2102+0000abc2@3589
2103+00002b42@3595
2104+00002b40@3596
2105+0000abc0@3597
2106+0000abe4@3598
2107+0000ebe0@3599
2108+0000ebe4@3600
2109+0000eb64@3602
2110+00006be4@3604
2111+0000ebe4@3606
2112+0000fbc4@3608
2113+0000fbe4@3609
2114+0000fb64@3610
2115+0000fbe4@3612
2116+00007be6@3613
2117+0000fbe6@3615
2118+0000f926@3617
2119+0000f9a6@3619
2120+000079a6@3623
2121+0000e9a6@3624
2122+0000e926@3625
2123+0000ebe6@3626
2124+0000ebc2@3627
2125+00006b42@3632
2126+00006b40@3633
2127+0000ebc0@3634
2128+0000ebe4@3636
2129+0000afe0@3638
2130+0000a5e0@3639
2131+0000a560@3640
2132+000025e0@3641
2133+0000a5e0@3643
2134+0000b5e0@3646
2135+0000b560@3647
2136+0000b5e0@3649
2137+000075e2@3651
2138+0000f5e2@3652
2139+0000fd7a@3654
2140+0000f91a@3655
2141+0000b99a@3656
2142+0000399a@3660
2143+0000a91a@3662
2144+0000a99a@3663
2145+0000abd2@3664
2146+00002bd2@3669
2147+00002b50@3670
2148+0000abd0@3671
2149+0000abf4@3673
2150+0000ebf4@3674
2151+0000eb54@3677
2152+0000ebf4@3678
2153+00006bd4@3679
2154+0000ebf4@3680
2155+0000fbf4@3683
2156+0000fb74@3684
2157+0000fb54@3685
2158+0000fbf4@3686
2159+00007bf6@3688
2160+0000fbf6@3690
2161+0000f91a@3692
2162+0000b91a@3693
2163+0000b99a@3694
2164+0000399a@3697
2165+0000a91a@3699
2166+0000a99a@3700
2167+0000abd2@3701
2168+00002bd2@3706
2169+00002b50@3707
2170+0000abd0@3708
2171+0000abf4@3710
2172+0000ebf4@3711
2173+0000ebd4@3713
2174+0000eb74@3714
2175+0000eb54@3715
2176+00006bf4@3716
2177+0000ebf4@3718
2178+0000fbd4@3720
2179+0000fbf4@3721
2180+0000fb54@3722
2181+0000fbf4@3723
2182+00007bf6@3725
2183+0000fbf6@3727
2184+0000f346@3729
2185+0000b346@3730
2186+0000b3c6@3731
2187+000033c6@3734
2188+0000a346@3736
2189+0000afc2@3738
2190+00002f42@3744
2191+00002f40@3745
2192+0000afc0@3746
2193+0000afe4@3747
2194+0000efe0@3748
2195+0000efe4@3749
2196+0000efc4@3750
2197+0000ef64@3751
2198+0000ef44@3752
2199+00006fe4@3753
2200+00006fc4@3754
2201+0000efe4@3755
2202+0000ffc0@3757
2203+0000ffe4@3758
2204+0000ff44@3759
2205+0000ffe4@3761
2206+00007fe6@3762
2207+0000ffe6@3764
2208+0000f346@3766
2209+0000b346@3767
2210+0000b3c6@3768
2211+000033c6@3772
2212+0000b3c6@3773
2213+0000a346@3774
2214+0000abe6@3775
2215+0000abe2@3776
2216+00002b62@3781
2217+00002b60@3782
2218+0000abe0@3783
2219+0000ebe4@3785
2220+0000eb64@3789
2221+00006be4@3790
2222+0000ebe4@3792
2223+0000fbe4@3795
2224+0000fb64@3796
2225+0000fbe4@3798
2226+00007be6@3800
2227+0000fbe6@3801
2228+0000ff7e@3803
2229+0000f53a@3804
2230+0000b5ba@3805
2231+000035ba@3809
2232+0000a53a@3811
2233+0000a5ba@3812
2234+0000a102@3813
2235+0000a182@3814
2236+00002182@3818
2237+00002100@3819
2238+0000a180@3820
2239+0000e1a4@3822
2240+0000e3a4@3823
2241+0000e1a4@3824
2242+0000e324@3826
2243+000061a4@3828
2244+0000e3a4@3829
2245+0000f3a4@3832
2246+0000f324@3833
2247+0000f304@3834
2248+0000f3a4@3835
2249+000073a6@3837
2250+0000f3a6@3839
2251+0000f7b6@3840
2252+0000f53a@3841
2253+0000b5ba@3843
2254+000035ba@3846
2255+0000a53a@3848
2256+0000a182@3850
2257+00002100@3856
2258+0000a180@3857
2259+0000a3a4@3859
2260+0000e3a4@3860
2261+0000e380@3862
2262+0000e324@3863
2263+0000e304@3864
2264+000061a4@3865
2265+0000e3a4@3867
2266+0000f3a4@3869
2267+0000f304@3871
2268+0000f3a4@3872
2269+000073a6@3874
2270+0000f3a6@3876
2271+0000f92a@3878
2272+0000b9aa@3880
2273+000039aa@3883
2274+0000a92a@3885
2275+0000abc2@3887
2276+00002b42@3893
2277+00002b40@3894
2278+0000abc0@3895
2279+0000abe4@3896
2280+0000ebe0@3897
2281+0000ebe4@3898
2282+0000eb64@3900
2283+00006be4@3902
2284+0000ebe4@3904
2285+0000fbc0@3906
2286+0000fbe4@3907
2287+0000fb64@3908
2288+0000fbe4@3909
2289+00007be6@3911
2290+0000fbe6@3913
2291+0000f92a@3915
2292+0000f9aa@3917
2293+000079aa@3921
2294+0000e9aa@3922
2295+0000e92a@3923
2296+0000ebea@3924
2297+0000ebc2@3925
2298+00006b42@3930
2299+00006b40@3931
2300+0000ebc0@3932
2301+0000ebe4@3934
2302+0000afe0@3936
2303+0000a5e0@3937
2304+0000a560@3938
2305+000025e0@3939
2306+0000a5e0@3941
2307+0000b5e0@3943
2308+0000b560@3945
2309+0000b5e0@3947
2310+000075e2@3949
2311+0000f5e2@3950
2312+0000fd7a@3952
2313+0000f91a@3953
2314+0000b99a@3954
2315+0000399a@3958
2316+0000a91a@3960
2317+0000a99a@3961
2318+0000abd2@3962
2319+00002bd2@3967
2320+00002b50@3968
2321+0000ab50@3969
2322+0000abd0@3970
2323+0000abf4@3971
2324+0000ebf4@3972
2325+0000eb74@3975
2326+00006b74@3976
2327+00006bf4@3977
2328+0000ebf4@3978
2329+0000fbf4@3981
2330+0000fb74@3982
2331+0000fb54@3983
2332+0000fbf4@3984
2333+00007bf6@3986
2334+0000fbf6@3988
2335+0000fbfe@3989
2336+0000f91a@3990
2337+0000b91a@3991
2338+0000b99a@3992
2339+0000399a@3995
2340+0000a91a@3997
2341+0000a99a@3998
2342+0000abd2@3999
2343+00002bd2@4004
2344+00002b50@4005
2345+0000abd0@4006
2346+0000abf4@4008
2347+0000ebf4@4009
2348+0000ebd4@4011
2349+0000eb74@4012
2350+0000eb54@4013
2351+00006bf4@4014
2352+0000ebf4@4016
2353+0000fbd4@4018
2354+0000fbf4@4019
2355+0000fb54@4020
2356+0000fbf4@4021
2357+00007bf6@4023
2358+0000fbf6@4025
2359+0000fb4a@4027
2360+0000b34a@4028
2361+0000b3ca@4029
2362+000033ca@4032
2363+0000a34a@4034
2364+0000afc2@4036
2365+00002f42@4042
2366+00002f40@4043
2367+0000afc0@4044
2368+0000afe4@4045
2369+0000efc0@4046
2370+0000efe4@4047
2371+0000efc4@4048
2372+0000ef64@4049
2373+0000ef44@4050
2374+00006fe4@4051
2375+00006fc4@4052
2376+0000efe4@4053
2377+0000ffc0@4055
2378+0000ffe4@4056
2379+0000ff44@4057
2380+0000ffc0@4058
2381+0000ffe4@4059
2382+00007fe6@4060
2383+0000ffe6@4062
2384+0000f346@4064
2385+0000b346@4065
2386+0000b3c6@4066
2387+000033c6@4070
2388+0000a3c6@4071
2389+0000a346@4072
2390+0000abe6@4073
2391+0000abe2@4074
2392+00002b62@4079
2393+00002b60@4080
2394+0000abe0@4081
2395+0000ebe4@4083
2396+0000eb64@4087
2397+00006be4@4088
2398+0000ebe4@4090
2399+0000fbe4@4093
2400+0000fb64@4094
2401+0000fbe4@4096
2402+00007be6@4098
2403+0000fbe6@4099
2404+0000ff7e@4101
2405+0000f53a@4102
2406+0000b5ba@4103
2407+000035ba@4107
2408+0000a53a@4109
2409+0000a5ba@4110
2410+0000a102@4111
2411+0000a182@4112
2412+00002182@4116
2413+00002100@4117
2414+0000a180@4118
2415+0000e1a4@4120
2416+0000e3a4@4121
2417+0000e1a4@4122
2418+0000e3a4@4123
2419+0000e324@4124
2420+00006324@4125
2421+000061a4@4126
2422+0000e3a4@4127
2423+0000f3a4@4130
2424+0000f324@4131
2425+0000f304@4132
2426+0000f3a4@4133
2427+000073a6@4135
2428+0000f3a6@4137
2429+0000f7b6@4138
2430+0000f53a@4139
2431+0000b5ba@4141
2432+000035ba@4144
2433+0000a53a@4146
2434+0000a182@4148
2435+00002100@4154
2436+0000a180@4155
2437+0000a3a4@4157
2438+0000e3a4@4158
2439+0000e324@4161
2440+0000e104@4162
2441+000061a4@4163
2442+0000e3a4@4165
2443+0000f1a4@4167
2444+0000f3a4@4168
2445+0000f104@4169
2446+0000f3a4@4170
2447+000073a6@4172
2448+0000f3a6@4174
2449+0000f92e@4176
2450+0000b9ae@4178
2451+000039ae@4181
2452+0000a92e@4183
2453+0000abc2@4185
2454+00002b42@4191
2455+00002b40@4192
2456+0000abc0@4193
2457+0000abe4@4194
2458+0000ebe0@4195
2459+0000ebe4@4196
2460+0000ebc4@4197
2461+0000eb64@4198
2462+0000eb44@4199
2463+00006be4@4200
2464+0000ebe4@4202
2465+0000fbc4@4204
2466+0000fbe4@4205
2467+0000fb64@4206
2468+0000fbe4@4207
2469+00007be6@4209
2470+0000fbe6@4211
2471+0000f92e@4213
2472+0000f9ae@4215
2473+000079ac@4219
2474+0000f9ac@4220
2475+0000f92c@4221
2476+0000fbe8@4222
2477+0000fbc0@4223
2478+0000ebc0@4224
2479+00006b40@4228
2480+0000ebc0@4230
2481+0000ebe4@4232
2482+0000eb44@4236
2483+00006be4@4237
2484+00006bc4@4238
2485+0000ebe4@4239
2486+0000ebc4@4241
2487+0000fbe4@4242
2488+0000fb64@4243
2489+0000fb44@4244
2490+0000fbe4@4245
2491+00007be6@4247
2492+0000fbe6@4248
2493+0000fb7e@4250
2494+0000f91a@4251
2495+0000b99a@4252
2496+0000399a@4256
2497+0000a91a@4258
2498+0000a99a@4259
2499+0000abd2@4260
2500+00002bd2@4265
2501+00002b50@4266
2502+0000abd0@4267
2503+0000abf4@4269
2504+0000ebf4@4270
2505+0000eb74@4273
2506+00006b74@4274
2507+00006bf4@4275
2508+0000ebf4@4276
2509+0000fbf4@4279
2510+0000fb74@4280
2511+0000fb54@4281
2512+0000fbf4@4282
2513+00007bf6@4284
2514+0000fbf6@4286
2515+0000f91a@4288
2516+0000b91a@4289
2517+0000b99a@4290
2518+0000399a@4293
2519+0000a91a@4295
2520+0000a99a@4296
2521+0000abd2@4297
2522+00002bd2@4302
2523+00002b50@4303
2524+0000ab50@4304
2525+0000abd0@4305
2526+0000abf4@4306
2527+0000ebf4@4307
2528+0000ebd4@4309
2529+0000eb74@4310
2530+0000eb54@4311
2531+00006bf4@4312
2532+0000ebf4@4314
2533+0000fbf4@4316
2534+0000fb74@4317
2535+0000fb54@4318
2536+0000fbf4@4319
2537+00007bf6@4321
2538+0000fbf6@4323
2539+0000f35e@4325
2540+0000b34e@4326
2541+0000b3ce@4327
2542+000033ce@4330
2543+0000a34e@4332
2544+0000afc2@4334
2545+00002f42@4340
2546+00002fc0@4341
2547+0000afc0@4342
2548+0000afe4@4343
2549+0000efc0@4344
2550+0000efe4@4345
2551+0000ef64@4347
2552+0000ef44@4348
2553+00006fe4@4349
2554+00006fc4@4350
2555+0000efe4@4351
2556+0000ffc0@4353
2557+0000ffe4@4354
2558+0000ff44@4355
2559+0000ffc4@4356
2560+0000ffe4@4357
2561+00007fe6@4358
2562+0000ffe6@4360
2563+0000f346@4362
2564+0000b346@4363
2565+0000b3c6@4364
2566+000033c6@4368
2567+0000a346@4369
2568+0000abe6@4371
2569+0000abe2@4372
2570+00002b62@4377
2571+00002b60@4378
2572+0000abe0@4379
2573+0000ebe4@4381
2574+0000eb64@4385
2575+00006be4@4386
2576+0000ebe4@4388
2577+0000fbe4@4391
2578+0000fb64@4392
2579+0000fbe4@4394
2580+00007be6@4396
2581+0000fbe6@4397
2582+0000ff7e@4399
2583+0000f53a@4400
2584+0000b5ba@4401
2585+000035ba@4405
2586+0000a53a@4407
2587+0000a5ba@4408
2588+0000a102@4409
2589+0000a182@4410
2590+00002182@4414
2591+00002100@4415
2592+0000a180@4416
2593+0000e1a4@4418
2594+0000e3a4@4419
2595+0000e1a4@4420
2596+0000e3a4@4421
2597+0000e324@4422
2598+000063a4@4423
2599+000061a4@4424
2600+0000e1a4@4425
2601+0000e3a4@4426
2602+0000f3a4@4428
2603+0000f324@4429
2604+0000f304@4430
2605+0000f3a4@4431
2606+000073a6@4433
2607+0000f3a6@4435
2608+0000f7be@4436
2609+0000f53a@4437
2610+0000b5ba@4439
2611+000035ba@4442
2612+0000a53a@4444
2613+0000a182@4446
2614+00002100@4452
2615+0000a180@4453
2616+0000a3a4@4455
2617+0000e3a4@4456
2618+0000e324@4459
2619+0000e104@4460
2620+000061a4@4461
2621+0000e3a4@4463
2622+0000f3a4@4465
2623+0000f324@4466
2624+0000f104@4467
2625+0000f3a4@4468
2626+000073a6@4470
2627+0000f3a6@4472
2628+0000f932@4474
2629+0000b9b2@4476
2630+000039b2@4479
2631+0000a932@4481
2632+0000abc2@4483
2633+00002b42@4489
2634+00002b40@4490
2635+0000abc0@4491
2636+0000abe4@4492
2637+0000ebc0@4493
2638+0000ebe4@4494
2639+0000eb64@4496
2640+00006be4@4498
2641+0000ebe4@4500
2642+0000fbc0@4502
2643+0000fbe4@4503
2644+0000fb64@4504
2645+0000fbe4@4505
2646+00007be6@4507
2647+0000fbe6@4509
2648+0000f972@4511
2649+0000f932@4512
2650+0000f9b2@4513
2651+000079b2@4517
2652+0000e9b2@4518
2653+0000e932@4519
2654+0000ebe2@4520
2655+0000ebc2@4521
2656+00006b42@4526
2657+00006b40@4527
2658+0000ebc0@4528
2659+0000ebe4@4530
2660+0000afe0@4532
2661+0000a5e0@4533
2662+0000a560@4534
2663+000025e0@4535
2664+0000a5e0@4537
2665+0000b5e0@4540
2666+0000b560@4541
2667+0000b5e0@4543
2668+000075e2@4545
2669+0000f5e2@4546
2670+0000fd3a@4548
2671+0000f91a@4549
2672+0000b99a@4550
2673+0000399a@4554
2674+0000a91a@4556
2675+0000a99a@4557
2676+0000abd2@4558
2677+00002b52@4563
2678+00002b50@4564
2679+0000abd0@4565
2680+0000abf4@4567
2681+0000ebf4@4568
2682+0000eb74@4571
2683+00006b74@4572
2684+00006bf4@4573
2685+0000ebf4@4574
2686+0000fbf4@4577
2687+0000fb74@4578
2688+0000fb54@4579
2689+0000fbf4@4580
2690+00007bf6@4582
2691+0000fbf6@4584
2692+0000fbfe@4585
2693+0000f91a@4586
2694+0000b91a@4587
2695+0000b99a@4588
2696+0000399a@4591
2697+0000a91a@4593
2698+0000a99a@4594
2699+0000abd2@4595
2700+00002bd2@4600
2701+00002b50@4601
2702+0000ab50@4602
2703+0000abd0@4603
2704+0000abf0@4604
2705+0000ebf4@4605
2706+0000ebd4@4607
2707+0000eb74@4608
2708+0000eb54@4609
2709+00006bf4@4610
2710+0000ebf4@4612
2711+0000fbf4@4614
2712+0000fb54@4616
2713+0000fbf4@4617
2714+00007bf6@4619
2715+0000fbf6@4621
2716+0000f352@4623
2717+0000b352@4624
2718+0000b3d2@4625
2719+000033d2@4628
2720+0000a352@4630
2721+0000afc2@4632
2722+00002f42@4638
2723+00002fc0@4639
2724+0000afc0@4640
2725+0000afe4@4641
2726+0000efc0@4642
2727+0000efe4@4643
2728+0000efc4@4644
2729+0000ef64@4645
2730+0000ef44@4646
2731+00006fe4@4647
2732+00006fc4@4648
2733+0000efe4@4649
2734+0000ffc0@4651
2735+0000ffe4@4652
2736+0000ff44@4653
2737+0000ffc4@4654
2738+0000ffe4@4655
2739+00007fe6@4656
2740+0000ffe6@4658
2741+0000f346@4660
2742+0000b346@4661
2743+0000b3c6@4662
2744+000033c6@4666
2745+0000a346@4667
2746+0000abe6@4669
2747+0000abe2@4670
2748+00002b62@4675
2749+00002b60@4676
2750+0000abe0@4677
2751+0000ebe4@4679
2752+0000eb64@4683
2753+00006be4@4684
2754+0000ebe4@4686
2755+0000fbe4@4689
2756+0000fb64@4690
2757+0000fbe4@4692
2758+00007be6@4694
2759+0000fbe6@4695
2760+0000ff7e@4697
2761+0000b53a@4698
2762+0000b5ba@4699
2763+000035ba@4703
2764+0000a53a@4705
2765+0000a5ba@4706
2766+0000a102@4707
2767+0000a182@4708
2768+00002182@4712
2769+00002100@4713
2770+0000a180@4714
2771+0000e1a4@4716
2772+0000e3a4@4717
2773+0000e1a4@4718
2774+0000e3a4@4719
2775+0000e304@4720
2776+000063a4@4721
2777+00006184@4722
2778+0000e1a4@4723
2779+0000e3a4@4724
2780+0000e1a4@4725
2781+0000f3a4@4726
2782+0000f324@4727
2783+0000f100@4728
2784+0000f3a4@4729
2785+000073a6@4731
2786+0000f3a6@4733
2787+0000f7be@4734
2788+0000f53a@4735
2789+0000b5ba@4737
2790+000035ba@4740
2791+0000a53a@4742
2792+0000a182@4744
2793+00002182@4749
2794+00002100@4750
2795+0000a180@4751
2796+0000a3a4@4753
2797+0000e3a4@4754
2798+0000e384@4756
2799+0000e324@4757
2800+0000e104@4758
2801+000061a4@4759
2802+0000e3a4@4761
2803+0000f3a4@4763
2804+0000f324@4764
2805+0000f104@4765
2806+0000f3a4@4766
2807+000073a6@4768
2808+0000f3a6@4770
2809+0000f936@4772
2810+0000b9b6@4774
2811+000039b6@4777
2812+0000a9b6@4779
2813+0000a936@4780
2814+0000abc2@4781
2815+00002b42@4787
2816+00002b40@4788
2817+0000abc0@4789
2818+0000abe4@4790
2819+0000ebe0@4791
2820+0000ebe4@4792
2821+0000eb64@4794
2822+00006be4@4796
2823+0000ebe4@4798
2824+0000fbc4@4800
2825+0000fbe4@4801
2826+0000fb64@4802
2827+0000fbe4@4803
2828+00007be6@4805
2829+0000fbe6@4807
2830+0000f936@4809
2831+0000f9b6@4811
2832+000079b6@4815
2833+0000e9b6@4816
2834+0000e936@4817
2835+0000ebf6@4818
2836+0000ebc2@4819
2837+00006b42@4824
2838+00006b40@4825
2839+0000ebc0@4826
2840+0000ebe4@4828
2841+0000afe0@4830
2842+0000a5e0@4831
2843+0000a560@4832
2844+000025e0@4833
2845+0000a5e0@4835
2846+0000b5e0@4838
2847+0000b560@4839
2848+0000b5e0@4841
2849+000075e2@4843
2850+0000f5e2@4844
2851+0000fd3a@4846
2852+0000f91a@4847
2853+0000b99a@4848
2854+0000399a@4852
2855+0000a91a@4854
2856+0000a9da@4855
2857+0000abd2@4856
2858+00002bd2@4861
2859+00002b50@4862
2860+0000abd0@4863
2861+0000abf4@4865
2862+0000ebf4@4866
2863+0000eb74@4869
2864+00006bf4@4870
2865+00006bd4@4871
2866+0000ebf4@4872
2867+0000fbf4@4875
2868+0000fb74@4876
2869+0000fb54@4877
2870+0000fbf4@4878
2871+00007bf6@4880
2872+0000fbf6@4882
2873+0000fbfe@4883
2874+0000f33a@4884
2875+0000b3ba@4885
2876+000033ba@4889
2877+0000a33a@4891
2878+0000a3ba@4892
2879+0000abd2@4893
2880+00002bd2@4898
2881+00002b50@4899
2882+0000ab50@4900
2883+0000abd0@4901
2884+0000abf0@4902
2885+0000ebf4@4903
2886+0000eb74@4906
2887+00006bf4@4908
2888+0000ebf4@4910
2889+0000fbf4@4912
2890+0000fb74@4914
2891+0000fbf4@4915
2892+00007bf6@4917
2893+0000fbf6@4919
2894+0000f356@4921
2895+0000b356@4922
2896+0000b3d6@4923
2897+000033d6@4926
2898+0000a356@4928
2899+0000afc2@4930
2900+00002f42@4936
2901+00002fc0@4937
2902+0000afc0@4938
2903+0000afe4@4939
2904+0000efc0@4940
2905+0000efe4@4941
2906+0000efc4@4942
2907+0000ef64@4943
2908+0000ef44@4944
2909+00006fe4@4945
2910+0000efe4@4947
2911+0000ffc4@4949
2912+0000ffe4@4950
2913+0000ff64@4951
2914+0000ffc4@4952
2915+0000ffe4@4953
2916+00007fe6@4954
2917+0000ffe6@4956
2918+0000f346@4958
2919+0000b346@4959
2920+0000b3c6@4960
2921+000033c6@4964
2922+0000a346@4965
2923+0000abe2@4967
2924+00002b62@4973
2925+00002b60@4974
2926+0000abe0@4975
2927+0000ebe4@4977
2928+0000eb64@4981
2929+00006be4@4982
2930+0000ebe4@4984
2931+0000fbe4@4987
2932+0000fb64@4988
2933+0000fbe4@4990
2934+00007be6@4992
2935+0000fbe6@4993
2936+0000ff7e@4995
2937+0000b53a@4996
2938+0000b5ba@4997
2939+000035ba@5001
2940+000025ba@5002
2941+0000a53a@5003
2942+0000a5ba@5004
2943+0000a102@5005
2944+0000a182@5006
2945+00002182@5010
2946+00002100@5011
2947+0000a180@5012
2948+0000e1a4@5014
2949+0000e3a4@5015
2950+0000e1a4@5016
2951+0000e324@5018
2952+00006324@5019
2953+00006184@5020
2954+0000e1a4@5021
2955+0000e3a4@5022
2956+0000f3a4@5024
2957+0000f324@5025
2958+0000f304@5026
2959+0000f3a4@5027
2960+000073a6@5029
2961+0000f3a6@5031
2962+0000f7be@5032
2963+0000f53a@5033
2964+0000b5ba@5035
2965+000035ba@5038
2966+0000a53a@5040
2967+0000a5ba@5041
2968+0000a102@5042
2969+0000a182@5043
2970+00002182@5047
2971+00002100@5048
2972+0000a180@5049
2973+0000a3a0@5051
2974+0000e3a4@5052
2975+0000e324@5055
2976+0000e104@5056
2977+000061a4@5057
2978+0000e3a4@5059
2979+0000f3a4@5061
2980+0000f324@5062
2981+0000f3a4@5064
2982+000073a6@5066
2983+0000f3a6@5068
2984+0000f93a@5070
2985+0000b9ba@5072
2986+000039ba@5075
2987+0000a93a@5077
2988+0000abc2@5079
2989+00002b42@5085
2990+00002b40@5086
2991+0000abc0@5087
2992+0000abe4@5088
2993+0000ebe0@5089
2994+0000ebe4@5090
2995+0000ebc4@5091
2996+0000eb64@5092
2997+0000eb44@5093
2998+00006be4@5094
2999+0000ebe4@5096
3000+0000fbc0@5098
3001+0000fbe4@5099
3002+0000fb64@5100
3003+0000fbe4@5101
3004+00007be6@5103
3005+0000fbe6@5105
3006+0000f97e@5107
3007+0000f93a@5108
3008+0000f9ba@5109
3009+000079ba@5113
3010+0000e9ba@5114
3011+0000e93a@5115
3012+0000ebe2@5116
3013+0000ebc2@5117
3014+00006b42@5122
3015+00006b40@5123
3016+0000ebc0@5124
3017+0000ebe4@5126
3018+0000ab24@5128
3019+0000a324@5129
3020+000023a4@5131
3021+0000a3a4@5133
3022+0000b3a4@5136
3023+0000b324@5137
3024+0000b3a4@5139
3025+000073a6@5141
3026+0000f3a6@5142
3027+0000fb7e@5144
3028+0000f97a@5145
3029+0000b9fa@5146
3030+000039fa@5150
3031+0000397a@5151
3032+0000a97a@5152
3033+0000a9fa@5153
3034+0000a102@5154
3035+0000a182@5155
3036+00002182@5159
3037+00002100@5160
3038+0000a180@5161
3039+0000e1a4@5163
3040+0000e3a4@5164
3041+0000e1a4@5165
3042+0000e3a4@5166
3043+0000e324@5167
3044+000063a4@5168
3045+000061a4@5169
3046+0000e1a4@5170
3047+0000e3a4@5171
3048+0000f3a4@5173
3049+0000f324@5174
3050+0000f304@5175
3051+0000f3a4@5176
3052+000073a6@5178
3053+0000f3a6@5180
3054+0000f3be@5181
3055+0000f11a@5182
3056+0000b11a@5183
3057+0000b19a@5184
3058+0000319a@5187
3059+0000a11a@5189
3060+0000a19a@5190
3061+0000a182@5191
3062+00002182@5196
3063+00002100@5197
3064+0000a180@5198
3065+0000a3a0@5200
3066+0000e3a4@5201
3067+0000e184@5203
3068+0000e324@5204
3069+0000e124@5205
3070+000061a4@5206
3071+0000e3a4@5208
3072+0000f184@5210
3073+0000f3a4@5211
3074+0000f104@5212
3075+0000f3a4@5213
3076+000073a6@5215
3077+0000f3a6@5217
3078+0000f35a@5219
3079+0000b3da@5221
3080+000033da@5224
3081+0000a35a@5226
3082+0000afc2@5228
3083+00002f42@5234
3084+00002fc0@5235
3085+0000afc0@5236
3086+0000afe4@5237
3087+0000efc0@5238
3088+0000efe4@5239
3089+0000efc0@5240
3090+0000ef64@5241
3091+0000ef44@5242
3092+00006fe4@5243
3093+00006fc4@5244
3094+0000efe4@5245
3095+0000ffc0@5247
3096+0000ffe4@5248
3097+0000ff44@5249
3098+0000ffc4@5250
3099+0000ffe4@5251
3100+00007fe6@5252
3101+0000ffe6@5254
3102+0000f346@5256
3103+0000b346@5257
3104+0000b3c6@5258
3105+000033c6@5262
3106+0000a346@5263
3107+0000abe2@5265
3108+00002b62@5271
3109+00002b60@5272
3110+0000abe0@5273
3111+0000abe4@5274
3112+0000ebe4@5275
3113+0000eb64@5279
3114+00006be4@5280
3115+0000ebe4@5282
3116+0000fbe4@5285
3117+0000fb64@5286
3118+0000fbe4@5288
3119+00007be6@5290
3120+0000fbe6@5291
3121+0000ff7e@5293
3122+0000b53a@5294
3123+0000b5ba@5295
3124+000035ba@5299
3125+0000a53a@5301
3126+0000a5ba@5302
3127+0000a102@5303
3128+0000a182@5304
3129+00002182@5308
3130+00002100@5309
3131+0000a180@5310
3132+0000e1a4@5312
3133+0000e3a4@5313
3134+0000e1a4@5314
3135+0000e324@5316
3136+000063a4@5317
3137+00006184@5318
3138+0000e1a4@5319
3139+0000e3a4@5320
3140+0000f3a4@5322
3141+0000f324@5323
3142+0000f304@5324
3143+0000f3a4@5325
3144+000073a6@5327
3145+0000f3a6@5329
3146+0000f7be@5330
3147+0000f53a@5331
3148+0000b5ba@5333
3149+000035ba@5336
3150+0000a53a@5338
3151+0000a182@5340
3152+00002182@5345
3153+00002100@5346
3154+0000a180@5347
3155+0000a3a0@5349
3156+0000e3a4@5350
3157+0000e324@5353
3158+0000e104@5354
3159+000061a4@5355
3160+0000e3a4@5357
3161+0000f3a4@5359
3162+0000f104@5361
3163+0000f3a4@5362
3164+000073a6@5364
3165+0000f3a6@5366
3166+0000f93e@5368
3167+0000b9be@5370
3168+000039be@5373
3169+0000a93e@5375
3170+0000abc2@5377
3171+00002b42@5383
3172+00002b40@5384
3173+0000abc0@5385
3174+0000abe4@5386
3175+0000ebe0@5387
3176+0000ebe4@5388
3177+0000eb64@5390
3178+00006be4@5392
3179+0000ebe4@5394
3180+0000fbc4@5396
3181+0000fbe4@5397
3182+0000fb64@5398
3183+0000fbe4@5399
3184+00007be6@5401
3185+0000fbe6@5403
3186+0000f97e@5405
3187+0000f93e@5406
3188+0000f9be@5407
3189+000079bc@5411
3190+0000f9bc@5412
3191+0000f93c@5413
3192+0000fbe0@5414
3193+0000fbc0@5415
3194+0000ebc0@5416
3195+00006b40@5420
3196+0000ebc0@5422
3197+0000ebe4@5424
3198+0000eb44@5428
3199+00006be4@5429
3200+00006bc4@5430
3201+0000ebe4@5431
3202+0000fbc4@5433
3203+0000fbe4@5434
3204+0000fb64@5435
3205+0000fb44@5436
3206+0000fbe4@5437
3207+00007be6@5439
3208+0000fbe6@5440
3209+0000fb5e@5442
3210+0000b11a@5443
3211+0000b19a@5444
3212+0000319a@5448
3213+0000a11a@5450
3214+0000a19a@5451
3215+0000a182@5452
3216+00002182@5457
3217+00002100@5458
3218+0000a180@5459
3219+0000e1a4@5461
3220+0000e3a4@5462
3221+0000e184@5463
3222+0000e3a4@5464
3223+0000e304@5465
3224+000063a4@5466
3225+00006184@5467
3226+0000e3a4@5468
3227+0000e1a4@5470
3228+0000f3a4@5471
3229+0000f324@5472
3230+0000f304@5473
3231+0000f3a4@5474
3232+000073a6@5476
3233+0000f3a6@5478
3234+0000f3be@5479
3235+0000f11a@5480
3236+0000b11a@5481
3237+0000b19a@5482
3238+0000319a@5485
3239+0000a11a@5487
3240+0000a19a@5488
3241+0000a182@5489
3242+00002182@5494
3243+00002100@5495
3244+0000a180@5496
3245+0000a3a0@5498
3246+0000e3a4@5499
3247+0000e384@5501
3248+0000e324@5502
3249+0000e104@5503
3250+000061a4@5504
3251+0000e3a4@5506
3252+0000f384@5508
3253+0000f3a4@5509
3254+0000f104@5510
3255+0000f3a4@5511
3256+000073a6@5513
3257+0000f3a6@5515
3258+0000f37e@5517
3259+0000f35e@5518
3260+0000b3de@5519
3261+000033de@5522
3262+0000a35e@5524
3263+0000afc2@5526
3264+00002f42@5532
3265+00002fc0@5533
3266+0000afc0@5534
3267+0000afe4@5535
3268+0000efc0@5536
3269+0000efe4@5537
3270+0000efc4@5538
3271+0000ef64@5539
3272+0000ef44@5540
3273+00006fe4@5541
3274+00006fc4@5542
3275+0000efe4@5543
3276+0000ffc4@5545
3277+0000ffe4@5546
3278+0000ff44@5547
3279+0000ffc4@5548
3280+0000ffe4@5549
3281+00007fe6@5550
3282+0000ffe6@5552
3283+0000f346@5554
3284+0000b346@5555
3285+0000b3c6@5556
3286+000033c6@5560
3287+0000a346@5561
3288+0000abe2@5563
3289+00002b62@5569
3290+00002b60@5570
3291+0000abe0@5571
3292+0000abe4@5572
3293+0000ebe4@5573
3294+0000eb64@5577
3295+00006be4@5578
3296+0000ebe4@5580
3297+0000fbe4@5583
3298+0000fb64@5584
3299+0000fbe4@5586
3300+00007be6@5588
3301+0000fbe6@5589
3302+0000fb7e@5591
3303+0000b91a@5592
3304+0000b99a@5593
3305+0000399a@5597
3306+0000a91a@5599
3307+0000abba@5600
3308+0000a7a2@5601
3309+000027a2@5606
3310+00002720@5607
3311+0000a7a0@5608
3312+0000a7a4@5610
3313+0000e7a4@5611
3314+0000e724@5614
3315+000067a4@5615
3316+0000e7a4@5617
3317+0000f7a4@5620
3318+0000f724@5621
3319+0000f7a4@5623
3320+000077a6@5625
3321+0000f7a6@5627
3322+0000ffbe@5628
3323+0000f93a@5629
3324+0000b93a@5630
3325+0000b9ba@5631
3326+000039ba@5634
3327+0000a93a@5636
3328+0000a9ba@5637
3329+0000af22@5638
3330+0000a7a2@5639
3331+000027a2@5643
3332+00002720@5644
3333+0000a7a0@5645
3334+0000a7a4@5647
3335+0000e7a4@5648
3336+0000e724@5651
3337+000067a4@5653
3338+0000e7a4@5655
3339+0000f7a4@5657
3340+0000f724@5658
3341+0000f7a4@5660
3342+000077a6@5662
3343+0000f7a6@5664
3344+0000f93a@5666
3345+0000f9ba@5668
3346+000079ba@5671
3347+0000e93a@5673
3348+0000efa2@5675
3349+0000e7a2@5676
3350+00006722@5681
3351+000067a0@5682
3352+0000e7a0@5683
3353+0000e7a4@5684
3354+0000e7a0@5685
3355+0000e7a4@5686
3356+0000a5e8@5687
3357+0000a568@5688
3358+0000a5e8@5689
3359+000025e8@5690
3360+0000a5e8@5692
3361+0000b5e8@5694
3362+0000b568@5696
3363+0000b5e8@5698
3364+000035ea@5699
3365+000075ea@5700
3366+0000f5ea@5701
3367+0000f93a@5703
3368+0000f9ba@5705
3369+000079ba@5709
3370+0000e9ba@5710
3371+0000e93a@5711
3372+0000efa2@5712
3373+0000e7a2@5713
3374+00006722@5718
3375+00006720@5719
3376+0000e7a0@5720
3377+0000e7a4@5721
3378+0000a7e8@5724
3379+0000a5e8@5725
3380+0000a568@5726
3381+000025e8@5727
3382+0000a5e8@5729
3383+0000b5e8@5732
3384+0000b568@5733
3385+0000b5e8@5735
3386+000075ea@5737
3387+0000f5ea@5738
3388+0000f53e@5740
3389+0000b11e@5741
3390+0000b19e@5742
3391+0000319e@5746
3392+0000a11e@5748
3393+0000a1de@5749
3394+0000a9d2@5750
3395+000029d2@5755
3396+00002950@5756
3397+0000a9d0@5757
3398+0000e9f4@5759
3399+0000ebf4@5760
3400+0000e9d4@5761
3401+0000eb54@5763
3402+00006bf4@5764
3403+000069d4@5765
3404+0000e9f4@5766
3405+0000ebf4@5767
3406+0000e9d4@5768
3407+0000fbf4@5769
3408+0000fb74@5770
3409+0000f954@5771
3410+0000fbf4@5772
3411+000079f6@5774
3412+00007bf6@5775
3413+0000fbf6@5776
3414+0000fbfe@5777
3415+0000f31e@5778
3416+0000b31e@5779
3417+0000b39e@5780
3418+0000339e@5783
3419+0000a31e@5785
3420+0000a39e@5786
3421+0000a9d2@5787
3422+000029d2@5792
3423+00002950@5793
3424+0000a950@5794
3425+0000a9d0@5795
3426+0000abf0@5796
3427+0000ebf4@5797
3428+0000ebd4@5799
3429+0000eb74@5800
3430+0000eb54@5801
3431+000069f4@5802
3432+00006bf4@5803
3433+0000ebf4@5804
3434+0000e9f4@5805
3435+0000fbf4@5806
3436+0000f954@5808
3437+0000fbf4@5809
3438+00007bf6@5811
3439+0000fbf6@5813
3440+0000f51e@5815
3441+0000b51e@5816
3442+0000b59e@5817
3443+0000359e@5820
3444+0000a59e@5822
3445+0000a51e@5823
3446+0000a9d2@5824
3447+00002952@5830
3448+00002950@5831
3449+0000a9d0@5832
3450+0000abf4@5833
3451+0000ebd0@5834
3452+0000ebf4@5835
3453+0000ebd4@5836
3454+0000eb74@5837
3455+0000eb54@5838
3456+00006bf4@5839
3457+000069d4@5840
3458+0000ebf4@5841
3459+0000f9d0@5843
3460+0000fbf4@5844
3461+0000fb54@5845
3462+0000fbd4@5846
3463+0000fbf4@5847
3464+00007bf6@5848
3465+0000fbf6@5850
3466+0000ff1e@5852
3467+0000b71e@5853
3468+0000b79e@5854
3469+0000379e@5858
3470+0000a79e@5859
3471+0000a71e@5860
3472+0000afd2@5861
3473+0000a9d2@5862
3474+00002952@5867
3475+00002950@5868
3476+0000a9d0@5869
3477+0000a9d4@5870
3478+0000ebf4@5871
3479+0000e9d4@5873
3480+0000ebf4@5874
3481+0000eb54@5875
3482+00006bf4@5876
3483+000069d4@5877
3484+0000e9f4@5878
3485+0000ebf4@5879
3486+0000e9d0@5880
3487+0000fbf4@5881
3488+0000fb74@5882
3489+0000f950@5883
3490+0000fbf4@5884
3491+000079f6@5886
3492+0000fbf6@5887
3493+0000fbd6@5888
3494+0000f95e@5889
3495+0000f91e@5890
3496+0000b99e@5891
3497+0000399e@5895
3498+0000a91e@5897
3499+0000a9fe@5898
3500+0000a5f2@5899
3501+00002572@5904
3502+00002570@5905
3503+0000a5f0@5906
3504+0000e5f4@5908
3505+0000e7f4@5909
3506+0000e5f4@5910
3507+0000e7f4@5911
3508+0000e774@5912
3509+000067f4@5913
3510+000065f4@5914
3511+0000e5f4@5915
3512+0000e7f4@5916
3513+0000f7f4@5918
3514+0000f774@5919
3515+0000f7f4@5921
3516+000077f6@5923
3517+0000f7f6@5925
3518+0000fffe@5926
3519+0000f93e@5927
3520+0000b9be@5928
3521+000039be@5932
3522+0000a93e@5934
3523+0000a9be@5935
3524+0000a5f2@5936
3525+000025f2@5941
3526+00002570@5942
3527+0000a5f0@5943
3528+0000a7f0@5945
3529+0000e7f4@5946
3530+0000e774@5949
3531+000065f4@5951
3532+0000e7f4@5952
3533+0000f7f4@5955
3534+0000f774@5956
3535+0000f7f4@5958
3536+000077f6@5960
3537+0000f7f6@5962
3538+0000fb1e@5964
3539+0000bb1e@5965
3540+0000bb9e@5966
3541+00003b9e@5969
3542+0000ab9e@5971
3543+0000ab1e@5972
3544+0000a5f2@5973
3545+00002572@5979
3546+00002570@5980
3547+0000a5f0@5981
3548+0000a7f4@5982
3549+0000e7f0@5983
3550+0000e7f4@5984
3551+0000e774@5986
3552+000067f4@5988
3553+0000e7f4@5990
3554+0000f7f0@5992
3555+0000f7f4@5993
3556+0000f774@5994
3557+0000f7f4@5995
3558+000077f6@5997
3559+0000f7f6@5999
3560+0000fd1e@6001
3561+0000b91e@6002
3562+0000b99e@6003
3563+0000399e@6007
3564+0000a99e@6008
3565+0000a91e@6009
3566+0000adf2@6010
3567+0000a5f2@6011
3568+00002572@6016
3569+00002570@6017
3570+0000a5f0@6018
3571+0000a5f4@6019
3572+0000e7f4@6020
3573+0000e5f4@6022
3574+0000e7f4@6023
3575+0000e774@6024
3576+000067f4@6025
3577+000065f4@6026
3578+0000e5f4@6027
3579+0000e7f4@6028
3580+0000f5f4@6029
3581+0000f7f4@6030
3582+0000f774@6031
3583+0000f7f4@6033
3584+000077f6@6035
3585+0000f7f6@6036
3586+0000fd3e@6038
3587+0000f93e@6039
3588+0000b9be@6040
3589+000039be@6044
3590+0000a93e@6046
3591+0000a9fe@6047
3592+0000a5f2@6048
3593+000025f2@6053
3594+00002570@6054
3595+0000a5f0@6055
3596+0000e5f4@6057
3597+0000e7f4@6058
3598+0000e5f4@6059
3599+0000e7f4@6060
3600+0000e774@6061
3601+000067f4@6062
3602+000065f4@6063
3603+0000e7f4@6064
3604+0000f7f4@6067
3605+0000f774@6068
3606+0000f7f4@6070
3607+000077f6@6072
3608+0000f7f6@6074
3609+0000f7fe@6075
3610+0000fb1e@6076
3611+0000bb9e@6077
3612+00003b9e@6081
3613+0000ab1e@6083
3614+0000ab9e@6084
3615+0000a5f2@6085
3616+000025f2@6090
3617+00002570@6091
3618+0000a5f0@6092
3619+0000a7f0@6094
3620+0000e7f4@6095
3621+0000e774@6098
3622+000065f4@6100
3623+000067f4@6101
3624+0000e7f4@6102
3625+0000f7f4@6104
3626+0000f774@6106
3627+0000f7f4@6107
3628+000077f6@6109
3629+0000f7f6@6111
3630+0000f91e@6113
3631+0000b91e@6114
3632+0000b99e@6115
3633+0000399e@6118
3634+0000a91e@6120
3635+0000a5f2@6122
3636+00002572@6128
3637+00002570@6129
3638+0000a5f0@6130
3639+0000a7f4@6131
3640+0000e7f0@6132
3641+0000e7f4@6133
3642+0000e774@6135
3643+000067f4@6137
3644+000065f4@6138
3645+0000e7f4@6139
3646+0000f5f4@6141
3647+0000f7f4@6142
3648+0000f774@6143
3649+0000f7f4@6144
3650+000077f6@6146
3651+0000f7f6@6148
3652+0000fd3e@6150
3653+0000b93e@6151
3654+0000b9be@6152
3655+000039be@6156
3656+0000a9be@6157
3657+0000a93e@6158
3658+0000adf2@6159
3659+0000a5f2@6160
3660+00002572@6165
3661+00002570@6166
3662+0000a5f0@6167
3663+0000a5f4@6168
3664+0000e7f4@6169
3665+0000e774@6173
3666+000067f4@6174
3667+000065f0@6175
3668+0000e7f4@6176
3669+0000e5f0@6178
3670+0000f7f4@6179
3671+0000f774@6180
3672+0000f7f4@6182
3673+000075f6@6184
3674+0000f7f6@6185
3675+0000ff3e@6187
3676+0000fb1e@6188
3677+0000bb9e@6189
3678+00003b9e@6193
3679+0000ab1e@6195
3680+0000abfe@6196
3681+0000a5f2@6197
3682+000025f2@6202
3683+00002570@6203
3684+0000a5f0@6204
3685+0000e5f4@6206
3686+0000e7f4@6207
3687+0000e5f4@6208
3688+0000e7f4@6209
3689+0000e774@6210
3690+000067f4@6211
3691+0000e5f4@6213
3692+0000e7f4@6214
3693+0000f7f4@6216
3694+0000f774@6217
3695+0000f7f4@6219
3696+000077f6@6221
3697+0000f7f6@6223
3698+0000fffe@6224
3699+0000f91e@6225
3700+0000b99e@6226
3701+0000399e@6230
3702+0000a91e@6232
3703+0000a99e@6233
3704+0000a5f2@6234
3705+000025f2@6239
3706+00002570@6240
3707+0000a570@6241
3708+0000a5f0@6242
3709+0000a7f0@6243
3710+0000e7f4@6244
3711+0000e774@6247
3712+000065f4@6249
3713+000067f4@6250
3714+0000e7f4@6251
3715+0000f7f4@6253
3716+0000f774@6255
3717+0000f7f4@6256
3718+000077f6@6258
3719+0000f7f6@6260
3720+0000f91e@6262
3721+0000f99e@6264
3722+0000799e@6267
3723+0000e99e@6269
3724+0000e91e@6270
3725+0000e5f2@6271
3726+00006570@6277
3727+0000e570@6278
3728+0000e5f0@6279
3729+0000e7f4@6280
3730+0000e7f0@6281
3731+0000a7f4@6282
3732+0000e188@6283
3733+0000a100@6284
3734+00002180@6286
3735+0000a180@6288
3736+0000b180@6290
3737+0000b100@6292
3738+0000b180@6293
3739+00003182@6295
3740+00007182@6296
3741+0000f182@6297
3742+0000f93e@6299
3743+0000f9be@6300
3744+0000b9be@6301
3745+000039be@6305
3746+0000a9be@6306
3747+0000a93e@6307
3748+0000adf2@6308
3749+0000a5f2@6309
3750+00002572@6314
3751+00002570@6315
3752+0000a5f0@6316
3753+0000a5f4@6317
3754+0000e7f4@6318
3755+0000e5f4@6320
3756+0000e7f4@6321
3757+0000e774@6322
3758+000067f4@6323
3759+000065f4@6324
3760+0000e5f4@6325
3761+0000e7f4@6326
3762+0000e5f0@6327
3763+0000f7f4@6328
3764+0000f774@6329
3765+0000f7f4@6331
3766+000075f6@6333
3767+0000f7f6@6334
3768+0000ff3e@6336
3769+0000fb1e@6337
3770+0000bb9e@6338
3771+00003b9e@6342
3772+0000ab1e@6344
3773+0000abfe@6345
3774+0000a5f2@6346
3775+00002572@6351
3776+00002570@6352
3777+0000a5f0@6353
3778+0000e5f4@6355
3779+0000e7f4@6356
3780+0000e5f4@6357
3781+0000e7f4@6358
3782+0000e774@6359
3783+000067f4@6360
3784+000065f4@6361
3785+0000e5f4@6362
3786+0000e7f4@6363
3787+0000f7f4@6365
3788+0000f774@6366
3789+0000f7f4@6368
3790+000077f6@6370
3791+0000f7f6@6372
3792+0000fffe@6373
3793+0000f91a@6374
3794+0000b99a@6375
3795+0000399a@6379
3796+0000a91a@6381
3797+0000a99a@6382
3798+0000a5f2@6383
3799+000025f2@6388
3800+00002570@6389
3801+0000a5f0@6390
3802+0000a7f0@6392
3803+0000e7f4@6393
3804+0000e774@6396
3805+000065f4@6398
3806+0000e7f4@6400
3807+0000f7f4@6402
3808+0000f774@6404
3809+0000f7f4@6405
3810+000077f6@6407
3811+0000f7f6@6409
3812+0000f93a@6411
3813+0000b93a@6412
3814+0000b9ba@6413
3815+000039ba@6416
3816+0000a93a@6418
3817+0000a5f2@6420
3818+00002572@6426
3819+00002570@6427
3820+0000a5f0@6428
3821+0000a7f4@6429
3822+0000e7f0@6430
3823+0000e7f4@6431
3824+0000e774@6433
3825+000067f4@6435
3826+000065f4@6436
3827+0000e7f4@6437
3828+0000f5f0@6439
3829+0000f7f4@6440
3830+0000f774@6441
3831+0000f7f4@6442
3832+000077f6@6444
3833+0000f7f6@6446
3834+0000ff1e@6448
3835+0000bb1a@6449
3836+0000bb9a@6450
3837+00003b9a@6454
3838+0000ab9a@6455
3839+0000ab1a@6456
3840+0000aff2@6457
3841+0000a5f2@6458
3842+00002572@6463
3843+00002570@6464
3844+0000a5f0@6465
3845+0000a5f4@6466
3846+0000e7f4@6467
3847+0000e774@6471
3848+000067f4@6472
3849+000065f0@6473
3850+0000e7f4@6474
3851+0000f7f0@6476
3852+0000f7f4@6477
3853+0000f774@6478
3854+0000f770@6479
3855+0000f7f4@6480
3856+000077f6@6482
3857+0000f7f6@6483
3858+0000fd7e@6485
3859+0000f81a@6486
3860+0000b89a@6487
3861+0000389a@6491
3862+0000a81a@6493
3863+0000a8fa@6494
3864+0000a4f2@6495
3865+00002472@6500
3866+00002470@6501
3867+0000a470@6502
3868+0000e474@6504
3869+0000e6f4@6505
3870+000066f4@6509
3871+00006474@6510
3872+0000e474@6511
3873+0000e674@6512
3874+0000e474@6513
3875+0000f6f4@6514
3876+00007476@6519
3877+00007676@6520
3878+0000f676@6521
3879+0000fe7e@6522
3880+0000f8ba@6523
3881+0000b8ba@6524
3882+000038ba@6528
3883+0000383a@6529
3884+0000a83a@6530
3885+0000a472@6532
3886+0000a4f2@6533
3887+000024f2@6537
3888+00002470@6538
3889+0000a470@6539
3890+0000a670@6541
3891+0000e6f4@6542
3892+00006474@6547
3893+0000e674@6549
3894+0000f6f4@6551
3895+00007676@6556
3896+0000f676@6558
3897+0000fa1a@6560
3898+0000ba9a@6561
3899+00003a9a@6565
3900+00003a1a@6566
3901+0000aa1a@6567
3902+0000a4f2@6569
3903+00002472@6575
3904+0000a470@6576
3905+0000a674@6578
3906+0000e6f0@6579
3907+0000e6f4@6580
3908+00006674@6584
3909+00006470@6585
3910+0000e674@6586
3911+0000f6f4@6588
3912+000076f6@6593
3913+00007676@6594
3914+0000f676@6595
3915+0000f61e@6597
3916+0000b29a@6598
3917+0000321a@6603
3918+0000a21a@6604
3919+0000a672@6606
3920+0000a4f2@6607
3921+00002472@6612
3922+00002470@6613
3923+0000a470@6614
3924+0000a474@6615
3925+0000e6f4@6616
3926+0000e4f4@6617
3927+0000e6f4@6618
3928+000066f4@6621
3929+00006470@6622
3930+0000e474@6623
3931+0000e674@6624
3932+0000e474@6625
3933+0000f6f4@6626
3934+00007476@6631
3935+0000f676@6632
3936+0000f67e@6634
3937+0000b29a@6635
3938+0000329a@6640
3939+0000221a@6641
3940+0000a29a@6642
3941+0000a6fa@6643
3942+0000a4f2@6644
3943+0000a472@6647
3944+000024f2@6649
3945+000024f0@6650
3946+0000a4f0@6651
3947+0000e4f4@6653
3948+0000e6f4@6654
3949+0000e674@6655
3950+0000e474@6656
3951+0000e674@6657
3952+00006674@6658
3953+000064f4@6659
3954+0000e4f4@6660
3955+0000e6f4@6661
3956+0000f6f4@6663
3957+0000f674@6664
3958+000074f6@6668
3959+000076f6@6669
3960+0000f6f6@6670
3961+0000f6fe@6671
3962+0000f29a@6672
3963+0000b29a@6673
3964+0000b21a@6674
3965+0000329a@6677
3966+0000a29a@6679
3967+0000a4f2@6681
3968+0000a472@6683
3969+00002472@6686
3970+000024f0@6687
3971+0000a4f0@6688
3972+0000a6f0@6690
3973+0000e6f4@6691
3974+0000e674@6692
3975+000064f4@6696
3976+0000e6f4@6698
3977+0000f6f4@6700
3978+0000f674@6702
3979+00007676@6705
3980+000076f6@6706
3981+0000f6f6@6707
3982+0000f2ae@6709
3983+0000b2ae@6710
3984+0000b22e@6711
3985+000032ae@6714
3986+0000a2ae@6716
3987+0000a082@6718
3988+0000a002@6720
3989+00002082@6724
3990+00002080@6725
3991+0000a080@6726
3992+0000a2a4@6727
3993+0000e280@6728
3994+0000e2a4@6729
3995+0000e204@6730
3996+0000e224@6731
3997+0000e204@6732
3998+00006224@6733
3999+000060a4@6734
4000+0000e2a4@6735
4001+0000f284@6737
4002+0000f2a4@6738
4003+0000f224@6739
4004+0000f204@6740
4005+0000f224@6741
4006+00007226@6742
4007+00007286@6743
4008+0000f2a6@6744
4009+0000faa6@6745
4010+0000f2ae@6746
4011+0000f22e@6748
4012+000072ae@6752
4013+0000e2ae@6753
4014+0000e2aa@6755
4015+0000e082@6756
4016+0000e002@6757
4017+00006082@6761
4018+00006080@6762
4019+0000e080@6763
4020+0000e084@6764
4021+0000e2a4@6765
4022+0000e084@6766
4023+0000a60c@6767
4024+0000e60c@6768
4025+0000a60c@6769
4026+0000260c@6770
4027+0000268c@6771
4028+0000a68c@6772
4029+0000b68c@6774
4030+0000b60c@6776
4031+0000768e@6780
4032+0000f68e@6781
4033+0000f69e@6783
4034+0000b49e@6784
4035+0000b41e@6786
4036+0000349e@6789
4037+0000a49e@6791
4038+0000a4fe@6792
4039+0000aaf2@6793
4040+0000aa72@6795
4041+0000aaf2@6796
4042+00002af2@6798
4043+00002af0@6799
4044+0000aaf0@6800
4045+0000ea74@6802
4046+0000eaf4@6804
4047+00006af4@6807
4048+0000eaf4@6809
4049+0000ea74@6810
4050+0000fa74@6812
4051+0000faf4@6813
4052+00007af6@6817
4053+0000fa76@6819
4054+0000fe76@6820
4055+0000f426@6821
4056+0000b426@6822
4057+0000b4a6@6823
4058+000034a6@6826
4059+0000a426@6828
4060+0000a472@6830
4061+0000a4f2@6832
4062+000024f2@6835
4063+000024f0@6836
4064+0000a4f0@6837
4065+0000a470@6838
4066+0000a670@6839
4067+0000e674@6840
4068+0000e6f4@6841
4069+000064f4@6845
4070+0000e674@6847
4071+0000e474@6848
4072+0000f674@6849
4073+0000f6f4@6851
4074+000076f6@6854
4075+0000f676@6856
4076+0000f606@6858
4077+0000b606@6859
4078+0000b686@6860
4079+00003686@6863
4080+0000a686@6865
4081+0000a606@6866
4082+0000a472@6867
4083+0000a4f2@6869
4084+000024f2@6873
4085+0000a4f0@6874
4086+0000a470@6875
4087+0000a674@6876
4088+0000e670@6877
4089+0000e674@6878
4090+0000e6f4@6879
4091+000066f4@6882
4092+000064f4@6883
4093+0000e674@6884
4094+0000f674@6886
4095+0000f6f4@6888
4096+000076f6@6891
4097+0000f6f6@6893
4098+0000f676@6894
4099+0000f626@6895
4100+0000b626@6896
4101+0000b6a6@6897
4102+000036a6@6901
4103+0000a6a6@6902
4104+0000a626@6903
4105+0000a672@6904
4106+0000a472@6905
4107+0000a4f2@6906
4108+000024f2@6910
4109+000024f0@6911
4110+0000a470@6912
4111+0000a474@6913
4112+0000e674@6914
4113+0000e474@6915
4114+0000e6f4@6916
4115+000066f4@6919
4116+000064f4@6920
4117+0000e674@6921
4118+0000f674@6924
4119+0000f6f4@6925
4120+000074f6@6929
4121+0000f6f6@6930
4122+0000f676@6931
4123+0000b226@6933
4124+0000b2a6@6934
4125+000032a6@6938
4126+0000a226@6940
4127+0000a002@6942
4128+0000a082@6944
4129+00002082@6947
4130+00002080@6948
4131+0000a000@6949
4132+0000a080@6950
4133+0000e0a4@6951
4134+0000e2a4@6952
4135+000062a4@6956
4136+00006004@6957
4137+0000e0a4@6958
4138+0000e2a4@6959
4139+0000e0a4@6960
4140+0000f2a4@6961
4141+0000f224@6964
4142+00007026@6966
4143+00007226@6967
4144+0000f2a6@6968
4145+0000fabe@6969
4146+0000f8be@6970
4147+0000f9be@6971
4148+0000b9be@6972
4149+0000b93e@6974
4150+0000393e@6975
4151+0000a9be@6977
4152+0000abc2@6979
4153+0000ab42@6983
4154+00002b42@6984
4155+00002b40@6985
4156+0000ab40@6986
4157+0000abc0@6987
4158+0000abe0@6988
4159+0000ebe4@6989
4160+0000eb64@6992
4161+00006b64@6994
4162+0000eb44@6995
4163+0000ebe4@6996
4164+0000fbe4@6998
4165+0000fb64@7002
4166+00007b66@7003
4167+00007b46@7004
4168+0000fbe6@7005
4169+0000f3a6@7007
4170+0000b3a6@7008
4171+0000b326@7011
4172+00003326@7012
4173+0000a326@7014
4174+0000a3a6@7015
4175+0000a182@7016
4176+0000a102@7020
4177+00002102@7022
4178+0000a100@7023
4179+0000a180@7024
4180+0000a3a4@7025
4181+0000e3a0@7026
4182+0000e3a4@7027
4183+0000e324@7029
4184+0000e304@7030
4185+00006324@7031
4186+00006304@7032
4187+0000e3a4@7033
4188+0000f384@7035
4189+0000f3a4@7036
4190+0000f324@7039
4191+00007326@7040
4192+00007306@7041
4193+0000f3a6@7042
4194+0000f19e@7044
4195+0000b19e@7046
4196+0000b11e@7048
4197+0000311e@7050
4198+0000a11e@7051
4199+0000a19e@7052
4200+0000a182@7053
4201+0000a102@7057
4202+00002102@7059
4203+00002100@7060
4204+0000a180@7061
4205+0000a184@7062
4206+0000e3a4@7063
4207+0000e184@7065
4208+0000e3a4@7066
4209+0000e304@7067
4210+00006304@7068
4211+00006104@7069
4212+0000e1a4@7070
4213+0000e3a4@7071
4214+0000f184@7072
4215+0000f3a4@7073
4216+0000f384@7075
4217+0000f324@7076
4218+00007304@7077
4219+00007106@7078
4220+0000f326@7079
4221+0000f3a6@7080
4222+0000f19e@7081
4223+0000b19e@7083
4224+0000b11e@7085
4225+0000311e@7087
4226+0000211e@7088
4227+0000a19e@7089
4228+0000a182@7091
4229+0000a102@7095
4230+00002102@7096
4231+00002100@7097
4232+0000a180@7098
4233+0000e1a4@7100
4234+0000e3a4@7101
4235+0000e1a4@7102
4236+0000e3a4@7103
4237+0000e304@7104
4238+000063a4@7105
4239+00006184@7106
4240+0000e1a4@7107
4241+0000e3a4@7108
4242+0000e1a4@7109
4243+0000f3a4@7110
4244+0000f324@7111
4245+0000f304@7112
4246+0000f3a4@7113
4247+000073a6@7115
4248+0000f3a6@7117
4249+0000f3fe@7118
4250+0000f15e@7119
4251+0000b1de@7120
4252+000031de@7124
4253+0000a15e@7126
4254+0000bf42@7128
4255+0000afc2@7129
4256+00002fc2@7133
4257+00002f40@7134
4258+0000afc0@7135
4259+0000afe0@7137
4260+0000efe4@7138
4261+0000efc4@7140
4262+0000ef64@7141
4263+0000ef44@7142
4264+00006fe4@7143
4265+0000efe4@7144
4266+0000ffe4@7147
4267+0000ff64@7148
4268+0000ff44@7149
4269+0000ffe4@7150
4270+00007fe6@7152
4271+0000ffe6@7154
4272+0000f356@7156
4273+0000b3d6@7158
4274+000033d6@7161
4275+0000a356@7163
4276+0000a7f2@7165
4277+00002770@7171
4278+0000a7f0@7172
4279+0000a7f4@7174
4280+0000e7f0@7175
4281+0000e7f4@7176
4282+0000e774@7178
4283+000067f4@7180
4284+0000e7f4@7182
4285+0000f7f4@7184
4286+0000f774@7186
4287+0000f7f4@7187
4288+000077f6@7189
4289+0000f7f6@7191
4290+0000f53e@7193
4291+0000b53e@7194
4292+0000b5be@7195
4293+000035be@7199
4294+0000a5be@7200
4295+0000a53e@7201
4296+0000afa2@7202
4297+0000ab82@7203
4298+00002b02@7208
4299+00002b00@7209
4300+0000ab80@7210
4301+0000ab84@7211
4302+0000eba4@7212
4303+0000eb24@7215
4304+00006ba4@7217
4305+00006b84@7218
4306+0000eba4@7219
4307+0000fba4@7222
4308+0000fb24@7223
4309+0000fb04@7224
4310+0000fba4@7225
4311+00007ba4@7226
4312+00007ba6@7227
4313+0000fba6@7228
4314+0000ff1e@7230
4315+0000f71e@7231
4316+0000b79e@7232
4317+0000379e@7236
4318+0000a71e@7238
4319+0000a79e@7239
4320+0000ab02@7240
4321+0000ab82@7241
4322+00002b82@7245
4323+00002b00@7246
4324+0000ab80@7247
4325+0000eba4@7249
4326+0000eb04@7253
4327+00006ba4@7254
4328+00006b84@7255
4329+0000eba4@7256
4330+0000fba4@7259
4331+0000fb24@7260
4332+0000fb04@7261
4333+0000fba4@7262
4334+00007ba6@7264
4335+0000fba6@7266
4336+0000f902@7268
4337+0000b982@7269
4338+00003982@7273
4339+0000a902@7275
4340+0000a982@7276
4341+0000abc2@7277
4342+00002bc2@7282
4343+00002b40@7283
4344+0000abc0@7284
4345+0000abe0@7286
4346+0000ebe4@7287
4347+0000eb64@7290
4348+00006be4@7292
4349+0000ebe4@7293
4350+0000fbe4@7296
4351+0000fb64@7297
4352+0000fb44@7298
4353+0000fbe4@7299
4354+00007be6@7301
4355+0000fbe6@7303
4356+0000f902@7305
4357+0000f982@7307
4358+00007982@7310
4359+0000e902@7312
4360+0000ebc2@7314
4361+00006b40@7320
4362+0000eb40@7321
4363+0000ebc0@7322
4364+0000ebe4@7323
4365+0000ebc0@7324
4366+0000abe4@7325
4367+0000e180@7326
4368+0000a100@7327
4369+00002180@7329
4370+0000a180@7331
4371+0000b180@7333
4372+0000b100@7335
4373+0000b180@7336
4374+00003182@7338
4375+00007182@7339
4376+0000f182@7340
4377+0000f11e@7342
4378+0000b19e@7344
4379+0000319e@7348
4380+0000a19e@7349
4381+0000a11e@7350
4382+0000a182@7351
4383+00002102@7357
4384+00002100@7358
4385+0000a180@7359
4386+0000a184@7360
4387+0000e3a4@7361
4388+0000e184@7363
4389+0000e3a4@7364
4390+0000e304@7365
4391+000063a4@7366
4392+00006184@7367
4393+0000e1a4@7368
4394+0000e3a4@7369
4395+0000f180@7370
4396+0000f3a4@7371
4397+0000f304@7372
4398+0000f3a4@7374
4399+000071a6@7376
4400+0000f3a6@7377
4401+0000f11e@7379
4402+0000b19e@7381
4403+0000319e@7385
4404+0000a11e@7387
4405+0000a19e@7388
4406+0000a182@7389
4407+00002182@7394
4408+00002100@7395
4409+0000a180@7396
4410+0000e1a4@7398
4411+0000e3a4@7399
4412+0000e184@7400
4413+0000e3a4@7401
4414+0000e304@7402
4415+000063a4@7403
4416+00006184@7404
4417+0000e1a4@7405
4418+0000e3a4@7406
4419+0000f3a4@7408
4420+0000f324@7409
4421+0000f104@7410
4422+0000f3a4@7411
4423+000073a6@7413
4424+0000f3a6@7415
4425+0000f3e6@7416
4426+0000f162@7417
4427+0000b1e2@7418
4428+000031e2@7422
4429+00003162@7423
4430+0000a162@7424
4431+0000a1e2@7425
4432+0000bf42@7426
4433+0000afc2@7427
4434+00002fc2@7431
4435+00002f40@7432
4436+0000afc0@7433
4437+0000afe0@7435
4438+0000efe4@7436
4439+0000ef64@7439
4440+00006fe4@7441
4441+0000efe4@7442
4442+0000ffe4@7445
4443+0000ff64@7446
4444+0000ff44@7447
4445+0000ffe4@7448
4446+00007fe6@7450
4447+0000ffe6@7452
4448+0000f346@7454
4449+0000b346@7455
4450+0000b3c6@7456
4451+000033c6@7459
4452+0000a346@7461
4453+0000abe2@7463
4454+00002b60@7469
4455+0000abe0@7470
4456+0000abe4@7472
4457+0000ebe0@7473
4458+0000ebe4@7474
4459+0000eb64@7476
4460+00006be4@7478
4461+0000ebe4@7480
4462+0000fbe4@7482
4463+0000fb64@7484
4464+0000fbe4@7485
4465+00007be6@7487
4466+0000fbe6@7489
4467+0000ff3e@7491
4468+0000f73e@7492
4469+0000b7be@7493
4470+000037be@7497
4471+0000a7be@7498
4472+0000a73e@7499
4473+0000afa2@7500
4474+0000ab82@7501
4475+00002b02@7506
4476+00002b00@7507
4477+0000ab80@7508
4478+0000ab84@7509
4479+0000eba4@7510
4480+0000eb24@7514
4481+00006ba4@7515
4482+0000eba4@7517
4483+0000fba4@7520
4484+0000fb24@7521
4485+0000fba4@7523
4486+00007ba4@7524
4487+00007ba6@7525
4488+0000fba6@7526
4489+0000fb1e@7528
4490+0000f91e@7529
4491+0000b99e@7530
4492+0000399e@7534
4493+0000a91e@7536
4494+0000ab9e@7537
4495+0000ab82@7538
4496+00002b82@7543
4497+00002b00@7544
4498+0000ab80@7545
4499+0000eba4@7547
4500+0000eb24@7551
4501+00006ba4@7552
4502+0000eba4@7554
4503+0000fba4@7557
4504+0000fb24@7558
4505+0000fb04@7559
4506+0000fba4@7560
4507+00007ba6@7562
4508+0000fba6@7564
4509+0000f906@7566
4510+0000b986@7567
4511+00003986@7571
4512+00003906@7572
4513+0000a906@7573
4514+0000a986@7574
4515+0000abc2@7575
4516+00002bc2@7580
4517+00002b40@7581
4518+0000abc0@7582
4519+0000abe0@7584
4520+0000ebe4@7585
4521+0000eb64@7588
4522+00006be4@7590
4523+0000ebe4@7591
4524+0000fbe4@7594
4525+0000fb64@7595
4526+0000fb44@7596
4527+0000fbe4@7597
4528+00007be6@7599
4529+0000fbe6@7601
4530+0000f906@7603
4531+0000f986@7605
4532+00007986@7608
4533+0000e986@7610
4534+0000e906@7611
4535+0000ebc2@7612
4536+00006b40@7618
4537+0000eb40@7619
4538+0000ebc0@7620
4539+0000ebe4@7621
4540+0000ebc0@7622
4541+0000abe4@7623
4542+0000e180@7624
4543+0000a100@7625
4544+00002180@7627
4545+0000a180@7629
4546+0000b180@7631
4547+0000b100@7633
4548+0000b180@7634
4549+00003182@7636
4550+00007182@7637
4551+0000f182@7638
4552+0000f11e@7640
4553+0000b19e@7642
4554+0000319e@7646
4555+0000a11e@7647
4556+0000a182@7649
4557+00002102@7655
4558+00002100@7656
4559+0000a180@7657
4560+0000a184@7658
4561+0000e3a4@7659
4562+0000e184@7661
4563+0000e3a4@7662
4564+0000e304@7663
4565+000063a4@7664
4566+00006184@7665
4567+0000e1a4@7666
4568+0000e3a4@7667
4569+0000e180@7668
4570+0000f3a4@7669
4571+0000f304@7670
4572+0000f3a4@7672
4573+000071a6@7674
4574+0000f3a6@7675
4575+0000f97e@7677
4576+0000f9fe@7678
4577+0000b9fe@7679
4578+000039fe@7683
4579+0000397e@7684
4580+0000a97e@7685
4581+0000a9fe@7686
4582+0000a102@7687
4583+0000a182@7688
4584+00002182@7692
4585+00002100@7693
4586+0000a180@7694
4587+0000e1a4@7696
4588+0000e3a4@7697
4589+0000e1a4@7698
4590+0000e304@7700
4591+000063a4@7701
4592+00006184@7702
4593+0000e1a4@7703
4594+0000e3a4@7704
4595+0000e1a4@7705
4596+0000f3a4@7706
4597+0000f324@7707
4598+0000f104@7708
4599+0000f3a4@7709
4600+000071a6@7711
4601+000073a6@7712
4602+0000f3a6@7713
4603+0000f3e6@7714
4604+0000f166@7715
4605+0000b1e6@7716
4606+000031e6@7720
4607+00003166@7721
4608+0000a166@7722
4609+0000a1e6@7723
4610+0000bf42@7724
4611+0000afc2@7725
4612+00002fc2@7729
4613+00002f40@7730
4614+0000afc0@7731
4615+0000afe0@7733
4616+0000efe4@7734
4617+0000ef64@7737
4618+00006fe4@7739
4619+0000efe4@7740
4620+0000ffe4@7743
4621+0000ff64@7744
4622+0000ff44@7745
4623+0000ffe4@7746
4624+00007fe6@7748
4625+0000ffe6@7750
4626+0000f346@7752
4627+0000b346@7753
4628+0000b3c6@7754
4629+000033c6@7757
4630+0000a346@7759
4631+0000abe2@7761
4632+00002b60@7767
4633+0000abe0@7768
4634+0000abe4@7770
4635+0000ebe0@7771
4636+0000ebe4@7772
4637+0000eb64@7774
4638+00006be4@7776
4639+0000ebe4@7778
4640+0000fbe4@7780
4641+0000fb64@7782
4642+0000fbe4@7783
4643+00007be6@7785
4644+0000fbe6@7787
4645+0000f93e@7789
4646+0000b9be@7791
4647+000039be@7795
4648+0000a9be@7796
4649+0000a93e@7797
4650+0000ab82@7798
4651+00002b02@7804
4652+00002b00@7805
4653+0000ab80@7806
4654+0000ab84@7807
4655+0000eba4@7808
4656+0000eb24@7812
4657+00006ba4@7813
4658+0000eba4@7815
4659+0000fba4@7818
4660+0000fb24@7819
4661+0000fb04@7820
4662+0000fba4@7821
4663+00007ba4@7822
4664+00007ba6@7823
4665+0000fba6@7824
4666+0000fb1e@7826
4667+0000f31e@7827
4668+0000b39e@7828
4669+0000339e@7832
4670+0000331e@7833
4671+0000a31e@7834
4672+0000a7be@7835
4673+0000ada2@7836
4674+00002da2@7841
4675+00002d20@7842
4676+0000ada0@7843
4677+0000eda4@7845
4678+0000efa4@7846
4679+0000eda4@7847
4680+0000efa4@7848
4681+0000ef24@7849
4682+00006fa4@7850
4683+00006da4@7851
4684+0000efa4@7852
4685+0000ffa4@7855
4686+0000ff24@7856
4687+0000ffa4@7858
4688+00007fa6@7860
4689+0000ffa6@7862
4690+0000ffae@7863
4691+0000f90a@7864
4692+0000b98a@7865
4693+0000398a@7869
4694+0000a90a@7871
4695+0000a98a@7872
4696+0000abc2@7873
4697+00002bc2@7878
4698+00002b40@7879
4699+0000abc0@7880
4700+0000abe0@7882
4701+0000ebe4@7883
4702+0000ebc4@7885
4703+0000eb64@7886
4704+00006be4@7888
4705+0000ebe4@7889
4706+0000fbe4@7892
4707+0000fb64@7893
4708+0000fb44@7894
4709+0000fbe4@7895
4710+00007be6@7897
4711+0000fbe6@7899
4712+0000f90a@7901
4713+0000f98a@7903
4714+0000798a@7906
4715+0000e90a@7908
4716+0000ebc2@7910
4717+00006b40@7916
4718+0000eb40@7917
4719+0000ebc0@7918
4720+0000ebe4@7919
4721+0000ebe0@7920
4722+0000abe4@7921
4723+0000a5e0@7922
4724+0000a560@7923
4725+0000a5e0@7924
4726+000025e0@7925
4727+0000a5e0@7927
4728+0000b5e0@7929
4729+0000b560@7931
4730+0000b5e0@7932
4731+000035e2@7934
4732+000075e2@7935
4733+0000f5e2@7936
4734+0000f91e@7938
4735+0000b91e@7939
4736+0000b99e@7940
4737+0000399e@7944
4738+0000a99e@7945
4739+0000a91e@7946
4740+0000abd2@7947
4741+00002b52@7953
4742+00002b50@7954
4743+0000abd0@7955
4744+0000abf4@7956
4745+0000ebf4@7957
4746+0000ebd4@7959
4747+0000ebf4@7960
4748+0000eb54@7961
4749+00006bf4@7962
4750+00006bd4@7963
4751+0000ebf4@7964
4752+0000ebd0@7966
4753+0000fbf4@7967
4754+0000fb74@7968
4755+0000fb54@7969
4756+0000fbf4@7970
4757+00007bf4@7971
4758+00007bf6@7972
4759+0000fbf6@7973
4760+0000fb1e@7975
4761+0000b91e@7976
4762+0000b99e@7977
4763+0000399e@7981
4764+0000299e@7982
4765+0000a91e@7983
4766+0000abde@7984
4767+0000abd2@7985
4768+00002b52@7990
4769+00002b50@7991
4770+0000abd0@7992
4771+0000ebf4@7994
4772+0000ebd4@7997
4773+0000eb54@7998
4774+00006bf4@7999
4775+00006bd4@8000
4776+0000ebf4@8001
4777+0000fbf4@8004
4778+0000fb74@8005
4779+0000fb54@8006
4780+0000fbf4@8007
4781+00007bf6@8009
4782+0000fbf6@8011
4783+0000fbfe@8012
4784+0000f16a@8013
4785+0000b1ea@8014
4786+000031ea@8018
4787+0000a16a@8020
4788+0000a1ea@8021
4789+0000bf42@8022
4790+0000afc2@8023
4791+00002fc2@8027
4792+00002f40@8028
4793+0000afc0@8029
4794+0000afe0@8031
4795+0000efe4@8032
4796+0000ef64@8035
4797+0000ef44@8036
4798+00006fe4@8037
4799+0000efe4@8038
4800+0000ffe4@8041
4801+0000ff64@8042
4802+0000ffe4@8044
4803+00007fe6@8046
4804+0000ffe6@8048
4805+0000f346@8050
4806+0000b346@8051
4807+0000b3c6@8052
4808+000033c6@8055
4809+0000a346@8057
4810+0000abe2@8059
4811+00002b60@8065
4812+0000abe0@8066
4813+0000abe4@8068
4814+0000ebe4@8069
4815+0000eb64@8072
4816+00006be4@8074
4817+0000ebe4@8076
4818+0000fbe4@8078
4819+0000fb64@8080
4820+0000fbe4@8081
4821+00007be6@8083
4822+0000fbe6@8085
4823+0000f33e@8087
4824+0000b3be@8089
4825+000033be@8093
4826+0000a3be@8094
4827+0000a33e@8095
4828+0000afa2@8096
4829+0000ada2@8097
4830+00002d22@8102
4831+00002d20@8103
4832+0000ada0@8104
4833+0000ada4@8105
4834+0000efa4@8106
4835+0000ef24@8110
4836+00006fa4@8111
4837+0000efa4@8113
4838+0000efa0@8115
4839+0000ffa4@8116
4840+0000ff24@8117
4841+0000ffa4@8119
4842+00007fa4@8120
4843+00007fa6@8121
4844+0000ffa6@8122
4845+0000fd3e@8124
4846+0000f51e@8125
4847+0000b59e@8126
4848+0000359e@8130
4849+0000351e@8131
4850+0000a51e@8132
4851+0000a5be@8133
4852+0000ada2@8134
4853+00002da2@8139
4854+00002d20@8140
4855+0000ada0@8141
4856+0000eda4@8143
4857+0000efa4@8144
4858+0000eda4@8145
4859+0000efa4@8146
4860+0000ef24@8147
4861+00006fa4@8148
4862+00006da4@8149
4863+0000eda4@8150
4864+0000efa4@8151
4865+0000eda4@8152
4866+0000ffa4@8153
4867+0000ff24@8154
4868+0000ffa4@8156
4869+00007da6@8158
4870+00007fa6@8159
4871+0000ffa6@8160
4872+0000ffae@8161
4873+0000f90e@8162
4874+0000b98e@8163
4875+0000398e@8167
4876+0000a90e@8169
4877+0000a98e@8170
4878+0000abc2@8171
4879+00002bc2@8176
4880+00002b40@8177
4881+0000abc0@8178
4882+0000abe0@8180
4883+0000ebe4@8181
4884+0000eb64@8184
4885+00006be4@8186
4886+0000ebe4@8187
4887+0000fbe4@8190
4888+0000fb64@8191
4889+0000fb44@8192
4890+0000fbe4@8193
4891+00007be6@8195
4892+0000fbe6@8197
4893+0000f90e@8199
4894+0000f98e@8201
4895+0000798e@8204
4896+0000798c@8205
4897+0000f90c@8206
4898+0000fbc0@8208
4899+0000ebc0@8210
4900+00006b40@8214
4901+0000eb40@8215
4902+0000ebc0@8216
4903+0000ebe4@8217
4904+0000ebe0@8218
4905+0000ebe4@8219
4906+0000ebc4@8220
4907+0000eb64@8221
4908+0000eb44@8222
4909+00006be4@8223
4910+0000ebe4@8225
4911+0000fbc4@8227
4912+0000fbe4@8228
4913+0000fb44@8229
4914+0000fbe4@8230
4915+00007be6@8232
4916+0000fbe6@8234
4917+0000f91e@8236
4918+0000b99e@8238
4919+0000399e@8242
4920+0000a99e@8243
4921+0000a91e@8244
4922+0000abd2@8245
4923+00002b52@8251
4924+00002b50@8252
4925+0000abd0@8253
4926+0000abf4@8254
4927+0000ebf4@8255
4928+0000ebd4@8257
4929+0000eb74@8258
4930+0000eb54@8259
4931+00006bf4@8260
4932+00006bd4@8261
4933+0000ebf4@8262
4934+0000ebd0@8264
4935+0000fbf4@8265
4936+0000fb74@8266
4937+0000fb54@8267
4938+0000fbf4@8268
4939+00007bf4@8269
4940+00007bf6@8270
4941+0000fbf6@8271
4942+0000fb1e@8273
4943+0000b91e@8274
4944+0000b99e@8275
4945+0000399e@8279
4946+0000a91e@8281
4947+0000abde@8282
4948+0000abd2@8283
4949+00002b52@8288
4950+00002b50@8289
4951+0000abd0@8290
4952+0000ebf4@8292
4953+0000eb54@8296
4954+00006bf4@8297
4955+00006bd4@8298
4956+0000ebf4@8299
4957+0000fbf4@8302
4958+0000fb74@8303
4959+0000fb54@8304
4960+0000fbf4@8305
4961+00007bf6@8307
4962+0000fbf6@8309
4963+0000fbfe@8310
4964+0000f16e@8311
4965+0000b1ee@8312
4966+000031ee@8316
4967+0000a16e@8318
4968+0000a1ee@8319
4969+0000bf42@8320
4970+0000afc2@8321
4971+00002fc2@8325
4972+00002f40@8326
4973+0000afc0@8327
4974+0000afe0@8329
4975+0000efe4@8330
4976+0000ef64@8333
4977+00006fe4@8335
4978+0000efe4@8336
4979+0000ffe4@8339
4980+0000ff64@8340
4981+0000ff44@8341
4982+0000ffe4@8342
4983+00007fe6@8344
4984+0000ffe6@8346
4985+0000f346@8348
4986+0000b346@8349
4987+0000b3c6@8350
4988+000033c6@8353
4989+0000a346@8355
4990+0000abe2@8357
4991+00002b60@8363
4992+0000abe0@8364
4993+0000abe4@8366
4994+0000ebe0@8367
4995+0000ebe4@8368
4996+0000eb64@8370
4997+00006be4@8372
4998+0000ebe4@8374
4999+0000fbe4@8376
5000+0000fb64@8378
5001+0000fbe4@8379
5002+00007be6@8381
5003+0000fbe6@8383
5004+0000fd3e@8385
5005+0000b53e@8386
5006+0000b5be@8387
5007+000035be@8391
5008+0000a5be@8392
5009+0000a53e@8393
5010+0000ada2@8394
5011+00002d22@8400
5012+00002d20@8401
5013+0000ada0@8402
5014+0000ada4@8403
5015+0000efa4@8404
5016+0000ef24@8407
5017+00006fa4@8409
5018+00006da4@8410
5019+0000efa4@8411
5020+0000ffa4@8413
5021+0000ff24@8415
5022+0000ffa4@8417
5023+00007fa4@8418
5024+00007fa6@8419
5025+0000ffa6@8420
5026+0000ff3e@8422
5027+0000f71e@8423
5028+0000b79e@8424
5029+0000379e@8428
5030+0000a71e@8430
5031+0000a7be@8431
5032+0000ada2@8432
5033+00002da2@8437
5034+00002d20@8438
5035+0000ada0@8439
5036+0000eda4@8441
5037+0000efa4@8442
5038+0000eda4@8443
5039+0000efa4@8444
5040+0000ef24@8445
5041+00006fa4@8446
5042+00006da4@8447
5043+0000efa4@8448
5044+0000ffa4@8451
5045+0000ff24@8452
5046+0000ffa4@8454
5047+00007fa6@8456
5048+0000ffa6@8458
5049+0000ffb6@8459
5050+0000f912@8460
5051+0000b992@8461
5052+00003992@8465
5053+0000a912@8467
5054+0000a992@8468
5055+0000abc2@8469
5056+00002bc2@8474
5057+00002b40@8475
5058+0000abc0@8476
5059+0000abe0@8478
5060+0000ebe4@8479
5061+0000eb64@8482
5062+00006be4@8484
5063+0000ebe4@8485
5064+0000fbe4@8488
5065+0000fb64@8489
5066+0000fb44@8490
5067+0000fbe4@8491
5068+00007be6@8493
5069+0000fbe6@8495
5070+0000f912@8497
5071+0000f992@8499
5072+00007992@8502
5073+0000e912@8504
5074+0000ebc2@8506
5075+00006b40@8512
5076+0000eb40@8513
5077+0000ebc0@8514
5078+0000ebe4@8515
5079+0000ebc0@8516
5080+0000abe4@8517
5081+0000a5e0@8518
5082+0000a560@8519
5083+0000a5e0@8520
5084+000025e0@8521
5085+0000a5e0@8523
5086+0000b5e0@8525
5087+0000b560@8527
5088+0000b5e0@8528
5089+000035e2@8530
5090+000075e2@8531
5091+0000f5e2@8532
5092+0000f91e@8534
5093+0000b91e@8535
5094+0000b99e@8536
5095+0000399e@8540
5096+0000a99e@8541
5097+0000a91e@8542
5098+0000abd2@8543
5099+00002b52@8549
5100+00002b50@8550
5101+0000abd0@8551
5102+0000abf4@8552
5103+0000ebf4@8553
5104+0000ebd4@8555
5105+0000ebf4@8556
5106+0000eb54@8557
5107+00006bf4@8558
5108+00006bd4@8559
5109+0000ebf4@8560
5110+0000fbd4@8562
5111+0000fbf4@8563
5112+0000fb54@8564
5113+0000fbf4@8566
5114+00007bf4@8567
5115+00007bf6@8568
5116+0000fbf6@8569
5117+0000fb1e@8571
5118+0000b91e@8572
5119+0000b99e@8573
5120+0000399e@8577
5121+0000a91e@8579
5122+0000abde@8580
5123+0000abd2@8581
5124+00002b52@8586
5125+00002b50@8587
5126+0000abd0@8588
5127+0000ebf4@8590
5128+0000eb74@8594
5129+00006bf4@8595
5130+0000ebf4@8597
5131+0000fbf4@8600
5132+0000fb74@8601
5133+0000fb54@8602
5134+0000fbf4@8603
5135+00007bf6@8605
5136+0000fbf6@8607
5137+0000f172@8609
5138+0000b1f2@8610
5139+000031f2@8614
5140+0000a172@8616
5141+0000a1f2@8617
5142+0000bf42@8618
5143+0000afc2@8619
5144+00002fc2@8623
5145+00002f40@8624
5146+0000afc0@8625
5147+0000afe0@8627
5148+0000efe4@8628
5149+0000ef64@8631
5150+00006fe4@8633
5151+0000efe4@8634
5152+0000ffe4@8637
5153+0000ff64@8638
5154+0000ff44@8639
5155+0000ffe4@8640
5156+00007fe6@8642
5157+0000ffe6@8644
5158+0000f346@8646
5159+0000b346@8647
5160+0000b3c6@8648
5161+000033c6@8651
5162+0000a346@8653
5163+0000abe2@8655
5164+00002b60@8661
5165+0000abe0@8662
5166+0000abe4@8664
5167+0000ebe4@8665
5168+0000eb64@8668
5169+00006be4@8670
5170+0000ebe4@8672
5171+0000fbe4@8674
5172+0000fb64@8676
5173+0000fbe4@8677
5174+00007be6@8679
5175+0000fbe6@8681
5176+0000fb1e@8683
5177+0000bb9e@8685
5178+00003b9e@8689
5179+0000ab9e@8690
5180+0000ab1e@8691
5181+0000ab82@8692
5182+00002b02@8698
5183+00002b00@8699
5184+0000ab80@8700
5185+0000aba4@8701
5186+0000eba4@8702
5187+0000eb24@8706
5188+00006ba4@8707
5189+00006b84@8708
5190+0000eba4@8709
5191+0000eb84@8711
5192+0000fba4@8712
5193+0000fb24@8713
5194+0000fb04@8714
5195+0000fba4@8715
5196+00007ba6@8716
5197+0000fba6@8718
5198+0000fb3e@8720
5199+0000bbbe@8722
5200+00003bbe@8726
5201+00003b3e@8727
5202+0000ab3e@8728
5203+0000abbe@8729
5204+0000ab02@8730
5205+0000ab82@8731
5206+00002b82@8735
5207+00002b00@8736
5208+0000ab80@8737
5209+0000eba4@8739
5210+0000eb24@8743
5211+00006ba4@8744
5212+0000eba4@8746
5213+0000fba4@8749
5214+0000fb24@8750
5215+0000fb04@8751
5216+0000fba4@8752
5217+00007ba6@8754
5218+0000fba6@8756
5219+0000fbb6@8757
5220+0000f916@8758
5221+0000b996@8759
5222+00003996@8763
5223+0000a916@8765
5224+0000a996@8766
5225+0000abc2@8767
5226+00002bc2@8772
5227+00002b40@8773
5228+0000abc0@8774
5229+0000abe0@8776
5230+0000ebe4@8777
5231+0000ebc4@8779
5232+0000eb64@8780
5233+00006bc4@8782
5234+0000ebe4@8783
5235+0000fbe4@8786
5236+0000fb64@8787
5237+0000fb44@8788
5238+0000fbe4@8789
5239+00007be6@8791
5240+0000fbe6@8793
5241+0000f916@8795
5242+0000f996@8797
5243+00007996@8800
5244+0000e916@8802
5245+0000ebc2@8804
5246+00006b40@8810
5247+0000eb40@8811
5248+0000ebc0@8812
5249+0000ebe4@8813
5250+0000ebe0@8814
5251+0000abe4@8815
5252+0000a5e0@8816
5253+0000a560@8817
5254+0000a5e0@8818
5255+000025e0@8819
5256+0000a5e0@8821
5257+0000b5e0@8823
5258+0000b560@8825
5259+0000b5e0@8827
5260+000035e2@8828
5261+000075e2@8829
5262+0000f5e2@8830
5263+0000f91e@8832
5264+0000b91e@8833
5265+0000b99e@8834
5266+0000399e@8838
5267+0000a99e@8839
5268+0000a91e@8840
5269+0000abd2@8841
5270+00002b52@8847
5271+00002b50@8848
5272+0000abd0@8849
5273+0000abf4@8850
5274+0000ebf4@8851
5275+0000eb74@8854
5276+0000eb54@8855
5277+00006bf4@8856
5278+0000ebf4@8858
5279+0000ebd4@8860
5280+0000fbf4@8861
5281+0000fb74@8862
5282+0000fb54@8863
5283+0000fbf4@8864
5284+00007bf4@8865
5285+00007bf6@8866
5286+0000fbf6@8867
5287+0000fb1e@8869
5288+0000b91e@8870
5289+0000b99e@8871
5290+0000399e@8875
5291+0000299e@8876
5292+0000a91e@8877
5293+0000abde@8878
5294+0000abd2@8879
5295+00002b52@8884
5296+00002b50@8885
5297+0000abd0@8886
5298+0000ebf4@8888
5299+0000eb54@8892
5300+00006bf4@8893
5301+00006bd4@8894
5302+0000ebf4@8895
5303+0000ebd4@8897
5304+0000fbf4@8898
5305+0000fb74@8899
5306+0000fb54@8900
5307+0000fbf4@8901
5308+00007bf6@8903
5309+0000fbf6@8905
5310+0000f176@8907
5311+0000b1f6@8908
5312+000031f6@8912
5313+0000a176@8914
5314+0000a1f6@8915
5315+0000bf42@8916
5316+0000afc2@8917
5317+00002fc2@8921
5318+00002f40@8922
5319+0000afc0@8923
5320+0000afe0@8925
5321+0000efe4@8926
5322+0000efc4@8928
5323+0000ef64@8929
5324+00006fe4@8931
5325+0000efe4@8932
5326+0000ffe4@8935
5327+0000ff64@8936
5328+0000ff44@8937
5329+0000ffe4@8938
5330+00007fe6@8940
5331+0000ffe6@8942
5332+0000f346@8944
5333+0000b346@8945
5334+0000b3c6@8946
5335+000033c6@8949
5336+0000a346@8951
5337+0000abe2@8953
5338+00002b60@8959
5339+0000ab60@8960
5340+0000abe0@8961
5341+0000abe4@8962
5342+0000ebe4@8963
5343+0000eb64@8966
5344+00006be4@8968
5345+0000ebe4@8970
5346+0000fbe4@8972
5347+0000fb64@8974
5348+0000fbe4@8975
5349+00007be6@8977
5350+0000fbe6@8979
5351+0000ff1e@8981
5352+0000bd1e@8982
5353+0000bd9e@8983
5354+00003d9e@8987
5355+0000ad9e@8988
5356+0000ad1e@8989
5357+0000af82@8990
5358+0000ab82@8991
5359+00002b02@8996
5360+00002b00@8997
5361+0000ab80@8998
5362+0000aba4@8999
5363+0000eba4@9000
5364+0000eb84@9002
5365+0000eba4@9003
5366+0000eb04@9004
5367+00006ba4@9005
5368+0000eba4@9007
5369+0000eb84@9009
5370+0000fba4@9010
5371+0000fb24@9011
5372+0000fb04@9012
5373+0000fba4@9013
5374+00007ba6@9014
5375+0000fba6@9016
5376+0000ff3e@9018
5377+0000fd3e@9019
5378+0000bdbe@9020
5379+00003dbe@9024
5380+0000ad3e@9026
5381+0000afbe@9027
5382+0000ab02@9028
5383+0000ab82@9029
5384+00002b82@9033
5385+00002b00@9034
5386+0000ab80@9035
5387+0000eba4@9037
5388+0000eb24@9041
5389+00006ba4@9042
5390+0000eba4@9044
5391+0000fba4@9047
5392+0000fb24@9048
5393+0000fb04@9049
5394+0000fba4@9050
5395+00007ba6@9052
5396+0000fba6@9054
5397+0000fbbe@9055
5398+0000f91a@9056
5399+0000b99a@9057
5400+0000399a@9061
5401+0000a91a@9063
5402+0000a99a@9064
5403+0000abc2@9065
5404+00002bc2@9070
5405+00002b40@9071
5406+0000abc0@9072
5407+0000abe0@9074
5408+0000ebe4@9075
5409+0000ebc4@9077
5410+0000eb64@9078
5411+00006bc4@9080
5412+0000ebe4@9081
5413+0000fbe4@9084
5414+0000fb64@9085
5415+0000fb44@9086
5416+0000fbe4@9087
5417+00007be6@9089
5418+0000fbe6@9091
5419+0000f91a@9093
5420+0000f99a@9095
5421+0000799a@9098
5422+0000e91a@9100
5423+0000ebc2@9102
5424+00006b40@9108
5425+0000eb40@9109
5426+0000ebc0@9110
5427+0000ebe4@9111
5428+0000ebe0@9112
5429+0000abe4@9113
5430+0000a5e0@9114
5431+0000a560@9115
5432+0000a5e0@9116
5433+000025e0@9117
5434+0000a5e0@9119
5435+0000b5e0@9121
5436+0000b560@9123
5437+0000b5e0@9124
5438+000035e2@9126
5439+000075e2@9127
5440+0000f5e2@9128
5441+0000f91e@9130
5442+0000b91e@9131
5443+0000b99e@9132
5444+0000399e@9136
5445+0000a99e@9137
5446+0000a91e@9138
5447+0000abd2@9139
5448+00002b52@9145
5449+00002b50@9146
5450+0000abd0@9147
5451+0000abf4@9148
5452+0000ebf4@9149
5453+0000ebd4@9151
5454+0000eb74@9152
5455+0000eb54@9153
5456+00006bf4@9154
5457+00006bd4@9155
5458+0000ebf4@9156
5459+0000fbd4@9158
5460+0000fbf4@9159
5461+0000fb74@9160
5462+0000fb54@9161
5463+0000fbf4@9162
5464+00007bf6@9163
5465+0000fbf6@9165
5466+0000fb1e@9167
5467+0000b91e@9168
5468+0000b99e@9169
5469+0000399e@9173
5470+0000299e@9174
5471+0000a91e@9175
5472+0000abde@9176
5473+0000abd2@9177
5474+00002b52@9182
5475+00002b50@9183
5476+0000abd0@9184
5477+0000ebf4@9186
5478+0000eb74@9190
5479+00006bf4@9191
5480+00006bd4@9192
5481+0000ebf4@9193
5482+0000fbf4@9196
5483+0000fb74@9197
5484+0000fb54@9198
5485+0000fbf4@9199
5486+00007bf6@9201
5487+0000fbf6@9203
5488+0000fbfe@9204
5489+0000f17a@9205
5490+0000b1fa@9206
5491+000031fa@9210
5492+0000a17a@9212
5493+0000a1fa@9213
5494+0000bf42@9214
5495+0000afc2@9215
5496+00002fc2@9219
5497+00002f40@9220
5498+0000afc0@9221
5499+0000afe0@9223
5500+0000efe4@9224
5501+0000ef64@9227
5502+00006fe4@9229
5503+0000efe4@9230
5504+0000ffe4@9233
5505+0000ff64@9234
5506+0000ff44@9235
5507+0000ffe4@9236
5508+00007fe6@9238
5509+0000ffe6@9240
5510+0000f346@9242
5511+0000b346@9243
5512+0000b3c6@9244
5513+000033c6@9247
5514+0000a346@9249
5515+0000abe2@9251
5516+00002b60@9257
5517+0000abe0@9258
5518+0000abe4@9260
5519+0000ebe4@9261
5520+0000eb64@9264
5521+00006be4@9266
5522+0000ebe4@9268
5523+0000fbe4@9270
5524+0000fb64@9272
5525+0000fbe4@9273
5526+00007be6@9275
5527+0000fbe6@9277
5528+0000ff1e@9279
5529+0000bf1e@9280
5530+0000bf9e@9281
5531+00003f9e@9285
5532+0000af9e@9286
5533+0000af1e@9287
5534+0000ab82@9288
5535+00002b02@9294
5536+00002b00@9295
5537+0000ab80@9296
5538+0000aba4@9297
5539+0000eba0@9298
5540+0000eba4@9299
5541+0000eb24@9301
5542+0000eb04@9302
5543+00006ba4@9303
5544+00006b84@9304
5545+0000eba4@9305
5546+0000eb84@9307
5547+0000fba4@9308
5548+0000fb24@9309
5549+0000fb04@9310
5550+0000fba4@9311
5551+00007ba6@9312
5552+0000fba6@9314
5553+0000ff3e@9316
5554+0000bfbe@9318
5555+00003fbe@9322
5556+0000af3e@9324
5557+0000afbe@9325
5558+0000ab02@9326
5559+0000ab82@9327
5560+00002b82@9331
5561+00002b00@9332
5562+0000ab80@9333
5563+0000eba4@9335
5564+0000eb24@9339
5565+00006ba4@9340
5566+0000eba4@9342
5567+0000fba4@9345
5568+0000fb24@9346
5569+0000fb04@9347
5570+0000fba4@9348
5571+00007ba6@9350
5572+0000fba6@9352
5573+0000fbbe@9353
5574+0000f91e@9354
5575+0000b99e@9355
5576+0000399e@9359
5577+0000a91e@9361
5578+0000a99e@9362
5579+0000ab42@9363
5580+0000abc2@9364
5581+00002bc2@9368
5582+00002b40@9369
5583+0000ab40@9370
5584+0000abc0@9371
5585+0000abe0@9372
5586+0000ebe4@9373
5587+0000eb64@9376
5588+00006be4@9378
5589+0000ebe4@9379
5590+0000fbe4@9382
5591+0000fb64@9383
5592+0000fb44@9384
5593+0000fbe4@9385
5594+00007be6@9387
5595+0000fbe6@9389
5596+0000f91e@9391
5597+0000f99e@9393
5598+0000799e@9396
5599+0000799c@9397
5600+0000f91c@9398
5601+0000fbc0@9400
5602+0000ebc0@9401
5603+0000fbc0@9402
5604+0000ebc0@9403
5605+00006b40@9406
5606+0000eb40@9407
5607+0000ebc0@9408
5608+0000ebe4@9409
5609+0000ebc4@9412
5610+0000eb64@9413
5611+0000eb44@9414
5612+00006be4@9415
5613+00006bc4@9416
5614+0000ebe4@9417
5615+0000fbc4@9419
5616+0000fbe4@9420
5617+0000fb44@9421
5618+0000fbe4@9422
5619+00007be6@9424
5620+0000fbe6@9426
5621+0000f91e@9428
5622+0000b99e@9430
5623+0000399e@9434
5624+0000a99e@9435
5625+0000a91e@9436
5626+0000abd2@9437
5627+00002b52@9443
5628+00002b50@9444
5629+0000abd0@9445
5630+0000abf4@9446
5631+0000ebf0@9447
5632+0000ebf4@9448
5633+0000ebd4@9449
5634+0000eb74@9450
5635+0000eb54@9451
5636+00006bf4@9452
5637+00006bd4@9453
5638+0000ebf4@9454
5639+0000ebd4@9456
5640+0000fbf4@9457
5641+0000fb54@9458
5642+0000fbf4@9460
5643+00007bf6@9461
5644+0000fbf6@9463
5645+0000fb1e@9465
5646+0000bb9e@9467
5647+00003b9e@9471
5648+00002b9e@9472
5649+0000ab1e@9473
5650+0000abfe@9474
5651+0000abe2@9475
5652+00002b62@9480
5653+00002b60@9481
5654+0000abe0@9482
5655+0000ebe4@9484
5656+0000eb64@9488
5657+00006be4@9489
5658+0000ebe4@9491
5659+0000fbe4@9494
5660+0000fb64@9495
5661+0000fbe4@9497
5662+00007be6@9499
5663+0000fbe6@9501
5664+0000fbfe@9502
5665+0000f17e@9503
5666+0000b1fe@9504
5667+000031fe@9508
5668+0000317e@9509
5669+0000a17e@9510
5670+0000a1fe@9511
5671+0000bf42@9512
5672+0000afc2@9513
5673+00002fc2@9517
5674+00002f40@9518
5675+0000afc0@9519
5676+0000afe0@9521
5677+0000efe4@9522
5678+0000ef64@9525
5679+00006fe4@9527
5680+0000efe4@9528
5681+0000ffe4@9531
5682+0000ff64@9532
5683+0000ffe4@9534
5684+00007fe6@9536
5685+0000ffe6@9538
5686+0000f346@9540
5687+0000b346@9541
5688+0000b3c6@9542
5689+000033c6@9545
5690+0000a346@9547
5691+0000abe2@9549
5692+00002b60@9555
5693+0000abe0@9556
5694+0000abe4@9558
5695+0000ebe4@9559
5696+0000eb64@9562
5697+00006be4@9564
5698+0000ebe4@9566
5699+0000fbe4@9568
5700+0000fb64@9570
5701+0000fbe4@9571
5702+00007be6@9573
5703+0000fbe6@9575
5704+0000ff1e@9577
5705+0000b71e@9578
5706+0000b79e@9579
5707+0000379e@9583
5708+0000a79e@9584
5709+0000a71e@9585
5710+0000a992@9586
5711+00002912@9592
5712+00002910@9593
5713+0000a990@9594
5714+0000abb4@9595
5715+0000ebb0@9596
5716+0000ebb4@9597
5717+0000eb94@9598
5718+0000eb34@9599
5719+0000eb14@9600
5720+00006bb4@9601
5721+00006b90@9602
5722+0000ebb4@9603
5723+0000eb94@9605
5724+0000fbb4@9606
5725+0000fb34@9607
5726+0000fb14@9608
5727+0000fbb4@9609
5728+00007bb6@9610
5729+0000fbb6@9612
5730+0000ff3e@9614
5731+0000f73e@9615
5732+0000b7be@9616
5733+000037be@9620
5734+0000a73e@9622
5735+0000afbe@9623
5736+0000a912@9624
5737+0000a992@9625
5738+00002992@9629
5739+00002910@9630
5740+0000a990@9631
5741+0000e9b4@9633
5742+0000ebb4@9634
5743+0000e9b4@9635
5744+0000ebb4@9636
5745+0000eb14@9637
5746+00006bb4@9638
5747+0000e9b4@9640
5748+0000ebb4@9641
5749+0000fbb4@9643
5750+0000fb34@9644
5751+0000fb14@9645
5752+0000fbb4@9646
5753+000079b6@9648
5754+00007bb6@9649
5755+0000fbb6@9650
5756+0000f922@9652
5757+0000b9a2@9653
5758+000039a2@9657
5759+0000a922@9659
5760+0000a9a2@9660
5761+0000abc2@9661
5762+00002bc2@9666
5763+00002b40@9667
5764+0000abc0@9668
5765+0000abe0@9670
5766+0000ebe4@9671
5767+0000eb64@9674
5768+00006be4@9676
5769+0000ebe4@9677
5770+0000fbe4@9680
5771+0000fb64@9681
5772+0000fb44@9682
5773+0000fbe4@9683
5774+00007be6@9685
5775+0000fbe6@9687
5776+0000f922@9689
5777+0000f9a2@9691
5778+000079a2@9694
5779+0000e922@9696
5780+0000ebc2@9698
5781+00006b40@9704
5782+0000eb40@9705
5783+0000ebc0@9706
5784+0000ebe4@9707
5785+0000ebe0@9708
5786+0000abe4@9709
5787+0000a9ec@9710
5788+0000a96c@9711
5789+0000a9ec@9712
5790+000029ec@9713
5791+0000a9ec@9715
5792+0000b9ec@9717
5793+0000b96c@9719
5794+0000b9ec@9720
5795+000039ee@9722
5796+000079ee@9723
5797+0000f9ee@9724
5798+0000fb3e@9726
5799+0000bb3e@9727
5800+0000bbbe@9728
5801+00003bbe@9732
5802+0000abbe@9733
5803+0000ab3e@9734
5804+0000abe2@9735
5805+00002b62@9741
5806+00002b60@9742
5807+0000abe0@9743
5808+0000abe4@9744
5809+0000ebe4@9745
5810+0000eb64@9748
5811+00006be4@9750
5812+0000ebe4@9752
5813+0000fbe4@9755
5814+0000fb64@9756
5815+0000fbe4@9758
5816+00007be6@9759
5817+0000fbe6@9761
5818+0000fb3e@9763
5819+0000b91e@9764
5820+0000b99e@9765
5821+0000399e@9769
5822+0000299e@9770
5823+0000a91e@9771
5824+0000abde@9772
5825+0000abd2@9773
5826+00002b52@9778
5827+00002b50@9779
5828+0000abd0@9780
5829+0000ebf4@9782
5830+0000eb54@9786
5831+00006bf4@9787
5832+00006bd4@9788
5833+0000ebf4@9789
5834+0000fbf4@9792
5835+0000fb74@9793
5836+0000fb54@9794
5837+0000fbf4@9795
5838+00007bf6@9797
5839+0000fbf6@9799
5840+0000f342@9801
5841+0000b3c2@9802
5842+000033c2@9806
5843+0000a342@9808
5844+0000a3c2@9809
5845+0000afc2@9810
5846+00002fc2@9815
5847+00002f40@9816
5848+0000afc0@9817
5849+0000efe4@9820
5850+0000efe0@9821
5851+0000efc4@9822
5852+0000ef64@9823
5853+0000ef44@9824
5854+00006fe4@9825
5855+0000efe4@9826
5856+0000ffe4@9829
5857+0000ff64@9830
5858+0000ff44@9831
5859+0000ffe4@9832
5860+00007fe6@9834
5861+0000ffe6@9836
5862+0000f346@9838
5863+0000b346@9839
5864+0000b3c6@9840
5865+000033c6@9843
5866+0000a346@9845
5867+0000abe2@9847
5868+00002b60@9853
5869+0000abe0@9854
5870+0000abe4@9856
5871+0000ebe4@9857
5872+0000eb64@9860
5873+00006be4@9862
5874+0000ebe4@9864
5875+0000fbe4@9866
5876+0000fb64@9868
5877+0000fbe4@9869
5878+00007be6@9871
5879+0000fbe6@9873
5880+0000ff1e@9875
5881+0000bf9e@9877
5882+00003f9e@9881
5883+0000af9e@9882
5884+0000af1e@9883
5885+0000aba2@9884
5886+00002b22@9890
5887+00002b20@9891
5888+0000aba0@9892
5889+0000aba4@9893
5890+0000eba4@9894
5891+0000eb24@9897
5892+00006ba4@9899
5893+0000eba4@9901
5894+0000fba4@9904
5895+0000fb24@9905
5896+0000fba4@9907
5897+00007ba6@9908
5898+0000fba6@9910
5899+0000ff3e@9912
5900+0000f53e@9913
5901+0000b5be@9914
5902+000035be@9918
5903+0000253e@9919
5904+0000a53e@9920
5905+0000a5be@9921
5906+0000a102@9922
5907+0000a182@9923
5908+00002182@9927
5909+00002100@9928
5910+0000a180@9929
5911+0000e1a4@9931
5912+0000e3a4@9932
5913+0000e1a4@9933
5914+0000e3a4@9934
5915+0000e304@9935
5916+000063a4@9936
5917+00006184@9937
5918+0000e1a4@9938
5919+0000e3a4@9939
5920+0000e184@9940
5921+0000f3a4@9941
5922+0000f324@9942
5923+0000f104@9943
5924+0000f3a4@9944
5925+000071a6@9946
5926+000073a6@9947
5927+0000f3a6@9948
5928+0000fba6@9949
5929+0000f926@9950
5930+0000b9a6@9951
5931+000039a6@9955
5932+0000a926@9957
5933+0000a9a6@9958
5934+0000abc2@9959
5935+00002bc2@9964
5936+00002b40@9965
5937+0000abc0@9966
5938+0000abe4@9968
5939+0000ebe4@9969
5940+0000eb64@9972
5941+00006be4@9974
5942+0000ebe4@9975
5943+0000fbe4@9978
5944+0000fb64@9979
5945+0000fb44@9980
5946+0000fbe4@9981
5947+00007be6@9983
5948+0000fbe6@9985
5949+0000f926@9987
5950+0000f9a6@9989
5951+000079a6@9992
5952+0000e926@9994
5953+0000ebc2@9996
5954+00006b40@10002
5955+0000eb40@10003
5956+0000ebc0@10004
5957+0000ebe4@10005
5958+0000abe4@10007
5959+0000a5e0@10008
5960+0000a560@10009
5961+0000a5e0@10010
5962+000025e0@10011
5963+0000a5e0@10013
5964+0000b5e0@10015
5965+0000b560@10017
5966+0000b5e0@10018
5967+000035e2@10020
5968+000075e2@10021
5969+0000f5e2@10022
5970+0000f91e@10024
5971+0000b91e@10025
5972+0000b99e@10026
5973+0000399e@10030
5974+0000a99e@10031
5975+0000a91e@10032
5976+0000abd2@10033
5977+00002b52@10039
5978+00002b50@10040
5979+0000abd0@10041
5980+0000abf4@10042
5981+0000ebf0@10043
5982+0000ebf4@10044
5983+0000ebd4@10045
5984+0000eb74@10046
5985+0000eb54@10047
5986+00006bf4@10048
5987+00006bd4@10049
5988+0000ebf4@10050
5989+0000ebd0@10052
5990+0000fbf4@10053
5991+0000fb74@10054
5992+0000fb54@10055
5993+0000fbf4@10056
5994+00007bf6@10057
5995+0000fbf6@10059
5996+0000fb1e@10061
5997+0000b91e@10062
5998+0000b99e@10063
5999+0000399e@10067
6000+0000299e@10068
6001+0000a91e@10069
6002+0000abde@10070
6003+0000abd2@10071
6004+00002b52@10076
6005+00002b50@10077
6006+0000abd0@10078
6007+0000ebf4@10080
6008+0000eb54@10084
6009+00006bf4@10085
6010+00006bd4@10086
6011+0000ebf4@10087
6012+0000fbf4@10090
6013+0000fb74@10091
6014+0000fb54@10092
6015+0000fbf4@10093
6016+00007bf6@10095
6017+0000fbf6@10097
6018+0000fbd6@10098
6019+0000f346@10099
6020+0000b3c6@10100
6021+000033c6@10104
6022+00003346@10105
6023+0000a346@10106
6024+0000a3c6@10107
6025+0000afc2@10108
6026+00002fc2@10113
6027+00002f40@10114
6028+0000afc0@10115
6029+0000afe4@10117
6030+0000efe4@10118
6031+0000efc4@10120
6032+0000ef64@10121
6033+00006fe4@10123
6034+0000efe4@10124
6035+0000ffe4@10127
6036+0000ff64@10128
6037+0000ff44@10129
6038+0000ffe4@10130
6039+00007fe6@10132
6040+0000ffe6@10134
6041+0000f346@10136
6042+0000b346@10137
6043+0000b3c6@10138
6044+000033c6@10141
6045+0000a346@10143
6046+0000abe2@10145
6047+00002b60@10151
6048+0000abe0@10152
6049+0000abe4@10154
6050+0000ebe4@10155
6051+0000eb64@10158
6052+00006be4@10160
6053+0000ebe4@10162
6054+0000fbe4@10164
6055+0000fb64@10166
6056+0000fbe4@10167
6057+00007be6@10169
6058+0000fbe6@10171
6059+0000fd3e@10173
6060+0000f53e@10174
6061+0000b5be@10175
6062+000035be@10179
6063+0000a5be@10180
6064+0000a53e@10181
6065+0000a582@10182
6066+0000a182@10183
6067+00002102@10188
6068+00002100@10189
6069+0000a180@10190
6070+0000a1a4@10191
6071+0000e3a0@10192
6072+0000e3a4@10193
6073+0000e384@10194
6074+0000e324@10195
6075+0000e304@10196
6076+000063a4@10197
6077+00006180@10198
6078+0000e3a4@10199
6079+0000e180@10201
6080+0000f3a4@10202
6081+0000f324@10203
6082+0000f104@10204
6083+0000f3a4@10205
6084+000073a6@10206
6085+000071a6@10207
6086+0000f3a6@10208
6087+0000f53e@10210
6088+0000b5be@10212
6089+000035be@10216
6090+0000a53e@10218
6091+0000a5be@10219
6092+0000a102@10220
6093+0000a182@10221
6094+00002182@10225
6095+00002100@10226
6096+0000a180@10227
6097+0000e1a4@10229
6098+0000e3a4@10230
6099+0000e1a4@10231
6100+0000e3a4@10232
6101+0000e324@10233
6102+000063a4@10234
6103+00006184@10235
6104+0000e1a4@10236
6105+0000e3a4@10237
6106+0000e1a4@10238
6107+0000f3a4@10239
6108+0000f324@10240
6109+0000f304@10241
6110+0000f3a4@10242
6111+000073a6@10244
6112+0000f3a6@10246
6113+0000fbae@10247
6114+0000f92a@10248
6115+0000b9aa@10249
6116+000039aa@10253
6117+0000a92a@10255
6118+0000a9aa@10256
6119+0000abc2@10257
6120+00002bc2@10262
6121+00002b40@10263
6122+0000abc0@10264
6123+0000abe4@10266
6124+0000ebe4@10267
6125+0000eb64@10270
6126+00006be4@10272
6127+0000ebe4@10273
6128+0000fbe4@10276
6129+0000fb64@10277
6130+0000fbe4@10279
6131+00007be6@10281
6132+0000fbe6@10283
6133+0000f92a@10285
6134+0000f9aa@10287
6135+000079aa@10290
6136+0000e92a@10292
6137+0000e9aa@10293
6138+0000ebc2@10294
6139+00006b40@10300
6140+0000eb40@10301
6141+0000ebc0@10302
6142+0000ebe4@10303
6143+0000abe4@10305
6144+0000a5e0@10306
6145+0000a560@10307
6146+0000a5e0@10308
6147+000025e0@10309
6148+0000a5e0@10311
6149+0000b5e0@10313
6150+0000b560@10315
6151+0000b5e0@10316
6152+000035e2@10318
6153+000075e2@10319
6154+0000f5e2@10320
6155+0000f91e@10322
6156+0000b91e@10323
6157+0000b99e@10324
6158+0000399e@10328
6159+0000a99e@10329
6160+0000a91e@10330
6161+0000abd2@10331
6162+00002b52@10337
6163+00002b50@10338
6164+0000abd0@10339
6165+0000abf4@10340
6166+0000ebf0@10341
6167+0000ebf4@10342
6168+0000ebd4@10343
6169+0000eb74@10344
6170+0000eb54@10345
6171+00006bf4@10346
6172+00006bd4@10347
6173+0000ebf4@10348
6174+0000ebd0@10350
6175+0000fbf4@10351
6176+0000fb54@10352
6177+0000fbf4@10354
6178+00007bf6@10355
6179+0000fbf6@10357
6180+0000fb1e@10359
6181+0000b91e@10360
6182+0000b99e@10361
6183+0000399e@10365
6184+0000299e@10366
6185+0000a91e@10367
6186+0000abde@10368
6187+0000abd2@10369
6188+00002b52@10374
6189+00002b50@10375
6190+0000abd0@10376
6191+0000ebf4@10378
6192+0000eb74@10382
6193+00006bf4@10383
6194+00006bd4@10384
6195+0000ebf4@10385
6196+0000fbf4@10388
6197+0000fb74@10389
6198+0000fb54@10390
6199+0000fbf4@10391
6200+00007bf6@10393
6201+0000fbf6@10394
6202+0000fbde@10396
6203+0000f34a@10397
6204+0000b3ca@10398
6205+000033ca@10402
6206+0000334a@10403
6207+0000a34a@10404
6208+0000a3ca@10405
6209+0000afc2@10406
6210+00002fc2@10411
6211+00002f40@10412
6212+0000afc0@10413
6213+0000afe0@10415
6214+0000efe4@10416
6215+0000ef64@10419
6216+0000ef44@10420
6217+00006fe4@10421
6218+0000efe4@10422
6219+0000ffe4@10425
6220+0000ff64@10426
6221+0000ff44@10427
6222+0000ffe4@10428
6223+00007fe6@10430
6224+0000ffe6@10432
6225+0000f346@10434
6226+0000b346@10435
6227+0000b3c6@10436
6228+000033c6@10439
6229+0000a346@10441
6230+0000abe2@10443
6231+00002b60@10449
6232+0000abe0@10450
6233+0000abe4@10452
6234+0000ebe4@10453
6235+0000eb64@10456
6236+00006be4@10458
6237+0000ebe4@10460
6238+0000fbe4@10462
6239+0000fb64@10464
6240+0000fbe4@10465
6241+00007be6@10467
6242+0000fbe6@10469
6243+0000f53e@10471
6244+0000b5be@10473
6245+000035be@10477
6246+0000a5be@10478
6247+0000a53e@10479
6248+0000a582@10480
6249+0000a182@10481
6250+00002102@10486
6251+00002100@10487
6252+0000a180@10488
6253+0000a3a4@10489
6254+0000e3a0@10490
6255+0000e1a4@10491
6256+0000e384@10492
6257+0000e324@10493
6258+0000e304@10494
6259+000063a4@10495
6260+00006180@10496
6261+0000e3a4@10497
6262+0000e180@10499
6263+0000f3a4@10500
6264+0000f304@10501
6265+0000f384@10502
6266+0000f3a4@10503
6267+000073a6@10504
6268+0000f3a6@10506
6269+0000f53e@10508
6270+0000b5be@10510
6271+000035be@10514
6272+0000a53e@10516
6273+0000a5be@10517
6274+0000a102@10518
6275+0000a182@10519
6276+00002182@10523
6277+00002100@10524
6278+0000a180@10525
6279+0000e1a4@10527
6280+0000e3a4@10528
6281+0000e1a4@10529
6282+0000e3a4@10530
6283+0000e304@10531
6284+000063a4@10532
6285+00006184@10533
6286+0000e1a4@10534
6287+0000e3a4@10535
6288+0000e184@10536
6289+0000f3a4@10537
6290+0000f324@10538
6291+0000f104@10539
6292+0000f3a4@10540
6293+000071a6@10542
6294+000073a6@10543
6295+0000f3a6@10544
6296+0000fbae@10545
6297+0000f92e@10546
6298+0000b9ae@10547
6299+000039ae@10551
6300+0000a92e@10553
6301+0000a9ae@10554
6302+0000ab42@10555
6303+0000abc2@10556
6304+00002bc2@10560
6305+00002b40@10561
6306+0000abc0@10562
6307+0000abe4@10564
6308+0000ebe4@10565
6309+0000eb64@10568
6310+00006be4@10570
6311+0000ebe4@10571
6312+0000fbe4@10574
6313+0000fb64@10575
6314+0000fb44@10576
6315+0000fbe4@10577
6316+00007be6@10579
6317+0000fbe6@10581
6318+0000f92e@10583
6319+0000f9ae@10585
6320+000079ae@10588
6321+000079ac@10589
6322+0000f92c@10590
6323+0000fbc0@10592
6324+0000ebc0@10594
6325+00006b40@10598
6326+0000eb40@10599
6327+0000ebc0@10600
6328+0000ebe4@10601
6329+0000eb64@10605
6330+0000eb44@10606
6331+00006be4@10607
6332+0000ebe4@10609
6333+0000fbe4@10611
6334+0000fb64@10613
6335+0000fbe4@10614
6336+00007be6@10616
6337+0000fbe6@10618
6338+0000f91e@10620
6339+0000b99e@10622
6340+0000399e@10626
6341+0000a99e@10627
6342+0000a91e@10628
6343+0000abd2@10629
6344+00002b52@10635
6345+00002b50@10636
6346+0000abd0@10637
6347+0000abf4@10638
6348+0000ebf0@10639
6349+0000ebf4@10640
6350+0000ebd4@10641
6351+0000eb74@10642
6352+0000eb54@10643
6353+00006bf4@10644
6354+0000ebf4@10646
6355+0000fbd4@10648
6356+0000fbf4@10649
6357+0000fb74@10650
6358+0000fb54@10651
6359+0000fbf4@10652
6360+00007bf6@10653
6361+0000fbf6@10655
6362+0000fb1e@10657
6363+0000b91e@10658
6364+0000b99e@10659
6365+0000399e@10663
6366+0000299e@10664
6367+0000a91e@10665
6368+0000abde@10666
6369+0000abd2@10667
6370+00002b52@10672
6371+00002b50@10673
6372+0000abd0@10674
6373+0000ebf4@10676
6374+0000ebd4@10678
6375+0000ebf4@10679
6376+0000eb54@10680
6377+00006bf4@10681
6378+00006bd4@10682
6379+0000ebf4@10683
6380+0000ebd4@10685
6381+0000fbf4@10686
6382+0000fb74@10687
6383+0000fb54@10688
6384+0000fbf4@10689
6385+00007bf6@10691
6386+0000fbf6@10692
6387+0000fbde@10694
6388+0000f34e@10695
6389+0000b3ce@10696
6390+000033ce@10700
6391+0000334e@10701
6392+0000a34e@10702
6393+0000a3ce@10703
6394+0000af42@10704
6395+0000afc2@10705
6396+00002fc2@10709
6397+00002f40@10710
6398+0000afc0@10711
6399+0000afe4@10713
6400+0000efe4@10714
6401+0000ef44@10717
6402+0000ef64@10718
6403+00006fe4@10719
6404+0000efe4@10720
6405+0000ffe4@10723
6406+0000ff64@10724
6407+0000ff44@10725
6408+0000ffe4@10726
6409+00007fe6@10728
6410+0000ffe6@10730
6411+0000f346@10732
6412+0000b346@10733
6413+0000b3c6@10734
6414+000033c6@10737
6415+0000a346@10739
6416+0000a3c6@10740
6417+0000ab62@10741
6418+0000abe2@10742
6419+00002b60@10747
6420+0000abe0@10748
6421+0000abe4@10750
6422+0000ebe4@10751
6423+0000eb64@10754
6424+00006be4@10756
6425+0000ebe4@10758
6426+0000fbe4@10760
6427+0000fb64@10762
6428+0000fbe4@10763
6429+00007be6@10765
6430+0000fbe6@10767
6431+0000f53e@10769
6432+0000b5be@10771
6433+000035be@10775
6434+0000a5be@10776
6435+0000a53e@10777
6436+0000a582@10778
6437+0000a182@10779
6438+00002102@10784
6439+00002100@10785
6440+0000a180@10786
6441+0000a3a4@10787
6442+0000e3a0@10788
6443+0000e3a4@10789
6444+0000e384@10790
6445+0000e324@10791
6446+0000e304@10792
6447+000063a4@10793
6448+00006184@10794
6449+0000e3a4@10795
6450+0000e184@10797
6451+0000f3a4@10798
6452+0000f324@10799
6453+0000f304@10800
6454+0000f3a4@10801
6455+000073a6@10802
6456+0000f3a6@10804
6457+0000f53e@10806
6458+0000b5be@10808
6459+000035be@10812
6460+0000a53e@10814
6461+0000a5be@10815
6462+0000a102@10816
6463+0000a182@10817
6464+00002182@10821
6465+00002100@10822
6466+0000a180@10823
6467+0000e1a4@10825
6468+0000e3a4@10826
6469+0000e1a4@10827
6470+0000e3a4@10828
6471+0000e304@10829
6472+000063a4@10830
6473+00006184@10831
6474+0000e1a4@10832
6475+0000e3a4@10833
6476+0000e184@10834
6477+0000f3a4@10835
6478+0000f324@10836
6479+0000f104@10837
6480+0000f3a4@10838
6481+000071a6@10840
6482+000073a6@10841
6483+0000f3a6@10842
6484+0000fbb6@10843
6485+0000f932@10844
6486+0000b9b2@10845
6487+000039b2@10849
6488+00003932@10850
6489+0000a932@10851
6490+0000a9b2@10852
6491+0000abc2@10853
6492+00002bc2@10858
6493+00002b40@10859
6494+0000abc0@10860
6495+0000abe4@10862
6496+0000ebe4@10863
6497+0000eb64@10866
6498+0000ebe4@10867
6499+00006be4@10868
6500+0000ebe4@10869
6501+0000fbe4@10872
6502+0000fb64@10873
6503+0000fb44@10874
6504+0000fbe4@10875
6505+00007be6@10877
6506+0000fbe6@10879
6507+0000f932@10881
6508+0000f9b2@10883
6509+000079b2@10886
6510+0000e932@10888
6511+0000e9b2@10889
6512+0000ebc2@10890
6513+00006b40@10896
6514+0000eb40@10897
6515+0000ebc0@10898
6516+0000ebe4@10899
6517+0000abe4@10901
6518+0000a5e0@10902
6519+0000a560@10903
6520+0000a5e0@10904
6521+000025e0@10905
6522+0000a5e0@10907
6523+0000b5e0@10909
6524+0000b560@10911
6525+0000b5e0@10912
6526+000035e2@10914
6527+000075e2@10915
6528+0000f5e2@10916
6529+0000f91e@10918
6530+0000b91e@10919
6531+0000b99e@10920
6532+0000399e@10924
6533+0000a99e@10925
6534+0000a91e@10926
6535+0000abd2@10927
6536+00002b52@10933
6537+00002b50@10934
6538+0000abd0@10935
6539+0000abf4@10936
6540+0000ebf0@10937
6541+0000ebf4@10938
6542+0000eb74@10940
6543+0000eb54@10941
6544+00006bf4@10942
6545+0000ebf4@10944
6546+0000ebd0@10946
6547+0000fbf4@10947
6548+0000fb74@10948
6549+0000fb54@10949
6550+0000fbf4@10950
6551+00007bf6@10951
6552+0000fbf6@10953
6553+0000fb1e@10955
6554+0000b91e@10956
6555+0000b99e@10957
6556+0000399e@10961
6557+0000299e@10962
6558+0000a91e@10963
6559+0000abde@10964
6560+0000abd2@10965
6561+00002b52@10970
6562+00002b50@10971
6563+0000abd0@10972
6564+0000ebf4@10974
6565+0000ebd4@10976
6566+0000eb54@10978
6567+00006bf4@10979
6568+00006bd4@10980
6569+0000ebf4@10981
6570+0000ebd0@10983
6571+0000fbf4@10984
6572+0000fb74@10985
6573+0000fb54@10986
6574+0000fbf4@10987
6575+00007bf6@10989
6576+0000fbf6@10990
6577+0000fbd6@10992
6578+0000f352@10993
6579+0000b3d2@10994
6580+000033d2@10998
6581+00003352@10999
6582+0000a352@11000
6583+0000a3d2@11001
6584+0000afc2@11002
6585+00002fc2@11007
6586+00002f40@11008
6587+0000afc0@11009
6588+0000afe4@11011
6589+0000efe4@11012
6590+0000efc4@11014
6591+0000ef64@11015
6592+0000ef44@11016
6593+00006fc4@11017
6594+0000efe4@11018
6595+0000ffe4@11021
6596+0000ff64@11022
6597+0000ff44@11023
6598+0000ffe4@11024
6599+00007fe6@11026
6600+0000ffe6@11028
6601+0000f346@11030
6602+0000b346@11031
6603+0000b3c6@11032
6604+000033c6@11035
6605+0000a346@11037
6606+0000abe2@11039
6607+00002b60@11045
6608+0000abe0@11046
6609+0000abe4@11048
6610+0000ebe4@11049
6611+0000eb64@11052
6612+00006be4@11054
6613+0000ebe4@11056
6614+0000fbe4@11058
6615+0000fb64@11060
6616+0000fbe4@11061
6617+00007be6@11063
6618+0000fbe6@11065
6619+0000f53e@11067
6620+0000b5be@11069
6621+000035be@11072
6622+0000a5be@11074
6623+0000a53e@11075
6624+0000a582@11076
6625+0000a182@11077
6626+00002102@11082
6627+00002100@11083
6628+0000a180@11084
6629+0000a3a4@11085
6630+0000e3a0@11086
6631+0000e3a4@11087
6632+0000e324@11089
6633+0000e304@11090
6634+000063a4@11091
6635+00006184@11092
6636+0000e3a4@11093
6637+0000e180@11095
6638+0000f3a4@11096
6639+0000f324@11097
6640+0000f304@11098
6641+0000f3a4@11099
6642+000073a6@11100
6643+0000f3a6@11102
6644+0000f53e@11104
6645+0000b5be@11106
6646+000035be@11110
6647+0000a53e@11112
6648+0000a5be@11113
6649+0000a102@11114
6650+0000a182@11115
6651+00002182@11119
6652+00002100@11120
6653+0000a180@11121
6654+0000e1a4@11123
6655+0000e3a4@11124
6656+0000e1a4@11125
6657+0000e3a4@11126
6658+0000e304@11127
6659+000063a4@11128
6660+00006184@11129
6661+0000e1a4@11130
6662+0000e3a4@11131
6663+0000e184@11132
6664+0000f3a4@11133
6665+0000f324@11134
6666+0000f304@11135
6667+0000f3a4@11136
6668+000073a6@11138
6669+0000f3a6@11140
6670+0000fbb6@11141
6671+0000f936@11142
6672+0000b9b6@11143
6673+000039b6@11147
6674+00003936@11148
6675+0000a936@11149
6676+0000a9b6@11150
6677+0000ab42@11151
6678+0000abc2@11152
6679+00002bc2@11156
6680+00002b40@11157
6681+0000abc0@11158
6682+0000abe4@11160
6683+0000ebe4@11161
6684+0000eb64@11164
6685+00006be4@11166
6686+0000ebe4@11167
6687+0000fbe4@11170
6688+0000fb64@11171
6689+0000fb44@11172
6690+0000fbe4@11173
6691+00007be6@11175
6692+0000fbe6@11177
6693+0000f936@11179
6694+0000f9b6@11181
6695+000079b6@11184
6696+0000e936@11186
6697+0000ebc2@11188
6698+00006b40@11194
6699+0000eb40@11195
6700+0000ebc0@11196
6701+0000ebe4@11197
6702+0000abe4@11199
6703+0000a5e0@11200
6704+0000a560@11201
6705+0000a5e0@11202
6706+000025e0@11203
6707+0000a5e0@11205
6708+0000b5e0@11207
6709+0000b560@11209
6710+0000b5e0@11211
6711+000035e2@11212
6712+000075e2@11213
6713+0000f5e2@11214
6714+0000f91e@11216
6715+0000b91e@11217
6716+0000b99e@11218
6717+0000399e@11221
6718+0000a99e@11223
6719+0000a91e@11224
6720+0000abd2@11225
6721+00002b52@11231
6722+00002b50@11232
6723+0000abd0@11233
6724+0000abf4@11234
6725+0000ebf0@11235
6726+0000ebf4@11236
6727+0000ebd4@11237
6728+0000eb74@11238
6729+0000eb54@11239
6730+00006bf4@11240
6731+00006bd4@11241
6732+0000ebf4@11242
6733+0000ebd0@11244
6734+0000fbf4@11245
6735+0000fb54@11246
6736+0000fbd4@11247
6737+0000fbf4@11248
6738+00007bf6@11249
6739+0000fbf6@11251
6740+0000fb3e@11253
6741+0000f33e@11254
6742+0000b3be@11255
6743+000033be@11259
6744+000023be@11260
6745+0000a33e@11261
6746+0000abfe@11262
6747+0000abd2@11263
6748+00002b52@11268
6749+00002b50@11269
6750+0000abd0@11270
6751+0000ebf4@11272
6752+0000eb74@11276
6753+00006bf4@11277
6754+00006bd4@11278
6755+0000ebf4@11279
6756+0000fbf4@11282
6757+0000fb74@11283
6758+0000fb54@11284
6759+0000fbf4@11285
6760+00007bf6@11287
6761+0000fbf6@11288
6762+0000fbd6@11290
6763+0000f356@11291
6764+0000b3d6@11292
6765+000033d6@11296
6766+00003356@11297
6767+0000a356@11298
6768+0000a3d6@11299
6769+0000af42@11300
6770+0000afc2@11301
6771+00002fc2@11305
6772+00002f40@11306
6773+0000afc0@11307
6774+0000afe4@11309
6775+0000efe4@11310
6776+0000efc4@11312
6777+0000ef64@11313
6778+00006fc4@11315
6779+0000efe4@11316
6780+0000ffe4@11319
6781+0000ff64@11320
6782+0000ff44@11321
6783+0000ffe4@11322
6784+00007fe6@11324
6785+0000ffe6@11326
6786+0000f346@11328
6787+0000b346@11329
6788+0000b3c6@11330
6789+000033c6@11333
6790+0000a346@11335
6791+0000abe2@11337
6792+00002b60@11343
6793+0000abe0@11344
6794+0000abe4@11346
6795+0000ebe4@11347
6796+0000eb64@11350
6797+00006be4@11352
6798+0000ebe4@11354
6799+0000fbe4@11356
6800+0000fb64@11358
6801+0000fbe4@11359
6802+00007be6@11361
6803+0000fbe6@11363
6804+0000fd3e@11365
6805+0000f53e@11366
6806+0000b5be@11367
6807+000035be@11370
6808+0000a5be@11372
6809+0000a53e@11373
6810+0000a582@11374
6811+0000a182@11375
6812+00002102@11380
6813+00002100@11381
6814+0000a180@11382
6815+0000a3a4@11383
6816+0000e3a0@11384
6817+0000e3a4@11385
6818+0000e324@11387
6819+0000e304@11388
6820+000063a4@11389
6821+00006184@11390
6822+0000e3a4@11391
6823+0000f184@11393
6824+0000f3a4@11394
6825+0000f324@11395
6826+0000f304@11396
6827+0000f3a4@11397
6828+000073a6@11398
6829+0000f3a6@11400
6830+0000f53e@11402
6831+0000b5be@11404
6832+000035be@11408
6833+0000a53e@11410
6834+0000a5be@11411
6835+0000a102@11412
6836+0000a182@11413
6837+00002182@11417
6838+00002100@11418
6839+0000a180@11419
6840+0000e1a4@11421
6841+0000e3a4@11422
6842+0000e1a4@11423
6843+0000e3a4@11424
6844+0000e324@11425
6845+000063a4@11426
6846+00006184@11427
6847+0000e1a4@11428
6848+0000e3a4@11429
6849+0000f3a4@11431
6850+0000f324@11432
6851+0000f304@11433
6852+0000f3a4@11434
6853+000071a6@11436
6854+0000f3a6@11437
6855+0000fb3e@11439
6856+0000f93a@11440
6857+0000b9ba@11441
6858+000039ba@11445
6859+0000393a@11446
6860+0000a93a@11447
6861+0000a9ba@11448
6862+0000ab42@11449
6863+0000abc2@11450
6864+00002bc2@11454
6865+00002b40@11455
6866+0000abc0@11456
6867+0000abe4@11458
6868+0000ebe4@11459
6869+0000eb64@11462
6870+00006be4@11464
6871+0000ebe4@11465
6872+0000fbe4@11468
6873+0000fb64@11469
6874+0000fb44@11470
6875+0000fbe4@11471
6876+00007be6@11473
6877+0000fbe6@11475
6878+0000f93a@11477
6879+0000f9ba@11479
6880+000079ba@11482
6881+0000e93a@11484
6882+0000e9ba@11485
6883+0000eb42@11486
6884+0000ebc2@11487
6885+00006b40@11492
6886+0000ebc0@11493
6887+0000ebe4@11495
6888+0000abe4@11497
6889+0000a3a4@11498
6890+0000a324@11499
6891+000023a4@11501
6892+0000a3a4@11503
6893+0000b3a4@11505
6894+0000b324@11507
6895+0000b3a4@11508
6896+000033a6@11510
6897+000073a6@11511
6898+0000f3a6@11512
6899+0000f97e@11514
6900+0000b9fe@11516
6901+000039fe@11519
6902+0000a97e@11521
6903+0000a982@11523
6904+0000a182@11524
6905+00002102@11529
6906+00002180@11530
6907+0000a180@11531
6908+0000a3a4@11532
6909+0000e3a0@11533
6910+0000e3a4@11534
6911+0000e384@11535
6912+0000e324@11536
6913+0000e304@11537
6914+000063a4@11538
6915+00006184@11539
6916+0000e3a4@11540
6917+0000f184@11542
6918+0000f3a4@11543
6919+0000f304@11544
6920+0000f3a4@11545
6921+000073a6@11547
6922+0000f3a6@11549
6923+0000f11e@11551
6924+0000b19e@11553
6925+0000319e@11557
6926+0000211e@11558
6927+0000a11e@11559
6928+0000a19e@11560
6929+0000a182@11561
6930+00002102@11566
6931+00002100@11567
6932+0000a180@11568
6933+0000e1a4@11570
6934+0000e3a4@11571
6935+0000e184@11572
6936+0000e384@11573
6937+0000e304@11574
6938+000063a4@11575
6939+00006184@11576
6940+0000e1a4@11577
6941+0000e3a4@11578
6942+0000e184@11579
6943+0000f3a4@11580
6944+0000f324@11581
6945+0000f104@11582
6946+0000f3a4@11583
6947+000071a6@11585
6948+0000f3a6@11586
6949+0000f3da@11588
6950+0000f35a@11589
6951+0000b3da@11590
6952+000033da@11594
6953+0000335a@11595
6954+0000a35a@11596
6955+0000a3da@11597
6956+0000af42@11598
6957+0000afc2@11599
6958+00002fc2@11603
6959+00002f40@11604
6960+0000af40@11605
6961+0000afc0@11606
6962+0000afe4@11607
6963+0000efe4@11608
6964+0000ef64@11611
6965+00006fe4@11613
6966+0000efe4@11614
6967+0000ffe4@11617
6968+0000ff64@11618
6969+0000ff44@11619
6970+0000ffe4@11620
6971+00007fe6@11622
6972+0000ffe6@11624
6973+0000f346@11626
6974+0000b346@11627
6975+0000b3c6@11628
6976+000033c6@11631
6977+00003346@11632
6978+0000a346@11633
6979+0000abe2@11635
6980+00002b60@11641
6981+0000abe0@11642
6982+0000abe4@11644
6983+0000ebe4@11645
6984+0000eb64@11648
6985+00006be4@11650
6986+0000ebe4@11652
6987+0000fbe4@11654
6988+0000fb64@11656
6989+0000fbe4@11657
6990+00007be6@11659
6991+0000fbe6@11661
6992+0000f53e@11663
6993+0000b5be@11665
6994+000035be@11668
6995+0000a5be@11670
6996+0000a53e@11671
6997+0000a582@11672
6998+0000a182@11673
6999+00002102@11678
7000+00002100@11679
7001+0000a180@11680
7002+0000a3a4@11681
7003+0000e3a0@11682
7004+0000e3a4@11683
7005+0000e384@11684
7006+0000e324@11685
7007+0000e304@11686
7008+000063a4@11687
7009+000061a4@11688
7010+0000e3a4@11689
7011+0000f184@11691
7012+0000f3a4@11692
7013+0000f324@11693
7014+0000f304@11694
7015+0000f3a4@11695
7016+000073a6@11696
7017+0000f3a6@11698
7018+0000f53e@11700
7019+0000b5be@11702
7020+000035be@11706
7021+0000a53e@11708
7022+0000a5be@11709
7023+0000a102@11710
7024+0000a182@11711
7025+00002182@11715
7026+00002100@11716
7027+0000a180@11717
7028+0000e1a4@11719
7029+0000e3a4@11720
7030+0000e1a4@11721
7031+0000e3a4@11722
7032+0000e304@11723
7033+000063a4@11724
7034+00006184@11725
7035+0000e1a4@11726
7036+0000e3a4@11727
7037+0000e184@11728
7038+0000f3a4@11729
7039+0000f324@11730
7040+0000f104@11731
7041+0000f3a4@11732
7042+000071a6@11734
7043+0000f3a6@11735
7044+0000fb3e@11737
7045+0000f93e@11738
7046+0000b9be@11739
7047+000039be@11743
7048+0000393e@11744
7049+0000a93e@11745
7050+0000a9be@11746
7051+0000ab42@11747
7052+0000abc2@11748
7053+00002bc2@11752
7054+00002b40@11753
7055+0000abc0@11754
7056+0000abe4@11756
7057+0000ebe4@11757
7058+0000ebc4@11759
7059+0000eb64@11760
7060+00006be4@11762
7061+0000ebe4@11763
7062+0000fbe4@11766
7063+0000fb64@11767
7064+0000fb44@11768
7065+0000fbe4@11769
7066+00007be6@11771
7067+0000fbe6@11773
7068+0000f93e@11775
7069+0000f9be@11777
7070+000079be@11780
7071+000079bc@11781
7072+0000f93c@11782
7073+0000fbc0@11784
7074+0000ebc0@11785
7075+0000fbc0@11786
7076+0000ebc0@11787
7077+00006b40@11790
7078+0000eb40@11791
7079+0000ebc0@11792
7080+0000ebe4@11793
7081+0000ebc4@11796
7082+0000eb64@11797
7083+0000eb44@11798
7084+00006be4@11799
7085+0000ebe4@11801
7086+0000fbe4@11803
7087+0000fb64@11805
7088+0000fbe4@11806
7089+00007be6@11808
7090+0000fbe6@11810
7091+0000f11e@11812
7092+0000b19e@11814
7093+0000319e@11817
7094+0000a19e@11819
7095+0000a11e@11820
7096+0000a182@11821
7097+00002102@11827
7098+00002100@11828
7099+0000a180@11829
7100+0000a3a4@11830
7101+0000e3a0@11831
7102+0000e3a4@11832
7103+0000e184@11833
7104+0000e324@11834
7105+0000e304@11835
7106+000063a4@11836
7107+00006184@11837
7108+0000e3a4@11838
7109+0000f180@11840
7110+0000f3a4@11841
7111+0000f304@11842
7112+0000f3a4@11844
7113+000073a6@11845
7114+0000f3a6@11847
7115+0000f11e@11849
7116+0000b19e@11851
7117+0000319e@11855
7118+0000a19e@11856
7119+0000a11e@11857
7120+0000a19e@11858
7121+0000a182@11859
7122+00002102@11864
7123+00002100@11865
7124+0000a180@11866
7125+0000e3a4@11868
7126+0000e184@11870
7127+0000e3a4@11871
7128+0000e304@11872
7129+000063a4@11873
7130+00006184@11874
7131+0000e1a4@11875
7132+0000e3a4@11876
7133+0000e184@11877
7134+0000f3a4@11878
7135+0000f324@11879
7136+0000f304@11880
7137+0000f3a4@11881
7138+000071a6@11883
7139+0000f3a6@11884
7140+0000f3de@11886
7141+0000b3de@11888
7142+000033de@11892
7143+0000a35e@11894
7144+0000a3de@11895
7145+0000af42@11896
7146+0000afc2@11897
7147+00002fc2@11901
7148+00002f40@11902
7149+0000afc0@11903
7150+0000afe4@11905
7151+0000efe4@11906
7152+0000efc4@11908
7153+0000ef64@11909
7154+00006fe4@11911
7155+0000efe4@11912
7156+0000ffe4@11915
7157+0000ff64@11916
7158+0000ff44@11917
7159+0000ffe4@11918
7160+00007fe6@11920
7161+0000ffe6@11922
7162+0000f346@11924
7163+0000b3c6@11925
7164+000033c6@11929
7165+0000a346@11931
7166+0000abe2@11933
7167+00002b60@11939
7168+0000abe0@11940
7169+0000abe4@11942
7170+0000ebe4@11943
7171+0000eb64@11946
7172+00006be4@11948
7173+0000ebe4@11950
7174+0000fbe4@11952
7175+0000fb64@11954
7176+0000fbe4@11955
7177+00007be6@11957
7178+0000fbe6@11959
7179+0000f91e@11961
7180+0000b91e@11962
7181+0000b99e@11963
7182+0000399e@11966
7183+0000a99e@11968
7184+0000a91e@11969
7185+0000afa2@11970
7186+0000a7a2@11971
7187+00002722@11976
7188+00002720@11977
7189+0000a7a0@11978
7190+0000a7a4@11979
7191+0000e7a0@11980
7192+0000e7a4@11981
7193+0000e724@11983
7194+000067a4@11985
7195+0000e7a4@11987
7196+0000f7a4@11989
7197+0000f724@11991
7198+0000f7a4@11993
7199+000077a6@11994
7200+0000f7a6@11996
7201+0000f93e@11998
7202+0000b9be@12000
7203+000039be@12004
7204+0000293e@12005
7205+0000a93e@12006
7206+0000afbe@12007
7207+0000a7a2@12008
7208+00002722@12013
7209+00002720@12014
7210+0000a7a0@12015
7211+0000e7a4@12017
7212+0000e724@12021
7213+000067a4@12022
7214+0000e7a4@12024
7215+0000f7a4@12027
7216+0000f724@12028
7217+0000f7a4@12030
7218+000077a6@12032
7219+0000f7a6@12033
7220+0000ff3e@12035
7221+0000f93e@12036
7222+0000f9be@12037
7223+000079be@12041
7224+0000e93e@12043
7225+0000e9be@12044
7226+0000e722@12045
7227+0000e7a2@12046
7228+000067a2@12050
7229+00006720@12051
7230+0000e7a0@12052
7231+0000e7a4@12054
7232+0000a7a4@12056
7233+0000a5fe@12057
7234+0000a56c@12058
7235+0000a5ec@12059
7236+000025ec@12060
7237+0000a5ec@12061
7238+0000b5ec@12064
7239+0000b56c@12065
7240+0000b5ec@12067
7241+000035ee@12069
7242+000075ee@12070
7243+0000f5ee@12071
7244+0000f93e@12073
7245+0000f9be@12075
7246+000079be@12078
7247+0000e93e@12080
7248+0000ef22@12082
7249+0000e7a2@12083
7250+00006720@12088
7251+0000e7a0@12089
7252+0000e7a4@12091
7253+0000a7a4@12093
7254+0000a5ec@12094
7255+0000a56c@12095
7256+0000a5ec@12096
7257+000025ec@12097
7258+0000a5ec@12099
7259+0000b5ec@12101
7260+0000b56c@12102
7261+0000b5ec@12104
7262+000035ee@12106
7263+000075ee@12107
7264+0000f5ee@12108
7265+0000f11e@12110
7266+0000b11e@12111
7267+0000b19e@12112
7268+0000319e@12115
7269+0000a19e@12117
7270+0000a11e@12118
7271+0000a9d2@12119
7272+00002952@12125
7273+00002950@12126
7274+0000a9d0@12127
7275+0000abf4@12128
7276+0000ebf0@12129
7277+0000ebf4@12130
7278+0000ebd4@12131
7279+0000eb74@12132
7280+0000e950@12133
7281+00006bf4@12134
7282+000069d0@12135
7283+0000ebf4@12136
7284+0000e9d0@12138
7285+0000fbf4@12139
7286+0000fb54@12140
7287+0000f9d4@12141
7288+0000fbf4@12142
7289+00007bf6@12143
7290+000079f6@12144
7291+0000fbf6@12145
7292+0000fb1e@12147
7293+0000b31e@12148
7294+0000b39e@12149
7295+0000339e@12153
7296+0000a39e@12154
7297+0000a31e@12155
7298+0000abda@12156
7299+0000a9d2@12157
7300+00002952@12162
7301+00002950@12163
7302+0000a9d0@12164
7303+0000ebf4@12166
7304+0000e9d4@12168
7305+0000ebf4@12169
7306+0000eb54@12170
7307+00006bf4@12171
7308+000069d4@12172
7309+0000e9f4@12173
7310+0000ebf4@12174
7311+0000e9d4@12175
7312+0000fbf4@12176
7313+0000fb74@12177
7314+0000fb54@12178
7315+0000fbf4@12179
7316+000079f6@12181
7317+0000fbf6@12182
7318+0000ff5e@12184
7319+0000f51e@12185
7320+0000b59e@12186
7321+0000359e@12190
7322+0000a51e@12192
7323+0000a59e@12193
7324+0000a9d2@12194
7325+000029d2@12199
7326+00002950@12200
7327+0000a950@12201
7328+0000a9d0@12202
7329+0000a9d4@12203
7330+0000ebf4@12204
7331+0000e9d4@12205
7332+0000ebf4@12206
7333+0000eb54@12207
7334+000069f4@12209
7335+0000e9f4@12210
7336+0000ebf4@12211
7337+0000fbf4@12213
7338+0000fb74@12214
7339+0000f954@12215
7340+0000fbf4@12216
7341+00007bf6@12218
7342+0000fbf6@12220
7343+0000f71e@12222
7344+0000b71e@12223
7345+0000b79e@12224
7346+0000379e@12227
7347+0000a71e@12229
7348+0000a79e@12230
7349+0000a9d2@12231
7350+00002950@12237
7351+0000a9d0@12238
7352+0000abf4@12240
7353+0000ebf4@12241
7354+0000ebd4@12243
7355+0000eb74@12244
7356+0000eb54@12245
7357+00006bf4@12246
7358+0000ebf4@12248
7359+0000fbd4@12250
7360+0000fbf4@12251
7361+0000fb54@12252
7362+0000fbd4@12253
7363+0000fbf4@12254
7364+00007bf6@12255
7365+0000fbf6@12257
7366+0000f91e@12259
7367+0000b91e@12260
7368+0000b99e@12261
7369+0000399e@12264
7370+0000a99e@12266
7371+0000a91e@12267
7372+0000adf2@12268
7373+0000a5f2@12269
7374+00002572@12274
7375+00002570@12275
7376+0000a5f0@12276
7377+0000a7f4@12277
7378+0000e7f0@12278
7379+0000e7f4@12279
7380+0000e774@12281
7381+000067f4@12283
7382+000065f4@12284
7383+0000e7f4@12285
7384+0000e7f4@12288
+10211, -0
    1@@ -0,0 +1,10211 @@
    2+;Size: 10203
    3+;Rate: 50000000
    4+;Channels: 16
    5+;EnabledChannels: 65535
    6+;TriggerPosition: 119
    7+;Compressed: true
    8+;AbsoluteLength: 12287
    9+;CursorEnabled: true
   10+000065f4@0
   11+0000e7f4@1
   12+0000f7f4@2
   13+0000f574@3
   14+0000f7f4@4
   15+000077f6@5
   16+0000f7fe@6
   17+0000f99e@7
   18+0000799e@9
   19+0000e91e@10
   20+0000e5f2@11
   21+00006570@14
   22+0000e5f0@15
   23+0000e7f4@16
   24+0000a180@17
   25+0000a100@18
   26+00002180@19
   27+0000a180@20
   28+0000b180@21
   29+00003182@23
   30+0000f182@24
   31+0000f93e@25
   32+0000b9be@26
   33+000039be@28
   34+0000a93e@29
   35+0000a5f2@30
   36+00002570@33
   37+0000a7f4@34
   38+0000e7f4@35
   39+0000e774@36
   40+000067f4@37
   41+0000e7f4@38
   42+0000f5f4@39
   43+0000f774@40
   44+0000f7f4@41
   45+000077f6@42
   46+0000f7f6@43
   47+0000bb1e@44
   48+0000bb9e@45
   49+0000ab9e@47
   50+0000aff2@48
   51+0000a5f2@49
   52+00002572@51
   53+0000a5f0@52
   54+0000e7f4@53
   55+0000e5f4@54
   56+0000e774@55
   57+000067f4@56
   58+0000e7f4@57
   59+0000f7f4@58
   60+0000f774@59
   61+0000f7f4@60
   62+0000f7f6@61
   63+0000fd7e@62
   64+0000b99a@63
   65+0000399a@65
   66+0000a91a@66
   67+0000a5f2@67
   68+00002570@70
   69+0000a5f0@71
   70+0000e7f4@72
   71+000067f4@74
   72+0000e5f4@75
   73+0000e7f4@76
   74+0000f774@77
   75+0000f7f4@78
   76+000077f6@79
   77+0000f7f6@80
   78+0000f93a@81
   79+0000b9ba@82
   80+000039ba@84
   81+0000a9ba@85
   82+0000a5f2@86
   83+000025f2@88
   84+0000a570@89
   85+0000a7f0@90
   86+0000e7f4@91
   87+0000e774@92
   88+000065f4@93
   89+0000e7f4@94
   90+0000f7f4@95
   91+0000f774@96
   92+0000f7f4@97
   93+000077f6@98
   94+0000f7f6@99
   95+0000bb1a@100
   96+0000bb9a@101
   97+00003b9a@102
   98+0000ab9a@103
   99+0000a5f2@104
  100+00002572@107
  101+0000a5f0@108
  102+0000e7f0@109
  103+0000e7f4@110
  104+0000e774@111
  105+000067f4@112
  106+0000e7f4@113
  107+0000f7f4@114
  108+000077f6@116
  109+0000f7f6@117
  110+0000fd1e@118
  111+0000b89a@119
  112+0000389a@121
  113+0000a81a@122
  114+0000a4f2@123
  115+00002470@126
  116+0000a474@127
  117+0000e6f4@128
  118+000066f4@130
  119+0000e474@131
  120+0000f6f4@133
  121+00007476@135
  122+0000f676@136
  123+0000f8ba@137
  124+0000b8ba@138
  125+0000383a@140
  126+0000a8fa@141
  127+0000a4f2@142
  128+000024f2@144
  129+0000a470@145
  130+0000e474@146
  131+0000e6f4@147
  132+00006470@149
  133+0000e674@150
  134+0000f6f4@151
  135+00007676@154
  136+0000f67e@155
  137+0000ba9a@156
  138+00003a9a@158
  139+0000aa1a@159
  140+0000a4f2@160
  141+00002470@163
  142+0000a470@164
  143+0000e6f4@165
  144+00006474@168
  145+0000e674@169
  146+0000f6f4@170
  147+00007676@172
  148+0000f676@173
  149+0000f29a@174
  150+0000b29a@175
  151+0000321a@177
  152+0000a21a@178
  153+0000a4f2@179
  154+00002470@182
  155+0000a674@183
  156+0000e6f4@184
  157+00006674@186
  158+0000e674@187
  159+0000f474@188
  160+0000f6f4@189
  161+00007676@191
  162+0000f676@192
  163+0000b29a@193
  164+0000a29a@196
  165+0000a6f2@197
  166+0000a4f2@198
  167+0000a472@199
  168+000024f2@200
  169+0000a4f0@201
  170+0000e6f4@202
  171+0000e474@203
  172+0000e674@204
  173+000064f0@205
  174+0000e6f4@206
  175+0000f6f4@207
  176+0000f674@208
  177+0000f6f6@210
  178+0000f6fe@211
  179+0000b21a@212
  180+0000329a@214
  181+0000a29a@215
  182+0000a4f2@216
  183+0000a472@217
  184+000024f0@219
  185+0000a4f0@220
  186+0000e6f4@221
  187+0000e474@222
  188+00006674@223
  189+0000e6f4@224
  190+0000f674@226
  191+000076f6@228
  192+0000f6f6@229
  193+0000f2ae@230
  194+0000b22e@231
  195+000032ae@233
  196+0000a2ae@234
  197+0000a082@235
  198+0000a002@236
  199+00002002@237
  200+0000a080@238
  201+0000a2a0@239
  202+0000e2a4@240
  203+0000e224@241
  204+000060a4@242
  205+0000e2a4@243
  206+0000f2a4@244
  207+0000f224@245
  208+0000f204@246
  209+000072a6@247
  210+0000f2a6@248
  211+0000f2ae@249
  212+0000f22e@250
  213+0000722e@251
  214+0000e2ae@252
  215+0000e082@253
  216+0000e002@254
  217+00006082@256
  218+0000e080@257
  219+0000e280@258
  220+0000a60c@259
  221+0000268c@261
  222+0000a68c@262
  223+0000b68c@263
  224+0000b60c@264
  225+0000360e@265
  226+0000f68e@266
  227+0000f492@267
  228+0000b412@268
  229+00003492@270
  230+0000a492@271
  231+0000aaf2@272
  232+0000aa72@273
  233+0000aaf2@274
  234+00002af0@275
  235+0000aaf4@276
  236+0000eaf4@277
  237+00006af4@279
  238+0000ea74@280
  239+0000fa74@282
  240+0000faf4@283
  241+00007af6@284
  242+0000fa76@285
  243+0000b426@286
  244+0000b4a6@287
  245+000034a6@289
  246+0000a476@290
  247+0000a472@291
  248+0000a4f2@292
  249+000024f2@293
  250+0000a470@294
  251+0000e474@295
  252+0000e6f4@296
  253+000064f4@298
  254+0000e674@299
  255+0000f674@300
  256+0000f6f4@301
  257+000076f6@303
  258+0000f676@304
  259+0000b606@305
  260+0000b686@306
  261+00003686@307
  262+0000a606@308
  263+0000a472@309
  264+0000a4f2@310
  265+000024f0@312
  266+0000a470@313
  267+0000e674@314
  268+0000e6f4@315
  269+000066f4@317
  270+0000e674@318
  271+0000f6f4@319
  272+000076f6@321
  273+0000f676@322
  274+0000f626@323
  275+0000b6a6@324
  276+000036a6@326
  277+0000a626@327
  278+0000a472@328
  279+0000a4f2@329
  280+000024f0@331
  281+0000a674@332
  282+0000e674@333
  283+0000e6f4@334
  284+000066f4@335
  285+0000e674@336
  286+0000f674@337
  287+0000f6f4@338
  288+000076f6@340
  289+0000f676@341
  290+0000b226@342
  291+0000b2a6@343
  292+0000a2a6@345
  293+0000a226@346
  294+0000a082@347
  295+00002082@349
  296+0000a000@350
  297+0000e2a4@351
  298+00006000@354
  299+0000e2a4@355
  300+0000f2a4@356
  301+0000f224@358
  302+0000f226@359
  303+0000f8be@360
  304+0000b9be@361
  305+0000393e@363
  306+0000a9be@364
  307+0000abc2@365
  308+0000ab42@367
  309+00002b40@368
  310+0000abc0@369
  311+0000ebe4@370
  312+00006b64@372
  313+0000eb64@373
  314+0000ebe4@374
  315+0000fbe4@375
  316+0000fb64@376
  317+00007b66@377
  318+0000fbe6@378
  319+0000f3a6@379
  320+0000b3a6@380
  321+0000b326@381
  322+00003326@382
  323+0000a3a6@383
  324+0000a182@384
  325+00002102@386
  326+0000a100@387
  327+0000a3a0@388
  328+0000e3a4@389
  329+0000e324@390
  330+00006104@391
  331+0000e3a4@392
  332+0000f3a4@393
  333+0000f324@395
  334+00007306@396
  335+0000f3a6@397
  336+0000b192@398
  337+00003112@400
  338+0000a112@401
  339+0000a182@402
  340+0000a102@404
  341+00002102@405
  342+0000a180@406
  343+0000e380@407
  344+0000e384@408
  345+0000e304@409
  346+00006100@410
  347+0000e3a4@411
  348+0000f3a4@412
  349+00007306@414
  350+0000f1a6@415
  351+0000f192@416
  352+0000b192@417
  353+0000b112@418
  354+00003112@419
  355+0000a192@420
  356+0000a182@421
  357+0000a102@423
  358+00002100@424
  359+0000a184@425
  360+0000e3a4@426
  361+000063a4@428
  362+0000e3a4@429
  363+0000e180@430
  364+0000f324@431
  365+0000f3a4@432
  366+000071a6@433
  367+0000f3a6@434
  368+0000f1de@435
  369+0000b1de@436
  370+0000315e@438
  371+0000a5de@439
  372+0000afc2@440
  373+00002fc2@442
  374+0000afc0@443
  375+0000afe4@444
  376+0000efe4@445
  377+0000ef44@446
  378+00006fc4@447
  379+0000efe4@448
  380+0000ffe4@449
  381+0000ff44@450
  382+0000ffe4@451
  383+00007fe6@452
  384+0000fff6@453
  385+0000b3d6@454
  386+000033d6@456
  387+0000a356@457
  388+0000a7f2@458
  389+00002770@461
  390+0000a7f0@462
  391+0000e7f4@463
  392+0000e774@465
  393+000067f4@466
  394+0000e7f4@467
  395+0000f774@468
  396+0000f7f4@469
  397+000077f6@470
  398+0000f7f6@471
  399+0000f532@472
  400+0000b5b2@473
  401+000035b2@475
  402+0000a532@476
  403+0000ab82@477
  404+00002b00@480
  405+0000aba4@481
  406+0000eba4@482
  407+0000eb24@483
  408+00006ba4@484
  409+0000eba4@485
  410+0000fba4@486
  411+0000fb04@487
  412+0000fba4@488
  413+00007ba6@489
  414+0000fba6@490
  415+0000f712@491
  416+0000b792@492
  417+0000a792@494
  418+0000af92@495
  419+0000ab82@496
  420+00002b02@498
  421+0000ab80@499
  422+0000eba4@500
  423+0000eb24@502
  424+00006b84@503
  425+0000eba4@504
  426+0000fba4@505
  427+0000fb04@506
  428+0000fba4@507
  429+0000fba6@508
  430+0000fb82@509
  431+0000b982@510
  432+00003982@512
  433+0000a902@513
  434+0000abc2@514
  435+00002b40@517
  436+0000abc0@518
  437+0000ebe4@519
  438+00006be4@521
  439+0000ebe4@522
  440+0000fb64@524
  441+0000fbe4@525
  442+00007be6@526
  443+0000fbe6@527
  444+0000f902@528
  445+0000f982@529
  446+00007982@531
  447+0000e982@532
  448+0000ebc2@533
  449+00006bc2@535
  450+0000ebc0@536
  451+0000ebe0@537
  452+0000abe4@538
  453+0000a100@539
  454+00002180@540
  455+0000a180@541
  456+0000b180@542
  457+0000b100@543
  458+0000b180@544
  459+00007182@545
  460+0000f182@546
  461+0000b112@547
  462+0000b192@548
  463+00003192@549
  464+0000a112@550
  465+0000a182@551
  466+00002102@554
  467+0000a180@555
  468+0000e380@556
  469+0000e384@557
  470+0000e304@558
  471+00006384@559
  472+0000e3a4@560
  473+0000f3a4@561
  474+0000f384@562
  475+000073a6@563
  476+0000f3a6@564
  477+0000f112@565
  478+0000b192@566
  479+00003192@568
  480+0000a112@569
  481+0000a182@570
  482+00002100@573
  483+0000a184@574
  484+0000e3a4@575
  485+000063a4@577
  486+0000e1a4@578
  487+0000e180@579
  488+0000f324@580
  489+0000f3a4@581
  490+000071a6@582
  491+0000f3a6@583
  492+0000f162@584
  493+0000b1e2@585
  494+00003162@587
  495+0000a5e2@588
  496+0000afc2@589
  497+00002fc2@591
  498+0000afc0@592
  499+0000efe4@593
  500+0000ef44@595
  501+00006fc4@596
  502+0000efe4@597
  503+0000ffe4@598
  504+0000ff44@599
  505+0000ffe4@600
  506+00007fe6@601
  507+0000ffe6@602
  508+0000b3c6@603
  509+000033c6@605
  510+0000a346@606
  511+0000abe2@607
  512+00002b60@610
  513+0000abe0@611
  514+0000ebe4@612
  515+0000eb64@614
  516+0000ebe4@615
  517+0000fb64@617
  518+0000fbe4@618
  519+00007be6@619
  520+0000fbe6@620
  521+0000f732@621
  522+0000b7b2@622
  523+000037b2@624
  524+0000a732@625
  525+0000ab82@626
  526+00002b00@629
  527+0000aba4@630
  528+0000eba4@631
  529+0000eb24@632
  530+00006ba4@633
  531+0000eba4@634
  532+0000fba4@635
  533+0000fb24@636
  534+0000fba4@637
  535+00007ba6@638
  536+0000fba6@639
  537+0000b912@640
  538+0000b992@641
  539+0000a912@643
  540+0000ab92@644
  541+0000ab82@645
  542+00002b02@647
  543+0000ab80@648
  544+0000eba4@649
  545+0000eb04@651
  546+00006b84@652
  547+0000eba4@653
  548+0000fba4@654
  549+0000fb04@655
  550+0000fba4@656
  551+0000fba6@657
  552+0000fb06@658
  553+0000b986@659
  554+00003986@661
  555+0000a906@662
  556+0000abc2@663
  557+00002b40@666
  558+0000abc0@667
  559+0000ebe4@668
  560+0000ebc4@669
  561+00006be4@670
  562+0000ebe4@671
  563+0000fb64@673
  564+0000fbe4@674
  565+00007be6@675
  566+0000fbe6@676
  567+0000f906@677
  568+0000f986@678
  569+00007986@680
  570+0000e986@681
  571+0000ebc2@682
  572+00006bc2@684
  573+0000eb40@685
  574+0000ebe0@686
  575+0000abe4@687
  576+0000a100@688
  577+00002180@689
  578+0000a180@690
  579+0000b180@691
  580+0000b100@692
  581+0000b180@693
  582+00007182@694
  583+0000f182@695
  584+0000b112@696
  585+0000b192@697
  586+00003192@698
  587+0000a112@699
  588+0000a182@700
  589+00002102@703
  590+0000a180@704
  591+0000e3a0@705
  592+0000e384@706
  593+0000e304@707
  594+000061a4@708
  595+0000e3a4@709
  596+0000f3a4@710
  597+0000f384@711
  598+000073a6@712
  599+0000f3a6@713
  600+0000f972@714
  601+0000b9f2@715
  602+000039f2@717
  603+0000a972@718
  604+0000a182@719
  605+00002100@722
  606+0000a184@723
  607+0000e1a4@724
  608+0000e3a4@725
  609+000063a4@726
  610+0000e1a4@727
  611+0000e180@728
  612+0000f324@729
  613+0000f3a4@730
  614+000071a6@731
  615+0000f3a6@732
  616+0000f166@733
  617+0000b1e6@734
  618+00003166@736
  619+0000a5e6@737
  620+0000afc2@738
  621+00002fc2@740
  622+0000afc0@741
  623+0000afe4@742
  624+0000efe4@743
  625+0000ef64@744
  626+00006fc4@745
  627+0000efe4@746
  628+0000ffe4@747
  629+0000ff44@748
  630+0000ffe4@749
  631+00007fe6@750
  632+0000ffe6@751
  633+0000b3c6@752
  634+000033c6@754
  635+0000a346@755
  636+0000abe2@756
  637+00002b60@759
  638+0000abe0@760
  639+0000ebe4@761
  640+0000eb64@763
  641+0000ebe4@764
  642+0000fb64@766
  643+0000fbe4@767
  644+00007be6@768
  645+0000fbe6@769
  646+0000f932@770
  647+0000b9b2@771
  648+000039b2@773
  649+0000a932@774
  650+0000ab82@775
  651+0000ab80@778
  652+0000aba4@779
  653+0000eba4@780
  654+0000eb24@781
  655+00006ba4@782
  656+0000eba4@783
  657+0000fb80@784
  658+0000fb24@785
  659+0000fba4@786
  660+00007ba6@787
  661+0000fba6@788
  662+0000b312@789
  663+0000b392@790
  664+0000a312@792
  665+0000afb2@793
  666+0000ada2@794
  667+00002d22@796
  668+0000ada0@797
  669+0000efa4@798
  670+0000ef24@800
  671+00006fa0@801
  672+0000efa4@802
  673+0000ffa4@803
  674+0000ff24@804
  675+0000ffa4@805
  676+0000ffa6@806
  677+0000fdae@807
  678+0000b98a@808
  679+0000398a@810
  680+0000a90a@811
  681+0000abc2@812
  682+00002b40@815
  683+0000abc0@816
  684+0000ebe4@817
  685+00006be4@819
  686+0000ebe4@820
  687+0000fb64@822
  688+0000fbe4@823
  689+00007be6@824
  690+0000fbe6@825
  691+0000f90a@826
  692+0000f98a@827
  693+0000798a@829
  694+0000e98a@830
  695+0000ebc2@831
  696+00006bc2@833
  697+0000ebc0@834
  698+0000ebe0@835
  699+0000abe4@836
  700+0000a560@837
  701+000025e0@838
  702+0000a5e0@839
  703+0000b5e0@840
  704+0000b560@841
  705+0000b5e0@842
  706+000075e2@843
  707+0000f5e2@844
  708+0000b912@845
  709+0000b992@846
  710+00003992@847
  711+0000a912@848
  712+0000abd2@849
  713+00002b50@852
  714+0000abd0@853
  715+0000ebf0@854
  716+0000ebd4@855
  717+0000eb54@856
  718+00006bd4@857
  719+0000ebf4@858
  720+0000fbf4@859
  721+00007bf6@861
  722+0000fbf6@862
  723+0000f912@863
  724+0000b992@864
  725+00003992@866
  726+0000a912@867
  727+0000abd2@868
  728+00002b50@871
  729+0000abd4@872
  730+0000ebf4@873
  731+0000eb74@874
  732+00006bf4@875
  733+0000ebf4@876
  734+0000ebd0@877
  735+0000fb74@878
  736+0000fbf4@879
  737+00007bf6@880
  738+0000fbf6@881
  739+0000b16a@882
  740+0000b1ea@883
  741+000031ea@885
  742+0000a5ea@886
  743+0000afc2@887
  744+00002fc2@889
  745+0000afc0@890
  746+0000efe4@891
  747+0000ef44@893
  748+00006fc4@894
  749+0000efe4@895
  750+0000ffe4@896
  751+0000ff40@897
  752+0000ffe4@898
  753+00007fe6@899
  754+0000ffe6@900
  755+0000b3c6@901
  756+000033c6@903
  757+0000a346@904
  758+0000abe2@905
  759+00002b60@908
  760+0000abe0@909
  761+0000ebe4@910
  762+0000eb64@912
  763+0000ebe4@913
  764+0000fb64@915
  765+0000fbe4@916
  766+00007be6@917
  767+0000fbe6@918
  768+0000f332@919
  769+0000b3b2@920
  770+000033b2@922
  771+0000a332@923
  772+0000ada2@924
  773+0000ada0@927
  774+0000afa4@928
  775+0000efa4@929
  776+0000ef24@930
  777+00006fa4@931
  778+0000efa4@932
  779+0000ffa0@933
  780+0000ff24@934
  781+0000ffa4@935
  782+00007fa6@936
  783+0000ffa6@937
  784+0000b512@938
  785+0000b592@939
  786+0000a512@941
  787+0000adb2@942
  788+0000ada2@943
  789+00002d22@945
  790+0000ada0@946
  791+0000efa4@947
  792+0000eda4@948
  793+0000ef24@949
  794+00006da4@950
  795+0000efa4@951
  796+0000ffa4@952
  797+0000ff24@953
  798+0000ffa4@954
  799+0000ffa6@955
  800+0000fd2e@956
  801+0000b98e@957
  802+0000398e@959
  803+0000a90e@960
  804+0000abc2@961
  805+00002b40@964
  806+0000abc0@965
  807+0000ebe4@966
  808+00006be4@968
  809+0000ebe4@969
  810+0000fb64@971
  811+0000fbe4@972
  812+00007be6@973
  813+0000fbe6@974
  814+0000f90e@975
  815+0000f98e@976
  816+0000798c@978
  817+0000f98c@979
  818+0000fbc0@980
  819+0000ebc0@981
  820+00006bc0@982
  821+0000ebc0@983
  822+0000ebe0@984
  823+0000ebe4@985
  824+0000eb64@986
  825+00006be4@987
  826+0000ebe4@988
  827+0000fbe4@989
  828+0000fb44@990
  829+0000fbe4@991
  830+00007be6@992
  831+0000fbe6@993
  832+0000b912@994
  833+0000b992@995
  834+00003992@996
  835+0000a912@997
  836+0000abd2@998
  837+00002b50@1001
  838+0000abd0@1002
  839+0000ebf0@1003
  840+0000ebd4@1004
  841+0000eb54@1005
  842+00006bf4@1006
  843+0000ebf4@1007
  844+0000fbf4@1008
  845+00007bf6@1010
  846+0000fbf6@1011
  847+0000f912@1012
  848+0000b992@1013
  849+00003992@1015
  850+0000a912@1016
  851+0000abd2@1017
  852+00002b50@1020
  853+0000abd4@1021
  854+0000ebf4@1022
  855+00006bf4@1024
  856+0000ebf4@1025
  857+0000ebd0@1026
  858+0000fb74@1027
  859+0000fbf4@1028
  860+00007bf6@1029
  861+0000fbf6@1030
  862+0000b16e@1031
  863+0000b1ee@1032
  864+000021ee@1034
  865+0000a5ee@1035
  866+0000afc2@1036
  867+00002fc2@1038
  868+0000afc0@1039
  869+0000efe4@1040
  870+0000ef64@1042
  871+00006fc4@1043
  872+0000efe4@1044
  873+0000ffe4@1045
  874+0000ff64@1046
  875+0000ffe4@1047
  876+00007fe6@1048
  877+0000ffe6@1049
  878+0000b3c6@1050
  879+000033c6@1052
  880+0000a346@1053
  881+0000abe2@1054
  882+00002b60@1057
  883+0000abe0@1058
  884+0000ebe4@1059
  885+0000eb64@1061
  886+0000ebe4@1062
  887+0000fb64@1064
  888+0000fbe4@1065
  889+00007be6@1066
  890+0000fbe6@1067
  891+0000f532@1068
  892+0000b5b2@1069
  893+000035b2@1071
  894+0000a532@1072
  895+0000ada2@1073
  896+0000ada0@1076
  897+0000afa4@1077
  898+0000efa4@1078
  899+0000ef24@1079
  900+00006fa4@1080
  901+0000efa4@1081
  902+0000ffa4@1082
  903+0000ff24@1083
  904+0000ffa4@1084
  905+00007fa6@1085
  906+0000ffa6@1086
  907+0000b712@1087
  908+0000b792@1088
  909+0000a712@1090
  910+0000adb2@1091
  911+0000ada2@1092
  912+00002d22@1094
  913+0000ada0@1095
  914+0000efa4@1096
  915+0000ef24@1098
  916+00006fa4@1099
  917+0000efa4@1100
  918+0000ffa4@1101
  919+0000ff20@1102
  920+00007fa4@1103
  921+0000ffa6@1104
  922+0000fdb2@1105
  923+0000b992@1106
  924+00003992@1108
  925+0000a912@1109
  926+0000abc2@1110
  927+00002b40@1113
  928+0000abc0@1114
  929+0000ebe4@1115
  930+00006be4@1117
  931+0000ebe4@1118
  932+0000fb64@1120
  933+0000fbe4@1121
  934+00007be6@1122
  935+0000fbe6@1123
  936+0000f912@1124
  937+0000f992@1125
  938+00007992@1127
  939+0000e992@1128
  940+0000ebc2@1129
  941+00006bc2@1131
  942+0000ebc0@1132
  943+0000ebe0@1133
  944+0000abe4@1134
  945+0000a560@1135
  946+000025e0@1136
  947+0000a5e0@1137
  948+0000b5e0@1138
  949+0000b560@1139
  950+0000b5e0@1140
  951+000075e2@1141
  952+0000f5e2@1142
  953+0000b912@1143
  954+0000b992@1144
  955+00003992@1145
  956+0000a912@1146
  957+0000abd2@1147
  958+00002b50@1150
  959+0000abd0@1151
  960+0000ebf0@1152
  961+0000ebd0@1153
  962+0000eb54@1154
  963+00006bf4@1155
  964+0000ebf4@1156
  965+0000fbf4@1157
  966+00007bf6@1159
  967+0000fbf6@1160
  968+0000f912@1161
  969+0000b992@1162
  970+00003992@1164
  971+0000a912@1165
  972+0000abd2@1166
  973+00002b50@1169
  974+0000abf4@1170
  975+0000ebf4@1171
  976+0000eb74@1172
  977+00006bf4@1173
  978+0000ebf4@1174
  979+0000ebd0@1175
  980+0000fb74@1176
  981+0000fbf4@1177
  982+00007bf6@1178
  983+0000fbf6@1179
  984+0000b172@1180
  985+0000b1f2@1181
  986+00002172@1183
  987+0000a5f2@1184
  988+0000afc2@1185
  989+00002f42@1187
  990+0000afc0@1188
  991+0000efe4@1189
  992+0000ef64@1191
  993+00006fc4@1192
  994+0000efe4@1193
  995+0000ffe4@1194
  996+0000ff44@1195
  997+0000ffe4@1196
  998+00007fe6@1197
  999+0000ffe6@1198
 1000+0000b3c6@1199
 1001+000033c6@1201
 1002+0000a346@1202
 1003+0000abe2@1203
 1004+00002b60@1206
 1005+0000abe0@1207
 1006+0000ebe4@1208
 1007+0000eb64@1210
 1008+0000ebe4@1211
 1009+0000fb64@1213
 1010+0000fbe4@1214
 1011+00007be6@1215
 1012+0000fbe6@1216
 1013+0000fb12@1217
 1014+0000bb92@1218
 1015+00003b92@1220
 1016+0000ab12@1221
 1017+0000ab82@1222
 1018+0000ab00@1225
 1019+0000aba4@1226
 1020+0000eba4@1227
 1021+0000eb24@1228
 1022+00006ba4@1229
 1023+0000eba4@1230
 1024+0000fb84@1231
 1025+0000fb24@1232
 1026+0000fba4@1233
 1027+00007ba6@1234
 1028+0000fba6@1235
 1029+0000fb32@1236
 1030+0000bbb2@1237
 1031+0000ab32@1239
 1032+0000ab82@1240
 1033+00002b02@1243
 1034+0000ab80@1244
 1035+0000eba4@1245
 1036+0000eb84@1246
 1037+0000eb04@1247
 1038+00006b84@1248
 1039+0000eba4@1249
 1040+0000fba4@1250
 1041+0000fb00@1251
 1042+00007ba4@1252
 1043+0000fba6@1253
 1044+0000fb16@1254
 1045+0000b996@1255
 1046+00003996@1257
 1047+0000a916@1258
 1048+0000abc2@1259
 1049+00002b40@1262
 1050+0000abc0@1263
 1051+0000ebe4@1264
 1052+0000ebc4@1265
 1053+00006be4@1266
 1054+0000ebe4@1267
 1055+0000fb64@1269
 1056+0000fbe4@1270
 1057+00007be6@1271
 1058+0000fbe6@1272
 1059+0000f916@1273
 1060+0000f996@1274
 1061+00007996@1276
 1062+0000e996@1277
 1063+0000ebc2@1278
 1064+00006bc2@1280
 1065+0000eb40@1281
 1066+0000ebe0@1282
 1067+0000abe4@1283
 1068+0000a560@1284
 1069+000025e0@1285
 1070+0000a5e0@1286
 1071+0000b5e0@1287
 1072+0000b560@1288
 1073+0000b5e0@1289
 1074+000075e2@1290
 1075+0000f5e2@1291
 1076+0000b912@1292
 1077+0000b992@1293
 1078+00003992@1294
 1079+0000a912@1295
 1080+0000abd2@1296
 1081+00002b50@1299
 1082+0000abd0@1300
 1083+0000ebf0@1301
 1084+0000ebd4@1302
 1085+0000eb54@1303
 1086+00006bf4@1304
 1087+0000ebf4@1305
 1088+0000fbf4@1306
 1089+00007bf6@1308
 1090+0000fbf6@1309
 1091+0000f912@1310
 1092+0000b992@1311
 1093+00003992@1313
 1094+0000a912@1314
 1095+0000abd2@1315
 1096+00002b50@1318
 1097+0000abf4@1319
 1098+0000ebf4@1320
 1099+0000eb74@1321
 1100+00006bf4@1322
 1101+0000ebf4@1323
 1102+0000ebd0@1324
 1103+0000fb74@1325
 1104+0000fbf4@1326
 1105+00007bf6@1327
 1106+0000fbf6@1328
 1107+0000b176@1329
 1108+0000b1f6@1330
 1109+00003176@1332
 1110+0000a7f6@1333
 1111+0000afc2@1334
 1112+00002fc2@1336
 1113+0000afc0@1337
 1114+0000efe4@1338
 1115+0000ef64@1340
 1116+00006fc4@1341
 1117+0000efe4@1342
 1118+0000ffe4@1343
 1119+0000ff44@1344
 1120+0000ffe4@1345
 1121+00007fe6@1346
 1122+0000ffe6@1347
 1123+0000b3c6@1348
 1124+000033c6@1350
 1125+0000a346@1351
 1126+0000abe2@1352
 1127+00002b60@1355
 1128+0000abe0@1356
 1129+0000ebe4@1357
 1130+0000eb64@1359
 1131+0000ebe4@1360
 1132+0000fbe4@1362
 1133+00007be6@1364
 1134+0000fbe6@1365
 1135+0000fd12@1366
 1136+0000bd92@1367
 1137+00003d92@1369
 1138+0000ad12@1370
 1139+0000ab82@1371
 1140+0000ab80@1374
 1141+0000aba4@1375
 1142+0000eba4@1376
 1143+0000eb24@1377
 1144+00006ba4@1378
 1145+0000eba4@1379
 1146+0000fb84@1380
 1147+0000fb04@1381
 1148+0000fba4@1382
 1149+00007ba6@1383
 1150+0000fba6@1384
 1151+0000fd32@1385
 1152+0000bdb2@1386
 1153+0000adb2@1388
 1154+0000af82@1389
 1155+0000ab82@1390
 1156+00002b02@1392
 1157+0000ab80@1393
 1158+0000eba4@1394
 1159+0000eb24@1396
 1160+00006ba4@1397
 1161+0000eba4@1398
 1162+0000fba4@1399
 1163+0000fb24@1400
 1164+00007ba6@1401
 1165+0000fba6@1402
 1166+0000fb1e@1403
 1167+0000b99a@1404
 1168+0000399a@1406
 1169+0000a91a@1407
 1170+0000abc2@1408
 1171+00002b40@1411
 1172+0000abc0@1412
 1173+0000ebe4@1413
 1174+00006be4@1415
 1175+0000ebe4@1416
 1176+0000fb64@1418
 1177+0000fbe4@1419
 1178+00007be6@1420
 1179+0000fbe6@1421
 1180+0000f91a@1422
 1181+0000f99a@1423
 1182+0000799a@1425
 1183+0000e99a@1426
 1184+0000ebc2@1427
 1185+00006bc2@1429
 1186+0000ebc0@1430
 1187+0000ebe0@1431
 1188+0000abe4@1432
 1189+0000a560@1433
 1190+000025e0@1434
 1191+0000a5e0@1435
 1192+0000b5e0@1436
 1193+0000b560@1437
 1194+0000b5e0@1438
 1195+000075e2@1439
 1196+0000f5e2@1440
 1197+0000b912@1441
 1198+0000b992@1442
 1199+00003992@1443
 1200+0000a912@1444
 1201+0000abd2@1445
 1202+00002b50@1448
 1203+0000abd0@1449
 1204+0000ebf0@1450
 1205+0000ebd4@1451
 1206+0000eb54@1452
 1207+00006bf4@1453
 1208+0000ebf4@1454
 1209+0000fbf4@1455
 1210+00007bf6@1457
 1211+0000fbf6@1458
 1212+0000f912@1459
 1213+0000b992@1460
 1214+00003992@1462
 1215+0000a912@1463
 1216+0000abd2@1464
 1217+00002b50@1467
 1218+0000abf4@1468
 1219+0000ebf4@1469
 1220+0000eb74@1470
 1221+00006bf4@1471
 1222+0000ebf4@1472
 1223+0000ebd0@1473
 1224+0000fb74@1474
 1225+0000fbf4@1475
 1226+00007bf6@1476
 1227+0000fbf6@1477
 1228+0000b17a@1478
 1229+0000b1fa@1479
 1230+0000217a@1481
 1231+0000a7fa@1482
 1232+0000afc2@1483
 1233+00002fc2@1485
 1234+0000afc0@1486
 1235+0000efe4@1487
 1236+0000ef64@1489
 1237+00006fe4@1490
 1238+0000efe4@1491
 1239+0000ffe4@1492
 1240+0000ff44@1493
 1241+0000ffe4@1494
 1242+00007fe6@1495
 1243+0000ffe6@1496
 1244+0000b3c6@1497
 1245+000033c6@1499
 1246+0000a346@1500
 1247+0000abe2@1501
 1248+00002b60@1504
 1249+0000abe0@1505
 1250+0000ebe4@1506
 1251+0000eb64@1508
 1252+0000ebe4@1509
 1253+0000fb64@1511
 1254+0000fbe4@1512
 1255+00007be6@1513
 1256+0000fbe6@1514
 1257+0000ff12@1515
 1258+0000bf92@1516
 1259+00003f92@1518
 1260+0000af12@1519
 1261+0000ab82@1520
 1262+0000ab80@1523
 1263+0000aba4@1524
 1264+0000eba4@1525
 1265+0000eb24@1526
 1266+00006ba4@1527
 1267+0000eba4@1528
 1268+0000fb84@1529
 1269+0000fb04@1530
 1270+0000fba4@1531
 1271+00007ba6@1532
 1272+0000fba6@1533
 1273+0000ff32@1534
 1274+0000bfb2@1535
 1275+0000afb2@1537
 1276+0000ab82@1538
 1277+00002b02@1541
 1278+0000ab80@1542
 1279+0000eba4@1543
 1280+0000eb84@1544
 1281+0000eb24@1545
 1282+00006ba4@1546
 1283+0000eba4@1547
 1284+0000fba4@1548
 1285+0000fb04@1549
 1286+00007ba6@1550
 1287+0000fba6@1551
 1288+0000fb1e@1552
 1289+0000b99e@1553
 1290+0000399e@1555
 1291+0000a91e@1556
 1292+0000abc2@1557
 1293+00002b40@1560
 1294+0000abc0@1561
 1295+0000ebe4@1562
 1296+00006be4@1564
 1297+0000ebe4@1565
 1298+0000fb64@1567
 1299+0000fbe4@1568
 1300+00007be6@1569
 1301+0000fbe6@1570
 1302+0000f91e@1571
 1303+0000f99e@1572
 1304+0000799c@1574
 1305+0000f99c@1575
 1306+0000fbc0@1576
 1307+0000ebc0@1577
 1308+00006bc0@1578
 1309+0000ebc0@1579
 1310+0000ebe0@1580
 1311+0000ebe4@1581
 1312+0000eb64@1582
 1313+00006be4@1583
 1314+0000ebe4@1584
 1315+0000fbe4@1585
 1316+0000fb44@1586
 1317+0000fbe4@1587
 1318+00007be6@1588
 1319+0000fbe6@1589
 1320+0000b912@1590
 1321+0000b992@1591
 1322+00003992@1592
 1323+0000a912@1593
 1324+0000abd2@1594
 1325+00002b50@1597
 1326+0000abd0@1598
 1327+0000ebf0@1599
 1328+0000ebd0@1600
 1329+0000eb54@1601
 1330+00006bf4@1602
 1331+0000ebf4@1603
 1332+0000fbf4@1604
 1333+00007bf6@1606
 1334+0000fbf6@1607
 1335+0000fb12@1608
 1336+0000bb92@1609
 1337+00003b92@1611
 1338+0000ab12@1612
 1339+0000abe2@1613
 1340+00002b60@1616
 1341+0000abe4@1617
 1342+0000ebe4@1618
 1343+0000eb64@1619
 1344+00006be4@1620
 1345+0000ebe4@1621
 1346+0000ebe0@1622
 1347+0000fb64@1623
 1348+0000fbe4@1624
 1349+00007be6@1625
 1350+0000fbe6@1626
 1351+0000f17e@1627
 1352+0000b1fe@1628
 1353+000021fe@1630
 1354+0000a7fe@1631
 1355+0000afc2@1632
 1356+00002fc2@1634
 1357+0000afc0@1635
 1358+0000efe4@1636
 1359+0000ef44@1638
 1360+00006fc4@1639
 1361+0000efe4@1640
 1362+0000ffe4@1641
 1363+0000ff44@1642
 1364+0000ffe4@1643
 1365+00007fe6@1644
 1366+0000ffe6@1645
 1367+0000b3c6@1646
 1368+000033c6@1648
 1369+0000a346@1649
 1370+0000abe2@1650
 1371+00002b60@1653
 1372+0000abe0@1654
 1373+0000ebe4@1655
 1374+0000eb64@1657
 1375+0000ebe4@1658
 1376+0000fb64@1660
 1377+0000fbe4@1661
 1378+00007be6@1662
 1379+0000fbe6@1663
 1380+0000f712@1664
 1381+0000b792@1665
 1382+00003792@1667
 1383+0000a712@1668
 1384+0000a992@1669
 1385+0000a990@1672
 1386+0000abb4@1673
 1387+0000ebb4@1674
 1388+0000eb34@1675
 1389+00006bb4@1676
 1390+0000ebb4@1677
 1391+0000fb94@1678
 1392+0000fb14@1679
 1393+0000fbb4@1680
 1394+00007b96@1681
 1395+0000fbb6@1682
 1396+0000b732@1683
 1397+0000b7b2@1684
 1398+0000a7b2@1686
 1399+0000a9b2@1687
 1400+0000a992@1688
 1401+00002912@1690
 1402+0000a990@1691
 1403+0000ebb4@1692
 1404+0000eb94@1693
 1405+0000eb14@1694
 1406+00006990@1695
 1407+0000ebb4@1696
 1408+0000fbb4@1697
 1409+0000fb10@1698
 1410+00007bb4@1699
 1411+0000fbb6@1700
 1412+0000f9b2@1701
 1413+0000b9a2@1702
 1414+000039a2@1704
 1415+0000a922@1705
 1416+0000abc2@1706
 1417+00002b40@1709
 1418+0000abc0@1710
 1419+0000ebe4@1711
 1420+00006be4@1713
 1421+0000ebe4@1714
 1422+0000fb64@1716
 1423+0000fbe4@1717
 1424+00007be6@1718
 1425+0000fbe6@1719
 1426+0000f922@1720
 1427+0000f9a2@1721
 1428+000079a2@1723
 1429+0000e9a2@1724
 1430+0000ebc2@1725
 1431+00006bc2@1727
 1432+0000ebc0@1728
 1433+0000ebe4@1729
 1434+0000abe4@1730
 1435+0000a96c@1731
 1436+000029ec@1732
 1437+0000a9ec@1733
 1438+0000b9ec@1734
 1439+0000b96c@1735
 1440+0000b9ec@1736
 1441+000079ee@1737
 1442+0000f9ee@1738
 1443+0000bbb2@1739
 1444+00003bb2@1741
 1445+0000ab32@1742
 1446+0000abe2@1743
 1447+00002b60@1746
 1448+0000abe0@1747
 1449+0000ebe4@1748
 1450+0000eb64@1750
 1451+00006be4@1751
 1452+0000ebe4@1752
 1453+0000fbe4@1753
 1454+00007be6@1755
 1455+0000fbe6@1756
 1456+0000f912@1757
 1457+0000b992@1758
 1458+00003992@1760
 1459+0000a912@1761
 1460+0000abd2@1762
 1461+00002b50@1765
 1462+0000abf4@1766
 1463+0000ebf4@1767
 1464+0000eb74@1768
 1465+00006bf4@1769
 1466+0000ebf4@1770
 1467+0000ebd0@1771
 1468+0000fb74@1772
 1469+0000fbf4@1773
 1470+00007bf6@1774
 1471+0000fbf6@1775
 1472+0000b342@1776
 1473+0000b3c2@1777
 1474+000023c2@1779
 1475+0000a7c2@1780
 1476+0000afc2@1781
 1477+00002f42@1783
 1478+0000afc0@1784
 1479+0000efe4@1785
 1480+0000ef44@1787
 1481+00006fc4@1788
 1482+0000efe4@1789
 1483+0000ffe4@1790
 1484+0000ff44@1791
 1485+0000ffe4@1792
 1486+00007fe6@1793
 1487+0000ffe6@1794
 1488+0000b3c6@1795
 1489+000033c6@1797
 1490+0000a346@1798
 1491+0000abe2@1799
 1492+00002b60@1802
 1493+0000abe0@1803
 1494+0000ebe4@1804
 1495+0000eb64@1806
 1496+0000ebe4@1807
 1497+0000fb64@1809
 1498+0000fbe4@1810
 1499+00007be6@1811
 1500+0000fbe6@1812
 1501+0000ff12@1813
 1502+0000bf92@1814
 1503+00003f92@1816
 1504+0000af12@1817
 1505+0000aba2@1818
 1506+0000aba0@1821
 1507+0000aba4@1822
 1508+0000eba4@1823
 1509+0000eb24@1824
 1510+00006ba4@1825
 1511+0000eba4@1826
 1512+0000fba4@1827
 1513+0000fb24@1828
 1514+0000fba4@1829
 1515+00007ba6@1830
 1516+0000fba6@1831
 1517+0000b532@1832
 1518+0000b5b2@1833
 1519+0000a532@1835
 1520+0000a182@1836
 1521+00002102@1839
 1522+0000a180@1840
 1523+0000e3a4@1841
 1524+0000e304@1843
 1525+00006180@1844
 1526+0000e3a4@1845
 1527+0000f3a4@1846
 1528+0000f304@1847
 1529+000073a6@1848
 1530+0000f3a6@1849
 1531+0000f926@1850
 1532+0000b9a6@1851
 1533+000039a6@1853
 1534+0000a926@1854
 1535+0000abc2@1855
 1536+00002b40@1858
 1537+0000abc0@1859
 1538+0000ebe4@1860
 1539+00006be4@1862
 1540+0000ebe4@1863
 1541+0000fb64@1865
 1542+0000fbe4@1866
 1543+00007be6@1867
 1544+0000fbe6@1868
 1545+0000f926@1869
 1546+0000f9a6@1870
 1547+000079a6@1872
 1548+0000e9a6@1873
 1549+0000ebc2@1874
 1550+00006bc2@1876
 1551+0000ebc0@1877
 1552+0000ebe4@1878
 1553+0000abe4@1879
 1554+0000a560@1880
 1555+000025e0@1881
 1556+0000a5e0@1882
 1557+0000b5e0@1883
 1558+0000b560@1884
 1559+0000b5e0@1885
 1560+000075e2@1886
 1561+0000f5e2@1887
 1562+0000b912@1888
 1563+0000b992@1889
 1564+00003992@1890
 1565+0000a912@1891
 1566+0000abd2@1892
 1567+00002b50@1895
 1568+0000abd0@1896
 1569+0000ebf0@1897
 1570+0000ebd4@1898
 1571+0000eb54@1899
 1572+00006bf4@1900
 1573+0000ebf4@1901
 1574+0000fbf4@1902
 1575+00007bf6@1904
 1576+0000fbf6@1905
 1577+0000f912@1906
 1578+0000b992@1907
 1579+00003992@1909
 1580+0000a912@1910
 1581+0000abd2@1911
 1582+00002b50@1914
 1583+0000abf4@1915
 1584+0000ebf4@1916
 1585+0000eb74@1917
 1586+00006bf4@1918
 1587+0000ebf4@1919
 1588+0000ebd0@1920
 1589+0000fb74@1921
 1590+0000fbf4@1922
 1591+00007bf6@1923
 1592+0000fbf6@1924
 1593+0000b346@1925
 1594+0000b3c6@1926
 1595+000023c6@1928
 1596+0000afc6@1929
 1597+0000afc2@1930
 1598+00002f42@1932
 1599+0000afc0@1933
 1600+0000efe4@1934
 1601+0000ef64@1936
 1602+00006fc4@1937
 1603+0000efe4@1938
 1604+0000ffe4@1939
 1605+0000ff44@1940
 1606+0000ffe4@1941
 1607+00007fe6@1942
 1608+0000ffe6@1943
 1609+0000b3c6@1944
 1610+000033c6@1946
 1611+0000a346@1947
 1612+0000abe2@1948
 1613+00002b60@1951
 1614+0000abe0@1952
 1615+0000ebe4@1953
 1616+0000eb64@1955
 1617+0000ebe4@1956
 1618+0000fb64@1958
 1619+0000fbe4@1959
 1620+00007be6@1960
 1621+0000fbe6@1961
 1622+0000f532@1962
 1623+0000b5b2@1963
 1624+000035b2@1965
 1625+0000a532@1966
 1626+0000a182@1967
 1627+0000a180@1970
 1628+0000a3a4@1971
 1629+0000e3a4@1972
 1630+0000e324@1973
 1631+000063a4@1974
 1632+0000e3a4@1975
 1633+0000f184@1976
 1634+0000f304@1977
 1635+0000f3a4@1978
 1636+000073a6@1979
 1637+0000f3a6@1980
 1638+0000f532@1981
 1639+0000b5b2@1982
 1640+0000a5b2@1984
 1641+0000a182@1985
 1642+00002102@1988
 1643+0000a180@1989
 1644+0000e3a4@1990
 1645+0000e324@1992
 1646+00006380@1993
 1647+0000e3a4@1994
 1648+0000f3a4@1995
 1649+0000f304@1996
 1650+000073a6@1997
 1651+0000f3a6@1998
 1652+0000f92a@1999
 1653+0000b9aa@2000
 1654+000039aa@2002
 1655+0000a92a@2003
 1656+0000abc2@2004
 1657+00002b40@2007
 1658+0000abc0@2008
 1659+0000ebe4@2009
 1660+00006be4@2011
 1661+0000ebe4@2012
 1662+0000fb64@2014
 1663+0000fbe4@2015
 1664+00007be6@2016
 1665+0000fbe6@2017
 1666+0000f92a@2018
 1667+0000f9aa@2019
 1668+000079aa@2021
 1669+0000e9aa@2022
 1670+0000ebc2@2023
 1671+00006bc2@2025
 1672+0000ebc0@2026
 1673+0000ebe4@2027
 1674+0000abe4@2028
 1675+0000a560@2029
 1676+000025e0@2030
 1677+0000a5e0@2031
 1678+0000b5e0@2032
 1679+0000b560@2033
 1680+0000b5e0@2034
 1681+000075e2@2035
 1682+0000f5e2@2036
 1683+0000b912@2037
 1684+0000b992@2038
 1685+00003992@2039
 1686+0000a912@2040
 1687+0000abd2@2041
 1688+00002b50@2044
 1689+0000abd0@2045
 1690+0000ebf4@2046
 1691+0000ebd4@2047
 1692+0000eb54@2048
 1693+00006bf4@2049
 1694+0000ebf4@2050
 1695+0000fbf4@2051
 1696+00007bf6@2053
 1697+0000fbf6@2054
 1698+0000f912@2055
 1699+0000b992@2056
 1700+00003992@2058
 1701+0000a912@2059
 1702+0000abd2@2060
 1703+00002b50@2063
 1704+0000abf4@2064
 1705+0000ebf4@2065
 1706+0000eb74@2066
 1707+00006bf4@2067
 1708+0000ebf4@2068
 1709+0000ebd0@2069
 1710+0000fb74@2070
 1711+0000fbf4@2071
 1712+00007bf6@2072
 1713+0000fbf6@2073
 1714+0000b34a@2074
 1715+0000b3ca@2075
 1716+000033ca@2077
 1717+0000afca@2078
 1718+0000afc2@2079
 1719+00002f42@2081
 1720+0000afc0@2082
 1721+0000efe4@2083
 1722+0000efc4@2084
 1723+0000ef44@2085
 1724+00006fc4@2086
 1725+0000efe4@2087
 1726+0000ffe4@2088
 1727+0000ff40@2089
 1728+0000ffe4@2090
 1729+00007fe6@2091
 1730+0000ffe6@2092
 1731+0000b3c6@2093
 1732+000033c6@2095
 1733+0000a346@2096
 1734+0000abe2@2097
 1735+00002b60@2100
 1736+0000abe0@2101
 1737+0000ebe4@2102
 1738+0000eb64@2104
 1739+0000ebe4@2105
 1740+0000fb64@2107
 1741+0000fbe4@2108
 1742+00007be6@2109
 1743+0000fbe6@2110
 1744+0000f532@2111
 1745+0000b5b2@2112
 1746+000035b2@2114
 1747+0000a532@2115
 1748+0000a182@2116
 1749+0000a180@2119
 1750+0000a3a4@2120
 1751+0000e3a4@2121
 1752+0000e324@2122
 1753+000063a4@2123
 1754+0000e3a4@2124
 1755+0000f384@2125
 1756+0000f304@2126
 1757+0000f3a4@2127
 1758+000073a6@2128
 1759+0000f3a6@2129
 1760+0000f532@2130
 1761+0000b5b2@2131
 1762+0000a532@2133
 1763+0000a182@2134
 1764+00002102@2137
 1765+0000a180@2138
 1766+0000e3a4@2139
 1767+0000e304@2141
 1768+00006184@2142
 1769+0000e3a4@2143
 1770+0000f3a4@2144
 1771+0000f300@2145
 1772+000073a6@2146
 1773+0000f3a6@2147
 1774+0000f92e@2148
 1775+0000b9ae@2149
 1776+000039ae@2151
 1777+0000a92e@2152
 1778+0000abc2@2153
 1779+00002b40@2156
 1780+0000abc0@2157
 1781+0000ebe4@2158
 1782+00006be4@2160
 1783+0000ebe4@2161
 1784+0000fb64@2163
 1785+0000fbe4@2164
 1786+00007be6@2165
 1787+0000fbe6@2166
 1788+0000f92e@2167
 1789+0000f9ae@2168
 1790+000079ac@2170
 1791+0000f9ac@2171
 1792+0000fbc0@2172
 1793+0000ebc0@2173
 1794+00006bc0@2174
 1795+0000ebc0@2175
 1796+0000ebe4@2176
 1797+0000eb64@2178
 1798+00006be4@2179
 1799+0000ebe4@2180
 1800+0000fbe4@2181
 1801+0000fb44@2182
 1802+0000fbe4@2183
 1803+00007be6@2184
 1804+0000fbe6@2185
 1805+0000b912@2186
 1806+0000b992@2187
 1807+00003992@2188
 1808+0000a912@2189
 1809+0000abd2@2190
 1810+00002b50@2193
 1811+0000abd0@2194
 1812+0000ebf4@2195
 1813+0000ebd4@2196
 1814+0000eb54@2197
 1815+00006bf4@2198
 1816+0000ebf4@2199
 1817+0000fbf4@2200
 1818+00007bf6@2202
 1819+0000fbf6@2203
 1820+0000f912@2204
 1821+0000b992@2205
 1822+00003992@2207
 1823+0000a912@2208
 1824+0000abd2@2209
 1825+00002b50@2212
 1826+0000abf4@2213
 1827+0000ebf4@2214
 1828+0000eb74@2215
 1829+00006bf4@2216
 1830+0000ebf4@2217
 1831+0000ebd0@2218
 1832+0000fb74@2219
 1833+0000fbf4@2220
 1834+00007bf6@2221
 1835+0000fbf6@2222
 1836+0000b34e@2223
 1837+0000b3ce@2224
 1838+0000234e@2226
 1839+0000afce@2227
 1840+0000afc2@2228
 1841+00002f42@2230
 1842+0000afc0@2231
 1843+0000efe4@2232
 1844+0000ef44@2234
 1845+00006fc4@2235
 1846+0000efe4@2236
 1847+0000ffe4@2237
 1848+0000ff44@2238
 1849+0000ffe4@2239
 1850+0000ffe6@2240
 1851+0000b3c6@2242
 1852+000033c6@2244
 1853+0000a346@2245
 1854+0000abe2@2246
 1855+00002b60@2249
 1856+0000abe0@2250
 1857+0000ebe4@2251
 1858+0000eb64@2253
 1859+0000ebe4@2254
 1860+0000fb64@2256
 1861+0000fbe4@2257
 1862+00007be6@2258
 1863+0000fbe6@2259
 1864+0000f532@2260
 1865+0000b5b2@2261
 1866+000035b2@2263
 1867+0000a532@2264
 1868+0000a182@2265
 1869+0000a180@2268
 1870+0000a3a4@2269
 1871+0000e3a4@2270
 1872+0000e324@2271
 1873+000063a4@2272
 1874+0000e3a4@2273
 1875+0000f384@2274
 1876+0000f324@2275
 1877+0000f3a4@2276
 1878+000073a6@2277
 1879+0000f3a6@2278
 1880+0000f532@2279
 1881+0000b5b2@2280
 1882+0000a532@2282
 1883+0000a182@2283
 1884+00002102@2286
 1885+0000a180@2287
 1886+0000e3a0@2288
 1887+0000e3a4@2289
 1888+0000e304@2290
 1889+00006180@2291
 1890+0000e3a4@2292
 1891+0000f3a4@2293
 1892+0000f104@2294
 1893+000073a6@2295
 1894+0000f3a6@2296
 1895+0000f932@2297
 1896+0000b9b2@2298
 1897+000039b2@2300
 1898+0000a932@2301
 1899+0000abc2@2302
 1900+00002b40@2305
 1901+0000abc0@2306
 1902+0000ebe4@2307
 1903+00006be4@2309
 1904+0000ebe4@2310
 1905+0000fb64@2312
 1906+0000fbe4@2313
 1907+00007be6@2314
 1908+0000fbe6@2315
 1909+0000f932@2316
 1910+0000f9b2@2317
 1911+000079b2@2319
 1912+0000e9b2@2320
 1913+0000ebc2@2321
 1914+00006bc2@2323
 1915+0000ebc0@2324
 1916+0000ebe4@2325
 1917+0000abe4@2326
 1918+0000a560@2327
 1919+000025e0@2328
 1920+0000a5e0@2329
 1921+0000b5e0@2330
 1922+0000b560@2331
 1923+0000b5e0@2332
 1924+000075e2@2333
 1925+0000f5e2@2334
 1926+0000b912@2335
 1927+0000b992@2336
 1928+00003992@2337
 1929+0000a912@2338
 1930+0000abd2@2339
 1931+00002b50@2342
 1932+0000abd0@2343
 1933+0000ebf4@2344
 1934+0000ebd4@2345
 1935+0000eb54@2346
 1936+00006bf4@2347
 1937+0000ebf4@2348
 1938+0000fbf4@2349
 1939+00007bf6@2351
 1940+0000fbf6@2352
 1941+0000f912@2353
 1942+0000b992@2354
 1943+00003992@2356
 1944+0000a912@2357
 1945+0000abd2@2358
 1946+00002b50@2361
 1947+0000abf4@2362
 1948+0000ebf4@2363
 1949+0000eb74@2364
 1950+00006bf4@2365
 1951+0000ebf4@2366
 1952+0000ebd0@2367
 1953+0000fb74@2368
 1954+0000fbf4@2369
 1955+00007bf6@2370
 1956+0000fbf6@2371
 1957+0000b352@2372
 1958+0000b3d2@2373
 1959+000023d2@2375
 1960+0000afd2@2376
 1961+0000afc2@2377
 1962+00002f42@2379
 1963+0000afc0@2380
 1964+0000efe4@2381
 1965+0000efc4@2382
 1966+0000ef64@2383
 1967+00006fc4@2384
 1968+0000efe4@2385
 1969+0000ffe4@2386
 1970+0000ff44@2387
 1971+0000ffe4@2388
 1972+0000ffe6@2389
 1973+0000b3c6@2391
 1974+000033c6@2393
 1975+0000a346@2394
 1976+0000abe2@2395
 1977+00002b60@2398
 1978+0000abe0@2399
 1979+0000ebe4@2400
 1980+0000eb64@2402
 1981+0000ebe4@2403
 1982+0000fb64@2405
 1983+0000fbe4@2406
 1984+00007be6@2407
 1985+0000fbe6@2408
 1986+0000f532@2409
 1987+0000b5b2@2410
 1988+000035b2@2412
 1989+0000a532@2413
 1990+0000a182@2414
 1991+0000a100@2417
 1992+0000a3a4@2418
 1993+0000e3a4@2419
 1994+0000e324@2420
 1995+000061a4@2421
 1996+0000e3a4@2422
 1997+0000f184@2423
 1998+0000f304@2424
 1999+0000f3a4@2425
 2000+000073a6@2426
 2001+0000f3a6@2427
 2002+0000f532@2428
 2003+0000b5b2@2429
 2004+000035b2@2430
 2005+0000a5b2@2431
 2006+0000a182@2432
 2007+00002102@2435
 2008+0000a180@2436
 2009+0000e3a0@2437
 2010+0000e384@2438
 2011+0000e304@2439
 2012+00006180@2440
 2013+0000e3a4@2441
 2014+0000f3a4@2442
 2015+000073a6@2444
 2016+0000f3a6@2445
 2017+0000f936@2446
 2018+0000b9b6@2447
 2019+000039b6@2449
 2020+0000a936@2450
 2021+0000abc2@2451
 2022+00002b40@2454
 2023+0000abc0@2455
 2024+0000ebe4@2456
 2025+00006be4@2458
 2026+0000ebe4@2459
 2027+0000fb64@2461
 2028+0000fbe4@2462
 2029+00007be6@2463
 2030+0000fbe6@2464
 2031+0000f936@2465
 2032+0000f9b6@2466
 2033+000079b6@2468
 2034+0000e9b6@2469
 2035+0000ebc2@2470
 2036+00006bc2@2472
 2037+0000eb40@2473
 2038+0000ebe4@2474
 2039+0000abe4@2475
 2040+0000a560@2476
 2041+000025e0@2477
 2042+0000a5e0@2478
 2043+0000b5e0@2479
 2044+0000b560@2480
 2045+0000b5e0@2481
 2046+000075e2@2482
 2047+0000f5e2@2483
 2048+0000b912@2484
 2049+0000b992@2485
 2050+00003992@2486
 2051+0000a912@2487
 2052+0000abd2@2488
 2053+00002b50@2491
 2054+0000abd0@2492
 2055+0000ebf4@2493
 2056+0000ebd4@2494
 2057+0000eb74@2495
 2058+00006bf4@2496
 2059+0000ebf4@2497
 2060+0000fbf4@2498
 2061+00007bf6@2500
 2062+0000fbf6@2501
 2063+0000f332@2502
 2064+0000b3b2@2503
 2065+000033b2@2505
 2066+0000a332@2506
 2067+0000abd2@2507
 2068+00002b50@2510
 2069+0000abf4@2511
 2070+0000ebf4@2512
 2071+0000eb74@2513
 2072+00006bf4@2514
 2073+0000ebf4@2515
 2074+0000fbd0@2516
 2075+0000fb74@2517
 2076+0000fbf4@2518
 2077+00007bf6@2519
 2078+0000fbf6@2520
 2079+0000b356@2521
 2080+0000b3d6@2522
 2081+00002356@2524
 2082+0000afd6@2525
 2083+0000afc2@2526
 2084+00002f42@2528
 2085+0000afc0@2529
 2086+0000efe4@2530
 2087+0000ef44@2532
 2088+00006fc4@2533
 2089+0000efe4@2534
 2090+0000ffe4@2535
 2091+0000ff44@2536
 2092+0000ffe4@2537
 2093+0000ffe6@2538
 2094+0000b3c6@2540
 2095+000033c6@2542
 2096+0000a346@2543
 2097+0000abe2@2544
 2098+00002b60@2547
 2099+0000abe0@2548
 2100+0000ebe4@2549
 2101+0000eb64@2551
 2102+0000ebe4@2552
 2103+0000fb64@2554
 2104+0000fbe4@2555
 2105+00007be6@2556
 2106+0000fbe6@2557
 2107+0000f532@2558
 2108+0000b5b2@2559
 2109+000035b2@2561
 2110+0000a532@2562
 2111+0000a182@2563
 2112+0000a180@2566
 2113+0000a3a4@2567
 2114+0000e3a4@2568
 2115+0000e324@2569
 2116+000063a4@2570
 2117+0000e3a4@2571
 2118+0000f3a4@2572
 2119+0000f324@2573
 2120+0000f3a4@2574
 2121+000073a6@2575
 2122+0000f3a6@2576
 2123+0000f532@2577
 2124+0000b5b2@2578
 2125+000035b2@2579
 2126+0000a5b2@2580
 2127+0000a182@2581
 2128+00002102@2584
 2129+0000a180@2585
 2130+0000e3a0@2586
 2131+0000e384@2587
 2132+0000e304@2588
 2133+00006184@2589
 2134+0000e3a4@2590
 2135+0000f3a4@2591
 2136+0000f304@2592
 2137+000073a6@2593
 2138+0000f3a6@2594
 2139+0000f93a@2595
 2140+0000b9ba@2596
 2141+000039ba@2598
 2142+0000a93a@2599
 2143+0000abc2@2600
 2144+00002b40@2603
 2145+0000abc0@2604
 2146+0000ebe4@2605
 2147+00006be4@2607
 2148+0000ebe4@2608
 2149+0000fb64@2610
 2150+0000fbe4@2611
 2151+00007be6@2612
 2152+0000fbe6@2613
 2153+0000f93a@2614
 2154+0000f9ba@2615
 2155+000079ba@2617
 2156+0000e9ba@2618
 2157+0000ebc2@2619
 2158+00006bc2@2621
 2159+0000ebc0@2622
 2160+0000ebe4@2623
 2161+0000abe4@2624
 2162+0000a324@2625
 2163+000023a4@2626
 2164+0000a3a4@2627
 2165+0000b3a4@2628
 2166+0000b324@2629
 2167+0000b3a4@2630
 2168+000073a6@2631
 2169+0000f3a6@2632
 2170+0000b9f2@2633
 2171+000039f2@2635
 2172+0000a972@2636
 2173+0000a182@2637
 2174+00002100@2640
 2175+0000a180@2641
 2176+0000e3a4@2642
 2177+0000e104@2644
 2178+000063a4@2645
 2179+0000e3a4@2646
 2180+0000f3a4@2647
 2181+000073a6@2649
 2182+0000f3a6@2650
 2183+0000f112@2651
 2184+0000b192@2652
 2185+00003192@2654
 2186+0000a112@2655
 2187+0000a182@2656
 2188+00002100@2659
 2189+0000a3a4@2660
 2190+0000e3a4@2661
 2191+0000e324@2662
 2192+000063a4@2663
 2193+0000e3a4@2664
 2194+0000e180@2665
 2195+0000f304@2666
 2196+0000f3a4@2667
 2197+000073a6@2668
 2198+0000f3a6@2669
 2199+0000f35a@2670
 2200+0000b3da@2671
 2201+0000335a@2673
 2202+0000afda@2674
 2203+0000afc2@2675
 2204+00002f42@2677
 2205+0000afc0@2678
 2206+0000efe4@2679
 2207+0000ef44@2681
 2208+00006fc4@2682
 2209+0000efe4@2683
 2210+0000ffe4@2684
 2211+0000ff40@2685
 2212+0000ffe4@2686
 2213+0000ffe6@2687
 2214+0000b3c6@2689
 2215+000033c6@2691
 2216+0000a346@2692
 2217+0000abe2@2693
 2218+00002b60@2696
 2219+0000abe0@2697
 2220+0000ebe4@2698
 2221+0000eb64@2700
 2222+0000ebe4@2701
 2223+0000fb64@2703
 2224+0000fbe4@2704
 2225+00007be6@2705
 2226+0000fbe6@2706
 2227+0000f532@2707
 2228+0000b5b2@2708
 2229+000035b2@2710
 2230+0000a5b2@2711
 2231+0000a182@2712
 2232+0000a180@2715
 2233+0000a3a4@2716
 2234+0000e3a4@2717
 2235+0000e324@2718
 2236+000063a4@2719
 2237+0000e3a4@2720
 2238+0000f384@2721
 2239+0000f324@2722
 2240+0000f3a4@2723
 2241+000073a6@2724
 2242+0000f3a6@2725
 2243+0000f532@2726
 2244+0000b5b2@2727
 2245+000035b2@2728
 2246+0000a532@2729
 2247+0000a182@2730
 2248+00002102@2733
 2249+0000a180@2734
 2250+0000e3a0@2735
 2251+0000e3a4@2736
 2252+0000e304@2737
 2253+00006180@2738
 2254+0000e3a4@2739
 2255+0000f3a4@2740
 2256+0000f304@2741
 2257+000073a6@2742
 2258+0000f3a6@2743
 2259+0000f93e@2744
 2260+0000b9be@2745
 2261+000039be@2747
 2262+0000a93e@2748
 2263+0000abc2@2749
 2264+00002b40@2752
 2265+0000abc0@2753
 2266+0000ebe4@2754
 2267+00006be4@2756
 2268+0000ebe4@2757
 2269+0000ebc0@2758
 2270+0000fb64@2759
 2271+0000fbe4@2760
 2272+00007be6@2761
 2273+0000fbe6@2762
 2274+0000f93e@2763
 2275+0000f9be@2764
 2276+000079bc@2766
 2277+0000f9bc@2767
 2278+0000ebc0@2768
 2279+00006bc0@2770
 2280+0000ebc0@2771
 2281+0000ebe4@2772
 2282+0000eb64@2774
 2283+00006be4@2775
 2284+0000ebe4@2776
 2285+0000fbe4@2777
 2286+0000fb44@2778
 2287+0000fbe4@2779
 2288+00007be6@2780
 2289+0000fbe6@2781
 2290+0000b112@2782
 2291+0000b192@2783
 2292+00003192@2784
 2293+0000a112@2785
 2294+0000a182@2786
 2295+00002100@2789
 2296+0000a180@2790
 2297+0000e3a4@2791
 2298+0000e384@2792
 2299+0000e104@2793
 2300+000063a4@2794
 2301+0000e3a4@2795
 2302+0000f3a4@2796
 2303+000073a6@2798
 2304+0000f3a6@2799
 2305+0000f112@2800
 2306+0000b192@2801
 2307+00003192@2803
 2308+0000a112@2804
 2309+0000a182@2805
 2310+00002100@2808
 2311+0000a3a4@2809
 2312+0000e3a4@2810
 2313+0000e324@2811
 2314+00006384@2812
 2315+0000e3a4@2813
 2316+0000f180@2814
 2317+0000f304@2815
 2318+0000f3a4@2816
 2319+000073a6@2817
 2320+0000f3a6@2818
 2321+0000f3de@2819
 2322+0000b3de@2820
 2323+0000335e@2822
 2324+0000afde@2823
 2325+0000afc2@2824
 2326+00002fc2@2826
 2327+0000afc0@2827
 2328+0000efe4@2828
 2329+0000ef44@2830
 2330+00006fc0@2831
 2331+0000efe4@2832
 2332+0000ffe4@2833
 2333+0000ff44@2834
 2334+0000ffe4@2835
 2335+0000ffe6@2836
 2336+0000b3c6@2838
 2337+000033c6@2840
 2338+0000a346@2841
 2339+0000abe2@2842
 2340+00002b60@2845
 2341+0000abe0@2846
 2342+0000ebe4@2847
 2343+0000eb64@2849
 2344+0000ebe4@2850
 2345+0000fb64@2852
 2346+0000fbe4@2853
 2347+00007be6@2854
 2348+0000fbe6@2855
 2349+0000f912@2856
 2350+0000b992@2857
 2351+00003992@2859
 2352+0000a992@2860
 2353+0000a7a2@2861
 2354+0000a7a0@2864
 2355+0000a7a4@2865
 2356+0000e7a4@2866
 2357+0000e724@2867
 2358+000067a4@2868
 2359+0000e7a4@2869
 2360+0000f7a0@2870
 2361+0000f724@2871
 2362+0000f7a4@2872
 2363+000077a6@2873
 2364+0000f7a6@2874
 2365+0000f932@2875
 2366+0000b9b2@2876
 2367+000039b2@2877
 2368+0000a932@2878
 2369+0000a7a2@2879
 2370+00002722@2882
 2371+0000a7a0@2883
 2372+0000e7a0@2884
 2373+0000e7a4@2885
 2374+0000e724@2886
 2375+000067a4@2887
 2376+0000e7a4@2888
 2377+0000f7a4@2889
 2378+0000f724@2890
 2379+000077a6@2891
 2380+0000f7a6@2892
 2381+0000f932@2893
 2382+0000f9b2@2894
 2383+000079b2@2896
 2384+0000e932@2897
 2385+0000e7a2@2898
 2386+00006720@2901
 2387+0000e7a0@2902
 2388+0000e7a4@2903
 2389+0000a1e4@2904
 2390+000021e4@2905
 2391+0000a1e4@2906
 2392+0000b164@2908
 2393+0000b1e4@2909
 2394+000071e6@2910
 2395+0000f1e6@2911
 2396+0000f932@2912
 2397+0000f9b2@2913
 2398+000079b2@2915
 2399+0000e9b2@2916
 2400+0000e7a2@2917
 2401+000067a2@2919
 2402+0000e7a0@2920
 2403+0000a7a4@2922
 2404+0000a164@2923
 2405+000021e4@2924
 2406+0000a1e4@2925
 2407+0000b1e4@2926
 2408+0000b164@2927
 2409+0000b1e4@2928
 2410+000071e6@2929
 2411+0000f1e6@2930
 2412+0000b11e@2931
 2413+0000b19e@2932
 2414+0000319e@2933
 2415+0000a11e@2934
 2416+0000a9d2@2935
 2417+00002950@2938
 2418+0000a9d0@2939
 2419+0000ebf4@2940
 2420+0000ebd4@2941
 2421+0000e954@2942
 2422+00006bf4@2943
 2423+0000ebf4@2944
 2424+0000fbf4@2945
 2425+00007bf6@2947
 2426+0000f9f6@2948
 2427+0000f31e@2949
 2428+0000b39e@2950
 2429+0000339e@2952
 2430+0000a31e@2953
 2431+0000a9d2@2954
 2432+00002950@2957
 2433+0000abf4@2958
 2434+0000ebf4@2959
 2435+0000eb74@2960
 2436+00006bf4@2961
 2437+0000ebf4@2962
 2438+0000f9d0@2963
 2439+0000fb54@2964
 2440+0000fbf4@2965
 2441+00007bf6@2966
 2442+0000fbf6@2967
 2443+0000b51e@2968
 2444+0000b59e@2969
 2445+0000359e@2971
 2446+0000adde@2972
 2447+0000a9d2@2973
 2448+00002952@2975
 2449+0000a9d0@2976
 2450+0000e9f4@2977
 2451+0000e9d4@2978
 2452+0000eb54@2979
 2453+000069d4@2980
 2454+0000ebf4@2981
 2455+0000fbf4@2982
 2456+0000fb54@2983
 2457+0000fbf4@2984
 2458+0000fbf6@2985
 2459+0000ff5e@2986
 2460+0000b79e@2987
 2461+0000379e@2989
 2462+0000a71e@2990
 2463+0000a9d2@2991
 2464+00002950@2994
 2465+0000a9d0@2995
 2466+0000ebf4@2996
 2467+0000ebd4@2997
 2468+0000eb54@2998
 2469+0000e9f4@2999
 2470+0000ebf4@3000
 2471+0000fb74@3001
 2472+0000fbf4@3002
 2473+00007bf6@3003
 2474+0000fbf6@3004
 2475+0000f91e@3005
 2476+0000b99e@3006
 2477+0000399e@3008
 2478+0000a99e@3009
 2479+0000a5f2@3010
 2480+0000a570@3013
 2481+0000a7f4@3014
 2482+0000e7f4@3015
 2483+0000e774@3016
 2484+000065f4@3017
 2485+0000e7f4@3018
 2486+0000f7f4@3019
 2487+0000f774@3020
 2488+0000f7f4@3021
 2489+000077f6@3022
 2490+0000f7f6@3023
 2491+0000b93e@3024
 2492+0000b9be@3025
 2493+000039be@3026
 2494+0000a9be@3027
 2495+0000adf2@3028
 2496+0000a5f2@3029
 2497+00002572@3031
 2498+0000a5f0@3032
 2499+0000e7f0@3033
 2500+0000e7f4@3034
 2501+0000e774@3035
 2502+000065f4@3036
 2503+0000e7f4@3037
 2504+0000f7f4@3038
 2505+0000f774@3039
 2506+000077f6@3040
 2507+0000f7f6@3041
 2508+0000ff1e@3042
 2509+0000bb9e@3043
 2510+00003b9e@3045
 2511+0000ab1e@3046
 2512+0000a5f2@3047
 2513+00002570@3050
 2514+0000a5f0@3051
 2515+0000e7f4@3052
 2516+000067f4@3054
 2517+0000e5f4@3055
 2518+0000e7f4@3056
 2519+0000f774@3057
 2520+0000f7f4@3058
 2521+000077f6@3059
 2522+0000f7f6@3060
 2523+0000f91e@3061
 2524+0000b99e@3062
 2525+0000399e@3064
 2526+0000a99e@3065
 2527+0000a5f2@3066
 2528+000025f2@3068
 2529+0000a570@3069
 2530+0000a5f0@3070
 2531+0000e7f4@3071
 2532+0000e774@3072
 2533+000065f4@3073
 2534+0000e7f4@3074
 2535+0000f7f4@3075
 2536+0000f574@3076
 2537+0000f7f4@3077
 2538+000077f6@3078
 2539+0000f7f6@3079
 2540+0000b93e@3080
 2541+0000b9be@3081
 2542+000039be@3082
 2543+0000a93e@3083
 2544+0000adf2@3084
 2545+0000a5f2@3085
 2546+00002570@3087
 2547+0000a5f0@3088
 2548+0000e7f4@3089
 2549+0000e774@3091
 2550+000067f4@3092
 2551+0000e7f4@3093
 2552+0000f7f4@3094
 2553+000077f6@3096
 2554+0000f7f6@3097
 2555+0000ff1e@3098
 2556+0000bb9e@3099
 2557+00003b9e@3101
 2558+0000ab1e@3102
 2559+0000a5f2@3103
 2560+00002570@3106
 2561+0000a7f4@3107
 2562+0000e7f4@3108
 2563+0000e774@3109
 2564+000067f4@3110
 2565+0000e7f4@3111
 2566+0000f5f0@3112
 2567+0000f774@3113
 2568+0000f7f4@3114
 2569+000077f6@3115
 2570+0000f7f6@3116
 2571+0000b91e@3117
 2572+0000b99e@3118
 2573+0000299e@3120
 2574+0000adfa@3121
 2575+0000a5f2@3122
 2576+00002572@3124
 2577+0000a5f0@3125
 2578+0000e5f4@3126
 2579+0000e774@3128
 2580+000067f4@3129
 2581+0000e7f4@3130
 2582+0000f7f4@3131
 2583+0000f770@3132
 2584+0000f7f4@3133
 2585+0000f7f6@3134
 2586+0000fd7e@3135
 2587+0000b9be@3136
 2588+000039be@3138
 2589+0000a93e@3139
 2590+0000a5f2@3140
 2591+00002570@3143
 2592+0000a5f0@3144
 2593+0000e7f4@3145
 2594+0000e774@3147
 2595+0000e7f4@3148
 2596+0000f774@3150
 2597+0000f7f4@3151
 2598+000077f6@3152
 2599+0000f7f6@3153
 2600+0000fb1e@3154
 2601+0000bb9e@3155
 2602+00003b9e@3157
 2603+0000ab9e@3158
 2604+0000a5f2@3159
 2605+0000a570@3162
 2606+0000a7f4@3163
 2607+0000e7f4@3164
 2608+0000e774@3165
 2609+000065f4@3166
 2610+0000e7f4@3167
 2611+0000f7f4@3168
 2612+0000f774@3169
 2613+0000f7f4@3170
 2614+000077f6@3171
 2615+0000f7f6@3172
 2616+0000b91e@3173
 2617+0000b99e@3174
 2618+0000399e@3175
 2619+0000a99e@3176
 2620+0000adf2@3177
 2621+0000a5f2@3178
 2622+00002572@3180
 2623+0000a5f0@3181
 2624+0000e7f4@3182
 2625+0000e774@3184
 2626+000065f4@3185
 2627+0000e7f4@3186
 2628+0000f7f4@3187
 2629+0000f774@3188
 2630+000077f6@3189
 2631+0000f7f6@3190
 2632+0000fd1e@3191
 2633+0000f99e@3192
 2634+0000799e@3194
 2635+0000f91e@3195
 2636+0000e5f2@3196
 2637+00006570@3199
 2638+0000e5f0@3200
 2639+0000e5f4@3201
 2640+0000a100@3202
 2641+00002180@3203
 2642+0000a180@3204
 2643+0000b180@3205
 2644+0000b100@3206
 2645+0000b180@3207
 2646+00007182@3208
 2647+0000f182@3209
 2648+0000f9be@3210
 2649+0000b9be@3211
 2650+0000393e@3213
 2651+0000a9be@3214
 2652+0000a5f2@3215
 2653+000025f2@3217
 2654+0000a5f0@3218
 2655+0000e7f4@3220
 2656+0000e774@3221
 2657+000065f4@3222
 2658+0000e7f4@3223
 2659+0000f7f4@3224
 2660+0000f574@3225
 2661+0000f7f4@3226
 2662+000077f6@3227
 2663+0000f7f6@3228
 2664+0000bb9e@3229
 2665+00003b9e@3231
 2666+0000ab1e@3232
 2667+0000a5f2@3233
 2668+00002570@3236
 2669+0000a5f0@3237
 2670+0000e7f4@3238
 2671+0000e774@3240
 2672+000067f4@3241
 2673+0000e7f4@3242
 2674+0000f7f4@3243
 2675+000077f6@3245
 2676+0000f7f6@3246
 2677+0000fd1a@3247
 2678+0000b99a@3248
 2679+0000399a@3250
 2680+0000a91a@3251
 2681+0000a5f2@3252
 2682+00002570@3255
 2683+0000a7f4@3256
 2684+0000e7f4@3257
 2685+0000e774@3258
 2686+000067f4@3259
 2687+0000e7f4@3260
 2688+0000e5f0@3261
 2689+0000f774@3262
 2690+0000f7f4@3263
 2691+000077f6@3264
 2692+0000f7f6@3265
 2693+0000b93a@3266
 2694+0000b9ba@3267
 2695+0000a93a@3269
 2696+0000adfa@3270
 2697+0000a5f2@3271
 2698+00002572@3273
 2699+0000a5f0@3274
 2700+0000e5f4@3275
 2701+0000e774@3277
 2702+000065f0@3278
 2703+0000e7f4@3279
 2704+0000f7f4@3280
 2705+0000f770@3281
 2706+0000f7f4@3282
 2707+0000f7f6@3283
 2708+0000fffe@3284
 2709+0000bb9a@3285
 2710+00003b9a@3287
 2711+0000ab1a@3288
 2712+0000a5f2@3289
 2713+00002570@3292
 2714+0000a5f0@3293
 2715+0000e7f4@3294
 2716+0000e774@3296
 2717+0000e7f4@3297
 2718+0000f774@3299
 2719+0000f7f4@3300
 2720+000077f6@3301
 2721+0000f7f6@3302
 2722+0000f81a@3303
 2723+0000b89a@3304
 2724+0000389a@3306
 2725+0000a89a@3307
 2726+0000a4f2@3308
 2727+0000a470@3311
 2728+0000a674@3312
 2729+0000e6f4@3313
 2730+00006474@3315
 2731+0000e674@3316
 2732+0000f6f4@3317
 2733+00007676@3320
 2734+0000f676@3321
 2735+0000f8ba@3322
 2736+0000b8ba@3323
 2737+000038ba@3324
 2738+0000a83a@3325
 2739+0000acf2@3326
 2740+0000a4f2@3327
 2741+00002472@3329
 2742+0000a470@3330
 2743+0000e6f0@3331
 2744+0000e6f4@3332
 2745+00006470@3334
 2746+0000e674@3335
 2747+0000f6f4@3336
 2748+000076f6@3338
 2749+0000f476@3339
 2750+0000fe1e@3340
 2751+0000ba9a@3341
 2752+00003a1a@3343
 2753+0000aa1a@3344
 2754+0000a4f2@3345
 2755+00002470@3348
 2756+0000a470@3349
 2757+0000e6f4@3350
 2758+000066f4@3352
 2759+0000e474@3353
 2760+0000f6f4@3355
 2761+00007676@3357
 2762+0000f676@3358
 2763+0000f21a@3359
 2764+0000b29a@3360
 2765+0000321a@3362
 2766+0000a21a@3363
 2767+0000a4f2@3364
 2768+000024f2@3366
 2769+0000a470@3367
 2770+0000e470@3368
 2771+0000e6f4@3369
 2772+00006474@3371
 2773+0000e674@3372
 2774+0000f6f4@3373
 2775+00007676@3376
 2776+0000f676@3377
 2777+0000b29a@3378
 2778+0000329a@3380
 2779+0000a29a@3381
 2780+0000a4f2@3382
 2781+0000a472@3384
 2782+000024f0@3385
 2783+0000a4f0@3386
 2784+0000e6f4@3387
 2785+0000e674@3388
 2786+000064f4@3390
 2787+0000e6f4@3391
 2788+0000f6f4@3392
 2789+0000f674@3393
 2790+00007676@3394
 2791+0000f6f6@3395
 2792+0000f29a@3396
 2793+0000b21a@3397
 2794+0000329a@3399
 2795+0000a29a@3400
 2796+0000a4f2@3401
 2797+0000a472@3402
 2798+000024f0@3404
 2799+0000a6f4@3405
 2800+0000e6f4@3406
 2801+0000e674@3407
 2802+00006674@3408
 2803+0000e6f4@3409
 2804+0000f4f0@3410
 2805+0000f674@3411
 2806+000076f6@3413
 2807+0000f6f6@3414
 2808+0000b22e@3415
 2809+0000a2ae@3418
 2810+0000a082@3420
 2811+0000a002@3421
 2812+00002082@3422
 2813+0000a080@3423
 2814+0000e0a4@3424
 2815+0000e024@3425
 2816+0000e204@3426
 2817+00006084@3427
 2818+0000e2a4@3428
 2819+0000f2a4@3429
 2820+0000f204@3430
 2821+0000f2a6@3432
 2822+0000f2ae@3433
 2823+0000f22e@3435
 2824+0000722e@3436
 2825+0000e2ae@3437
 2826+0000e082@3438
 2827+0000e002@3439
 2828+00006080@3441
 2829+0000e080@3442
 2830+0000e2a4@3443
 2831+0000a60c@3444
 2832+0000260c@3445
 2833+0000a68c@3446
 2834+0000b68c@3448
 2835+0000b60c@3449
 2836+0000768e@3450
 2837+0000f68e@3451
 2838+0000f496@3452
 2839+0000b416@3453
 2840+00003496@3455
 2841+0000a496@3456
 2842+0000aaf2@3457
 2843+0000aaf0@3460
 2844+0000aa74@3461
 2845+0000eaf4@3462
 2846+00006af4@3464
 2847+0000ea74@3465
 2848+0000fa74@3466
 2849+0000faf4@3467
 2850+00007af6@3469
 2851+0000fa76@3470
 2852+0000b426@3471
 2853+0000b4a6@3472
 2854+000034a6@3473
 2855+0000a4a6@3474
 2856+0000a472@3475
 2857+0000a4f2@3476
 2858+000024f2@3478
 2859+0000a470@3479
 2860+0000e670@3480
 2861+0000e6f4@3481
 2862+000064f4@3483
 2863+0000e674@3484
 2864+0000f674@3485
 2865+0000f6f4@3486
 2866+000076f6@3487
 2867+0000f6f6@3488
 2868+0000f606@3489
 2869+0000b686@3490
 2870+00003686@3492
 2871+0000a606@3493
 2872+0000a472@3494
 2873+0000a4f2@3495
 2874+000024f0@3497
 2875+0000a470@3498
 2876+0000e474@3499
 2877+0000e6f4@3500
 2878+000066f4@3501
 2879+0000e4f4@3502
 2880+0000e474@3503
 2881+0000f6f4@3504
 2882+000074f6@3506
 2883+0000f676@3507
 2884+0000f626@3508
 2885+0000b6a6@3509
 2886+000036a6@3511
 2887+0000a626@3512
 2888+0000a472@3513
 2889+0000a4f2@3514
 2890+000024f2@3515
 2891+0000a470@3516
 2892+0000e474@3517
 2893+0000e6f4@3518
 2894+000064f4@3520
 2895+0000e674@3521
 2896+0000f674@3522
 2897+0000f6f4@3523
 2898+000076f6@3525
 2899+0000f676@3526
 2900+0000b226@3527
 2901+0000b2a6@3528
 2902+000032a6@3529
 2903+0000a226@3530
 2904+0000a002@3531
 2905+0000a082@3532
 2906+00002080@3534
 2907+0000a000@3535
 2908+0000e2a4@3536
 2909+00006004@3539
 2910+0000e2a4@3540
 2911+0000f2a4@3541
 2912+0000f204@3542
 2913+00007226@3543
 2914+0000f2a6@3544
 2915+0000f8be@3545
 2916+0000b9be@3546
 2917+0000b93e@3547
 2918+0000393e@3548
 2919+0000a9be@3549
 2920+0000abc2@3550
 2921+0000ab42@3552
 2922+00002b40@3553
 2923+0000abe4@3554
 2924+0000ebe4@3555
 2925+0000eb64@3556
 2926+00006b64@3557
 2927+0000ebe4@3558
 2928+0000fbe4@3559
 2929+0000fb64@3561
 2930+00007b46@3562
 2931+0000fbe6@3563
 2932+0000b3a6@3564
 2933+0000b326@3566
 2934+0000a326@3567
 2935+0000a3a6@3568
 2936+0000a182@3569
 2937+0000a102@3570
 2938+00002102@3571
 2939+0000a180@3572
 2940+0000e3a4@3573
 2941+0000e1a4@3574
 2942+0000e324@3575
 2943+00006104@3576
 2944+0000e3a4@3577
 2945+0000f3a4@3578
 2946+0000f324@3580
 2947+0000f326@3581
 2948+0000f196@3582
 2949+0000b196@3583
 2950+0000b116@3584
 2951+00003116@3585
 2952+0000a196@3586
 2953+0000a182@3587
 2954+0000a102@3589
 2955+00002100@3590
 2956+0000a180@3591
 2957+0000e3a4@3592
 2958+0000e1a4@3593
 2959+00006304@3594
 2960+0000e104@3595
 2961+0000e1a4@3596
 2962+0000f3a4@3597
 2963+0000f324@3598
 2964+00007126@3599
 2965+0000f3a6@3600
 2966+0000f196@3601
 2967+0000b196@3602
 2968+0000b116@3603
 2969+00003116@3604
 2970+0000a196@3605
 2971+0000a182@3606
 2972+0000a102@3608
 2973+0000a100@3609
 2974+0000a3a4@3610
 2975+0000e3a4@3611
 2976+0000e324@3612
 2977+000061a4@3613
 2978+0000e3a4@3614
 2979+0000f3a4@3615
 2980+0000f304@3616
 2981+0000f3a4@3617
 2982+000073a6@3618
 2983+0000f3a6@3619
 2984+0000f15e@3620
 2985+0000b1de@3621
 2986+000031de@3622
 2987+0000a15e@3623
 2988+0000afc2@3624
 2989+00002f42@3627
 2990+0000afc0@3628
 2991+0000efe0@3629
 2992+0000efc4@3630
 2993+0000ef44@3631
 2994+00006fe4@3632
 2995+0000efe4@3633
 2996+0000ffe4@3634
 2997+0000ff44@3635
 2998+00007fe6@3636
 2999+0000ffe6@3637
 3000+0000f356@3638
 3001+0000b3d6@3639
 3002+000033d6@3641
 3003+0000a356@3642
 3004+0000a7f2@3643
 3005+00002770@3646
 3006+0000a7f0@3647
 3007+0000e7f4@3648
 3008+000067f4@3650
 3009+0000e7f4@3651
 3010+0000f774@3653
 3011+0000f7f4@3654
 3012+000077f6@3655
 3013+0000f7f6@3656
 3014+0000b536@3657
 3015+0000b5b6@3658
 3016+000035b6@3660
 3017+0000a5b6@3661
 3018+0000ab82@3662
 3019+00002b82@3664
 3020+0000ab80@3665
 3021+0000aba4@3666
 3022+0000eba4@3667
 3023+0000eb24@3668
 3024+00006ba4@3669
 3025+0000eba4@3670
 3026+0000fba4@3671
 3027+0000fb04@3672
 3028+0000fba4@3673
 3029+00007ba6@3674
 3030+0000fba6@3675
 3031+0000f716@3676
 3032+0000b796@3677
 3033+00003796@3678
 3034+0000a716@3679
 3035+0000ab82@3680
 3036+00002b00@3683
 3037+0000ab80@3684
 3038+0000eba4@3685
 3039+0000eb04@3687
 3040+00006ba4@3688
 3041+0000eba4@3689
 3042+0000fba4@3690
 3043+00007ba6@3692
 3044+0000fba6@3693
 3045+0000f902@3694
 3046+0000b982@3695
 3047+00003982@3697
 3048+0000a902@3698
 3049+0000abc2@3699
 3050+00002b40@3702
 3051+0000abe4@3703
 3052+0000ebe4@3704
 3053+0000eb64@3705
 3054+00006be4@3706
 3055+0000ebe4@3707
 3056+0000fbc0@3708
 3057+0000fb64@3709
 3058+0000fbe4@3710
 3059+00007be6@3711
 3060+0000fbe6@3712
 3061+0000f902@3713
 3062+0000f982@3714
 3063+0000e982@3716
 3064+0000ebc2@3717
 3065+00006b42@3720
 3066+0000ebc0@3721
 3067+0000ebe4@3722
 3068+0000ebc0@3723
 3069+0000a100@3724
 3070+00002180@3725
 3071+0000a180@3726
 3072+0000b180@3727
 3073+0000b100@3728
 3074+0000b180@3729
 3075+0000f182@3730
 3076+0000f116@3731
 3077+0000b196@3732
 3078+00003196@3734
 3079+0000a116@3735
 3080+0000a182@3736
 3081+00002100@3739
 3082+0000a180@3740
 3083+0000e3a4@3741
 3084+0000e184@3742
 3085+000063a4@3743
 3086+0000e1a4@3744
 3087+0000f324@3746
 3088+0000f3a4@3747
 3089+000073a6@3748
 3090+0000f3a6@3749
 3091+0000f116@3750
 3092+0000b196@3751
 3093+00003196@3753
 3094+0000a116@3754
 3095+0000a182@3755
 3096+00002182@3757
 3097+0000a180@3758
 3098+0000a3a4@3759
 3099+0000e3a4@3760
 3100+0000e324@3761
 3101+000061a4@3762
 3102+0000e3a4@3763
 3103+0000f184@3764
 3104+0000f104@3765
 3105+0000f3a4@3766
 3106+000073a6@3767
 3107+0000f3a6@3768
 3108+0000b162@3769
 3109+0000b1e2@3770
 3110+000031e2@3771
 3111+0000a162@3772
 3112+0000af42@3773
 3113+0000afc2@3774
 3114+00002f42@3776
 3115+0000afc0@3777
 3116+0000efe0@3778
 3117+0000efc4@3779
 3118+0000ef44@3780
 3119+00006fe4@3781
 3120+0000efe4@3782
 3121+0000ffe4@3783
 3122+0000ff64@3784
 3123+00007fe6@3785
 3124+0000ffe6@3786
 3125+0000f346@3787
 3126+0000b3c6@3788
 3127+000033c6@3790
 3128+0000a346@3791
 3129+0000abe2@3792
 3130+00002b60@3795
 3131+0000abe0@3796
 3132+0000ebe4@3797
 3133+00006be4@3799
 3134+0000ebe4@3800
 3135+0000ebe0@3801
 3136+0000fb64@3802
 3137+0000fbe4@3803
 3138+00007be6@3804
 3139+0000fbe6@3805
 3140+0000f736@3806
 3141+0000b7b6@3807
 3142+000037b6@3809
 3143+0000a7b6@3810
 3144+0000ab82@3811
 3145+00002b82@3813
 3146+0000ab80@3814
 3147+0000aba4@3815
 3148+0000eba4@3816
 3149+0000eb24@3817
 3150+00006ba4@3818
 3151+0000eba4@3819
 3152+0000fba4@3820
 3153+0000fb24@3821
 3154+0000fba4@3822
 3155+00007ba6@3823
 3156+0000fba6@3824
 3157+0000f916@3825
 3158+0000b996@3826
 3159+00003996@3827
 3160+0000a916@3828
 3161+0000ab82@3829
 3162+00002b00@3832
 3163+0000ab80@3833
 3164+0000eba4@3834
 3165+0000eb84@3835
 3166+0000eb04@3836
 3167+00006ba4@3837
 3168+0000eba4@3838
 3169+0000fba4@3839
 3170+00007ba6@3841
 3171+0000fba6@3842
 3172+0000f906@3843
 3173+0000b986@3844
 3174+00003986@3846
 3175+0000a906@3847
 3176+0000abc2@3848
 3177+00002b40@3851
 3178+0000abe4@3852
 3179+0000ebe4@3853
 3180+0000eb64@3854
 3181+00006be4@3855
 3182+0000ebe4@3856
 3183+0000fbc4@3857
 3184+0000fb64@3858
 3185+0000fbe4@3859
 3186+00007be6@3860
 3187+0000fbe6@3861
 3188+0000f906@3862
 3189+0000f986@3863
 3190+0000e986@3865
 3191+0000ebc6@3866
 3192+0000ebc2@3867
 3193+00006b42@3869
 3194+0000ebc0@3870
 3195+0000ebe4@3871
 3196+0000ebc0@3872
 3197+0000a100@3873
 3198+00002180@3874
 3199+0000a180@3875
 3200+0000b180@3876
 3201+0000b100@3877
 3202+0000b180@3878
 3203+0000f182@3879
 3204+0000f116@3880
 3205+0000b196@3881
 3206+00003196@3883
 3207+0000a116@3884
 3208+0000a182@3885
 3209+00002100@3888
 3210+0000a180@3889
 3211+0000e3a4@3890
 3212+0000e1a4@3891
 3213+00006324@3892
 3214+0000e1a4@3893
 3215+0000e3a4@3894
 3216+0000f324@3895
 3217+0000f3a4@3896
 3218+000073a6@3897
 3219+0000f3a6@3898
 3220+0000f976@3899
 3221+0000b9f6@3900
 3222+000039f6@3902
 3223+0000a976@3903
 3224+0000a182@3904
 3225+00002182@3906
 3226+0000a180@3907
 3227+0000a3a4@3908
 3228+0000e3a4@3909
 3229+0000e324@3910
 3230+000061a4@3911
 3231+0000e3a4@3912
 3232+0000f184@3913
 3233+0000f104@3914
 3234+0000f3a4@3915
 3235+000073a6@3916
 3236+0000f3a6@3917
 3237+0000f166@3918
 3238+0000b1e6@3919
 3239+000031e6@3920
 3240+0000a166@3921
 3241+0000af42@3922
 3242+0000afc2@3923
 3243+00002f42@3925
 3244+0000afc0@3926
 3245+0000efc0@3927
 3246+0000efe4@3928
 3247+0000ef64@3929
 3248+00006fe4@3930
 3249+0000efe4@3931
 3250+0000ffe4@3932
 3251+00007fe6@3934
 3252+0000ffe6@3935
 3253+0000f346@3936
 3254+0000b3c6@3937
 3255+000033c6@3939
 3256+0000a346@3940
 3257+0000abe2@3941
 3258+00002b60@3944
 3259+0000abe0@3945
 3260+0000ebe4@3946
 3261+00006be4@3948
 3262+0000ebe4@3949
 3263+0000fbe4@3950
 3264+0000fb64@3951
 3265+0000fbe4@3952
 3266+00007be6@3953
 3267+0000fbe6@3954
 3268+0000f936@3955
 3269+0000b9b6@3956
 3270+000039b6@3958
 3271+0000a9b6@3959
 3272+0000ab82@3960
 3273+00002b82@3962
 3274+0000ab80@3963
 3275+0000aba4@3964
 3276+0000eba4@3965
 3277+0000eb24@3966
 3278+00006ba4@3967
 3279+0000eba4@3968
 3280+0000fba4@3969
 3281+0000fb04@3970
 3282+0000fba4@3971
 3283+00007ba6@3972
 3284+0000fba6@3973
 3285+0000b316@3974
 3286+0000b396@3975
 3287+00003396@3976
 3288+0000a316@3977
 3289+0000afa2@3978
 3290+0000ada2@3979
 3291+00002d20@3981
 3292+0000ada0@3982
 3293+0000efa4@3983
 3294+0000ef24@3985
 3295+00006fa4@3986
 3296+0000efa4@3987
 3297+0000ff24@3988
 3298+0000ffa4@3989
 3299+00007fa6@3990
 3300+0000ffa6@3991
 3301+0000f90a@3992
 3302+0000b98a@3993
 3303+0000398a@3995
 3304+0000a90a@3996
 3305+0000abc2@3997
 3306+00002b40@4000
 3307+0000abe4@4001
 3308+0000ebe4@4002
 3309+0000eb64@4003
 3310+00006be4@4004
 3311+0000ebe4@4005
 3312+0000fbc4@4006
 3313+0000fb64@4007
 3314+0000fbe4@4008
 3315+00007be6@4009
 3316+0000fbe6@4010
 3317+0000f90a@4011
 3318+0000f98a@4012
 3319+0000e98a@4014
 3320+0000ebca@4015
 3321+0000ebc2@4016
 3322+00006b42@4018
 3323+0000ebc0@4019
 3324+0000ebe4@4020
 3325+0000afe0@4021
 3326+0000a560@4022
 3327+000025e0@4023
 3328+0000a5e0@4024
 3329+0000b5e0@4025
 3330+0000b560@4026
 3331+0000b5e0@4027
 3332+0000f5e2@4028
 3333+0000fd76@4029
 3334+0000b996@4030
 3335+00003996@4032
 3336+0000a916@4033
 3337+0000abd2@4034
 3338+00002b50@4037
 3339+0000abd0@4038
 3340+0000ebf4@4039
 3341+00006b74@4041
 3342+0000ebf4@4042
 3343+0000fb74@4044
 3344+0000fbf4@4045
 3345+00007bf6@4046
 3346+0000fbf6@4047
 3347+0000f916@4048
 3348+0000b996@4049
 3349+00003996@4051
 3350+0000a996@4052
 3351+0000abd2@4053
 3352+00002bd2@4055
 3353+0000ab50@4056
 3354+0000abf4@4057
 3355+0000ebf4@4058
 3356+0000eb74@4059
 3357+00006bf4@4060
 3358+0000ebf4@4061
 3359+0000fbf4@4062
 3360+0000fb54@4063
 3361+0000fbf4@4064
 3362+00007bf6@4065
 3363+0000fbf6@4066
 3364+0000b16a@4067
 3365+0000b1ea@4068
 3366+000031ea@4069
 3367+0000a16a@4070
 3368+0000afc2@4071
 3369+00002f42@4074
 3370+0000afc0@4075
 3371+0000efc0@4076
 3372+0000efc4@4077
 3373+0000ef44@4078
 3374+00006fe0@4079
 3375+0000efe4@4080
 3376+0000ffe4@4081
 3377+0000ff64@4082
 3378+00007fe6@4083
 3379+0000ffe6@4084
 3380+0000f346@4085
 3381+0000b3c6@4086
 3382+000033c6@4088
 3383+0000a346@4089
 3384+0000abe2@4090
 3385+00002b60@4093
 3386+0000abe0@4094
 3387+0000ebe4@4095
 3388+00006be4@4097
 3389+0000ebe4@4098
 3390+0000fb64@4100
 3391+0000fbe4@4101
 3392+00007be6@4102
 3393+0000fbe6@4103
 3394+0000f336@4104
 3395+0000b3b6@4105
 3396+000033b6@4107
 3397+0000a3b6@4108
 3398+0000ada2@4109
 3399+00002da2@4111
 3400+0000ada0@4112
 3401+0000eda4@4113
 3402+0000efa4@4114
 3403+0000ef24@4115
 3404+00006da4@4116
 3405+0000efa4@4117
 3406+0000ffa4@4118
 3407+0000ff24@4119
 3408+0000ffa4@4120
 3409+00007fa6@4121
 3410+0000ffa6@4122
 3411+0000b516@4123
 3412+0000b596@4124
 3413+00003596@4125
 3414+0000a516@4126
 3415+0000ada2@4127
 3416+00002d20@4130
 3417+0000ada0@4131
 3418+0000efa4@4132
 3419+0000eda4@4133
 3420+0000ef24@4134
 3421+00006fa4@4135
 3422+0000efa4@4136
 3423+0000ffa4@4137
 3424+00007fa6@4139
 3425+0000ffa6@4140
 3426+0000f90e@4141
 3427+0000b98e@4142
 3428+0000398e@4144
 3429+0000a90e@4145
 3430+0000abc2@4146
 3431+00002b40@4149
 3432+0000abe4@4150
 3433+0000ebe4@4151
 3434+0000eb64@4152
 3435+00006be4@4153
 3436+0000ebe4@4154
 3437+0000fbc4@4155
 3438+0000fb64@4156
 3439+0000fbe4@4157
 3440+00007be6@4158
 3441+0000fbe6@4159
 3442+0000f90e@4160
 3443+0000f98e@4161
 3444+0000f98c@4163
 3445+0000fbc0@4164
 3446+0000ebc0@4165
 3447+00006b40@4167
 3448+0000ebc0@4168
 3449+0000ebe4@4169
 3450+0000eb44@4171
 3451+00006bc4@4172
 3452+0000ebe4@4173
 3453+0000fbe4@4174
 3454+0000fb44@4175
 3455+0000fbe4@4176
 3456+0000fbe6@4177
 3457+0000fb56@4178
 3458+0000b996@4179
 3459+00003996@4181
 3460+0000a916@4182
 3461+0000abd2@4183
 3462+00002b50@4186
 3463+0000abd0@4187
 3464+0000ebf4@4188
 3465+00006b74@4190
 3466+0000ebf4@4191
 3467+0000fb74@4193
 3468+0000fbf4@4194
 3469+00007bf6@4195
 3470+0000fbf6@4196
 3471+0000f916@4197
 3472+0000b996@4198
 3473+00003996@4200
 3474+0000a996@4201
 3475+0000abd2@4202
 3476+00002bd2@4204
 3477+0000abd0@4205
 3478+0000abf4@4206
 3479+0000ebf4@4207
 3480+0000eb74@4208
 3481+00006bf4@4209
 3482+0000ebf4@4210
 3483+0000fbf4@4211
 3484+0000fb54@4212
 3485+0000fbf4@4213
 3486+00007bf6@4214
 3487+0000fbf6@4215
 3488+0000b16e@4216
 3489+0000b1ee@4217
 3490+000031ee@4218
 3491+0000a16e@4219
 3492+0000afc2@4220
 3493+00002f42@4223
 3494+0000afc0@4224
 3495+0000efe0@4225
 3496+0000efc4@4226
 3497+0000ef44@4227
 3498+00006fe4@4228
 3499+0000efe4@4229
 3500+0000ffe4@4230
 3501+0000ffc4@4231
 3502+00007fe6@4232
 3503+0000ffe6@4233
 3504+0000f346@4234
 3505+0000b3c6@4235
 3506+000033c6@4237
 3507+0000a346@4238
 3508+0000abe2@4239
 3509+00002b60@4242
 3510+0000abe0@4243
 3511+0000ebe4@4244
 3512+00006be4@4246
 3513+0000ebe4@4247
 3514+0000fbe4@4248
 3515+0000fb64@4249
 3516+0000fbe4@4250
 3517+00007be6@4251
 3518+0000fbe6@4252
 3519+0000b536@4253
 3520+0000b5b6@4254
 3521+000025b6@4256
 3522+0000a5b6@4257
 3523+0000ada2@4258
 3524+00002da2@4260
 3525+0000ada0@4261
 3526+0000eda4@4262
 3527+0000ef24@4264
 3528+00006da4@4265
 3529+0000efa4@4266
 3530+0000ffa4@4267
 3531+0000ff24@4268
 3532+0000ffa4@4269
 3533+00007fa6@4270
 3534+0000ffa6@4271
 3535+0000b796@4272
 3536+00003796@4274
 3537+0000a716@4275
 3538+0000ada2@4276
 3539+00002d20@4279
 3540+0000ada0@4280
 3541+0000efa4@4281
 3542+0000ef24@4283
 3543+00006fa4@4284
 3544+0000efa4@4285
 3545+0000ffa4@4286
 3546+00007fa6@4288
 3547+0000ffa6@4289
 3548+0000f912@4290
 3549+0000b992@4291
 3550+00003992@4293
 3551+0000a912@4294
 3552+0000abc2@4295
 3553+00002b40@4298
 3554+0000abe4@4299
 3555+0000ebe4@4300
 3556+0000eb64@4301
 3557+00006be4@4302
 3558+0000ebe4@4303
 3559+0000fbc0@4304
 3560+0000fb64@4305
 3561+0000fbe4@4306
 3562+00007be6@4307
 3563+0000fbe6@4308
 3564+0000f912@4309
 3565+0000f992@4310
 3566+0000e992@4312
 3567+0000ebd2@4313
 3568+0000ebc2@4314
 3569+00006b42@4316
 3570+0000ebc0@4317
 3571+0000ebe4@4318
 3572+0000afe0@4319
 3573+0000a560@4320
 3574+000025e0@4321
 3575+0000a5e0@4322
 3576+0000b5e0@4323
 3577+0000b560@4324
 3578+0000b5e0@4325
 3579+0000f5e2@4326
 3580+0000fd36@4327
 3581+0000b996@4328
 3582+00003996@4330
 3583+0000a916@4331
 3584+0000abd2@4332
 3585+00002b50@4335
 3586+0000abd0@4336
 3587+0000ebf4@4337
 3588+00006b74@4339
 3589+0000ebf4@4340
 3590+0000fb74@4342
 3591+0000fbf4@4343
 3592+00007bf6@4344
 3593+0000fbf6@4345
 3594+0000f916@4346
 3595+0000b996@4347
 3596+00003996@4349
 3597+0000a996@4350
 3598+0000abd2@4351
 3599+00002bd2@4353
 3600+0000ab50@4354
 3601+0000abf4@4355
 3602+0000ebf4@4356
 3603+0000eb74@4357
 3604+00006bf4@4358
 3605+0000ebf4@4359
 3606+0000fbf4@4360
 3607+0000fb54@4361
 3608+0000fbf4@4362
 3609+00007bf6@4363
 3610+0000fbf6@4364
 3611+0000b172@4365
 3612+0000b1f2@4366
 3613+000031f2@4367
 3614+0000a172@4368
 3615+0000af42@4369
 3616+0000afc2@4370
 3617+00002f42@4372
 3618+0000afc0@4373
 3619+0000efc0@4374
 3620+0000ef44@4376
 3621+00006fc0@4377
 3622+0000efe4@4378
 3623+0000ffe4@4379
 3624+00007fe6@4381
 3625+0000ffe6@4382
 3626+0000f346@4383
 3627+0000b3c6@4384
 3628+000033c6@4386
 3629+0000a346@4387
 3630+0000abe2@4388
 3631+00002b60@4391
 3632+0000abe0@4392
 3633+0000ebe4@4393
 3634+00006be4@4395
 3635+0000ebe4@4396
 3636+0000fb64@4398
 3637+0000fbe4@4399
 3638+00007be6@4400
 3639+0000fbe6@4401
 3640+0000fb16@4402
 3641+0000bb96@4403
 3642+00003b96@4405
 3643+0000ab96@4406
 3644+0000ab82@4407
 3645+00002b82@4409
 3646+0000ab80@4410
 3647+0000aba4@4411
 3648+0000eba4@4412
 3649+0000eb24@4413
 3650+00006ba4@4414
 3651+0000eba4@4415
 3652+0000fba4@4416
 3653+0000fb04@4417
 3654+0000fba4@4418
 3655+00007ba6@4419
 3656+0000fbb6@4420
 3657+0000fb36@4421
 3658+0000bbb6@4422
 3659+00003bb6@4423
 3660+0000ab36@4424
 3661+0000ab02@4425
 3662+0000ab82@4426
 3663+00002b00@4428
 3664+0000ab80@4429
 3665+0000eba4@4430
 3666+0000eb24@4432
 3667+00006ba4@4433
 3668+0000eba4@4434
 3669+0000fb24@4435
 3670+0000fba4@4436
 3671+00007ba6@4437
 3672+0000fba6@4438
 3673+0000f916@4439
 3674+0000b996@4440
 3675+00003996@4442
 3676+0000a916@4443
 3677+0000abc2@4444
 3678+00002b40@4447
 3679+0000abe4@4448
 3680+0000ebe4@4449
 3681+0000eb64@4450
 3682+00006be4@4451
 3683+0000ebe4@4452
 3684+0000fbc4@4453
 3685+0000fb44@4454
 3686+0000fbe4@4455
 3687+00007be6@4456
 3688+0000fbe6@4457
 3689+0000f916@4458
 3690+0000f996@4459
 3691+0000e996@4461
 3692+0000ebd6@4462
 3693+0000ebc2@4463
 3694+00006b42@4465
 3695+0000ebc0@4466
 3696+0000ebe4@4467
 3697+0000afe0@4468
 3698+0000a560@4469
 3699+000025e0@4470
 3700+0000a5e0@4471
 3701+0000b5e0@4472
 3702+0000b560@4473
 3703+0000b5e0@4474
 3704+0000f5e2@4475
 3705+0000fd36@4476
 3706+0000b996@4477
 3707+00003996@4479
 3708+0000a916@4480
 3709+0000abd2@4481
 3710+00002b50@4484
 3711+0000abd0@4485
 3712+0000ebf4@4486
 3713+00006bf4@4488
 3714+0000ebf4@4489
 3715+0000fb74@4491
 3716+0000fbf4@4492
 3717+00007bf6@4493
 3718+0000fbf6@4494
 3719+0000f916@4495
 3720+0000b996@4496
 3721+00003996@4498
 3722+0000a996@4499
 3723+0000abd2@4500
 3724+00002bd2@4502
 3725+0000ab50@4503
 3726+0000abf0@4504
 3727+0000ebf4@4505
 3728+0000eb74@4506
 3729+00006bf4@4507
 3730+0000ebf4@4508
 3731+0000fbf4@4509
 3732+0000fb54@4510
 3733+0000fbf4@4511
 3734+00007bf6@4512
 3735+0000fbf6@4513
 3736+0000f176@4514
 3737+0000b1f6@4515
 3738+000031f6@4516
 3739+0000a176@4517
 3740+0000afc2@4518
 3741+00002f42@4521
 3742+0000afc0@4522
 3743+0000efc0@4523
 3744+0000efc4@4524
 3745+0000ef64@4525
 3746+00006fe4@4526
 3747+0000efe4@4527
 3748+0000ffe4@4528
 3749+00007fe6@4530
 3750+0000ffe6@4531
 3751+0000f346@4532
 3752+0000b3c6@4533
 3753+000033c6@4535
 3754+0000a346@4536
 3755+0000abe2@4537
 3756+00002b60@4540
 3757+0000abe0@4541
 3758+0000ebe4@4542
 3759+00006be4@4544
 3760+0000ebe4@4545
 3761+0000fb64@4547
 3762+0000fbe4@4548
 3763+00007be6@4549
 3764+0000fbe6@4550
 3765+0000fd16@4551
 3766+0000bd96@4552
 3767+00003d96@4554
 3768+0000ad96@4555
 3769+0000ab82@4556
 3770+00002b82@4558
 3771+0000ab80@4559
 3772+0000aba4@4560
 3773+0000eba4@4561
 3774+0000eb24@4562
 3775+00006ba4@4563
 3776+0000eba4@4564
 3777+0000fba4@4565
 3778+0000fb04@4566
 3779+0000fba4@4567
 3780+00007ba6@4568
 3781+0000ffb6@4569
 3782+0000fd36@4570
 3783+0000bdb6@4571
 3784+00003db6@4572
 3785+0000ad36@4573
 3786+0000ab02@4574
 3787+0000ab82@4575
 3788+00002b00@4577
 3789+0000ab80@4578
 3790+0000eba4@4579
 3791+0000eb24@4581
 3792+00006ba4@4582
 3793+0000eba4@4583
 3794+0000fb24@4584
 3795+0000fba4@4585
 3796+00007ba6@4586
 3797+0000fba6@4587
 3798+0000f91a@4588
 3799+0000b99a@4589
 3800+0000399a@4591
 3801+0000a91a@4592
 3802+0000abc2@4593
 3803+00002b40@4596
 3804+0000abe4@4597
 3805+0000ebe4@4598
 3806+0000eb64@4599
 3807+00006be4@4600
 3808+0000ebe4@4601
 3809+0000fbc0@4602
 3810+0000fb44@4603
 3811+0000fbe4@4604
 3812+00007be6@4605
 3813+0000fbe6@4606
 3814+0000f91a@4607
 3815+0000f99a@4608
 3816+0000e99a@4610
 3817+0000ebc2@4611
 3818+00006b42@4614
 3819+0000ebc0@4615
 3820+0000ebe4@4616
 3821+0000afe0@4617
 3822+0000a560@4618
 3823+000025e0@4619
 3824+0000a5e0@4620
 3825+0000b5e0@4621
 3826+0000b560@4622
 3827+0000b5e0@4623
 3828+0000f5e2@4624
 3829+0000fd36@4625
 3830+0000b996@4626
 3831+00003996@4628
 3832+0000a916@4629
 3833+0000abd2@4630
 3834+00002b50@4633
 3835+0000abd0@4634
 3836+0000ebf4@4635
 3837+00006bf4@4637
 3838+0000ebf4@4638
 3839+0000fb74@4640
 3840+0000fbf4@4641
 3841+00007bf6@4642
 3842+0000fbf6@4643
 3843+0000f916@4644
 3844+0000b996@4645
 3845+00003996@4647
 3846+0000a996@4648
 3847+0000abd2@4649
 3848+00002bd2@4651
 3849+0000ab50@4652
 3850+0000abf0@4653
 3851+0000ebf4@4654
 3852+0000eb74@4655
 3853+00006bf4@4656
 3854+0000ebf4@4657
 3855+0000fbf4@4658
 3856+0000fb54@4659
 3857+0000fbf4@4660
 3858+00007bf6@4661
 3859+0000fbf6@4662
 3860+0000f17a@4663
 3861+0000b1fa@4664
 3862+000031fa@4665
 3863+0000a17a@4666
 3864+0000afc2@4667
 3865+00002f42@4670
 3866+0000afc0@4671
 3867+0000efe0@4672
 3868+0000efc4@4673
 3869+0000ef44@4674
 3870+00006fe4@4675
 3871+0000efe4@4676
 3872+0000ffe4@4677
 3873+00007fe6@4679
 3874+0000ffe6@4680
 3875+0000f346@4681
 3876+0000b3c6@4682
 3877+000033c6@4684
 3878+0000a346@4685
 3879+0000abe2@4686
 3880+00002b60@4689
 3881+0000abe4@4690
 3882+0000ebe4@4691
 3883+0000eb64@4692
 3884+00006be4@4693
 3885+0000ebe4@4694
 3886+0000fb64@4696
 3887+0000fbe4@4697
 3888+00007be6@4698
 3889+0000fbe6@4699
 3890+0000ff16@4700
 3891+0000bf96@4701
 3892+00003f96@4703
 3893+0000af96@4704
 3894+0000ab82@4705
 3895+00002b82@4707
 3896+0000ab80@4708
 3897+0000aba4@4709
 3898+0000eba4@4710
 3899+0000eb24@4711
 3900+00006b84@4712
 3901+0000eba4@4713
 3902+0000fba4@4714
 3903+0000fb04@4715
 3904+0000fba4@4716
 3905+00007ba6@4717
 3906+0000ffb6@4718
 3907+0000ff36@4719
 3908+0000bfb6@4720
 3909+00003fb6@4721
 3910+0000af36@4722
 3911+0000ab82@4723
 3912+00002b00@4726
 3913+0000ab80@4727
 3914+0000eba4@4728
 3915+0000eb24@4730
 3916+00006ba4@4731
 3917+0000eba4@4732
 3918+0000fb24@4733
 3919+0000fba4@4734
 3920+00007ba6@4735
 3921+0000fba6@4736
 3922+0000f91e@4737
 3923+0000b99e@4738
 3924+0000399e@4740
 3925+0000a91e@4741
 3926+0000abc2@4742
 3927+00002b40@4745
 3928+0000abe4@4746
 3929+0000ebe4@4747
 3930+0000eb64@4748
 3931+00006be4@4749
 3932+0000ebe4@4750
 3933+0000fbc4@4751
 3934+0000fb64@4752
 3935+0000fbe4@4753
 3936+00007be6@4754
 3937+0000fbe6@4755
 3938+0000f91e@4756
 3939+0000f99e@4757
 3940+0000f99c@4759
 3941+0000fbc0@4760
 3942+0000ebc0@4761
 3943+00006b40@4763
 3944+0000ebc0@4764
 3945+0000ebe4@4765
 3946+0000eb44@4767
 3947+00006bc4@4768
 3948+0000ebe4@4769
 3949+0000fbe4@4770
 3950+0000fb44@4771
 3951+0000fbe4@4772
 3952+0000fbe6@4773
 3953+0000fb56@4774
 3954+0000b996@4775
 3955+00003996@4777
 3956+0000a916@4778
 3957+0000abd2@4779
 3958+00002b50@4782
 3959+0000abd0@4783
 3960+0000ebf4@4784
 3961+00006bf4@4786
 3962+0000ebf4@4787
 3963+0000fb74@4789
 3964+0000fbf4@4790
 3965+00007bf6@4791
 3966+0000fbf6@4792
 3967+0000fb16@4793
 3968+0000bb96@4794
 3969+00003b96@4796
 3970+0000ab96@4797
 3971+0000abe2@4798
 3972+00002be2@4800
 3973+0000ab60@4801
 3974+0000abe0@4802
 3975+0000ebe4@4803
 3976+0000eb64@4804
 3977+00006be4@4805
 3978+0000ebe4@4806
 3979+0000fbe4@4807
 3980+0000fb64@4808
 3981+0000fbe4@4809
 3982+00007be6@4810
 3983+0000fbe6@4811
 3984+0000f17e@4812
 3985+0000b1fe@4813
 3986+000031fe@4814
 3987+0000a17e@4815
 3988+0000afc2@4816
 3989+00002f42@4819
 3990+0000afc0@4820
 3991+0000efc0@4821
 3992+0000efc4@4822
 3993+0000ef44@4823
 3994+00006fe4@4824
 3995+0000efe4@4825
 3996+0000ffe4@4826
 3997+00007fe6@4828
 3998+0000ffe6@4829
 3999+0000f346@4830
 4000+0000b3c6@4831
 4001+000033c6@4833
 4002+0000a346@4834
 4003+0000abe2@4835
 4004+00002b60@4838
 4005+0000abe4@4839
 4006+0000ebe4@4840
 4007+00006be4@4842
 4008+0000ebe4@4843
 4009+0000fb64@4845
 4010+0000fbe4@4846
 4011+00007be6@4847
 4012+0000fbe6@4848
 4013+0000f716@4849
 4014+0000b796@4850
 4015+00003796@4852
 4016+0000a796@4853
 4017+0000a992@4854
 4018+00002992@4856
 4019+0000a990@4857
 4020+0000e9b4@4858
 4021+0000e994@4859
 4022+0000eb34@4860
 4023+00006b94@4861
 4024+0000ebb4@4862
 4025+0000fbb4@4863
 4026+0000fb14@4864
 4027+0000fbb4@4865
 4028+00007bb6@4866
 4029+0000ffb6@4867
 4030+0000f736@4868
 4031+0000b7b6@4869
 4032+000037b6@4870
 4033+0000a736@4871
 4034+0000a992@4872
 4035+00002910@4875
 4036+0000a990@4876
 4037+0000ebb4@4877
 4038+0000e9b4@4878
 4039+0000eb34@4879
 4040+000069b4@4880
 4041+0000ebb4@4881
 4042+0000fbb4@4882
 4043+00007bb6@4884
 4044+0000fbb6@4885
 4045+0000f922@4886
 4046+0000b9a2@4887
 4047+000039a2@4889
 4048+0000a922@4890
 4049+0000abc2@4891
 4050+00002b40@4894
 4051+0000abe4@4895
 4052+0000ebe4@4896
 4053+0000eb64@4897
 4054+00006be4@4898
 4055+0000ebe4@4899
 4056+0000fbc4@4900
 4057+0000fb64@4901
 4058+0000fbe4@4902
 4059+00007be6@4903
 4060+0000fbe6@4904
 4061+0000f922@4905
 4062+0000f9a2@4906
 4063+0000e9a2@4908
 4064+0000ebe2@4909
 4065+0000ebc2@4910
 4066+00006b42@4912
 4067+0000ebc0@4913
 4068+0000ebe4@4914
 4069+0000ab6c@4915
 4070+0000a96c@4916
 4071+000029ec@4917
 4072+0000a9ec@4918
 4073+0000b9ec@4919
 4074+0000b96c@4920
 4075+0000b9ec@4921
 4076+0000f9ee@4922
 4077+0000fb3e@4923
 4078+0000bbb6@4924
 4079+00003bb6@4926
 4080+0000ab36@4927
 4081+0000abe2@4928
 4082+00002b60@4931
 4083+0000abe0@4932
 4084+0000ebe4@4933
 4085+00006be4@4935
 4086+0000ebe4@4936
 4087+0000fb64@4938
 4088+0000fbe4@4939
 4089+00007be6@4940
 4090+0000fbe6@4941
 4091+0000f916@4942
 4092+0000b996@4943
 4093+00003996@4945
 4094+0000a996@4946
 4095+0000abd2@4947
 4096+00002bd2@4949
 4097+0000abd0@4950
 4098+0000abf0@4951
 4099+0000ebf4@4952
 4100+0000eb74@4953
 4101+00006bf4@4954
 4102+0000ebf4@4955
 4103+0000fbf4@4956
 4104+0000fb54@4957
 4105+0000fbf4@4958
 4106+00007bf6@4959
 4107+0000fbf6@4960
 4108+0000b342@4961
 4109+0000b3c2@4962
 4110+000033c2@4963
 4111+0000a342@4964
 4112+0000af42@4965
 4113+0000afc2@4966
 4114+00002f40@4968
 4115+0000afc0@4969
 4116+0000efc0@4970
 4117+0000efc4@4971
 4118+0000ef44@4972
 4119+00006fc4@4973
 4120+0000efe4@4974
 4121+0000ffe4@4975
 4122+0000ffc4@4976
 4123+00007fe6@4977
 4124+0000ffe6@4978
 4125+0000f346@4979
 4126+0000b3c6@4980
 4127+000033c6@4982
 4128+0000a346@4983
 4129+0000abe2@4984
 4130+00002b60@4987
 4131+0000abe4@4988
 4132+0000ebe4@4989
 4133+00006be4@4991
 4134+0000ebe4@4992
 4135+0000fbe4@4993
 4136+0000fb64@4994
 4137+0000fbe4@4995
 4138+00007be6@4996
 4139+0000fbe6@4997
 4140+0000ff16@4998
 4141+0000bf96@4999
 4142+00003f96@5001
 4143+0000afb6@5002
 4144+0000aba2@5003
 4145+00002ba2@5005
 4146+0000aba0@5006
 4147+0000aba4@5007
 4148+0000eba4@5008
 4149+0000eb24@5009
 4150+00006ba4@5010
 4151+0000eba4@5011
 4152+0000fba4@5012
 4153+0000fb24@5013
 4154+0000fba4@5014
 4155+00007ba6@5015
 4156+0000ffb6@5016
 4157+0000b536@5017
 4158+0000b5b6@5018
 4159+000035b6@5019
 4160+0000a536@5020
 4161+0000a182@5021
 4162+00002100@5024
 4163+0000a180@5025
 4164+0000e3a4@5026
 4165+0000e104@5028
 4166+000061a4@5029
 4167+0000e3a4@5030
 4168+0000f3a4@5031
 4169+000073a6@5033
 4170+0000f3a6@5034
 4171+0000f926@5035
 4172+0000b9a6@5036
 4173+000039a6@5038
 4174+0000a926@5039
 4175+0000abc2@5040
 4176+00002b40@5043
 4177+0000abe4@5044
 4178+0000ebe4@5045
 4179+0000eb64@5046
 4180+00006be4@5047
 4181+0000ebe4@5048
 4182+0000fbc4@5049
 4183+0000fb64@5050
 4184+0000fbe4@5051
 4185+00007be6@5052
 4186+0000fbe6@5053
 4187+0000f926@5054
 4188+0000f9a6@5055
 4189+0000e9a6@5057
 4190+0000ebe2@5058
 4191+0000ebc2@5059
 4192+00006b42@5061
 4193+0000ebc0@5062
 4194+0000ebe4@5063
 4195+0000afe0@5064
 4196+0000a560@5065
 4197+000025e0@5066
 4198+0000a5e0@5067
 4199+0000b5e0@5068
 4200+0000b560@5069
 4201+0000b5e0@5070
 4202+0000f5e2@5071
 4203+0000fd36@5072
 4204+0000b996@5073
 4205+00003996@5075
 4206+0000a916@5076
 4207+0000abd2@5077
 4208+00002b50@5080
 4209+0000abd0@5081
 4210+0000ebf4@5082
 4211+00006bf4@5084
 4212+0000ebf4@5085
 4213+0000fb74@5087
 4214+0000fbf4@5088
 4215+00007bf6@5089
 4216+0000fbf6@5090
 4217+0000f916@5091
 4218+0000b996@5092
 4219+00003996@5094
 4220+0000a996@5095
 4221+0000abd2@5096
 4222+00002bd2@5098
 4223+0000ab50@5099
 4224+0000abf0@5100
 4225+0000ebf4@5101
 4226+0000eb74@5102
 4227+00006bf4@5103
 4228+0000ebf4@5104
 4229+0000fbf4@5105
 4230+0000fb54@5106
 4231+0000fbf4@5107
 4232+00007bf6@5108
 4233+0000fbf6@5109
 4234+0000b346@5110
 4235+0000b3c6@5111
 4236+000033c6@5112
 4237+0000a346@5113
 4238+0000afc2@5114
 4239+00002f42@5117
 4240+0000afc0@5118
 4241+0000efc0@5119
 4242+0000efc4@5120
 4243+0000ef44@5121
 4244+00006fe4@5122
 4245+0000efe4@5123
 4246+0000ffe4@5124
 4247+0000ffc4@5125
 4248+00007fe6@5126
 4249+0000ffe6@5127
 4250+0000f346@5128
 4251+0000b3c6@5129
 4252+000033c6@5131
 4253+0000a346@5132
 4254+0000abe2@5133
 4255+00002b60@5136
 4256+0000abe4@5137
 4257+0000ebe4@5138
 4258+00006be4@5140
 4259+0000ebe4@5141
 4260+0000fb64@5143
 4261+0000fbe4@5144
 4262+00007be6@5145
 4263+0000fbe6@5146
 4264+0000b536@5147
 4265+0000b5b6@5148
 4266+000035b6@5150
 4267+0000a5b6@5151
 4268+0000a182@5152
 4269+00002182@5154
 4270+0000a180@5155
 4271+0000e1a4@5156
 4272+0000e184@5157
 4273+0000e304@5158
 4274+00006184@5159
 4275+0000e3a4@5160
 4276+0000f3a4@5161
 4277+0000f104@5162
 4278+0000f3a4@5163
 4279+000073a6@5164
 4280+0000f7b6@5165
 4281+0000f536@5166
 4282+0000b5b6@5167
 4283+000035b6@5168
 4284+0000a536@5169
 4285+0000a182@5170
 4286+00002100@5173
 4287+0000a180@5174
 4288+0000e3a4@5175
 4289+0000e324@5177
 4290+0000e1a4@5178
 4291+0000f324@5180
 4292+0000f3a4@5181
 4293+000073a6@5182
 4294+0000f3a6@5183
 4295+0000f92a@5184
 4296+0000b9aa@5185
 4297+000039aa@5187
 4298+0000a92a@5188
 4299+0000abc2@5189
 4300+00002b40@5192
 4301+0000abe4@5193
 4302+0000ebe4@5194
 4303+0000eb64@5195
 4304+00006be4@5196
 4305+0000ebe4@5197
 4306+0000fbc4@5198
 4307+0000fb64@5199
 4308+0000fbe4@5200
 4309+00007be6@5201
 4310+0000fbe6@5202
 4311+0000f92a@5203
 4312+0000f9aa@5204
 4313+0000e9aa@5206
 4314+0000ebe2@5207
 4315+0000ebc2@5208
 4316+00006b42@5210
 4317+0000ebc0@5211
 4318+0000ebe4@5212
 4319+0000afe0@5213
 4320+0000a560@5214
 4321+000025e0@5215
 4322+0000a5e0@5216
 4323+0000b5e0@5217
 4324+0000b560@5218
 4325+0000b5e0@5219
 4326+0000f5e2@5220
 4327+0000fd36@5221
 4328+0000b996@5222
 4329+00003996@5224
 4330+0000a916@5225
 4331+0000abd2@5226
 4332+00002b50@5229
 4333+0000abd0@5230
 4334+0000ebf4@5231
 4335+00006bf4@5233
 4336+0000ebf4@5234
 4337+0000fb74@5236
 4338+0000fbf4@5237
 4339+00007bf6@5238
 4340+0000fbf6@5239
 4341+0000f916@5240
 4342+0000b996@5241
 4343+00003996@5243
 4344+0000a996@5244
 4345+0000abd2@5245
 4346+00002bd2@5247
 4347+0000abd0@5248
 4348+0000abf0@5249
 4349+0000ebf4@5250
 4350+0000eb74@5251
 4351+00006bf4@5252
 4352+0000ebf4@5253
 4353+0000fbf4@5254
 4354+0000fb54@5255
 4355+0000fbf4@5256
 4356+00007bf6@5257
 4357+0000fbf6@5258
 4358+0000b34a@5259
 4359+0000b3ca@5260
 4360+000033ca@5261
 4361+0000a34a@5262
 4362+0000afc2@5263
 4363+00002f42@5266
 4364+0000afc0@5267
 4365+0000efe0@5268
 4366+0000efc4@5269
 4367+0000ef44@5270
 4368+00006fc4@5271
 4369+0000efe4@5272
 4370+0000ffe4@5273
 4371+0000ffc4@5274
 4372+00007fe6@5275
 4373+0000ffe6@5276
 4374+0000f346@5277
 4375+0000b3c6@5278
 4376+000033c6@5280
 4377+0000a346@5281
 4378+0000abe2@5282
 4379+00002b60@5285
 4380+0000abe4@5286
 4381+0000ebe4@5287
 4382+0000eb64@5288
 4383+00006be4@5289
 4384+0000ebe4@5290
 4385+0000fbe4@5291
 4386+0000fb64@5292
 4387+0000fbe4@5293
 4388+00007be6@5294
 4389+0000fbe6@5295
 4390+0000b536@5296
 4391+0000b5b6@5297
 4392+000035b6@5299
 4393+0000a5b6@5300
 4394+0000a182@5301
 4395+00002182@5303
 4396+0000a180@5304
 4397+0000e1a4@5305
 4398+0000e304@5307
 4399+00006184@5308
 4400+0000e3a4@5309
 4401+0000f3a4@5310
 4402+0000f304@5311
 4403+0000f3a4@5312
 4404+000073a6@5313
 4405+0000f7b6@5314
 4406+0000f536@5315
 4407+0000b5b6@5316
 4408+000035b6@5317
 4409+0000a536@5318
 4410+0000a182@5319
 4411+00002100@5322
 4412+0000a180@5323
 4413+0000e3a4@5324
 4414+0000e304@5326
 4415+0000e3a4@5327
 4416+0000f3a4@5329
 4417+000073a6@5331
 4418+0000f3a6@5332
 4419+0000f92e@5333
 4420+0000b9ae@5334
 4421+000039ae@5336
 4422+0000a92e@5337
 4423+0000abc2@5338
 4424+00002b40@5341
 4425+0000abe4@5342
 4426+0000ebe4@5343
 4427+0000eb64@5344
 4428+00006be4@5345
 4429+0000ebe4@5346
 4430+0000fbc4@5347
 4431+0000fb64@5348
 4432+0000fbe4@5349
 4433+00007be6@5350
 4434+0000fbe6@5351
 4435+0000f92e@5352
 4436+0000f9ae@5353
 4437+0000f9ac@5355
 4438+0000fbe0@5356
 4439+0000ebc0@5357
 4440+00006b40@5359
 4441+0000ebc0@5360
 4442+0000ebe4@5361
 4443+0000eb44@5363
 4444+00006bc0@5364
 4445+0000ebe4@5365
 4446+0000fbe4@5366
 4447+0000fb44@5367
 4448+0000fbe4@5368
 4449+0000fbe6@5369
 4450+0000fb56@5370
 4451+0000b996@5371
 4452+00003996@5373
 4453+0000a916@5374
 4454+0000abd2@5375
 4455+00002b50@5378
 4456+0000abd0@5379
 4457+0000ebf4@5380
 4458+00006bf4@5382
 4459+0000ebf4@5383
 4460+0000fb74@5385
 4461+0000fbf4@5386
 4462+00007bf6@5387
 4463+0000fbf6@5388
 4464+0000f916@5389
 4465+0000b996@5390
 4466+00003996@5392
 4467+0000a996@5393
 4468+0000abd2@5394
 4469+00002bd2@5396
 4470+0000ab50@5397
 4471+0000abf0@5398
 4472+0000ebf4@5399
 4473+0000eb74@5400
 4474+00006bf4@5401
 4475+0000ebf4@5402
 4476+0000fbf4@5403
 4477+0000fb54@5404
 4478+0000fbf4@5405
 4479+00007bf6@5406
 4480+0000fbf6@5407
 4481+0000b34e@5408
 4482+0000b3ce@5409
 4483+000033ce@5410
 4484+0000a34e@5411
 4485+0000afc2@5412
 4486+00002f40@5415
 4487+0000afc0@5416
 4488+0000efc0@5417
 4489+0000efc4@5418
 4490+0000ef44@5419
 4491+00006fc4@5420
 4492+0000efe4@5421
 4493+0000ffe4@5422
 4494+00007fe6@5424
 4495+0000ffe6@5425
 4496+0000f346@5426
 4497+0000b3c6@5427
 4498+000033c6@5429
 4499+0000a346@5430
 4500+0000abe2@5431
 4501+00002b60@5434
 4502+0000abe4@5435
 4503+0000ebe4@5436
 4504+00006be4@5438
 4505+0000ebe4@5439
 4506+0000fb64@5441
 4507+0000fbe4@5442
 4508+00007be6@5443
 4509+0000fbe6@5444
 4510+0000b536@5445
 4511+0000b5b6@5446
 4512+000035b6@5448
 4513+0000a5b6@5449
 4514+0000a182@5450
 4515+00002102@5452
 4516+0000a180@5453
 4517+0000e1a4@5454
 4518+0000e324@5456
 4519+00006184@5457
 4520+0000e3a4@5458
 4521+0000f3a4@5459
 4522+0000f104@5460
 4523+0000f3a4@5461
 4524+000073a6@5462
 4525+0000f7b6@5463
 4526+0000f536@5464
 4527+0000b5b6@5465
 4528+000035b6@5466
 4529+0000a536@5467
 4530+0000a182@5468
 4531+00002100@5471
 4532+0000a180@5472
 4533+0000e3a4@5473
 4534+0000e304@5475
 4535+0000e1a4@5476
 4536+0000e3a4@5477
 4537+0000f324@5478
 4538+0000f3a4@5479
 4539+000073a6@5480
 4540+0000f3a6@5481
 4541+0000f932@5482
 4542+0000b9b2@5483
 4543+000039b2@5485
 4544+0000a932@5486
 4545+0000abc2@5487
 4546+00002b40@5490
 4547+0000abe4@5491
 4548+0000ebe4@5492
 4549+0000eb64@5493
 4550+00006be4@5494
 4551+0000ebe4@5495
 4552+0000fbc4@5496
 4553+0000fb64@5497
 4554+0000fbe4@5498
 4555+00007be6@5499
 4556+0000fbe6@5500
 4557+0000f932@5501
 4558+0000f9b2@5502
 4559+0000e9b2@5504
 4560+0000ebc2@5505
 4561+00006b42@5508
 4562+0000ebc0@5509
 4563+0000ebe4@5510
 4564+0000afe0@5511
 4565+0000a560@5512
 4566+000025e0@5513
 4567+0000a5e0@5514
 4568+0000b5e0@5515
 4569+0000b560@5516
 4570+0000b5e0@5517
 4571+0000f5e2@5518
 4572+0000fd36@5519
 4573+0000b996@5520
 4574+00003996@5522
 4575+0000a916@5523
 4576+0000abd2@5524
 4577+00002b50@5527
 4578+0000abd0@5528
 4579+0000ebf4@5529
 4580+00006bf4@5531
 4581+0000ebf4@5532
 4582+0000fb74@5534
 4583+0000fbf4@5535
 4584+00007bf6@5536
 4585+0000fbf6@5537
 4586+0000f916@5538
 4587+0000b996@5539
 4588+00003996@5541
 4589+0000a996@5542
 4590+0000abd2@5543
 4591+00002bd2@5545
 4592+0000abd0@5546
 4593+0000abf0@5547
 4594+0000ebf4@5548
 4595+0000eb74@5549
 4596+00006bf4@5550
 4597+0000ebf4@5551
 4598+0000fbf4@5552
 4599+0000fb54@5553
 4600+0000fbf4@5554
 4601+00007bf6@5555
 4602+0000fbf6@5556
 4603+0000b352@5557
 4604+0000b3d2@5558
 4605+000033d2@5559
 4606+0000a352@5560
 4607+0000af42@5561
 4608+0000afc2@5562
 4609+00002f40@5564
 4610+0000afc0@5565
 4611+0000efe0@5566
 4612+0000efc4@5567
 4613+0000ef44@5568
 4614+00006fe4@5569
 4615+0000efe4@5570
 4616+0000ffe4@5571
 4617+00007fe6@5573
 4618+0000ffe6@5574
 4619+0000f346@5575
 4620+0000b3c6@5576
 4621+000033c6@5578
 4622+0000a346@5579
 4623+0000abe2@5580
 4624+00002b60@5583
 4625+0000abe4@5584
 4626+0000ebe4@5585
 4627+0000eb64@5586
 4628+00006be4@5587
 4629+0000ebe4@5588
 4630+0000fb64@5590
 4631+0000fbe4@5591
 4632+00007be6@5592
 4633+0000fbe6@5593
 4634+0000b536@5594
 4635+0000b5b6@5595
 4636+000025b6@5597
 4637+0000a5b6@5598
 4638+0000a182@5599
 4639+00002182@5601
 4640+0000a180@5602
 4641+0000e1a4@5603
 4642+0000e304@5605
 4643+00006184@5606
 4644+0000e3a4@5607
 4645+0000f3a4@5608
 4646+0000f124@5609
 4647+0000f3a4@5610
 4648+000073a6@5611
 4649+0000f7b6@5612
 4650+0000f536@5613
 4651+0000b5b6@5614
 4652+000035b6@5615
 4653+0000a536@5616
 4654+0000a182@5617
 4655+00002100@5620
 4656+0000a180@5621
 4657+0000e3a4@5622
 4658+0000e324@5624
 4659+0000e1a4@5625
 4660+0000f324@5627
 4661+0000f3a4@5628
 4662+000073a6@5629
 4663+0000f3a6@5630
 4664+0000f936@5631
 4665+0000b9b6@5632
 4666+000039b6@5634
 4667+0000a936@5635
 4668+0000abc2@5636
 4669+0000ab40@5639
 4670+0000abe4@5640
 4671+0000ebe4@5641
 4672+0000eb64@5642
 4673+00006be4@5643
 4674+0000ebe4@5644
 4675+0000fbe4@5645
 4676+0000fb64@5646
 4677+0000fbe4@5647
 4678+00007be6@5648
 4679+0000fbe6@5649
 4680+0000f936@5650
 4681+0000f9b6@5651
 4682+0000e9b6@5653
 4683+0000ebc2@5654
 4684+00006b42@5657
 4685+0000ebc0@5658
 4686+0000ebe4@5659
 4687+0000afe0@5660
 4688+0000a560@5661
 4689+000025e0@5662
 4690+0000a5e0@5663
 4691+0000b5e0@5664
 4692+0000b560@5665
 4693+0000b5e0@5666
 4694+0000f5e2@5667
 4695+0000fd36@5668
 4696+0000b996@5669
 4697+00003996@5671
 4698+0000a916@5672
 4699+0000abd2@5673
 4700+00002b50@5676
 4701+0000abd0@5677
 4702+0000ebf4@5678
 4703+00006bf4@5680
 4704+0000ebf4@5681
 4705+0000fb74@5683
 4706+0000fbf4@5684
 4707+00007bf6@5685
 4708+0000fbf6@5686
 4709+0000f336@5687
 4710+0000b3b6@5688
 4711+000033b6@5690
 4712+0000a3b6@5691
 4713+0000abd2@5692
 4714+00002bd2@5694
 4715+0000abd0@5695
 4716+0000abf0@5696
 4717+0000ebf4@5697
 4718+0000eb74@5698
 4719+00006bf4@5699
 4720+0000ebf4@5700
 4721+0000fbf4@5701
 4722+0000fb54@5702
 4723+0000fbf4@5703
 4724+00007bf6@5704
 4725+0000fbf6@5705
 4726+0000b356@5706
 4727+0000b3d6@5707
 4728+000033d6@5708
 4729+0000a356@5709
 4730+0000afc2@5710
 4731+00002f40@5713
 4732+0000afc0@5714
 4733+0000efe0@5715
 4734+0000efc4@5716
 4735+0000ef44@5717
 4736+00006fe4@5718
 4737+0000efe4@5719
 4738+0000ffe4@5720
 4739+00007fe6@5722
 4740+0000ffe6@5723
 4741+0000f346@5724
 4742+0000b3c6@5725
 4743+000033c6@5727
 4744+0000a346@5728
 4745+0000abe2@5729
 4746+00002b60@5732
 4747+0000abe4@5733
 4748+0000ebe4@5734
 4749+0000eb64@5735
 4750+00006be4@5736
 4751+0000ebe4@5737
 4752+0000fb64@5739
 4753+0000fbe4@5740
 4754+00007be6@5741
 4755+0000fbe6@5742
 4756+0000b536@5743
 4757+0000b5b6@5744
 4758+000025b6@5746
 4759+0000a5b6@5747
 4760+0000a182@5748
 4761+00002182@5750
 4762+0000a180@5751
 4763+0000e1a4@5752
 4764+0000e324@5754
 4765+00006184@5755
 4766+0000e3a4@5756
 4767+0000f3a4@5757
 4768+0000f304@5758
 4769+0000f3a4@5759
 4770+000073a6@5760
 4771+0000f7b6@5761
 4772+0000f536@5762
 4773+0000b5b6@5763
 4774+000035b6@5764
 4775+0000a536@5765
 4776+0000a182@5766
 4777+00002100@5769
 4778+0000a180@5770
 4779+0000e3a4@5771
 4780+0000e384@5772
 4781+0000e304@5773
 4782+0000e3a4@5774
 4783+0000f324@5776
 4784+0000f3a4@5777
 4785+000073a6@5778
 4786+0000f3a6@5779
 4787+0000f93a@5780
 4788+0000b9ba@5781
 4789+000039ba@5783
 4790+0000a93a@5784
 4791+0000abc2@5785
 4792+0000ab40@5788
 4793+0000abe4@5789
 4794+0000ebe4@5790
 4795+0000eb64@5791
 4796+00006be4@5792
 4797+0000ebe4@5793
 4798+0000fbc4@5794
 4799+0000fb64@5795
 4800+0000fbe4@5796
 4801+00007be6@5797
 4802+0000fbe6@5798
 4803+0000f93a@5799
 4804+0000f9ba@5800
 4805+0000e9ba@5802
 4806+0000ebc2@5803
 4807+00006b42@5806
 4808+0000ebc0@5807
 4809+0000ebe4@5808
 4810+0000ab24@5809
 4811+0000a324@5810
 4812+000023a4@5811
 4813+0000a3a4@5812
 4814+0000b3a4@5813
 4815+0000b324@5814
 4816+0000b3a6@5815
 4817+0000f3a6@5816
 4818+0000fb76@5817
 4819+0000b9f6@5818
 4820+000039f6@5820
 4821+0000a976@5821
 4822+0000a102@5822
 4823+0000a182@5823
 4824+00002100@5825
 4825+0000a180@5826
 4826+0000e3a4@5827
 4827+000063a4@5829
 4828+0000e1a4@5830
 4829+0000f324@5832
 4830+0000f3a4@5833
 4831+000073a6@5834
 4832+0000f3a6@5835
 4833+0000f116@5836
 4834+0000b196@5837
 4835+00003196@5839
 4836+0000a196@5840
 4837+0000a182@5841
 4838+00002182@5843
 4839+0000a180@5844
 4840+0000a1a0@5845
 4841+0000e3a4@5846
 4842+0000e324@5847
 4843+000061a4@5848
 4844+0000e3a4@5849
 4845+0000f3a4@5850
 4846+0000f304@5851
 4847+0000f3a4@5852
 4848+000073a6@5853
 4849+0000f3a6@5854
 4850+0000f35a@5855
 4851+0000b3da@5856
 4852+000033da@5857
 4853+0000a35a@5858
 4854+0000af42@5859
 4855+0000afc2@5860
 4856+00002f40@5862
 4857+0000afc0@5863
 4858+0000efe0@5864
 4859+0000efc4@5865
 4860+0000ef44@5866
 4861+00006fe4@5867
 4862+0000efe4@5868
 4863+0000ffe4@5869
 4864+00007fe6@5871
 4865+0000ffe6@5872
 4866+0000f346@5873
 4867+0000b3c6@5874
 4868+000033c6@5876
 4869+0000a346@5877
 4870+0000abe2@5878
 4871+00002b60@5881
 4872+0000abe4@5882
 4873+0000ebe4@5883
 4874+00006be4@5885
 4875+0000ebe4@5886
 4876+0000fb64@5888
 4877+0000fbe4@5889
 4878+00007be6@5890
 4879+0000fbe6@5891
 4880+0000b536@5892
 4881+0000b5b6@5893
 4882+000025b6@5895
 4883+0000a5b6@5896
 4884+0000a182@5897
 4885+00002182@5899
 4886+0000a180@5900
 4887+0000e1a4@5901
 4888+0000e304@5903
 4889+00006184@5904
 4890+0000e3a4@5905
 4891+0000f3a4@5906
 4892+0000f304@5907
 4893+0000f3a4@5908
 4894+000073a6@5909
 4895+0000f7b6@5910
 4896+0000f5b6@5911
 4897+0000b5b6@5912
 4898+000035b6@5913
 4899+0000a536@5914
 4900+0000a182@5915
 4901+00002100@5918
 4902+0000a180@5919
 4903+0000e3a4@5920
 4904+0000e324@5922
 4905+0000e1a4@5923
 4906+0000e3a4@5924
 4907+0000f324@5925
 4908+0000f3a4@5926
 4909+000073a6@5927
 4910+0000f3a6@5928
 4911+0000f93e@5929
 4912+0000b9be@5930
 4913+000039be@5932
 4914+0000a93e@5933
 4915+0000abc2@5934
 4916+0000ab40@5937
 4917+0000abe4@5938
 4918+0000ebe4@5939
 4919+0000eb64@5940
 4920+00006be4@5941
 4921+0000ebe4@5942
 4922+0000fbc4@5943
 4923+0000fb44@5944
 4924+0000fbe4@5945
 4925+00007be6@5946
 4926+0000fbe6@5947
 4927+0000f93e@5948
 4928+0000f9be@5949
 4929+0000f9bc@5951
 4930+0000fbc0@5952
 4931+0000ebc0@5953
 4932+00006b40@5955
 4933+0000ebc0@5956
 4934+0000ebe4@5957
 4935+0000eb64@5959
 4936+00006bc4@5960
 4937+0000ebe4@5961
 4938+0000fbe4@5962
 4939+0000fb44@5963
 4940+00007be4@5964
 4941+0000fbe6@5965
 4942+0000fb16@5966
 4943+0000b196@5967
 4944+00003196@5969
 4945+0000a116@5970
 4946+0000a182@5971
 4947+00002100@5974
 4948+0000a180@5975
 4949+0000e3a4@5976
 4950+000063a4@5978
 4951+0000e1a4@5979
 4952+0000f324@5981
 4953+0000f3a4@5982
 4954+000071a6@5983
 4955+0000f3a6@5984
 4956+0000f116@5985
 4957+0000b196@5986
 4958+00003196@5988
 4959+0000a196@5989
 4960+0000a182@5990
 4961+00002182@5992
 4962+0000a180@5993
 4963+0000e3a4@5995
 4964+0000e324@5996
 4965+000061a4@5997
 4966+0000e3a4@5998
 4967+0000f3a4@5999
 4968+0000f104@6000
 4969+0000f3a4@6001
 4970+000073a6@6002
 4971+0000f3a6@6003
 4972+0000f35e@6004
 4973+0000b3de@6005
 4974+000033de@6006
 4975+0000a35e@6007
 4976+0000af42@6008
 4977+0000afc2@6009
 4978+00002f40@6011
 4979+0000afc0@6012
 4980+0000efe0@6013
 4981+0000efc4@6014
 4982+0000ef44@6015
 4983+00006fe4@6016
 4984+0000efe4@6017
 4985+0000ffe4@6018
 4986+00007fe6@6020
 4987+0000ffe6@6021
 4988+0000f346@6022
 4989+0000b3c6@6023
 4990+000033c6@6025
 4991+0000a346@6026
 4992+0000abe2@6027
 4993+00002b60@6030
 4994+0000abe4@6031
 4995+0000ebe4@6032
 4996+0000eb64@6033
 4997+00006be4@6034
 4998+0000ebe4@6035
 4999+0000fbe4@6036
 5000+0000fb64@6037
 5001+0000fbe4@6038
 5002+00007be6@6039
 5003+0000fbe6@6040
 5004+0000b916@6041
 5005+0000b996@6042
 5006+00003996@6044
 5007+0000afb6@6045
 5008+0000a7a2@6046
 5009+00002722@6048
 5010+0000a7a0@6049
 5011+0000e7a4@6050
 5012+0000e724@6052
 5013+000067a4@6053
 5014+0000e7a4@6054
 5015+0000f7a4@6055
 5016+0000f724@6056
 5017+0000f7a4@6057
 5018+000077a6@6058
 5019+0000ffb6@6059
 5020+0000b9b6@6060
 5021+000039b6@6062
 5022+0000a936@6063
 5023+0000a722@6064
 5024+0000a7a2@6065
 5025+00002720@6067
 5026+0000a7a0@6068
 5027+0000e7a4@6069
 5028+0000e724@6071
 5029+0000e7a4@6072
 5030+0000f724@6074
 5031+0000f7a4@6075
 5032+000077a6@6076
 5033+0000f7a6@6077
 5034+0000f936@6078
 5035+0000f9b6@6079
 5036+000079b6@6081
 5037+0000e936@6082
 5038+0000e7a2@6083
 5039+0000e7a0@6086
 5040+0000e7a4@6087
 5041+0000ab18@6089
 5042+00002b98@6090
 5043+0000ab98@6091
 5044+0000bb98@6092
 5045+0000bb18@6093
 5046+0000bb98@6094
 5047+00007b9a@6095
 5048+0000fb9a@6096
 5049+0000f936@6097
 5050+0000f9b6@6098
 5051+0000e936@6100
 5052+0000efa2@6101
 5053+0000e7a2@6102
 5054+00006722@6104
 5055+0000e7a0@6105
 5056+0000e7a4@6106
 5057+0000ab98@6107
 5058+0000ab18@6108
 5059+00002b98@6109
 5060+0000ab98@6110
 5061+0000bb98@6111
 5062+0000bb18@6112
 5063+00003b9a@6113
 5064+0000fb9a@6114
 5065+0000fb1e@6115
 5066+0000b19e@6116
 5067+0000319e@6118
 5068+0000a11e@6119
 5069+0000a9d2@6120
 5070+00002950@6123
 5071+0000a9d0@6124
 5072+0000ebf4@6125
 5073+0000ebd4@6126
 5074+00006bf4@6127
 5075+0000e9f4@6128
 5076+0000e9d0@6129
 5077+0000fb54@6130
 5078+0000fbf4@6131
 5079+000079f6@6132
 5080+0000fbf6@6133
 5081+0000f31e@6134
 5082+0000b39e@6135
 5083+0000339e@6137
 5084+0000a39e@6138
 5085+0000a9d2@6139
 5086+000029d2@6141
 5087+0000a9d0@6142
 5088+0000ebf4@6144
 5089+0000eb74@6145
 5090+000069f4@6146
 5091+0000ebf4@6147
 5092+0000fbf4@6148
 5093+0000fb54@6149
 5094+0000fbf4@6150
 5095+00007bf6@6151
 5096+0000fbf6@6152
 5097+0000b51e@6153
 5098+0000b59e@6154
 5099+0000359e@6155
 5100+0000a59e@6156
 5101+0000a9d2@6157
 5102+00002950@6160
 5103+0000a9d0@6161
 5104+0000ebf4@6162
 5105+0000e9d4@6163
 5106+0000e954@6164
 5107+00006bf4@6165
 5108+0000ebf4@6166
 5109+0000fbf4@6167
 5110+0000fbd4@6168
 5111+00007bf6@6169
 5112+0000fbf6@6170
 5113+0000ff1e@6171
 5114+0000b79e@6172
 5115+0000379e@6174
 5116+0000a71e@6175
 5117+0000a9d2@6176
 5118+00002950@6179
 5119+0000a9f4@6180
 5120+0000ebf4@6181
 5121+00006bf4@6183
 5122+0000ebf4@6184
 5123+0000e9d0@6185
 5124+0000fb54@6186
 5125+0000fbf4@6187
 5126+000079f6@6188
 5127+0000fbf6@6189
 5128+0000f91e@6190
 5129+0000b99e@6191
 5130+0000299e@6193
 5131+0000adfe@6194
 5132+0000a5f2@6195
 5133+00002572@6197
 5134+0000a5f0@6198
 5135+0000e5f4@6199
 5136+0000e774@6201
 5137+000065f4@6202
 5138+0000e7f4@6203
 5139+0000f7f4@6204
 5140+0000f574@6205
 5141+0000f7f4@6206
 5142+000077f6@6207
 5143+0000fffe@6208
 5144+0000b9be@6209
 5145+000039be@6211
 5146+0000a93e@6212
 5147+0000a5f2@6213
 5148+00002570@6216
 5149+0000a5f0@6217
 5150+0000e7f4@6218
 5151+0000e5f4@6219
 5152+0000e774@6220
 5153+0000e7f4@6221
 5154+0000f7f4@6223
 5155+000077f6@6225
 5156+0000f7f6@6226
 5157+0000fb1e@6227
 5158+0000bb9e@6228
 5159+00003b9e@6230
 5160+0000ab1e@6231
 5161+0000a5f2@6232
 5162+0000a570@6235
 5163+0000a7f4@6236
 5164+0000e7f4@6237
 5165+0000e774@6238
 5166+000067f4@6239
 5167+0000e7f4@6240
 5168+0000f5f4@6241
 5169+0000f774@6242
 5170+0000f7f4@6243
 5171+000077f6@6244
 5172+0000f7f6@6245
 5173+0000b91e@6246
 5174+0000b99e@6247
 5175+0000a99e@6249
 5176+0000adf2@6250
 5177+0000a5f2@6251
 5178+00002572@6253
 5179+0000a5f0@6254
 5180+0000e7f4@6255
 5181+0000e5f4@6256
 5182+0000e774@6257
 5183+000067f0@6258
 5184+0000e7f4@6259
 5185+0000f7f4@6260
 5186+0000f770@6261
 5187+000077f6@6262
 5188+0000f7f6@6263
 5189+0000fd3e@6264
 5190+0000b9be@6265
 5191+000039be@6267
 5192+0000a93e@6268
 5193+0000a5f2@6269
 5194+00002570@6272
 5195+0000a5f0@6273
 5196+0000e7f4@6274
 5197+000067f4@6276
 5198+0000e7f4@6277
 5199+0000f774@6279
 5200+0000f7f4@6280
 5201+000077f6@6281
 5202+0000f7f6@6282
 5203+0000fb1e@6283
 5204+0000bb9e@6284
 5205+00003b9e@6286
 5206+0000ab9e@6287
 5207+0000a5f2@6288
 5208+000025f2@6290
 5209+0000a5f0@6291
 5210+0000e7f4@6293
 5211+0000e774@6294
 5212+000065f4@6295
 5213+0000e7f4@6296
 5214+0000f7f4@6297
 5215+0000f774@6298
 5216+0000f7f4@6299
 5217+000077f6@6300
 5218+0000f7f6@6301
 5219+0000b91e@6302
 5220+0000b99e@6303
 5221+0000399e@6304
 5222+0000a91e@6305
 5223+0000a5f2@6306
 5224+00002570@6309
 5225+0000a5f0@6310
 5226+0000e7f4@6311
 5227+0000e774@6313
 5228+000067f4@6314
 5229+0000e7f4@6315
 5230+0000f7f4@6316
 5231+000077f6@6318
 5232+0000f7f6@6319
 5233+0000f93e@6320
 5234+0000b9be@6321
 5235+000039be@6323
 5236+0000a93e@6324
 5237+0000a5f2@6325
 5238+00002570@6328
 5239+0000a5f4@6329
 5240+0000e7f4@6330
 5241+0000e774@6331
 5242+000067f4@6332
 5243+0000e7f4@6333
 5244+0000e5f0@6334
 5245+0000f774@6335
 5246+0000f7f4@6336
 5247+000075f6@6337
 5248+0000f7f6@6338
 5249+0000fb1e@6339
 5250+0000bb9e@6340
 5251+00002b9e@6342
 5252+0000affe@6343
 5253+0000a5f2@6344
 5254+00002572@6346
 5255+0000a5f0@6347
 5256+0000e5f4@6348
 5257+0000e774@6350
 5258+000065f4@6351
 5259+0000e7f4@6352
 5260+0000f7f4@6353
 5261+0000f774@6354
 5262+0000f7f4@6355
 5263+000077f6@6356
 5264+0000fffe@6357
 5265+0000b99e@6358
 5266+0000399e@6360
 5267+0000a91e@6361
 5268+0000a5f2@6362
 5269+00002570@6365
 5270+0000a5f0@6366
 5271+0000e7f4@6367
 5272+0000e5f4@6368
 5273+0000e774@6369
 5274+0000e7f4@6370
 5275+0000f774@6372
 5276+0000f7f4@6373
 5277+000077f6@6374
 5278+0000f7f6@6375
 5279+0000f91e@6376
 5280+0000f99e@6377
 5281+0000799e@6379
 5282+0000e91e@6380
 5283+0000e5f2@6381
 5284+0000e570@6384
 5285+0000e7f4@6385
 5286+0000a7f4@6386
 5287+0000a100@6387
 5288+00002180@6388
 5289+0000a180@6389
 5290+0000b180@6390
 5291+0000b100@6391
 5292+0000b180@6392
 5293+00007182@6393
 5294+0000f182@6394
 5295+0000f93e@6395
 5296+0000b9be@6396
 5297+0000a9be@6398
 5298+0000adf2@6399
 5299+0000a5f2@6400
 5300+00002572@6402
 5301+0000a5f0@6403
 5302+0000e7f4@6404
 5303+0000e5f4@6405
 5304+0000e774@6406
 5305+000065f4@6407
 5306+0000e7f4@6408
 5307+0000f7f4@6409
 5308+0000f774@6410
 5309+000077f6@6411
 5310+0000f7f6@6412
 5311+0000ff3e@6413
 5312+0000bb9e@6414
 5313+00003b9e@6416
 5314+0000ab1e@6417
 5315+0000a5f2@6418
 5316+00002570@6421
 5317+0000a5f0@6422
 5318+0000e7f4@6423
 5319+000067f4@6425
 5320+0000e7f4@6426
 5321+0000f774@6428
 5322+0000f7f4@6429
 5323+000077f6@6430
 5324+0000f7f6@6431
 5325+0000f91a@6432
 5326+0000b99a@6433
 5327+0000399a@6435
 5328+0000a99a@6436
 5329+0000a5f2@6437
 5330+000025f2@6439
 5331+0000a570@6440
 5332+0000a5f0@6441
 5333+0000e7f4@6442
 5334+0000e774@6443
 5335+000065f4@6444
 5336+0000e7f4@6445
 5337+0000f7f4@6446
 5338+0000f774@6447
 5339+0000f7f4@6448
 5340+000077f6@6449
 5341+0000f7f6@6450
 5342+0000b93a@6451
 5343+0000b9ba@6452
 5344+000039ba@6453
 5345+0000a93a@6454
 5346+0000a5f2@6455
 5347+00002570@6458
 5348+0000a5f0@6459
 5349+0000e7f4@6460
 5350+0000e774@6462
 5351+000065f4@6463
 5352+0000e7f4@6464
 5353+0000f7f4@6465
 5354+000077f6@6467
 5355+0000f7f6@6468
 5356+0000ff1a@6469
 5357+0000bb9a@6470
 5358+00003b9a@6472
 5359+0000ab1a@6473
 5360+0000a5f2@6474
 5361+00002570@6477
 5362+0000a7f4@6478
 5363+0000e7f4@6479
 5364+0000e774@6480
 5365+000067f4@6481
 5366+0000e7f4@6482
 5367+0000e7f0@6483
 5368+0000f774@6484
 5369+0000f7f4@6485
 5370+000077f6@6486
 5371+0000f7f6@6487
 5372+0000f81a@6488
 5373+0000b89a@6489
 5374+0000389a@6491
 5375+0000acfa@6492
 5376+0000a4f2@6493
 5377+00002472@6495
 5378+0000a470@6496
 5379+0000e474@6497
 5380+0000e6f4@6498
 5381+00006470@6500
 5382+0000e674@6501
 5383+0000f6f4@6502
 5384+00007676@6505
 5385+0000fe7e@6506
 5386+0000b8ba@6507
 5387+000038ba@6509
 5388+0000a83a@6510
 5389+0000a4f2@6511
 5390+00002470@6514
 5391+0000a470@6515
 5392+0000e6f4@6516
 5393+0000e474@6519
 5394+0000f6f4@6521
 5395+00007676@6523
 5396+0000f676@6524
 5397+0000fa1a@6525
 5398+0000ba9a@6526
 5399+00003a1a@6528
 5400+0000aa1a@6529
 5401+0000a4f2@6530
 5402+0000a470@6533
 5403+0000a674@6534
 5404+0000e6f4@6535
 5405+00006674@6537
 5406+0000e674@6538
 5407+0000f6f4@6539
 5408+00007676@6542
 5409+0000f676@6543
 5410+0000b29a@6544
 5411+0000a21a@6547
 5412+0000a6f2@6548
 5413+0000a4f2@6549
 5414+00002472@6551
 5415+0000a470@6552
 5416+0000e6f4@6553
 5417+00006470@6556
 5418+0000e674@6557
 5419+0000f6f4@6558
 5420+000076f6@6560
 5421+0000f676@6561
 5422+0000f63e@6562
 5423+0000b29a@6563
 5424+0000321a@6565
 5425+0000a29a@6566
 5426+0000a4f2@6567
 5427+0000a472@6569
 5428+000024f0@6570
 5429+0000a4f0@6571
 5430+0000e6f4@6572
 5431+0000e674@6573
 5432+00006674@6574
 5433+0000e4f4@6575
 5434+0000e6f4@6576
 5435+0000f674@6577
 5436+000076f6@6579
 5437+0000f6f6@6580
 5438+0000f29a@6581
 5439+0000b21a@6582
 5440+0000329a@6584
 5441+0000a29a@6585
 5442+0000a4f2@6586
 5443+0000a472@6587
 5444+00002472@6588
 5445+0000a4f0@6589
 5446+0000e674@6591
 5447+000064f4@6593
 5448+0000e6f4@6594
 5449+0000f6f4@6595
 5450+0000f674@6596
 5451+000076f6@6598
 5452+0000f6f6@6599
 5453+0000b2ae@6600
 5454+0000b22e@6601
 5455+000032ae@6602
 5456+0000a2ae@6603
 5457+0000a082@6604
 5458+0000a002@6605
 5459+00002080@6607
 5460+0000a080@6608
 5461+0000e284@6609
 5462+0000e204@6610
 5463+000060a4@6612
 5464+0000e2a4@6613
 5465+0000f2a4@6614
 5466+0000f204@6615
 5467+00007226@6616
 5468+0000f2a6@6617
 5469+0000f2ae@6618
 5470+0000f22e@6619
 5471+000072ae@6621
 5472+0000e2ae@6622
 5473+0000e082@6623
 5474+0000e002@6624
 5475+00006080@6626
 5476+0000e2a4@6627
 5477+0000e0a4@6628
 5478+0000a60c@6629
 5479+0000260c@6630
 5480+0000a68c@6631
 5481+0000b68c@6632
 5482+0000b60c@6633
 5483+0000768e@6635
 5484+0000f68e@6636
 5485+0000b49a@6637
 5486+0000b41a@6638
 5487+0000349a@6640
 5488+0000a4fa@6641
 5489+0000aaf2@6642
 5490+00002af2@6644
 5491+0000aaf0@6645
 5492+0000ea74@6646
 5493+0000eaf4@6647
 5494+00006af4@6649
 5495+0000ea74@6650
 5496+0000fa74@6651
 5497+0000faf4@6652
 5498+00007af6@6654
 5499+0000fe76@6655
 5500+0000b426@6656
 5501+0000b4a6@6657
 5502+000034a6@6658
 5503+0000a426@6659
 5504+0000a472@6660
 5505+0000a4f2@6661
 5506+000024f0@6663
 5507+0000a470@6664
 5508+0000e674@6665
 5509+0000e6f4@6666
 5510+0000e4f4@6668
 5511+0000e474@6669
 5512+0000f6f4@6670
 5513+000076f6@6672
 5514+0000f676@6673
 5515+0000f606@6674
 5516+0000b686@6675
 5517+00003686@6677
 5518+0000a606@6678
 5519+0000a472@6679
 5520+0000a4f2@6680
 5521+0000a4f0@6682
 5522+0000a674@6683
 5523+0000e674@6684
 5524+0000e6f4@6685
 5525+000066f4@6686
 5526+0000e674@6687
 5527+0000f674@6688
 5528+0000f6f4@6689
 5529+000076f6@6691
 5530+0000f676@6692
 5531+0000b626@6693
 5532+0000b6a6@6694
 5533+0000a6a6@6696
 5534+0000a472@6697
 5535+0000a4f2@6698
 5536+000024f2@6700
 5537+0000a470@6701
 5538+0000e674@6702
 5539+0000e6f4@6703
 5540+000064f4@6705
 5541+0000e674@6706
 5542+0000f674@6707
 5543+0000f6f4@6708
 5544+000076f6@6709
 5545+0000f6f6@6710
 5546+0000f636@6711
 5547+0000b2a6@6712
 5548+000032a6@6714
 5549+0000a226@6715
 5550+0000a002@6716
 5551+0000a082@6717
 5552+00002080@6719
 5553+0000a080@6720
 5554+0000e2a4@6721
 5555+000062a4@6723
 5556+0000e0a4@6724
 5557+0000f2a4@6726
 5558+0000f224@6727
 5559+00007026@6728
 5560+0000f2a6@6729
 5561+0000f9be@6730
 5562+0000b9be@6731
 5563+0000b93e@6732
 5564+0000393e@6733
 5565+0000a9be@6734
 5566+0000abc2@6735
 5567+0000ab42@6736
 5568+00002b42@6737
 5569+0000ab40@6738
 5570+0000abe4@6739
 5571+0000ebe4@6740
 5572+0000eb64@6741
 5573+00006b44@6742
 5574+0000ebe4@6743
 5575+0000fbe4@6744
 5576+0000fb64@6746
 5577+00007b66@6747
 5578+0000fbe6@6748
 5579+0000f3a6@6749
 5580+0000b3a6@6750
 5581+00003326@6751
 5582+0000a3a6@6752
 5583+0000a182@6753
 5584+0000a102@6755
 5585+00002100@6756
 5586+0000a180@6757
 5587+0000e3a4@6758
 5588+0000e384@6759
 5589+0000e304@6760
 5590+00006304@6761
 5591+0000e3a4@6762
 5592+0000f3a4@6763
 5593+00007326@6765
 5594+0000f3a6@6766
 5595+0000f19a@6767
 5596+0000b19a@6768
 5597+0000b11a@6769
 5598+0000311a@6770
 5599+0000a19a@6771
 5600+0000a182@6772
 5601+0000a102@6774
 5602+00002100@6775
 5603+0000a3a4@6776
 5604+0000e3a4@6777
 5605+00006304@6779
 5606+0000e1a4@6780
 5607+0000e180@6781
 5608+0000f3a4@6782
 5609+0000f324@6783
 5610+00007106@6784
 5611+0000f3a6@6785
 5612+0000f19a@6786
 5613+0000b19a@6787
 5614+0000b11a@6788
 5615+0000211a@6789
 5616+0000a19a@6790
 5617+0000a182@6791
 5618+0000a102@6792
 5619+00002102@6793
 5620+0000a180@6794
 5621+0000e1a4@6795
 5622+0000e304@6797
 5623+00006184@6798
 5624+0000e3a4@6799
 5625+0000f3a4@6800
 5626+0000f304@6801
 5627+0000f3a4@6802
 5628+000073a6@6803
 5629+0000f3de@6804
 5630+0000b1de@6805
 5631+000031de@6807
 5632+0000a15e@6808
 5633+0000bf42@6809
 5634+0000afc2@6810
 5635+00002f40@6812
 5636+0000afc0@6813
 5637+0000efe4@6814
 5638+0000efc4@6815
 5639+0000ef44@6816
 5640+0000efe4@6817
 5641+0000ff64@6819
 5642+0000ffe4@6820
 5643+00007fe6@6821
 5644+0000ffe6@6822
 5645+0000f356@6823
 5646+0000b3d6@6824
 5647+000033d6@6826
 5648+0000a356@6827
 5649+0000a7f2@6828
 5650+0000a7f0@6831
 5651+0000a7f4@6832
 5652+0000e7f4@6833
 5653+0000e774@6834
 5654+000067f4@6835
 5655+0000e7f4@6836
 5656+0000f7f4@6837
 5657+0000f774@6838
 5658+0000f7f4@6839
 5659+000077f6@6840
 5660+0000f7f6@6841
 5661+0000b53a@6842
 5662+0000b5ba@6843
 5663+0000a5ba@6845
 5664+0000af82@6846
 5665+0000ab82@6847
 5666+00002b02@6849
 5667+0000ab80@6850
 5668+0000eba0@6851
 5669+0000eba4@6852
 5670+0000eb24@6853
 5671+00006ba4@6854
 5672+0000eba4@6855
 5673+0000fba4@6856
 5674+0000fb04@6857
 5675+00007ba6@6858
 5676+0000fba6@6859
 5677+0000ff1a@6860
 5678+0000b79a@6861
 5679+0000379a@6863
 5680+0000a71a@6864
 5681+0000ab82@6865
 5682+00002b00@6868
 5683+0000ab80@6869
 5684+0000eba4@6870
 5685+00006ba4@6872
 5686+0000eba4@6873
 5687+0000eb80@6874
 5688+0000fb24@6875
 5689+0000fba4@6876
 5690+00007ba6@6877
 5691+0000fba6@6878
 5692+0000f902@6879
 5693+0000b982@6880
 5694+00003982@6882
 5695+0000a982@6883
 5696+0000abc2@6884
 5697+00002bc2@6886
 5698+0000abc0@6887
 5699+0000abe4@6888
 5700+0000ebe4@6889
 5701+0000eb64@6890
 5702+00006be4@6891
 5703+0000ebe4@6892
 5704+0000fbe4@6893
 5705+0000fb44@6894
 5706+0000fbe4@6895
 5707+00007be6@6896
 5708+0000fbe6@6897
 5709+0000f902@6898
 5710+0000f982@6899
 5711+00007982@6900
 5712+0000e902@6901
 5713+0000ebc2@6902
 5714+00006b40@6905
 5715+0000ebc0@6906
 5716+0000ebe0@6907
 5717+0000e180@6908
 5718+0000a100@6909
 5719+00002180@6910
 5720+0000a180@6911
 5721+0000b180@6912
 5722+00003182@6914
 5723+0000f182@6915
 5724+0000f11a@6916
 5725+0000b19a@6917
 5726+0000319a@6919
 5727+0000a11a@6920
 5728+0000a182@6921
 5729+00002100@6924
 5730+0000a3a4@6925
 5731+0000e3a4@6926
 5732+0000e324@6927
 5733+000063a4@6928
 5734+0000e3a4@6929
 5735+0000f180@6930
 5736+0000f304@6931
 5737+0000f3a4@6932
 5738+000073a6@6933
 5739+0000f3a6@6934
 5740+0000f11a@6935
 5741+0000b19a@6936
 5742+0000219a@6938
 5743+0000a19a@6939
 5744+0000a182@6940
 5745+00002102@6942
 5746+0000a180@6943
 5747+0000e1a4@6944
 5748+0000e184@6945
 5749+0000e304@6946
 5750+00006180@6947
 5751+0000e3a4@6948
 5752+0000f3a4@6949
 5753+0000f304@6950
 5754+0000f3a4@6951
 5755+000073a6@6952
 5756+0000f3e2@6953
 5757+0000b1e2@6954
 5758+000031e2@6956
 5759+0000a162@6957
 5760+0000bfc2@6958
 5761+0000afc2@6959
 5762+00002f40@6961
 5763+0000afc0@6962
 5764+0000efe4@6963
 5765+0000ef64@6965
 5766+0000efe4@6966
 5767+0000ff64@6968
 5768+0000ffe4@6969
 5769+00007fe6@6970
 5770+0000ffe6@6971
 5771+0000f346@6972
 5772+0000b3c6@6973
 5773+000033c6@6975
 5774+0000a346@6976
 5775+0000abe2@6977
 5776+0000abe0@6980
 5777+0000abe4@6981
 5778+0000ebe4@6982
 5779+0000eb64@6983
 5780+00006be4@6984
 5781+0000ebe4@6985
 5782+0000fbe4@6986
 5783+0000fb64@6987
 5784+0000fbe4@6988
 5785+00007be6@6989
 5786+0000fbe6@6990
 5787+0000b73a@6991
 5788+0000b7ba@6992
 5789+0000a7ba@6994
 5790+0000af82@6995
 5791+0000ab82@6996
 5792+00002b02@6998
 5793+0000ab80@6999
 5794+0000eba0@7000
 5795+0000eba4@7001
 5796+0000eb24@7002
 5797+00006ba4@7003
 5798+0000eba4@7004
 5799+0000fba4@7005
 5800+00007ba6@7007
 5801+0000fba6@7008
 5802+0000fb1e@7009
 5803+0000b99a@7010
 5804+0000399a@7012
 5805+0000a91a@7013
 5806+0000ab82@7014
 5807+00002b00@7017
 5808+0000ab80@7018
 5809+0000eba4@7019
 5810+00006ba4@7021
 5811+0000eba4@7022
 5812+0000fb24@7024
 5813+0000fba4@7025
 5814+00007ba6@7026
 5815+0000fba6@7027
 5816+0000f906@7028
 5817+0000b986@7029
 5818+00003986@7031
 5819+0000a986@7032
 5820+0000abc2@7033
 5821+00002bc2@7035
 5822+0000abc0@7036
 5823+0000abe4@7037
 5824+0000ebe4@7038
 5825+0000eb64@7039
 5826+00006be4@7040
 5827+0000ebe4@7041
 5828+0000fbe4@7042
 5829+0000fb44@7043
 5830+0000fbe4@7044
 5831+00007be6@7045
 5832+0000fbe6@7046
 5833+0000f906@7047
 5834+0000f986@7048
 5835+00007986@7049
 5836+0000e906@7050
 5837+0000ebc2@7051
 5838+00006b40@7054
 5839+0000ebc0@7055
 5840+0000ebe4@7056
 5841+0000e180@7057
 5842+0000a100@7058
 5843+00002180@7059
 5844+0000a180@7060
 5845+0000b180@7061
 5846+00003182@7063
 5847+0000f182@7064
 5848+0000f11a@7065
 5849+0000b19a@7066
 5850+0000319a@7068
 5851+0000a11a@7069
 5852+0000a182@7070
 5853+00002100@7073
 5854+0000a3a4@7074
 5855+0000e3a4@7075
 5856+0000e324@7076
 5857+000063a4@7077
 5858+0000e3a4@7078
 5859+0000f180@7079
 5860+0000f304@7080
 5861+0000f3a4@7081
 5862+000073a6@7082
 5863+0000f3a6@7083
 5864+0000f9fa@7084
 5865+0000b9fa@7085
 5866+0000397a@7087
 5867+0000a9fa@7088
 5868+0000a182@7089
 5869+00002182@7091
 5870+0000a180@7092
 5871+0000e1a4@7093
 5872+0000e304@7095
 5873+00006184@7096
 5874+0000e3a4@7097
 5875+0000f3a4@7098
 5876+0000f300@7099
 5877+0000f3a4@7100
 5878+0000f3a6@7101
 5879+0000f3e6@7102
 5880+0000b1e6@7103
 5881+000031e6@7105
 5882+0000a166@7106
 5883+0000bf42@7107
 5884+0000afc2@7108
 5885+00002f40@7110
 5886+0000afc0@7111
 5887+0000efe4@7112
 5888+0000ef64@7114
 5889+0000efe4@7115
 5890+0000ff64@7117
 5891+0000ffe4@7118
 5892+00007fe6@7119
 5893+0000ffe6@7120
 5894+0000f346@7121
 5895+0000b3c6@7122
 5896+000033c6@7124
 5897+0000a346@7125
 5898+0000abe2@7126
 5899+0000abe0@7129
 5900+0000abe4@7130
 5901+0000ebe4@7131
 5902+0000eb64@7132
 5903+00006be4@7133
 5904+0000ebe4@7134
 5905+0000fbe4@7135
 5906+0000fb64@7136
 5907+0000fbe4@7137
 5908+00007be6@7138
 5909+0000fbe6@7139
 5910+0000b93a@7140
 5911+0000b9ba@7141
 5912+0000a9ba@7143
 5913+0000ab82@7144
 5914+00002b02@7147
 5915+0000ab80@7148
 5916+0000eba0@7149
 5917+0000eba4@7150
 5918+0000eb24@7151
 5919+00006ba4@7152
 5920+0000eba4@7153
 5921+0000fba4@7154
 5922+0000fb24@7155
 5923+00007ba6@7156
 5924+0000fba6@7157
 5925+0000fb1a@7158
 5926+0000b39a@7159
 5927+0000339a@7161
 5928+0000a31a@7162
 5929+0000ada2@7163
 5930+00002d20@7166
 5931+0000ada0@7167
 5932+0000efa4@7168
 5933+00006fa4@7170
 5934+0000efa4@7171
 5935+0000efa0@7172
 5936+0000ff24@7173
 5937+0000ffa4@7174
 5938+00007fa6@7175
 5939+0000ffa6@7176
 5940+0000b90a@7177
 5941+0000b98a@7178
 5942+0000390a@7180
 5943+0000a98a@7181
 5944+0000abc2@7182
 5945+00002bc2@7184
 5946+0000abc0@7185
 5947+0000abe4@7186
 5948+0000ebe4@7187
 5949+0000eb64@7188
 5950+00006bc4@7189
 5951+0000ebe4@7190
 5952+0000fbe4@7191
 5953+0000fb44@7192
 5954+0000fbe4@7193
 5955+00007be6@7194
 5956+0000fbe6@7195
 5957+0000f90a@7196
 5958+0000f98a@7197
 5959+0000798a@7198
 5960+0000e90a@7199
 5961+0000ebc2@7200
 5962+00006b40@7203
 5963+0000ebc0@7204
 5964+0000ebe4@7205
 5965+0000a5e0@7206
 5966+000025e0@7208
 5967+0000a5e0@7209
 5968+0000b5e0@7210
 5969+0000b560@7211
 5970+000035e2@7212
 5971+0000f5e2@7213
 5972+0000f91a@7214
 5973+0000b99a@7215
 5974+0000399a@7217
 5975+0000a91a@7218
 5976+0000abd2@7219
 5977+00002b50@7222
 5978+0000abf4@7223
 5979+0000ebf4@7224
 5980+0000eb74@7225
 5981+00006bf4@7226
 5982+0000ebf4@7227
 5983+0000ebd0@7228
 5984+0000fb74@7229
 5985+0000fbf4@7230
 5986+00007bf6@7231
 5987+0000fbf6@7232
 5988+0000b91a@7233
 5989+0000b99a@7234
 5990+0000299a@7236
 5991+0000abda@7237
 5992+0000abd2@7238
 5993+00002b52@7240
 5994+0000abd0@7241
 5995+0000ebf4@7242
 5996+0000ebd4@7243
 5997+0000eb54@7244
 5998+00006bd4@7245
 5999+0000ebf4@7246
 6000+0000fbf4@7247
 6001+0000fb50@7248
 6002+0000fbf4@7249
 6003+0000fbf6@7250
 6004+0000fbfe@7251
 6005+0000b1ea@7252
 6006+000031ea@7254
 6007+0000a16a@7255
 6008+0000bfc2@7256
 6009+0000afc2@7257
 6010+00002f40@7259
 6011+0000afc0@7260
 6012+0000efe4@7261
 6013+0000efc4@7262
 6014+0000ef64@7263
 6015+0000efe4@7264
 6016+0000ff64@7266
 6017+0000ffe4@7267
 6018+00007fe6@7268
 6019+0000ffe6@7269
 6020+0000f346@7270
 6021+0000b3c6@7271
 6022+000033c6@7273
 6023+0000a346@7274
 6024+0000abe2@7275
 6025+0000abe0@7278
 6026+0000abe4@7279
 6027+0000ebe4@7280
 6028+0000eb64@7281
 6029+00006be4@7282
 6030+0000ebe4@7283
 6031+0000fbe4@7284
 6032+0000fb64@7285
 6033+0000fbe4@7286
 6034+00007be6@7287
 6035+0000fbe6@7288
 6036+0000b33a@7289
 6037+0000b3ba@7290
 6038+0000a3ba@7292
 6039+0000afa2@7293
 6040+0000ada2@7294
 6041+00002d22@7296
 6042+0000ada0@7297
 6043+0000efa4@7298
 6044+0000ef20@7300
 6045+00006fa0@7301
 6046+0000efa4@7302
 6047+0000ffa4@7303
 6048+0000ff20@7304
 6049+00007fa6@7305
 6050+0000ffa6@7306
 6051+0000fd3e@7307
 6052+0000b59a@7308
 6053+0000359a@7310
 6054+0000a51a@7311
 6055+0000ada2@7312
 6056+00002d20@7315
 6057+0000ada0@7316
 6058+0000efa4@7317
 6059+00006fa4@7319
 6060+0000eda4@7320
 6061+0000eda0@7321
 6062+0000ff24@7322
 6063+0000ffa4@7323
 6064+00007da6@7324
 6065+0000ffa6@7325
 6066+0000f90e@7326
 6067+0000b98e@7327
 6068+0000390e@7329
 6069+0000a98e@7330
 6070+0000abc2@7331
 6071+00002bc2@7333
 6072+0000abc0@7334
 6073+0000abe4@7335
 6074+0000ebe4@7336
 6075+0000eb64@7337
 6076+00006be4@7338
 6077+0000ebe4@7339
 6078+0000fbe4@7340
 6079+0000fb44@7341
 6080+0000fbe4@7342
 6081+00007be6@7343
 6082+0000fbe6@7344
 6083+0000f90e@7345
 6084+0000f98e@7346
 6085+0000798e@7347
 6086+0000f90c@7348
 6087+0000fbc0@7349
 6088+0000ebc0@7350
 6089+00006b40@7352
 6090+0000ebc0@7353
 6091+0000ebe4@7354
 6092+0000ebc4@7355
 6093+0000eb44@7356
 6094+00006be4@7357
 6095+0000ebe4@7358
 6096+0000fbe4@7359
 6097+00007be6@7361
 6098+0000fbe6@7362
 6099+0000f91a@7363
 6100+0000b99a@7364
 6101+0000399a@7366
 6102+0000a91a@7367
 6103+0000abd2@7368
 6104+00002b50@7371
 6105+0000abf4@7372
 6106+0000ebf4@7373
 6107+0000eb74@7374
 6108+00006bf4@7375
 6109+0000ebf4@7376
 6110+0000ebd0@7377
 6111+0000fb54@7378
 6112+0000fbf4@7379
 6113+00007bf6@7380
 6114+0000fbf6@7381
 6115+0000b91a@7382
 6116+0000b99a@7383
 6117+0000299a@7385
 6118+0000abda@7386
 6119+0000abd2@7387
 6120+00002b52@7389
 6121+0000abd0@7390
 6122+0000ebf4@7391
 6123+0000eb54@7393
 6124+00006bd0@7394
 6125+0000ebf4@7395
 6126+0000fbf4@7396
 6127+0000fb54@7397
 6128+0000fbf4@7398
 6129+0000fbf6@7399
 6130+0000fbfe@7400
 6131+0000b1ee@7401
 6132+000031ee@7403
 6133+0000a16e@7404
 6134+0000bf42@7405
 6135+0000afc2@7406
 6136+00002f40@7408
 6137+0000afc0@7409
 6138+0000efe4@7410
 6139+0000ef64@7412
 6140+0000efe4@7413
 6141+0000ff64@7415
 6142+0000ffe4@7416
 6143+00007fe6@7417
 6144+0000ffe6@7418
 6145+0000f346@7419
 6146+0000b3c6@7420
 6147+000033c6@7422
 6148+0000a346@7423
 6149+0000abe2@7424
 6150+0000ab60@7427
 6151+0000abe4@7428
 6152+0000ebe4@7429
 6153+0000eb64@7430
 6154+00006be4@7431
 6155+0000ebe4@7432
 6156+0000fbe4@7433
 6157+0000fb64@7434
 6158+0000fbe4@7435
 6159+00007be6@7436
 6160+0000fbe6@7437
 6161+0000b53a@7438
 6162+0000b5ba@7439
 6163+0000a5ba@7441
 6164+0000ada2@7442
 6165+00002d22@7445
 6166+0000ada0@7446
 6167+0000efa0@7447
 6168+0000efa4@7448
 6169+0000ef24@7449
 6170+00006da0@7450
 6171+0000efa4@7451
 6172+0000ffa4@7452
 6173+0000ff24@7453
 6174+00007fa6@7454
 6175+0000ffa6@7455
 6176+0000ff3e@7456
 6177+0000b79a@7457
 6178+0000379a@7459
 6179+0000a71a@7460
 6180+0000ada2@7461
 6181+00002d20@7464
 6182+0000ada0@7465
 6183+0000efa4@7466
 6184+00006fa4@7468
 6185+0000efa4@7469
 6186+0000ff24@7471
 6187+0000ffa4@7472
 6188+00007fa6@7473
 6189+0000ffa6@7474
 6190+0000b912@7475
 6191+0000b992@7476
 6192+00003992@7478
 6193+0000a992@7479
 6194+0000abc2@7480
 6195+00002bc2@7482
 6196+0000abc0@7483
 6197+0000abe4@7484
 6198+0000ebe4@7485
 6199+0000eb64@7486
 6200+00006be4@7487
 6201+0000ebe4@7488
 6202+0000fbe4@7489
 6203+0000fb44@7490
 6204+0000fbe4@7491
 6205+00007be6@7492
 6206+0000fbe6@7493
 6207+0000f912@7494
 6208+0000f992@7495
 6209+00007992@7496
 6210+0000e912@7497
 6211+0000ebc2@7498
 6212+00006b40@7501
 6213+0000ebc0@7502
 6214+0000ebe4@7503
 6215+0000a5e0@7504
 6216+000025e0@7506
 6217+0000a5e0@7507
 6218+0000b5e0@7508
 6219+000035e2@7510
 6220+0000f5e2@7511
 6221+0000f91a@7512
 6222+0000b99a@7513
 6223+0000399a@7515
 6224+0000a91a@7516
 6225+0000abd2@7517
 6226+00002b50@7520
 6227+0000abf4@7521
 6228+0000ebf4@7522
 6229+0000eb74@7523
 6230+00006bf4@7524
 6231+0000ebf4@7525
 6232+0000fbd0@7526
 6233+0000fb74@7527
 6234+0000fbf4@7528
 6235+00007bf6@7529
 6236+0000fbf6@7530
 6237+0000b91a@7531
 6238+0000b99a@7532
 6239+0000399a@7534
 6240+0000abda@7535
 6241+0000abd2@7536
 6242+00002b52@7538
 6243+0000abd0@7539
 6244+0000ebf4@7540
 6245+0000ebd4@7541
 6246+0000eb54@7542
 6247+00006bd4@7543
 6248+0000ebf4@7544
 6249+0000fbf4@7545
 6250+0000fb54@7546
 6251+0000fbf4@7547
 6252+0000fbf6@7548
 6253+0000b1f2@7550
 6254+000031f2@7552
 6255+0000a172@7553
 6256+0000bf42@7554
 6257+0000afc2@7555
 6258+00002f40@7557
 6259+0000afc0@7558
 6260+0000efe4@7559
 6261+0000ef64@7561
 6262+0000efe4@7562
 6263+0000ff64@7564
 6264+0000ffe4@7565
 6265+00007fe6@7566
 6266+0000ffe6@7567
 6267+0000f346@7568
 6268+0000b3c6@7569
 6269+000033c6@7571
 6270+0000a346@7572
 6271+0000abe2@7573
 6272+0000abe0@7576
 6273+0000abe4@7577
 6274+0000ebe4@7578
 6275+0000eb64@7579
 6276+00006be4@7580
 6277+0000ebe4@7581
 6278+0000fbe4@7582
 6279+0000fb64@7583
 6280+0000fbe4@7584
 6281+00007be6@7585
 6282+0000fbe6@7586
 6283+0000bb1a@7587
 6284+0000bb9a@7588
 6285+00003b9a@7589
 6286+0000ab9a@7590
 6287+0000ab82@7591
 6288+00002b02@7594
 6289+0000ab80@7595
 6290+0000eba0@7596
 6291+0000eba4@7597
 6292+0000eb24@7598
 6293+00006ba4@7599
 6294+0000eba4@7600
 6295+0000fba4@7601
 6296+0000fb04@7602
 6297+00007ba6@7603
 6298+0000fba6@7604
 6299+0000fb3a@7605
 6300+0000bbba@7606
 6301+00003bba@7608
 6302+0000ab3a@7609
 6303+0000ab82@7610
 6304+00002b00@7613
 6305+0000ab80@7614
 6306+0000eba4@7615
 6307+00006ba4@7617
 6308+0000eba4@7618
 6309+0000fb24@7620
 6310+0000fba4@7621
 6311+00007ba6@7622
 6312+0000fba6@7623
 6313+0000f916@7624
 6314+0000b996@7625
 6315+00003916@7627
 6316+0000a996@7628
 6317+0000abc2@7629
 6318+00002bc2@7631
 6319+0000abc0@7632
 6320+0000abe4@7633
 6321+0000ebe4@7634
 6322+0000eb64@7635
 6323+00006bc4@7636
 6324+0000ebe4@7637
 6325+0000fbe4@7638
 6326+0000fb44@7639
 6327+0000fbe4@7640
 6328+00007be6@7641
 6329+0000fbe6@7642
 6330+0000f916@7643
 6331+0000f996@7644
 6332+00007996@7645
 6333+0000e916@7646
 6334+0000ebc2@7647
 6335+00006b40@7650
 6336+0000ebc0@7651
 6337+0000ebe4@7652
 6338+0000a5e0@7653
 6339+000025e0@7655
 6340+0000a5e0@7656
 6341+0000b5e0@7657
 6342+000035e2@7659
 6343+0000f5e2@7660
 6344+0000f91a@7661
 6345+0000b99a@7662
 6346+0000399a@7664
 6347+0000a91a@7665
 6348+0000abd2@7666
 6349+00002b50@7669
 6350+0000abf4@7670
 6351+0000ebf4@7671
 6352+0000eb74@7672
 6353+00006bf4@7673
 6354+0000ebf4@7674
 6355+0000ebd0@7675
 6356+0000fb74@7676
 6357+0000fbf4@7677
 6358+00007bf6@7678
 6359+0000fbf6@7679
 6360+0000b91a@7680
 6361+0000b99a@7681
 6362+0000a99a@7683
 6363+0000abda@7684
 6364+0000abd2@7685
 6365+00002b52@7687
 6366+0000abd0@7688
 6367+0000ebf4@7689
 6368+0000eb54@7691
 6369+00006bd4@7692
 6370+0000ebf4@7693
 6371+0000fbf4@7694
 6372+0000fb54@7695
 6373+0000fbf4@7696
 6374+0000fbf6@7697
 6375+0000b1f6@7699
 6376+000031f6@7701
 6377+0000a176@7702
 6378+0000bf42@7703
 6379+0000afc2@7704
 6380+00002f40@7706
 6381+0000afc0@7707
 6382+0000efe4@7708
 6383+0000ef64@7710
 6384+0000efe4@7711
 6385+0000ff64@7713
 6386+0000ffe4@7714
 6387+00007fe6@7715
 6388+0000ffe6@7716
 6389+0000f346@7717
 6390+0000b3c6@7718
 6391+000033c6@7720
 6392+0000a346@7721
 6393+0000abe2@7722
 6394+0000abe0@7725
 6395+0000abe4@7726
 6396+0000ebe4@7727
 6397+0000eb64@7728
 6398+00006be4@7729
 6399+0000ebe4@7730
 6400+0000fbe4@7731
 6401+0000fb64@7732
 6402+0000fbe4@7733
 6403+00007be6@7734
 6404+0000fbe6@7735
 6405+0000bd1a@7736
 6406+0000bd9a@7737
 6407+00003d9a@7738
 6408+0000ad9a@7739
 6409+0000af82@7740
 6410+0000ab82@7741
 6411+00002b02@7743
 6412+0000ab80@7744
 6413+0000eba0@7745
 6414+0000eb84@7746
 6415+0000eb04@7747
 6416+00006ba4@7748
 6417+0000eba4@7749
 6418+0000fba4@7750
 6419+0000fb04@7751
 6420+00007ba6@7752
 6421+0000fba6@7753
 6422+0000ff3a@7754
 6423+0000bdba@7755
 6424+00003dba@7757
 6425+0000ad3a@7758
 6426+0000ab82@7759
 6427+00002b00@7762
 6428+0000ab80@7763
 6429+0000eba4@7764
 6430+00006ba4@7766
 6431+0000eba4@7767
 6432+0000eba0@7768
 6433+0000fb24@7769
 6434+0000fba4@7770
 6435+00007ba6@7771
 6436+0000fba6@7772
 6437+0000f91a@7773
 6438+0000b99a@7774
 6439+0000399a@7776
 6440+0000a99a@7777
 6441+0000abc2@7778
 6442+00002bc2@7780
 6443+0000abc0@7781
 6444+0000abe4@7782
 6445+0000ebe4@7783
 6446+0000eb64@7784
 6447+00006be4@7785
 6448+0000ebe4@7786
 6449+0000fbe4@7787
 6450+0000fb44@7788
 6451+0000fbe4@7789
 6452+00007be6@7790
 6453+0000fbe6@7791
 6454+0000f91a@7792
 6455+0000f99a@7793
 6456+0000799a@7794
 6457+0000e91a@7795
 6458+0000ebc2@7796
 6459+00006b40@7799
 6460+0000ebc0@7800
 6461+0000ebe4@7801
 6462+0000a5e0@7802
 6463+000025e0@7804
 6464+0000a5e0@7805
 6465+0000b5e0@7806
 6466+000035e2@7808
 6467+0000f5e2@7809
 6468+0000f91a@7810
 6469+0000b99a@7811
 6470+0000399a@7813
 6471+0000a91a@7814
 6472+0000abd2@7815
 6473+00002b50@7818
 6474+0000abf4@7819
 6475+0000ebf4@7820
 6476+0000eb74@7821
 6477+00006bf4@7822
 6478+0000ebf4@7823
 6479+0000ebd0@7824
 6480+0000fb74@7825
 6481+0000fbf4@7826
 6482+00007bf6@7827
 6483+0000fbf6@7828
 6484+0000b91a@7829
 6485+0000b99a@7830
 6486+0000a99a@7832
 6487+0000abda@7833
 6488+0000abd2@7834
 6489+00002b52@7836
 6490+0000abd0@7837
 6491+0000ebf4@7838
 6492+0000eb54@7840
 6493+00006bd4@7841
 6494+0000ebf4@7842
 6495+0000fbf4@7843
 6496+0000fb54@7844
 6497+0000fbf4@7845
 6498+0000fbf6@7846
 6499+0000fbfe@7847
 6500+0000b1fa@7848
 6501+000031fa@7850
 6502+0000a17a@7851
 6503+0000bf42@7852
 6504+0000afc2@7853
 6505+00002f40@7855
 6506+0000afc0@7856
 6507+0000efe4@7857
 6508+0000ef44@7859
 6509+0000efe4@7860
 6510+0000ff64@7862
 6511+0000ffe4@7863
 6512+00007fe6@7864
 6513+0000ffe6@7865
 6514+0000f346@7866
 6515+0000b3c6@7867
 6516+000033c6@7869
 6517+0000a346@7870
 6518+0000abe2@7871
 6519+0000abe0@7874
 6520+0000abe4@7875
 6521+0000ebe4@7876
 6522+0000eb64@7877
 6523+00006be4@7878
 6524+0000ebe4@7879
 6525+0000fbe4@7880
 6526+0000fb64@7881
 6527+0000fbe4@7882
 6528+00007be6@7883
 6529+0000fbe6@7884
 6530+0000bf1a@7885
 6531+0000bf9a@7886
 6532+00003f9a@7887
 6533+0000af9a@7888
 6534+0000ab82@7889
 6535+00002b02@7892
 6536+0000ab80@7893
 6537+0000eba0@7894
 6538+0000eb84@7895
 6539+0000eb04@7896
 6540+00006b84@7897
 6541+0000eba4@7898
 6542+0000fba4@7899
 6543+0000fb04@7900
 6544+00007ba6@7901
 6545+0000fba6@7902
 6546+0000ff3a@7903
 6547+0000bfba@7904
 6548+00003fba@7906
 6549+0000af3a@7907
 6550+0000ab82@7908
 6551+00002b00@7911
 6552+0000ab80@7912
 6553+0000eba4@7913
 6554+00006ba4@7915
 6555+0000eba4@7916
 6556+0000fb24@7918
 6557+0000fba4@7919
 6558+00007ba6@7920
 6559+0000fba6@7921
 6560+0000f91e@7922
 6561+0000b99e@7923
 6562+0000391e@7925
 6563+0000a99e@7926
 6564+0000abc2@7927
 6565+00002bc2@7929
 6566+0000abc0@7930
 6567+0000abe4@7931
 6568+0000ebe4@7932
 6569+0000eb64@7933
 6570+00006be4@7934
 6571+0000ebe4@7935
 6572+0000fbe4@7936
 6573+0000fb44@7937
 6574+0000fbe4@7938
 6575+00007be6@7939
 6576+0000fbe6@7940
 6577+0000f91e@7941
 6578+0000f99e@7942
 6579+0000799e@7943
 6580+0000f91c@7944
 6581+0000fbc0@7945
 6582+0000ebc0@7947
 6583+00006b40@7948
 6584+0000ebc0@7949
 6585+0000ebe4@7950
 6586+0000eb44@7952
 6587+00006be4@7953
 6588+0000ebe4@7954
 6589+0000fbe4@7955
 6590+00007be6@7957
 6591+0000fbe6@7958
 6592+0000f91a@7959
 6593+0000b99a@7960
 6594+0000399a@7962
 6595+0000a91a@7963
 6596+0000abd2@7964
 6597+00002b50@7967
 6598+0000abf4@7968
 6599+0000ebf4@7969
 6600+0000eb74@7970
 6601+00006bf4@7971
 6602+0000ebf4@7972
 6603+0000fbd0@7973
 6604+0000fb74@7974
 6605+0000fbf4@7975
 6606+00007bf6@7976
 6607+0000fbf6@7977
 6608+0000bb1a@7978
 6609+0000bb9a@7979
 6610+0000ab9a@7981
 6611+0000abfa@7982
 6612+0000abe2@7983
 6613+00002b62@7985
 6614+0000abe0@7986
 6615+0000ebe4@7987
 6616+0000eb64@7989
 6617+00006be4@7990
 6618+0000ebe4@7991
 6619+0000fbe4@7992
 6620+0000fb64@7993
 6621+0000fbe4@7994
 6622+0000fbe6@7995
 6623+0000fb7e@7996
 6624+0000b1fe@7997
 6625+000031fe@7999
 6626+0000a17e@8000
 6627+0000bf42@8001
 6628+0000afc2@8002
 6629+00002f40@8004
 6630+0000afc0@8005
 6631+0000efe4@8006
 6632+0000ef64@8008
 6633+0000efe4@8009
 6634+0000ff64@8011
 6635+0000ffe4@8012
 6636+00007fe6@8013
 6637+0000ffe6@8014
 6638+0000f346@8015
 6639+0000b3c6@8016
 6640+000033c6@8018
 6641+0000a346@8019
 6642+0000abe2@8020
 6643+0000abe0@8023
 6644+0000abe4@8024
 6645+0000ebe4@8025
 6646+0000eb64@8026
 6647+00006be4@8027
 6648+0000ebe4@8028
 6649+0000fbe4@8029
 6650+0000fb64@8030
 6651+0000fbe4@8031
 6652+00007be6@8032
 6653+0000fbe6@8033
 6654+0000b71a@8034
 6655+0000b79a@8035
 6656+0000379a@8036
 6657+0000a79a@8037
 6658+0000a992@8038
 6659+00002912@8041
 6660+0000a990@8042
 6661+0000eb90@8043
 6662+0000eb94@8044
 6663+0000eb14@8045
 6664+00006b94@8046
 6665+0000ebb4@8047
 6666+0000fbb4@8048
 6667+0000fb14@8049
 6668+00007bb6@8050
 6669+0000fbb6@8051
 6670+0000ff3a@8052
 6671+0000b7ba@8053
 6672+000037ba@8055
 6673+0000a73a@8056
 6674+0000a992@8057
 6675+00002910@8060
 6676+0000a990@8061
 6677+0000ebb4@8062
 6678+00006bb4@8064
 6679+0000e9b4@8065
 6680+0000eb90@8066
 6681+0000fb34@8067
 6682+0000fbb4@8068
 6683+000079b6@8069
 6684+0000fbb6@8070
 6685+0000f922@8071
 6686+0000b9a2@8072
 6687+000039a2@8074
 6688+0000a9a2@8075
 6689+0000abc2@8076
 6690+00002bc2@8078
 6691+0000abc0@8079
 6692+0000abe4@8080
 6693+0000ebe4@8081
 6694+0000eb64@8082
 6695+00006be4@8083
 6696+0000ebe4@8084
 6697+0000fbe4@8085
 6698+0000fb44@8086
 6699+0000fbe4@8087
 6700+00007be6@8088
 6701+0000fbe6@8089
 6702+0000f922@8090
 6703+0000f9a2@8091
 6704+000079a2@8092
 6705+0000e922@8093
 6706+0000ebc2@8094
 6707+00006b40@8097
 6708+0000ebc0@8098
 6709+0000ebe4@8099
 6710+0000a9ec@8100
 6711+000029ec@8102
 6712+0000a9ec@8103
 6713+0000b9ec@8104
 6714+000039ee@8106
 6715+0000f9ee@8107
 6716+0000fb3a@8108
 6717+0000bbba@8109
 6718+00003bba@8111
 6719+0000ab3a@8112
 6720+0000abe2@8113
 6721+00002b60@8116
 6722+0000abe4@8117
 6723+0000ebe4@8118
 6724+0000eb64@8119
 6725+00006be4@8120
 6726+0000ebe4@8121
 6727+0000fbe4@8122
 6728+0000fb64@8123
 6729+0000fbe4@8124
 6730+00007be6@8125
 6731+0000fbe6@8126
 6732+0000b91a@8127
 6733+0000b99a@8128
 6734+0000a99a@8130
 6735+0000abda@8131
 6736+0000abd2@8132
 6737+00002b52@8134
 6738+0000abd0@8135
 6739+0000ebf4@8136
 6740+0000ebd4@8137
 6741+0000eb54@8138
 6742+00006bd4@8139
 6743+0000ebf4@8140
 6744+0000fbf4@8141
 6745+0000fb50@8142
 6746+0000fbf4@8143
 6747+0000fbf6@8144
 6748+0000fbd6@8145
 6749+0000b3c2@8146
 6750+000033c2@8148
 6751+0000a342@8149
 6752+0000afc2@8150
 6753+00002f40@8153
 6754+0000afc0@8154
 6755+0000efe4@8155
 6756+0000efc4@8156
 6757+0000ef44@8157
 6758+0000efe4@8158
 6759+0000ff64@8160
 6760+0000ffe4@8161
 6761+00007fe6@8162
 6762+0000ffe6@8163
 6763+0000f346@8164
 6764+0000b3c6@8165
 6765+000033c6@8167
 6766+0000a346@8168
 6767+0000abe2@8169
 6768+00002be2@8171
 6769+0000abe0@8172
 6770+0000abe4@8173
 6771+0000ebe4@8174
 6772+0000eb64@8175
 6773+00006be4@8176
 6774+0000ebe4@8177
 6775+0000fbe4@8178
 6776+0000fb64@8179
 6777+0000fbe4@8180
 6778+00007be6@8181
 6779+0000fbe6@8182
 6780+0000bf1a@8183
 6781+0000bf9a@8184
 6782+00003f9a@8185
 6783+0000af9a@8186
 6784+0000aba2@8187
 6785+00002b22@8190
 6786+0000aba0@8191
 6787+0000eba0@8192
 6788+0000eba4@8193
 6789+0000eb24@8194
 6790+00006ba4@8195
 6791+0000eba4@8196
 6792+0000fba4@8197
 6793+0000fb24@8198
 6794+00007ba6@8199
 6795+0000fba6@8200
 6796+0000ff3a@8201
 6797+0000b5ba@8202
 6798+000035ba@8204
 6799+0000a53a@8205
 6800+0000a182@8206
 6801+00002100@8209
 6802+0000a180@8210
 6803+0000e3a4@8211
 6804+000063a4@8213
 6805+0000e1a4@8214
 6806+0000e180@8215
 6807+0000f324@8216
 6808+0000f3a4@8217
 6809+000071a6@8218
 6810+0000f3a6@8219
 6811+0000f926@8220
 6812+0000b9a6@8221
 6813+000039a6@8223
 6814+0000a9a6@8224
 6815+0000abc2@8225
 6816+00002bc2@8227
 6817+0000abc0@8228
 6818+0000abe4@8229
 6819+0000ebe4@8230
 6820+0000eb64@8231
 6821+00006be4@8232
 6822+0000ebe4@8233
 6823+0000fbe4@8234
 6824+0000fb44@8235
 6825+0000fbe4@8236
 6826+00007be6@8237
 6827+0000fbe6@8238
 6828+0000f926@8239
 6829+0000f9a6@8240
 6830+000079a6@8241
 6831+0000e926@8242
 6832+0000ebc2@8243
 6833+00006b40@8246
 6834+0000ebc0@8247
 6835+0000ebe4@8248
 6836+0000a5e0@8249
 6837+000025e0@8251
 6838+0000a5e0@8252
 6839+0000b5e0@8253
 6840+000035e2@8255
 6841+0000f5e2@8256
 6842+0000f91a@8257
 6843+0000b99a@8258
 6844+0000399a@8260
 6845+0000a91a@8261
 6846+0000abd2@8262
 6847+00002b50@8265
 6848+0000abf4@8266
 6849+0000ebf4@8267
 6850+0000eb74@8268
 6851+00006bf4@8269
 6852+0000ebf4@8270
 6853+0000fbd0@8271
 6854+0000fb74@8272
 6855+0000fbf4@8273
 6856+00007bf6@8274
 6857+0000fbf6@8275
 6858+0000b91a@8276
 6859+0000b99a@8277
 6860+0000a99a@8279
 6861+0000abda@8280
 6862+0000abd2@8281
 6863+00002b52@8283
 6864+0000abd0@8284
 6865+0000ebf4@8285
 6866+0000ebd4@8286
 6867+0000eb54@8287
 6868+00006bd4@8288
 6869+0000ebf4@8289
 6870+0000fbf4@8290
 6871+0000fb50@8291
 6872+0000fbf4@8292
 6873+0000fbf6@8293
 6874+0000fbd6@8294
 6875+0000b3c6@8295
 6876+000033c6@8297
 6877+0000a346@8298
 6878+0000afc2@8299
 6879+00002f40@8302
 6880+0000afc0@8303
 6881+0000efe4@8304
 6882+00006f64@8306
 6883+0000efe4@8307
 6884+0000ff64@8309
 6885+0000ffe4@8310
 6886+00007fe6@8311
 6887+0000ffe6@8312
 6888+0000f346@8313
 6889+0000b3c6@8314
 6890+000033c6@8316
 6891+0000a346@8317
 6892+0000abe2@8318
 6893+00002be2@8320
 6894+0000abe0@8321
 6895+0000abe4@8322
 6896+0000ebe4@8323
 6897+0000eb64@8324
 6898+00006be4@8325
 6899+0000ebe4@8326
 6900+0000fbe4@8327
 6901+0000fb64@8328
 6902+0000fbe4@8329
 6903+00007be6@8330
 6904+0000fbe6@8331
 6905+0000b53a@8332
 6906+0000b5ba@8333
 6907+000035ba@8334
 6908+0000a5ba@8335
 6909+0000a182@8336
 6910+00002102@8339
 6911+0000a180@8340
 6912+0000e3a0@8341
 6913+0000e384@8342
 6914+0000e304@8343
 6915+00006184@8344
 6916+0000e3a4@8345
 6917+0000f3a4@8346
 6918+0000f304@8347
 6919+000073a6@8348
 6920+0000f3a6@8349
 6921+0000f53a@8350
 6922+0000b5ba@8351
 6923+000035ba@8353
 6924+0000b53a@8354
 6925+0000a182@8355
 6926+00002100@8358
 6927+0000a180@8359
 6928+0000e3a4@8360
 6929+000063a4@8362
 6930+0000e1a4@8363
 6931+0000e180@8364
 6932+0000f324@8365
 6933+0000f3a4@8366
 6934+000071a6@8367
 6935+0000f3a6@8368
 6936+0000f92a@8369
 6937+0000b9aa@8370
 6938+000039aa@8372
 6939+0000a9aa@8373
 6940+0000abc2@8374
 6941+00002bc2@8376
 6942+0000abc0@8377
 6943+0000abe4@8378
 6944+0000ebe4@8379
 6945+0000eb64@8380
 6946+00006be4@8381
 6947+0000ebe4@8382
 6948+0000fbe4@8383
 6949+0000fb44@8384
 6950+0000fbe4@8385
 6951+00007be6@8386
 6952+0000fbe6@8387
 6953+0000f92a@8388
 6954+0000f9aa@8389
 6955+000079aa@8390
 6956+0000e92a@8391
 6957+0000ebc2@8392
 6958+00006b40@8395
 6959+0000ebc0@8396
 6960+0000ebe4@8397
 6961+0000a5e0@8398
 6962+000025e0@8400
 6963+0000a5e0@8401
 6964+0000b5e0@8402
 6965+000035e2@8404
 6966+0000f5e2@8405
 6967+0000f91a@8406
 6968+0000b99a@8407
 6969+0000399a@8409
 6970+0000a91a@8410
 6971+0000abd2@8411
 6972+00002b50@8414
 6973+0000abf4@8415
 6974+0000ebf4@8416
 6975+0000eb74@8417
 6976+00006bf4@8418
 6977+0000ebf4@8419
 6978+0000fbd0@8420
 6979+0000fb54@8421
 6980+0000fbf4@8422
 6981+00007bf6@8423
 6982+0000fbf6@8424
 6983+0000b91a@8425
 6984+0000b99a@8426
 6985+0000a99a@8428
 6986+0000abda@8429
 6987+0000abd2@8430
 6988+00002b52@8432
 6989+0000abd0@8433
 6990+0000ebf4@8434
 6991+0000ebd4@8435
 6992+0000eb54@8436
 6993+00006bd4@8437
 6994+0000ebf4@8438
 6995+0000fbf4@8439
 6996+0000fb50@8440
 6997+0000fbf4@8441
 6998+0000fbf6@8442
 6999+0000fbde@8443
 7000+0000b3ca@8444
 7001+000033ca@8446
 7002+0000a34a@8447
 7003+0000afc2@8448
 7004+00002f40@8451
 7005+0000afc0@8452
 7006+0000efe4@8453
 7007+00006f64@8455
 7008+0000efe4@8456
 7009+0000ff64@8458
 7010+0000ffe4@8459
 7011+00007fe6@8460
 7012+0000ffe6@8461
 7013+0000f346@8462
 7014+0000b3c6@8463
 7015+000033c6@8465
 7016+0000a346@8466
 7017+0000abe2@8467
 7018+00002be2@8469
 7019+0000abe0@8470
 7020+0000abe4@8471
 7021+0000ebe4@8472
 7022+0000eb64@8473
 7023+00006be4@8474
 7024+0000ebe4@8475
 7025+0000fbe4@8476
 7026+0000fb64@8477
 7027+0000fbe4@8478
 7028+00007be6@8479
 7029+0000fbe6@8480
 7030+0000b53a@8481
 7031+0000b5ba@8482
 7032+000035ba@8483
 7033+0000a5ba@8484
 7034+0000a182@8485
 7035+00002102@8488
 7036+0000a180@8489
 7037+0000e3a0@8490
 7038+0000e3a4@8491
 7039+0000e304@8492
 7040+000061a4@8493
 7041+0000e3a4@8494
 7042+0000f3a4@8495
 7043+0000f324@8496
 7044+000073a6@8497
 7045+0000f3a6@8498
 7046+0000f53a@8499
 7047+0000b5ba@8500
 7048+000035ba@8502
 7049+0000a53a@8503
 7050+0000a182@8504
 7051+00002100@8507
 7052+0000a180@8508
 7053+0000e3a4@8509
 7054+000063a4@8511
 7055+0000e1a4@8512
 7056+0000e184@8513
 7057+0000f324@8514
 7058+0000f3a4@8515
 7059+000071a6@8516
 7060+0000f3a6@8517
 7061+0000f92e@8518
 7062+0000b9ae@8519
 7063+000039ae@8521
 7064+0000a9ae@8522
 7065+0000abc2@8523
 7066+00002bc2@8525
 7067+0000abc0@8526
 7068+0000abe4@8527
 7069+0000ebe4@8528
 7070+0000eb64@8529
 7071+00006be4@8530
 7072+0000ebe4@8531
 7073+0000fbe4@8532
 7074+0000fb44@8533
 7075+0000fbe4@8534
 7076+00007be6@8535
 7077+0000fbee@8536
 7078+0000f92e@8537
 7079+0000f9ae@8538
 7080+000079ae@8539
 7081+0000f92c@8540
 7082+0000fbc0@8541
 7083+0000ebc0@8542
 7084+00006b40@8544
 7085+0000ebc0@8545
 7086+0000ebe4@8546
 7087+0000eb64@8548
 7088+00006be4@8549
 7089+0000ebe4@8550
 7090+0000fbe4@8551
 7091+00007be6@8553
 7092+0000fbe6@8554
 7093+0000f91a@8555
 7094+0000b99a@8556
 7095+0000399a@8558
 7096+0000a91a@8559
 7097+0000abd2@8560
 7098+00002b50@8563
 7099+0000abf4@8564
 7100+0000ebf4@8565
 7101+0000eb74@8566
 7102+00006bf4@8567
 7103+0000ebf4@8568
 7104+0000fbd0@8569
 7105+0000fb74@8570
 7106+0000fbf4@8571
 7107+00007bf6@8572
 7108+0000fbf6@8573
 7109+0000b91a@8574
 7110+0000b99a@8575
 7111+0000a99a@8577
 7112+0000abda@8578
 7113+0000abd2@8579
 7114+00002b52@8581
 7115+0000abd0@8582
 7116+0000ebf4@8583
 7117+0000ebd4@8584
 7118+0000eb54@8585
 7119+00006bd4@8586
 7120+0000ebf4@8587
 7121+0000fbf4@8588
 7122+0000fb50@8589
 7123+0000fbf4@8590
 7124+0000fbf6@8591
 7125+0000fbde@8592
 7126+0000b3ce@8593
 7127+000033ce@8595
 7128+0000a34e@8596
 7129+0000afc2@8597
 7130+00002f40@8600
 7131+0000afc0@8601
 7132+0000efe4@8602
 7133+00006fc4@8604
 7134+0000efe4@8605
 7135+0000ff64@8607
 7136+0000ffe4@8608
 7137+00007fe6@8609
 7138+0000ffe6@8610
 7139+0000f346@8611
 7140+0000b3c6@8612
 7141+000033c6@8614
 7142+0000a346@8615
 7143+0000abe2@8616
 7144+00002be2@8618
 7145+0000abe0@8619
 7146+0000abe4@8620
 7147+0000ebe4@8621
 7148+0000eb64@8622
 7149+00006be4@8623
 7150+0000ebe4@8624
 7151+0000fbe4@8625
 7152+0000fb64@8626
 7153+0000fbe4@8627
 7154+00007be6@8628
 7155+0000fbe6@8629
 7156+0000b53a@8630
 7157+0000b5ba@8631
 7158+000035ba@8632
 7159+0000a5ba@8633
 7160+0000a182@8634
 7161+00002102@8637
 7162+0000a180@8638
 7163+0000e3a0@8639
 7164+0000e384@8640
 7165+0000e304@8641
 7166+000063a4@8642
 7167+0000e3a4@8643
 7168+0000f3a4@8644
 7169+000073a6@8646
 7170+0000f3a6@8647
 7171+0000f53a@8648
 7172+0000b5ba@8649
 7173+000035ba@8651
 7174+0000a53a@8652
 7175+0000a182@8653
 7176+00002100@8656
 7177+0000a180@8657
 7178+0000e3a4@8658
 7179+000063a4@8660
 7180+0000e1a4@8661
 7181+0000e180@8662
 7182+0000f324@8663
 7183+0000f3a4@8664
 7184+000071a6@8665
 7185+0000f3a6@8666
 7186+0000f932@8667
 7187+0000b9b2@8668
 7188+000039b2@8670
 7189+0000a9f2@8671
 7190+0000abc2@8672
 7191+00002bc2@8674
 7192+0000abc0@8675
 7193+0000abe4@8676
 7194+0000ebe4@8677
 7195+0000eb64@8678
 7196+00006bc4@8679
 7197+0000ebe4@8680
 7198+0000fbe4@8681
 7199+0000fb40@8682
 7200+0000fbe4@8683
 7201+00007be6@8684
 7202+0000fbf6@8685
 7203+0000f932@8686
 7204+0000f9b2@8687
 7205+000079b2@8688
 7206+0000e932@8689
 7207+0000ebc2@8690
 7208+00006b40@8693
 7209+0000ebc0@8694
 7210+0000ebe4@8695
 7211+0000a5e0@8696
 7212+000025e0@8698
 7213+0000a5e0@8699
 7214+0000b5e0@8700
 7215+000035e2@8702
 7216+0000f5e2@8703
 7217+0000f91a@8704
 7218+0000b99a@8705
 7219+0000399a@8707
 7220+0000a91a@8708
 7221+0000abd2@8709
 7222+00002b50@8712
 7223+0000abf4@8713
 7224+0000ebf4@8714
 7225+0000eb74@8715
 7226+00006bf4@8716
 7227+0000ebf4@8717
 7228+0000fbd0@8718
 7229+0000fb54@8719
 7230+0000fbf4@8720
 7231+00007bf6@8721
 7232+0000fbf6@8722
 7233+0000b91a@8723
 7234+0000b99a@8724
 7235+0000a99a@8726
 7236+0000abda@8727
 7237+0000abd2@8728
 7238+00002b52@8730
 7239+0000abd0@8731
 7240+0000ebf4@8732
 7241+0000eb74@8734
 7242+00006bd4@8735
 7243+0000ebf4@8736
 7244+0000fbf4@8737
 7245+0000fb54@8738
 7246+0000fbf4@8739
 7247+0000fbf6@8740
 7248+0000fbd2@8741
 7249+0000b3d2@8742
 7250+000033d2@8744
 7251+0000a352@8745
 7252+0000afc2@8746
 7253+00002f40@8749
 7254+0000afc0@8750
 7255+0000efe4@8751
 7256+00006f64@8753
 7257+0000efe4@8754
 7258+0000efc4@8755
 7259+0000ff64@8756
 7260+0000ffe4@8757
 7261+00007fe6@8758
 7262+0000ffe6@8759
 7263+0000f346@8760
 7264+0000b3c6@8761
 7265+000033c6@8763
 7266+0000a346@8764
 7267+0000abe2@8765
 7268+00002be2@8767
 7269+0000abe0@8768
 7270+0000abe4@8769
 7271+0000ebe4@8770
 7272+0000eb64@8771
 7273+00006be4@8772
 7274+0000ebe4@8773
 7275+0000fbe4@8774
 7276+0000fb64@8775
 7277+0000fbe4@8776
 7278+00007be6@8777
 7279+0000fbe6@8778
 7280+0000b53a@8779
 7281+0000b5ba@8780
 7282+000035ba@8781
 7283+0000a5ba@8782
 7284+0000a182@8783
 7285+00002102@8786
 7286+0000a180@8787
 7287+0000e3a0@8788
 7288+0000e3a4@8789
 7289+0000e104@8790
 7290+000061a4@8791
 7291+0000e3a4@8792
 7292+0000f3a4@8793
 7293+0000f304@8794
 7294+000073a6@8795
 7295+0000f3a6@8796
 7296+0000f53a@8797
 7297+0000b5ba@8798
 7298+000035ba@8800
 7299+0000a53a@8801
 7300+0000a182@8802
 7301+00002100@8805
 7302+0000a180@8806
 7303+0000e3a4@8807
 7304+000063a4@8809
 7305+0000e1a4@8810
 7306+0000e180@8811
 7307+0000f324@8812
 7308+0000f3a4@8813
 7309+000071a6@8814
 7310+0000f3a6@8815
 7311+0000f936@8816
 7312+0000b9b6@8817
 7313+00003936@8819
 7314+0000a9f6@8820
 7315+0000abc2@8821
 7316+00002bc2@8823
 7317+0000ab40@8824
 7318+0000ebe4@8825
 7319+0000eb64@8827
 7320+00006be4@8828
 7321+0000ebe4@8829
 7322+0000fbe4@8830
 7323+0000fb44@8831
 7324+0000fbe4@8832
 7325+00007be6@8833
 7326+0000fbf6@8834
 7327+0000f936@8835
 7328+0000f9b6@8836
 7329+000079b6@8837
 7330+0000e936@8838
 7331+0000ebc2@8839
 7332+00006b40@8842
 7333+0000ebc0@8843
 7334+0000ebe4@8844
 7335+0000a5e0@8845
 7336+000025e0@8847
 7337+0000a5e0@8848
 7338+0000b5e0@8849
 7339+000035e2@8851
 7340+0000f5e2@8852
 7341+0000f91a@8853
 7342+0000b99a@8854
 7343+0000399a@8856
 7344+0000a91a@8857
 7345+0000abd2@8858
 7346+00002b50@8861
 7347+0000abf4@8862
 7348+0000ebf4@8863
 7349+0000eb74@8864
 7350+00006bf4@8865
 7351+0000ebf4@8866
 7352+0000fbd0@8867
 7353+0000fb74@8868
 7354+0000fbf4@8869
 7355+00007bf6@8870
 7356+0000fbf6@8871
 7357+0000b33a@8872
 7358+0000b3ba@8873
 7359+0000a3ba@8875
 7360+0000abfa@8876
 7361+0000abd2@8877
 7362+00002b52@8879
 7363+0000abd0@8880
 7364+0000ebf4@8881
 7365+0000eb74@8883
 7366+00006bd4@8884
 7367+0000ebf4@8885
 7368+0000fbf4@8886
 7369+0000fb54@8887
 7370+0000fbf4@8888
 7371+0000fbf6@8889
 7372+0000fbd6@8890
 7373+0000b3d6@8891
 7374+000033d6@8893
 7375+0000a356@8894
 7376+0000afc2@8895
 7377+00002f40@8898
 7378+0000afc0@8899
 7379+0000efe4@8900
 7380+0000efc4@8901
 7381+00006f64@8902
 7382+0000efe4@8903
 7383+0000ff64@8905
 7384+0000ffe4@8906
 7385+00007fe6@8907
 7386+0000ffe6@8908
 7387+0000f346@8909
 7388+0000b3c6@8910
 7389+000033c6@8912
 7390+0000a3c6@8913
 7391+0000abe2@8914
 7392+00002be2@8916
 7393+0000abe0@8917
 7394+0000abe4@8918
 7395+0000ebe4@8919
 7396+0000eb64@8920
 7397+00006be4@8921
 7398+0000ebe4@8922
 7399+0000fbe4@8923
 7400+0000fb64@8924
 7401+0000fbe4@8925
 7402+00007be6@8926
 7403+0000fbe6@8927
 7404+0000b53a@8928
 7405+0000b5ba@8929
 7406+000035ba@8930
 7407+0000a53a@8931
 7408+0000a182@8932
 7409+00002102@8935
 7410+0000a180@8936
 7411+0000e380@8937
 7412+0000e3a4@8938
 7413+0000e304@8939
 7414+000061a4@8940
 7415+0000e3a4@8941
 7416+0000f3a4@8942
 7417+0000f384@8943
 7418+000073a6@8944
 7419+0000f3a6@8945
 7420+0000f53a@8946
 7421+0000b5ba@8947
 7422+000035ba@8949
 7423+0000a53a@8950
 7424+0000a182@8951
 7425+00002100@8954
 7426+0000a180@8955
 7427+0000e3a4@8956
 7428+000063a4@8958
 7429+0000e1a4@8959
 7430+0000e180@8960
 7431+0000f324@8961
 7432+0000f3a4@8962
 7433+000071a6@8963
 7434+0000f3a6@8964
 7435+0000f93a@8965
 7436+0000b9ba@8966
 7437+000039ba@8968
 7438+0000a9fa@8969
 7439+0000abc2@8970
 7440+00002bc2@8972
 7441+0000abc0@8973
 7442+0000abe4@8974
 7443+0000ebe4@8975
 7444+0000eb64@8976
 7445+00006be4@8977
 7446+0000ebe4@8978
 7447+0000fbe4@8979
 7448+0000fb40@8980
 7449+0000fbe4@8981
 7450+00007be6@8982
 7451+0000fbfe@8983
 7452+0000f93a@8984
 7453+0000f9ba@8985
 7454+000079ba@8986
 7455+0000e93a@8987
 7456+0000eb42@8988
 7457+0000ebc2@8989
 7458+00006b40@8991
 7459+0000ebc0@8992
 7460+0000ebe4@8993
 7461+0000a3a4@8994
 7462+0000a324@8995
 7463+000023a4@8996
 7464+0000a3a4@8997
 7465+0000b3a4@8998
 7466+000033a6@9000
 7467+0000f3a6@9001
 7468+0000f97e@9002
 7469+0000b9fa@9003
 7470+000039fa@9005
 7471+0000a97a@9006
 7472+0000a182@9007
 7473+00002180@9010
 7474+0000a3a4@9011
 7475+0000e3a4@9012
 7476+0000e324@9013
 7477+000063a4@9014
 7478+0000e3a4@9015
 7479+0000f180@9016
 7480+0000f304@9017
 7481+0000f3a4@9018
 7482+000073a6@9019
 7483+0000f3a6@9020
 7484+0000f11a@9021
 7485+0000b19a@9022
 7486+0000a19a@9024
 7487+0000a192@9025
 7488+0000a182@9026
 7489+00002102@9028
 7490+0000a180@9029
 7491+0000e3a4@9030
 7492+0000e184@9031
 7493+0000e304@9032
 7494+00006180@9033
 7495+0000e3a4@9034
 7496+0000f3a4@9035
 7497+0000f300@9036
 7498+0000f3a4@9037
 7499+0000f3a6@9038
 7500+0000f35a@9039
 7501+0000b3da@9040
 7502+000033da@9042
 7503+0000a35a@9043
 7504+0000afc2@9044
 7505+00002f40@9047
 7506+0000afc0@9048
 7507+0000efe4@9049
 7508+00006fe4@9051
 7509+0000efe4@9052
 7510+0000ff64@9054
 7511+0000ffe4@9055
 7512+00007fe6@9056
 7513+0000ffe6@9057
 7514+0000f346@9058
 7515+0000b3c6@9059
 7516+00003346@9061
 7517+0000a3c6@9062
 7518+0000abe2@9063
 7519+00002be2@9065
 7520+0000abe0@9066
 7521+0000ebe4@9068
 7522+0000eb64@9069
 7523+00006be4@9070
 7524+0000ebe4@9071
 7525+0000fbe4@9072
 7526+0000fb64@9073
 7527+0000fbe4@9074
 7528+00007be6@9075
 7529+0000fbe6@9076
 7530+0000b53a@9077
 7531+0000b5ba@9078
 7532+000035ba@9079
 7533+0000a5ba@9080
 7534+0000a182@9081
 7535+00002102@9084
 7536+0000a180@9085
 7537+0000e380@9086
 7538+0000e384@9087
 7539+0000e300@9088
 7540+000061a4@9089
 7541+0000e3a4@9090
 7542+0000f3a4@9091
 7543+000073a6@9093
 7544+0000f3a6@9094
 7545+0000f53a@9095
 7546+0000b5ba@9096
 7547+000035ba@9098
 7548+0000a53a@9099
 7549+0000a182@9100
 7550+00002100@9103
 7551+0000a180@9104
 7552+0000e1a4@9105
 7553+0000e3a4@9106
 7554+000063a4@9107
 7555+0000e1a4@9108
 7556+0000e180@9109
 7557+0000f324@9110
 7558+0000f3a4@9111
 7559+000071a6@9112
 7560+0000f3a6@9113
 7561+0000f93e@9114
 7562+0000b9be@9115
 7563+000039be@9117
 7564+0000a9fe@9118
 7565+0000abc2@9119
 7566+00002bc2@9121
 7567+0000ab40@9122
 7568+0000abe4@9123
 7569+0000ebe4@9124
 7570+0000eb64@9125
 7571+00006be4@9126
 7572+0000ebe4@9127
 7573+0000fbe4@9128
 7574+0000fb64@9129
 7575+0000fbe4@9130
 7576+00007be6@9131
 7577+0000fbfe@9132
 7578+0000f93e@9133
 7579+0000f9be@9134
 7580+000079be@9135
 7581+0000f93c@9136
 7582+0000fb40@9137
 7583+0000fbc0@9138
 7584+0000ebc0@9139
 7585+00006b40@9140
 7586+0000ebc0@9141
 7587+0000ebe4@9142
 7588+0000eb64@9144
 7589+00006be4@9145
 7590+0000ebe4@9146
 7591+0000fbe4@9147
 7592+00007be6@9149
 7593+0000fbe6@9150
 7594+0000f11a@9151
 7595+0000b19a@9152
 7596+0000319a@9154
 7597+0000a11a@9155
 7598+0000a182@9156
 7599+00002100@9159
 7600+0000a3a4@9160
 7601+0000e3a4@9161
 7602+0000e324@9162
 7603+000063a4@9163
 7604+0000e3a4@9164
 7605+0000f180@9165
 7606+0000f304@9166
 7607+0000f3a4@9167
 7608+000073a6@9168
 7609+0000f3a6@9169
 7610+0000f11a@9170
 7611+0000b19a@9171
 7612+0000a19a@9173
 7613+0000a182@9174
 7614+00002102@9177
 7615+0000a180@9178
 7616+0000e3a4@9179
 7617+0000e384@9180
 7618+0000e304@9181
 7619+00006180@9182
 7620+0000e3a4@9183
 7621+0000f3a4@9184
 7622+0000f304@9185
 7623+0000f3a4@9186
 7624+0000f3a6@9187
 7625+0000f35e@9188
 7626+0000b3de@9189
 7627+000033de@9191
 7628+0000a35e@9192
 7629+0000af42@9193
 7630+0000afc2@9194
 7631+00002f40@9196
 7632+0000afc0@9197
 7633+0000efe4@9198
 7634+00006fe4@9200
 7635+0000efe4@9201
 7636+0000ff64@9203
 7637+0000ffe4@9204
 7638+00007fe6@9205
 7639+0000ffe6@9206
 7640+0000f346@9207
 7641+0000b3c6@9208
 7642+000033c6@9210
 7643+0000a3c6@9211
 7644+0000abe2@9212
 7645+00002be2@9214
 7646+0000abe0@9215
 7647+0000ebe4@9217
 7648+0000eb64@9218
 7649+00006be4@9219
 7650+0000ebe4@9220
 7651+0000fbe4@9221
 7652+0000fb64@9222
 7653+0000fbe4@9223
 7654+00007be6@9224
 7655+0000fbe6@9225
 7656+0000b91a@9226
 7657+0000b99a@9227
 7658+0000399a@9228
 7659+0000a99a@9229
 7660+0000afa2@9230
 7661+0000a7a2@9231
 7662+00002722@9233
 7663+0000a7a0@9234
 7664+0000e7a0@9235
 7665+0000e7a4@9236
 7666+0000e724@9237
 7667+000067a4@9238
 7668+0000e7a4@9239
 7669+0000f7a4@9240
 7670+000077a6@9242
 7671+0000f7a6@9243
 7672+0000f93a@9244
 7673+0000b9ba@9245
 7674+000039ba@9247
 7675+0000a93a@9248
 7676+0000a7a2@9249
 7677+00002720@9252
 7678+0000a7a4@9253
 7679+0000e7a4@9254
 7680+000067a4@9256
 7681+0000e7a4@9257
 7682+0000f724@9259
 7683+0000f7a4@9260
 7684+000077a6@9261
 7685+0000f7a6@9262
 7686+0000f93a@9263
 7687+0000f9ba@9264
 7688+000079ba@9266
 7689+0000e9ba@9267
 7690+0000e7a2@9268
 7691+000067a2@9270
 7692+0000e7a0@9271
 7693+0000e7a4@9272
 7694+0000a7a4@9273
 7695+0000a568@9274
 7696+000025e8@9275
 7697+0000a5e8@9276
 7698+0000b5e8@9277
 7699+0000b568@9278
 7700+0000b5e8@9279
 7701+000075ea@9280
 7702+0000f5fa@9281
 7703+0000f9ba@9282
 7704+000079ba@9284
 7705+0000e93a@9285
 7706+0000ef22@9286
 7707+0000e7a2@9287
 7708+00006720@9289
 7709+0000e7a0@9290
 7710+0000e7a4@9291
 7711+0000a5e8@9292
 7712+000025e8@9294
 7713+0000a5e8@9295
 7714+0000b568@9296
 7715+0000b5e8@9297
 7716+000035ea@9298
 7717+0000f5ea@9299
 7718+0000f11e@9300
 7719+0000b19e@9301
 7720+0000319e@9303
 7721+0000a11e@9304
 7722+0000a9d2@9305
 7723+00002950@9308
 7724+0000abf4@9309
 7725+0000ebf4@9310
 7726+0000eb74@9311
 7727+00006bf4@9312
 7728+0000ebf4@9313
 7729+0000f9d0@9314
 7730+0000fb54@9315
 7731+0000fbf4@9316
 7732+00007bf6@9317
 7733+0000fbf6@9318
 7734+0000b31e@9319
 7735+0000b39e@9320
 7736+0000a39e@9322
 7737+0000abd2@9323
 7738+0000a9d2@9324
 7739+00002952@9326
 7740+0000a9d0@9327
 7741+0000ebf4@9328
 7742+0000e9d4@9329
 7743+0000eb54@9330
 7744+000069d4@9331
 7745+0000ebf4@9332
 7746+0000fbf4@9333
 7747+0000fb50@9334
 7748+0000fbf4@9335
 7749+0000fbf6@9336
 7750+0000ff1e@9337
 7751+0000b59e@9338
 7752+0000359e@9340
 7753+0000a51e@9341
 7754+0000a9d2@9342
 7755+00002950@9345
 7756+0000a9d0@9346
 7757+0000ebf4@9347
 7758+0000e9d4@9348
 7759+00006bf4@9349
 7760+0000e9f4@9350
 7761+0000fb74@9352
 7762+0000fbf4@9353
 7763+000079f6@9354
 7764+0000fbf6@9355
 7765+0000f71e@9356
 7766+0000b79e@9357
 7767+0000379e@9359
 7768+0000a79e@9360
 7769+0000a9d2@9361
 7770+000029d2@9363
 7771+0000a950@9364
 7772+0000abf0@9365
 7773+0000ebf4@9366
 7774+0000eb74@9367
 7775+000069f4@9368
 7776+0000ebf4@9369
 7777+0000fbf4@9370
 7778+0000fb54@9371
 7779+0000fbf4@9372
 7780+00007bf6@9373
 7781+0000fbf6@9374
 7782+0000b91e@9375
 7783+0000b99e@9376
 7784+0000399e@9377
 7785+0000a91e@9378
 7786+0000a5f2@9379
 7787+00002572@9382
 7788+0000a5f0@9383
 7789+0000e7f0@9384
 7790+0000e7f4@9385
 7791+0000e774@9386
 7792+000065f4@9387
 7793+0000e7f4@9388
 7794+0000f7f4@9389
 7795+000077f6@9391
 7796+0000f7f6@9392
 7797+0000f93e@9393
 7798+0000b9be@9394
 7799+000039be@9396
 7800+0000a93e@9397
 7801+0000a5f2@9398
 7802+00002570@9401
 7803+0000a5f4@9402
 7804+0000e7f4@9403
 7805+000067f4@9405
 7806+0000e7f4@9406
 7807+0000e5f0@9407
 7808+0000f774@9408
 7809+0000f7f4@9409
 7810+000075f6@9410
 7811+0000f7f6@9411
 7812+0000fb1e@9412
 7813+0000bb9e@9413
 7814+00003b9e@9415
 7815+0000abfe@9416
 7816+0000a5f2@9417
 7817+00002572@9419
 7818+0000a5f0@9420
 7819+0000e5f4@9421
 7820+0000e774@9423
 7821+000065f4@9424
 7822+0000e7f4@9425
 7823+0000f7f4@9426
 7824+0000f774@9427
 7825+0000f7f4@9428
 7826+000077f6@9429
 7827+0000fffe@9430
 7828+0000b99e@9431
 7829+0000399e@9433
 7830+0000a91e@9434
 7831+0000a5f2@9435
 7832+00002570@9438
 7833+0000a5f0@9439
 7834+0000e7f4@9440
 7835+0000e774@9442
 7836+000067f4@9443
 7837+0000e7f4@9444
 7838+0000f774@9445
 7839+0000f7f4@9446
 7840+000077f6@9447
 7841+0000f7f6@9448
 7842+0000f93e@9449
 7843+0000b9be@9450
 7844+000039be@9452
 7845+0000a93e@9453
 7846+0000a5f2@9454
 7847+0000a570@9457
 7848+0000a7f4@9458
 7849+0000e7f4@9459
 7850+0000e774@9460
 7851+000067f4@9461
 7852+0000e7f4@9462
 7853+0000f5f0@9463
 7854+0000f774@9464
 7855+0000f7f4@9465
 7856+000077f6@9466
 7857+0000f7f6@9467
 7858+0000bb1e@9468
 7859+0000bb9e@9469
 7860+0000ab9e@9471
 7861+0000aff2@9472
 7862+0000a5f2@9473
 7863+00002572@9475
 7864+0000a5f0@9476
 7865+0000e7f4@9477
 7866+0000e774@9479
 7867+000065f4@9480
 7868+0000e7f4@9481
 7869+0000f7f4@9482
 7870+0000f774@9483
 7871+0000f7f4@9484
 7872+0000f7f6@9485
 7873+0000fd3e@9486
 7874+0000b99e@9487
 7875+0000399e@9489
 7876+0000a91e@9490
 7877+0000a5f2@9491
 7878+00002570@9494
 7879+0000a5f0@9495
 7880+0000e7f4@9496
 7881+000067f4@9498
 7882+0000e7f4@9499
 7883+0000f774@9501
 7884+0000f7f4@9502
 7885+000075f6@9503
 7886+0000f7f6@9504
 7887+0000f93e@9505
 7888+0000b9be@9506
 7889+000039be@9508
 7890+0000a9be@9509
 7891+0000a5f2@9510
 7892+000025f2@9512
 7893+0000a5f0@9513
 7894+0000a7f0@9514
 7895+0000e7f4@9515
 7896+0000e774@9516
 7897+000065f4@9517
 7898+0000e7f4@9518
 7899+0000f7f4@9519
 7900+0000f774@9520
 7901+0000f7f4@9521
 7902+000077f6@9522
 7903+0000f7f6@9523
 7904+0000bb1e@9524
 7905+0000bb9e@9525
 7906+00003b9e@9526
 7907+0000ab1e@9527
 7908+0000a5f2@9528
 7909+00002572@9531
 7910+0000a5f0@9532
 7911+0000e7f0@9533
 7912+0000e7f4@9534
 7913+0000e774@9535
 7914+000067f4@9536
 7915+0000e7f4@9537
 7916+0000f7f4@9538
 7917+000077f6@9540
 7918+0000f7f6@9541
 7919+0000fd1e@9542
 7920+0000b99e@9543
 7921+0000399e@9545
 7922+0000a91e@9546
 7923+0000a5f2@9547
 7924+00002570@9550
 7925+0000a5f4@9551
 7926+0000e7f4@9552
 7927+0000e774@9553
 7928+000067f4@9554
 7929+0000e5f4@9555
 7930+0000f774@9557
 7931+0000f7f4@9558
 7932+000075f6@9559
 7933+0000f7f6@9560
 7934+0000f91e@9561
 7935+0000f99e@9562
 7936+0000799e@9564
 7937+0000e9fe@9565
 7938+0000e5f2@9566
 7939+000065f2@9568
 7940+0000e5f0@9569
 7941+0000e5f4@9570
 7942+0000a5f4@9571
 7943+0000a100@9572
 7944+00002180@9573
 7945+0000a180@9574
 7946+0000b180@9575
 7947+0000b100@9576
 7948+0000b180@9577
 7949+00007182@9578
 7950+0000f10e@9579
 7951+0000f93e@9580
 7952+0000b9be@9581
 7953+000039be@9582
 7954+0000a93e@9583
 7955+0000a5f2@9584
 7956+00002570@9587
 7957+0000a5f0@9588
 7958+0000e7f4@9589
 7959+0000e5f4@9590
 7960+0000e774@9591
 7961+000065f4@9592
 7962+0000e7f4@9593
 7963+0000f774@9594
 7964+0000f7f4@9595
 7965+000077f6@9596
 7966+0000f7f6@9597
 7967+0000fb1e@9598
 7968+0000bb9e@9599
 7969+00003b9e@9601
 7970+0000ab1e@9602
 7971+0000a5f2@9603
 7972+00002570@9606
 7973+0000a7f4@9607
 7974+0000e7f4@9608
 7975+0000e774@9609
 7976+000067f4@9610
 7977+0000e7f4@9611
 7978+0000f7f4@9612
 7979+0000f774@9613
 7980+0000f7f4@9614
 7981+000077f6@9615
 7982+0000f7f6@9616
 7983+0000b91a@9617
 7984+0000b99a@9618
 7985+0000a99a@9620
 7986+0000adf2@9621
 7987+0000a5f2@9622
 7988+00002572@9624
 7989+0000a5f0@9625
 7990+0000e7f4@9626
 7991+0000e5f4@9627
 7992+0000e774@9628
 7993+000065f0@9629
 7994+0000e7f4@9630
 7995+0000f7f4@9631
 7996+0000f770@9632
 7997+0000f7f4@9633
 7998+0000f7f6@9634
 7999+0000fd7e@9635
 8000+0000b9ba@9636
 8001+000039ba@9638
 8002+0000a93a@9639
 8003+0000a5f2@9640
 8004+00002570@9643
 8005+0000a5f0@9644
 8006+0000e7f4@9645
 8007+000067f4@9647
 8008+0000e5f4@9648
 8009+0000f774@9650
 8010+0000f7f4@9651
 8011+000075f6@9652
 8012+0000f7f6@9653
 8013+0000fb1a@9654
 8014+0000bb9a@9655
 8015+00003b9a@9657
 8016+0000ab9a@9658
 8017+0000a5f2@9659
 8018+000025f2@9661
 8019+0000a570@9662
 8020+0000a7f0@9663
 8021+0000e7f4@9664
 8022+0000e774@9665
 8023+000067f4@9666
 8024+0000e7f4@9667
 8025+0000f7f4@9668
 8026+0000f774@9669
 8027+0000f7f4@9670
 8028+000077f6@9671
 8029+0000f7f6@9672
 8030+0000b81a@9673
 8031+0000b89a@9674
 8032+0000389a@9675
 8033+0000a89a@9676
 8034+0000a4f2@9677
 8035+00002470@9680
 8036+0000a470@9681
 8037+0000e6f0@9682
 8038+0000e6f4@9683
 8039+00006470@9685
 8040+0000e674@9686
 8041+0000f6f4@9687
 8042+000076f6@9689
 8043+0000f676@9690
 8044+0000f83a@9691
 8045+0000b8ba@9692
 8046+0000383a@9694
 8047+0000a83a@9695
 8048+0000a4f2@9696
 8049+00002470@9699
 8050+0000a474@9700
 8051+0000e6f4@9701
 8052+000066f4@9703
 8053+0000e474@9704
 8054+0000f6f4@9706
 8055+00007476@9708
 8056+0000f676@9709
 8057+0000fa9a@9710
 8058+0000ba9a@9711
 8059+00003a1a@9713
 8060+0000aa7a@9714
 8061+0000a4f2@9715
 8062+000024f2@9717
 8063+0000a470@9718
 8064+0000e474@9719
 8065+0000e6f4@9720
 8066+00006474@9722
 8067+0000e674@9723
 8068+0000f6f4@9724
 8069+00007676@9727
 8070+0000f67e@9728
 8071+0000b29a@9729
 8072+0000329a@9731
 8073+0000a21a@9732
 8074+0000a4f2@9733
 8075+00002470@9736
 8076+0000a470@9737
 8077+0000e6f4@9738
 8078+0000e474@9741
 8079+0000e674@9742
 8080+0000f6f4@9743
 8081+00007676@9745
 8082+0000f676@9746
 8083+0000f21a@9747
 8084+0000b29a@9748
 8085+0000321a@9750
 8086+0000a29a@9751
 8087+0000a4f2@9752
 8088+0000a472@9754
 8089+0000a4f0@9755
 8090+0000a6f4@9756
 8091+0000e6f4@9757
 8092+0000e674@9758
 8093+00006674@9759
 8094+0000e6f4@9760
 8095+0000f6f4@9761
 8096+0000f674@9762
 8097+000076f6@9764
 8098+0000f6f6@9765
 8099+0000b21a@9766
 8100+0000a29a@9769
 8101+0000a6f2@9770
 8102+0000a4f2@9771
 8103+0000a472@9772
 8104+00002472@9773
 8105+0000a4f0@9774
 8106+0000e6f4@9775
 8107+0000e674@9776
 8108+000064f0@9778
 8109+0000e6f4@9779
 8110+0000f6f4@9780
 8111+0000f674@9781
 8112+00007674@9782
 8113+0000f6f6@9783
 8114+0000f6be@9784
 8115+0000b22e@9785
 8116+000032ae@9787
 8117+0000a2ae@9788
 8118+0000a082@9789
 8119+0000a002@9790
 8120+00002080@9792
 8121+0000a080@9793
 8122+0000e2a4@9794
 8123+0000e204@9795
 8124+00006224@9796
 8125+0000e0a4@9797
 8126+0000e2a4@9798
 8127+0000f224@9799
 8128+0000f204@9800
 8129+000072a6@9801
 8130+0000f2a6@9802
 8131+0000f2ae@9803
 8132+0000f22e@9804
 8133+000072ae@9806
 8134+0000e2ae@9807
 8135+0000e082@9808
 8136+0000e002@9809
 8137+00006002@9810
 8138+0000e080@9811
 8139+0000e2a0@9812
 8140+0000a2a4@9813
 8141+0000a60c@9814
 8142+0000268c@9815
 8143+0000a68c@9816
 8144+0000b68c@9817
 8145+0000b60c@9818
 8146+0000768e@9820
 8147+0000f68e@9821
 8148+0000b49e@9822
 8149+0000b41e@9823
 8150+0000341e@9824
 8151+0000a49e@9825
 8152+0000aef2@9826
 8153+0000aa72@9827
 8154+0000aaf2@9828
 8155+00002af0@9829
 8156+0000aaf0@9830
 8157+0000ea70@9831
 8158+0000eaf4@9832
 8159+00006af4@9834
 8160+0000ea74@9835
 8161+0000fa74@9836
 8162+0000faf4@9837
 8163+00007af6@9838
 8164+0000faf6@9839
 8165+0000fe26@9840
 8166+0000b4a6@9841
 8167+000034a6@9843
 8168+0000a426@9844
 8169+0000a472@9845
 8170+0000a4f2@9846
 8171+000024f0@9848
 8172+0000a474@9849
 8173+0000e474@9850
 8174+0000e6f4@9851
 8175+000066f4@9852
 8176+0000e6f4@9853
 8177+0000e474@9854
 8178+0000f6f4@9855
 8179+000074f6@9857
 8180+0000f676@9858
 8181+0000f606@9859
 8182+0000b686@9860
 8183+00003686@9862
 8184+0000a676@9863
 8185+0000a472@9864
 8186+0000a4f2@9865
 8187+000024f2@9866
 8188+0000a470@9867
 8189+0000e474@9868
 8190+0000e6f4@9869
 8191+000064f4@9871
 8192+0000e674@9872
 8193+0000f674@9873
 8194+0000f6f4@9874
 8195+000076f6@9876
 8196+0000f676@9877
 8197+0000b626@9878
 8198+0000b6a6@9879
 8199+000036a6@9880
 8200+0000a626@9881
 8201+0000a472@9882
 8202+0000a4f2@9883
 8203+000024f0@9885
 8204+0000a470@9886
 8205+0000e674@9887
 8206+0000e6f4@9888
 8207+000066f4@9890
 8208+0000e674@9891
 8209+0000f674@9892
 8210+0000f6f4@9893
 8211+000076f6@9894
 8212+0000f676@9895
 8213+0000f226@9896
 8214+0000b2a6@9897
 8215+000032a6@9899
 8216+0000a226@9900
 8217+0000a002@9901
 8218+0000a082@9902
 8219+00002080@9904
 8220+0000a2a4@9905
 8221+0000e2a4@9906
 8222+00006224@9908
 8223+0000e2a4@9909
 8224+0000f280@9910
 8225+0000f2a4@9911
 8226+0000f224@9912
 8227+00007206@9913
 8228+0000f2a6@9914
 8229+0000f9be@9915
 8230+0000b9be@9916
 8231+0000b93e@9917
 8232+0000a93e@9918
 8233+0000abe2@9919
 8234+0000abc2@9920
 8235+0000ab42@9921
 8236+00002b42@9922
 8237+0000abc0@9923
 8238+0000ebe4@9924
 8239+0000eb64@9926
 8240+00006b44@9927
 8241+0000ebe4@9928
 8242+0000fbe4@9929
 8243+00007b44@9931
 8244+0000fb66@9932
 8245+0000fbe6@9933
 8246+0000b3a6@9934
 8247+0000b326@9935
 8248+00003326@9936
 8249+0000a3a6@9937
 8250+0000a182@9938
 8251+0000a102@9940
 8252+00002100@9941
 8253+0000a180@9942
 8254+0000e3a4@9943
 8255+00006324@9945
 8256+0000e124@9946
 8257+0000e3a4@9947
 8258+0000f3a4@9948
 8259+0000f324@9949
 8260+00007326@9950
 8261+0000f3a6@9951
 8262+0000f19e@9952
 8263+0000b19e@9953
 8264+0000b11e@9954
 8265+0000311e@9955
 8266+0000a19e@9956
 8267+0000a182@9957
 8268+00002102@9959
 8269+0000a100@9960
 8270+0000a3a0@9961
 8271+0000e3a4@9962
 8272+0000e324@9963
 8273+00006104@9964
 8274+0000e3a4@9965
 8275+0000f3a4@9966
 8276+0000f324@9968
 8277+00007306@9969
 8278+0000f3a6@9970
 8279+0000f19e@9971
 8280+0000b19e@9972
 8281+0000311e@9973
 8282+0000a11e@9974
 8283+0000a182@9975
 8284+0000a102@9977
 8285+00002102@9978
 8286+0000a180@9979
 8287+0000e380@9980
 8288+0000e384@9981
 8289+0000e304@9982
 8290+000063a4@9983
 8291+0000e3a4@9984
 8292+0000f3a4@9985
 8293+000073a6@9987
 8294+0000f3a6@9988
 8295+0000f17e@9989
 8296+0000b1de@9990
 8297+000031de@9992
 8298+0000a15e@9993
 8299+0000afc2@9994
 8300+00002f40@9997
 8301+0000afc4@9998
 8302+0000efe4@9999
 8303+00006fe4@10001
 8304+0000efe4@10002
 8305+0000efc4@10003
 8306+0000ff64@10004
 8307+0000ffe4@10005
 8308+00007fe6@10006
 8309+0000ffe6@10007
 8310+0000b356@10008
 8311+0000b3d6@10009
 8312+00003356@10011
 8313+0000a7f6@10012
 8314+0000a7f2@10013
 8315+000027f2@10015
 8316+0000a7f0@10016
 8317+0000e7f4@10017
 8318+0000e774@10019
 8319+000067f4@10020
 8320+0000e7f4@10021
 8321+0000f7f4@10022
 8322+0000f774@10023
 8323+0000f7f4@10024
 8324+000077f6@10025
 8325+0000f7fe@10026
 8326+0000b53e@10027
 8327+0000b5be@10028
 8328+000035be@10029
 8329+0000a53e@10030
 8330+0000af02@10031
 8331+0000ab82@10032
 8332+00002b00@10034
 8333+0000ab80@10035
 8334+0000eba4@10036
 8335+0000eb24@10038
 8336+0000eba4@10039
 8337+0000fb24@10041
 8338+0000fba4@10042
 8339+00007ba6@10043
 8340+0000fba6@10044
 8341+0000f71e@10045
 8342+0000b79e@10046
 8343+0000379e@10048
 8344+0000a71e@10049
 8345+0000ab82@10050
 8346+0000ab80@10053
 8347+0000aba4@10054
 8348+0000eba4@10055
 8349+0000eb24@10056
 8350+00006ba4@10057
 8351+0000eba4@10058
 8352+0000fb84@10059
 8353+0000fb04@10060
 8354+0000fba4@10061
 8355+00007ba6@10062
 8356+0000fba6@10063
 8357+0000b902@10064
 8358+0000b982@10065
 8359+0000a902@10067
 8360+0000abc2@10068
 8361+00002b42@10071
 8362+0000abc0@10072
 8363+0000ebe4@10073
 8364+0000ebc4@10074
 8365+0000eb44@10075
 8366+00006bc4@10076
 8367+0000ebe4@10077
 8368+0000fbe4@10078
 8369+0000fb40@10079
 8370+00007be4@10080
 8371+0000fbe6@10081
 8372+0000fb46@10082
 8373+0000f982@10083
 8374+00007982@10085
 8375+0000e902@10086
 8376+0000ebc2@10087
 8377+00006b40@10090
 8378+0000ebc0@10091
 8379+0000ebe4@10092
 8380+0000a180@10093
 8381+00002100@10094
 8382+0000a180@10095
 8383+0000b100@10097
 8384+0000b180@10098
 8385+00007182@10099
 8386+0000f182@10100
 8387+0000f11e@10101
 8388+0000b19e@10102
 8389+0000319e@10104
 8390+0000a19e@10105
 8391+0000a182@10106
 8392+00002182@10108
 8393+0000a180@10109
 8394+0000a3a0@10110
 8395+0000e3a4@10111
 8396+0000e324@10112
 8397+000061a4@10113
 8398+0000e3a4@10114
 8399+0000f384@10115
 8400+0000f104@10116
 8401+0000f3a4@10117
 8402+000073a6@10118
 8403+0000f3a6@10119
 8404+0000f11e@10120
 8405+0000b19e@10121
 8406+0000319e@10122
 8407+0000a11e@10123
 8408+0000a182@10124
 8409+00002100@10127
 8410+0000a180@10128
 8411+0000e380@10129
 8412+0000e384@10130
 8413+0000e304@10131
 8414+00006184@10132
 8415+0000e3a4@10133
 8416+0000f3a4@10134
 8417+0000f384@10135
 8418+000073a6@10136
 8419+0000f3a6@10137
 8420+0000f162@10138
 8421+0000b1e2@10139
 8422+000031e2@10141
 8423+0000a162@10142
 8424+0000afc2@10143
 8425+00002f40@10146
 8426+0000afe4@10147
 8427+0000efe4@10148
 8428+0000ef64@10149
 8429+00006fe4@10150
 8430+0000efe4@10151
 8431+0000efc0@10152
 8432+0000ff64@10153
 8433+0000ffe4@10154
 8434+00007fe6@10155
 8435+0000ffe6@10156
 8436+0000b346@10157
 8437+0000b3c6@10158
 8438+000033c6@10160
 8439+0000a3e6@10161
 8440+0000abe2@10162
 8441+00002b62@10164
 8442+0000abe0@10165
 8443+0000ebe4@10166
 8444+0000eb64@10168
 8445+00006be4@10169
 8446+0000ebe4@10170
 8447+0000fbe4@10171
 8448+0000fb64@10172
 8449+0000fbe4@10173
 8450+00007be6@10174
 8451+0000fffe@10175
 8452+0000b7be@10176
 8453+000037be@10178
 8454+0000a73e@10179
 8455+0000ab02@10180
 8456+0000ab82@10181
 8457+00002b00@10183
 8458+0000ab80@10184
 8459+0000eba4@10185
 8460+0000eb24@10187
 8461+0000eba4@10188
 8462+0000fb24@10190
 8463+0000fba4@10191
 8464+00007ba6@10192
 8465+0000fba6@10193
 8466+0000f91e@10194
 8467+0000b99e@10195
 8468+0000399e@10197
 8469+0000a91e@10198
 8470+0000ab82@10199
 8471+0000ab00@10202
 8472+0000aba4@10203
 8473+0000eba4@10204
 8474+0000eb24@10205
 8475+00006ba4@10206
 8476+0000eba4@10207
 8477+0000fb84@10208
 8478+0000fb24@10209
 8479+0000fba4@10210
 8480+00007ba6@10211
 8481+0000fba6@10212
 8482+0000b906@10213
 8483+0000b986@10214
 8484+0000a906@10216
 8485+0000abc2@10217
 8486+00002b42@10220
 8487+0000abc0@10221
 8488+0000ebe4@10222
 8489+0000ebc4@10223
 8490+0000eb44@10224
 8491+00006bc4@10225
 8492+0000ebe4@10226
 8493+0000fbe4@10227
 8494+0000fb44@10228
 8495+0000fbe4@10229
 8496+0000fbe6@10230
 8497+0000fb06@10231
 8498+0000f986@10232
 8499+00007986@10234
 8500+0000e906@10235
 8501+0000ebc2@10236
 8502+00006b40@10239
 8503+0000ebc0@10240
 8504+0000ebe4@10241
 8505+0000a100@10242
 8506+00002100@10243
 8507+0000a180@10244
 8508+0000b100@10246
 8509+0000b180@10247
 8510+00007182@10248
 8511+0000f182@10249
 8512+0000f11e@10250
 8513+0000b19e@10251
 8514+0000319e@10253
 8515+0000a19e@10254
 8516+0000a182@10255
 8517+00002182@10257
 8518+0000a180@10258
 8519+0000a3a0@10259
 8520+0000e3a4@10260
 8521+0000e324@10261
 8522+000061a4@10262
 8523+0000e3a4@10263
 8524+0000f3a4@10264
 8525+0000f304@10265
 8526+0000f3a4@10266
 8527+000073a6@10267
 8528+0000f3a6@10268
 8529+0000f97e@10269
 8530+0000b9fe@10270
 8531+000039fe@10271
 8532+0000a97e@10272
 8533+0000a982@10273
 8534+0000a182@10274
 8535+00002102@10276
 8536+0000a180@10277
 8537+0000e3a0@10278
 8538+0000e384@10279
 8539+0000e104@10280
 8540+000061a4@10281
 8541+0000e3a4@10282
 8542+0000f3a4@10283
 8543+0000f384@10284
 8544+000073a6@10285
 8545+0000f3a6@10286
 8546+0000f166@10287
 8547+0000b1e6@10288
 8548+000031e6@10290
 8549+0000a166@10291
 8550+0000afc2@10292
 8551+00002f40@10295
 8552+0000afc4@10296
 8553+0000efe4@10297
 8554+00006fe4@10299
 8555+0000efe4@10300
 8556+0000efc0@10301
 8557+0000ff64@10302
 8558+0000ffe4@10303
 8559+00007fe6@10304
 8560+0000ffe6@10305
 8561+0000b346@10306
 8562+0000b3c6@10307
 8563+00003346@10309
 8564+0000a3e6@10310
 8565+0000abe2@10311
 8566+00002b62@10313
 8567+0000abe0@10314
 8568+0000ebe4@10315
 8569+0000eb64@10317
 8570+00006be4@10318
 8571+0000ebe4@10319
 8572+0000fbe4@10320
 8573+0000fb64@10321
 8574+0000fbe4@10322
 8575+00007be6@10323
 8576+0000fbfe@10324
 8577+0000b9be@10325
 8578+000039be@10327
 8579+0000a93e@10328
 8580+0000ab02@10329
 8581+0000ab82@10330
 8582+00002b00@10332
 8583+0000ab80@10333
 8584+0000eba4@10334
 8585+0000eb84@10335
 8586+0000eb24@10336
 8587+0000eba4@10337
 8588+0000fb24@10339
 8589+0000fba4@10340
 8590+00007ba6@10341
 8591+0000fba6@10342
 8592+0000f31e@10343
 8593+0000b39e@10344
 8594+0000339e@10346
 8595+0000a31e@10347
 8596+0000ada2@10348
 8597+0000ada0@10351
 8598+0000afa4@10352
 8599+0000efa4@10353
 8600+0000ef24@10354
 8601+00006fa4@10355
 8602+0000efa4@10356
 8603+0000ffa4@10357
 8604+0000ff24@10358
 8605+0000ffa4@10359
 8606+00007fa6@10360
 8607+0000ffa6@10361
 8608+0000b90a@10362
 8609+0000b98a@10363
 8610+0000a90a@10365
 8611+0000abc2@10366
 8612+00002b42@10369
 8613+0000abc0@10370
 8614+0000ebe4@10371
 8615+0000ebc4@10372
 8616+0000eb44@10373
 8617+00006bc0@10374
 8618+0000ebe4@10375
 8619+0000fbe4@10376
 8620+0000fb40@10377
 8621+00007be4@10378
 8622+0000fbe6@10379
 8623+0000fb0e@10380
 8624+0000f98a@10381
 8625+0000798a@10383
 8626+0000e90a@10384
 8627+0000ebc2@10385
 8628+00006b40@10388
 8629+0000ebc0@10389
 8630+0000ebe4@10390
 8631+0000a5e0@10391
 8632+000025e0@10392
 8633+0000a5e0@10393
 8634+0000b560@10395
 8635+0000b5e0@10396
 8636+000075e2@10397
 8637+0000f5e2@10398
 8638+0000f91e@10399
 8639+0000b99e@10400
 8640+0000399e@10402
 8641+0000a99e@10403
 8642+0000abd2@10404
 8643+00002bd2@10406
 8644+0000ab50@10407
 8645+0000abf0@10408
 8646+0000ebf4@10409
 8647+0000eb74@10410
 8648+00006bf4@10411
 8649+0000ebf4@10412
 8650+0000fbf4@10413
 8651+0000fb54@10414
 8652+0000fbf4@10415
 8653+00007bf6@10416
 8654+0000fbf6@10417
 8655+0000b91e@10418
 8656+0000b99e@10419
 8657+0000399e@10420
 8658+0000a91e@10421
 8659+0000abd2@10422
 8660+00002b50@10425
 8661+0000abd0@10426
 8662+0000ebf4@10427
 8663+0000eb74@10429
 8664+00006bf4@10430
 8665+0000ebf4@10431
 8666+0000fbf4@10432
 8667+00007bf6@10434
 8668+0000fbf6@10435
 8669+0000f97a@10436
 8670+0000b1ea@10437
 8671+000031ea@10439
 8672+0000b16a@10440
 8673+0000afc2@10441
 8674+00002f40@10444
 8675+0000afe4@10445
 8676+0000efe4@10446
 8677+0000ef64@10447
 8678+00006fe4@10448
 8679+0000efe4@10449
 8680+0000efc0@10450
 8681+0000ff64@10451
 8682+0000ffe4@10452
 8683+00007fe6@10453
 8684+0000ffe6@10454
 8685+0000b346@10455
 8686+0000b3c6@10456
 8687+00003346@10458
 8688+0000a3e6@10459
 8689+0000abe2@10460
 8690+00002be2@10462
 8691+0000abe0@10463
 8692+0000ebe4@10464
 8693+0000eb64@10466
 8694+00006be4@10467
 8695+0000ebe4@10468
 8696+0000fbe4@10469
 8697+0000fb64@10470
 8698+0000fbe4@10471
 8699+00007be6@10472
 8700+0000fb7e@10473
 8701+0000b3be@10474
 8702+000033be@10476
 8703+0000a33e@10477
 8704+0000ad22@10478
 8705+0000ada2@10479
 8706+00002d20@10481
 8707+0000ada0@10482
 8708+0000efa4@10483
 8709+0000ef24@10485
 8710+0000efa4@10486
 8711+0000ff24@10488
 8712+0000ffa4@10489
 8713+00007fa6@10490
 8714+0000ffa6@10491
 8715+0000f51e@10492
 8716+0000b59e@10493
 8717+0000359e@10495
 8718+0000a51e@10496
 8719+0000ada2@10497
 8720+0000ada0@10500
 8721+0000afa4@10501
 8722+0000efa4@10502
 8723+0000ef24@10503
 8724+00006fa4@10504
 8725+0000efa4@10505
 8726+0000ffa4@10506
 8727+0000ff24@10507
 8728+0000ffa4@10508
 8729+00007fa6@10509
 8730+0000ffa6@10510
 8731+0000b90e@10511
 8732+0000b98e@10512
 8733+0000a90e@10514
 8734+0000abc2@10515
 8735+00002b42@10518
 8736+0000abc0@10519
 8737+0000ebe4@10520
 8738+0000ebc4@10521
 8739+0000eb44@10522
 8740+00006bc4@10523
 8741+0000ebe4@10524
 8742+0000fbe4@10525
 8743+0000fb44@10526
 8744+00007be4@10527
 8745+0000fbe6@10528
 8746+0000fb0e@10529
 8747+0000f98e@10530
 8748+0000798e@10532
 8749+0000f90c@10533
 8750+0000fbc0@10534
 8751+0000ebc0@10535
 8752+00006b40@10537
 8753+0000ebc0@10538
 8754+0000ebe4@10539
 8755+00006be4@10541
 8756+0000ebe4@10542
 8757+0000fb64@10544
 8758+0000fbe4@10545
 8759+00007be6@10546
 8760+0000fbe6@10547
 8761+0000f91e@10548
 8762+0000b99e@10549
 8763+0000399e@10551
 8764+0000a99e@10552
 8765+0000abd2@10553
 8766+00002bd2@10555
 8767+0000ab50@10556
 8768+0000abf0@10557
 8769+0000ebf4@10558
 8770+0000eb74@10559
 8771+00006bf4@10560
 8772+0000ebf4@10561
 8773+0000fbf4@10562
 8774+0000fb54@10563
 8775+0000fbf4@10564
 8776+00007bf6@10565
 8777+0000fbf6@10566
 8778+0000b91e@10567
 8779+0000b99e@10568
 8780+0000399e@10569
 8781+0000a91e@10570
 8782+0000abd2@10571
 8783+00002b50@10574
 8784+0000abd0@10575
 8785+0000ebf0@10576
 8786+0000ebd4@10577
 8787+0000eb54@10578
 8788+00006bf4@10579
 8789+0000ebf4@10580
 8790+0000fbf4@10581
 8791+00007bf6@10583
 8792+0000fbf6@10584
 8793+0000f17e@10585
 8794+0000b1ee@10586
 8795+000031ee@10588
 8796+0000a16e@10589
 8797+0000afc2@10590
 8798+00002f40@10593
 8799+0000afe4@10594
 8800+0000efe4@10595
 8801+0000ef64@10596
 8802+00006fe4@10597
 8803+0000efe4@10598
 8804+0000efc4@10599
 8805+0000ff64@10600
 8806+0000ffe4@10601
 8807+00007fe6@10602
 8808+0000ffe6@10603
 8809+0000b346@10604
 8810+0000b3c6@10605
 8811+00002346@10607
 8812+0000a3e6@10608
 8813+0000abe2@10609
 8814+00002b62@10611
 8815+0000abe0@10612
 8816+0000ebe4@10613
 8817+0000eb64@10615
 8818+00006be4@10616
 8819+0000ebe4@10617
 8820+0000fbe4@10618
 8821+0000fb64@10619
 8822+0000fbe4@10620
 8823+00007be6@10621
 8824+0000fffe@10622
 8825+0000b5be@10623
 8826+000035be@10625
 8827+0000a53e@10626
 8828+0000ad22@10627
 8829+0000ada2@10628
 8830+00002d20@10630
 8831+0000ada0@10631
 8832+0000efa4@10632
 8833+0000eda4@10633
 8834+0000ef24@10634
 8835+0000efa4@10635
 8836+0000ff24@10637
 8837+0000ffa4@10638
 8838+00007fa6@10639
 8839+0000ffa6@10640
 8840+0000f71e@10641
 8841+0000b79e@10642
 8842+0000379e@10644
 8843+0000a71e@10645
 8844+0000ada2@10646
 8845+0000ada0@10649
 8846+0000afa4@10650
 8847+0000efa4@10651
 8848+0000ef24@10652
 8849+00006fa4@10653
 8850+0000efa4@10654
 8851+0000ffa4@10655
 8852+0000ff24@10656
 8853+0000ffa4@10657
 8854+00007fa6@10658
 8855+0000ffa6@10659
 8856+0000b912@10660
 8857+0000b992@10661
 8858+0000a992@10663
 8859+0000abc2@10664
 8860+00002b42@10667
 8861+0000abc0@10668
 8862+0000ebe4@10669
 8863+0000ebc4@10670
 8864+0000eb44@10671
 8865+00006bc4@10672
 8866+0000ebe4@10673
 8867+0000fbe4@10674
 8868+0000fb44@10675
 8869+00007be6@10676
 8870+0000fbe6@10677
 8871+0000fb52@10678
 8872+0000f992@10679
 8873+00007992@10681
 8874+0000e912@10682
 8875+0000ebc2@10683
 8876+00006b40@10686
 8877+0000ebc0@10687
 8878+0000ebe4@10688
 8879+0000a5e0@10689
 8880+000025e0@10690
 8881+0000a5e0@10691
 8882+0000b560@10693
 8883+0000b5e0@10694
 8884+000075e2@10695
 8885+0000f5e2@10696
 8886+0000f91e@10697
 8887+0000b99e@10698
 8888+0000399e@10700
 8889+0000a99e@10701
 8890+0000abd2@10702
 8891+00002bd2@10704
 8892+0000ab50@10705
 8893+0000abf0@10706
 8894+0000ebf4@10707
 8895+0000eb74@10708
 8896+00006bf4@10709
 8897+0000ebf4@10710
 8898+0000fbf4@10711
 8899+0000fb54@10712
 8900+0000fbf4@10713
 8901+00007bf6@10714
 8902+0000fbf6@10715
 8903+0000b91e@10716
 8904+0000b99e@10717
 8905+0000399e@10718
 8906+0000a91e@10719
 8907+0000abd2@10720
 8908+00002b50@10723
 8909+0000abd0@10724
 8910+0000ebf0@10725
 8911+0000ebd4@10726
 8912+0000eb54@10727
 8913+00006bf4@10728
 8914+0000ebf4@10729
 8915+0000fbf4@10730
 8916+00007bf6@10732
 8917+0000fbf6@10733
 8918+0000f172@10734
 8919+0000b1f2@10735
 8920+000031f2@10737
 8921+0000a172@10738
 8922+0000afc2@10739
 8923+00002f40@10742
 8924+0000afe4@10743
 8925+0000efe4@10744
 8926+0000ef64@10745
 8927+00006fe4@10746
 8928+0000efe4@10747
 8929+0000efc0@10748
 8930+0000ff64@10749
 8931+0000ffe4@10750
 8932+00007fe6@10751
 8933+0000ffe6@10752
 8934+0000b346@10753
 8935+0000b3c6@10754
 8936+00002346@10756
 8937+0000a3e6@10757
 8938+0000abe2@10758
 8939+00002b62@10760
 8940+0000abe0@10761
 8941+0000ebe4@10762
 8942+0000eb64@10764
 8943+00006be4@10765
 8944+0000ebe4@10766
 8945+0000fbe4@10767
 8946+0000fb64@10768
 8947+0000fbe4@10769
 8948+00007be6@10770
 8949+0000fb7e@10771
 8950+0000bb9e@10772
 8951+00003b9e@10774
 8952+0000ab1e@10775
 8953+0000ab02@10776
 8954+0000ab82@10777
 8955+00002b00@10779
 8956+0000ab80@10780
 8957+0000eba4@10781
 8958+0000eb84@10782
 8959+0000eb24@10783
 8960+0000eba4@10784
 8961+0000fb24@10786
 8962+0000fba4@10787
 8963+00007ba6@10788
 8964+0000fba6@10789
 8965+0000fb3e@10790
 8966+0000bbbe@10791
 8967+00003bbe@10793
 8968+0000ab3e@10794
 8969+0000ab82@10795
 8970+0000ab80@10798
 8971+0000aba4@10799
 8972+0000eba4@10800
 8973+0000eb24@10801
 8974+00006ba4@10802
 8975+0000eba4@10803
 8976+0000fb84@10804
 8977+0000fb24@10805
 8978+0000fba4@10806
 8979+00007ba6@10807
 8980+0000fba6@10808
 8981+0000f916@10809
 8982+0000b996@10810
 8983+0000a916@10812
 8984+0000abc2@10813
 8985+00002b42@10816
 8986+0000abc0@10817
 8987+0000ebe4@10818
 8988+0000ebc4@10819
 8989+0000eb44@10820
 8990+00006bc4@10821
 8991+0000ebe4@10822
 8992+0000fbe4@10823
 8993+0000fb44@10824
 8994+00007be4@10825
 8995+0000fbe6@10826
 8996+0000fb16@10827
 8997+0000f996@10828
 8998+00007996@10830
 8999+0000e916@10831
 9000+0000ebc2@10832
 9001+00006b40@10835
 9002+0000ebc0@10836
 9003+0000ebe4@10837
 9004+0000a5e0@10838
 9005+000025e0@10839
 9006+0000a5e0@10840
 9007+0000b560@10842
 9008+0000b5e0@10843
 9009+000075e2@10844
 9010+0000f5e2@10845
 9011+0000f91e@10846
 9012+0000b99e@10847
 9013+0000399e@10849
 9014+0000a99e@10850
 9015+0000abd2@10851
 9016+00002bd2@10853
 9017+0000abd0@10854
 9018+0000abf0@10855
 9019+0000ebf4@10856
 9020+0000eb74@10857
 9021+00006bd4@10858
 9022+0000ebf4@10859
 9023+0000fbf4@10860
 9024+0000fb54@10861
 9025+0000fbf4@10862
 9026+00007bf6@10863
 9027+0000fbf6@10864
 9028+0000b91e@10865
 9029+0000b99e@10866
 9030+0000399e@10867
 9031+0000a91e@10868
 9032+0000abd2@10869
 9033+00002b50@10872
 9034+0000abd0@10873
 9035+0000ebf0@10874
 9036+0000ebd4@10875
 9037+0000eb54@10876
 9038+00006bf4@10877
 9039+0000ebf4@10878
 9040+0000fbf4@10879
 9041+00007bf6@10881
 9042+0000fbf6@10882
 9043+0000f176@10883
 9044+0000b1f6@10884
 9045+000031f6@10886
 9046+0000a176@10887
 9047+0000afc2@10888
 9048+00002f40@10891
 9049+0000afe4@10892
 9050+0000efe4@10893
 9051+0000ef64@10894
 9052+00006fe4@10895
 9053+0000efe4@10896
 9054+0000efc0@10897
 9055+0000ff64@10898
 9056+0000ffe4@10899
 9057+00007fe6@10900
 9058+0000ffe6@10901
 9059+0000b346@10902
 9060+0000b3c6@10903
 9061+00002346@10905
 9062+0000a3e6@10906
 9063+0000abe2@10907
 9064+00002b62@10909
 9065+0000abe0@10910
 9066+0000ebe4@10911
 9067+0000eb64@10913
 9068+00006be4@10914
 9069+0000ebe4@10915
 9070+0000fbe4@10916
 9071+0000fb64@10917
 9072+0000fbe4@10918
 9073+00007be6@10919
 9074+0000ff7e@10920
 9075+0000bd9e@10921
 9076+00003d9e@10923
 9077+0000ad1e@10924
 9078+0000ab02@10925
 9079+0000ab82@10926
 9080+00002b00@10928
 9081+0000ab80@10929
 9082+0000eba4@10930
 9083+0000eb24@10932
 9084+0000eba4@10933
 9085+0000fb24@10935
 9086+0000fba4@10936
 9087+00007ba6@10937
 9088+0000fba6@10938
 9089+0000fd3e@10939
 9090+0000bdbe@10940
 9091+00003dbe@10942
 9092+0000ad3e@10943
 9093+0000ab82@10944
 9094+0000ab80@10947
 9095+0000aba4@10948
 9096+0000eba4@10949
 9097+0000eb24@10950
 9098+00006ba4@10951
 9099+0000eba4@10952
 9100+0000fb84@10953
 9101+0000fb24@10954
 9102+0000fba4@10955
 9103+00007ba6@10956
 9104+0000fba6@10957
 9105+0000f91a@10958
 9106+0000b99a@10959
 9107+0000a91a@10961
 9108+0000abc2@10962
 9109+00002b42@10965
 9110+0000abc0@10966
 9111+0000ebe4@10967
 9112+0000eb44@10969
 9113+00006bc4@10970
 9114+0000ebe4@10971
 9115+0000fbe4@10972
 9116+0000fb44@10973
 9117+00007be6@10974
 9118+0000fbe6@10975
 9119+0000fb1e@10976
 9120+0000f99a@10977
 9121+0000799a@10979
 9122+0000e91a@10980
 9123+0000ebc2@10981
 9124+00006b40@10984
 9125+0000ebc0@10985
 9126+0000ebe4@10986
 9127+0000a5e0@10987
 9128+000025e0@10988
 9129+0000a5e0@10989
 9130+0000b560@10991
 9131+0000b5e0@10992
 9132+000075e2@10993
 9133+0000f5e2@10994
 9134+0000f91e@10995
 9135+0000b99e@10996
 9136+0000399e@10998
 9137+0000a99e@10999
 9138+0000abd2@11000
 9139+00002bd2@11002
 9140+0000ab50@11003
 9141+0000abf0@11004
 9142+0000ebf4@11005
 9143+0000eb74@11006
 9144+00006bf4@11007
 9145+0000ebf4@11008
 9146+0000fbf4@11009
 9147+0000fb54@11010
 9148+0000fbf4@11011
 9149+00007bf6@11012
 9150+0000fbf6@11013
 9151+0000b91e@11014
 9152+0000b99e@11015
 9153+0000399e@11016
 9154+0000a91e@11017
 9155+0000abd2@11018
 9156+00002b50@11021
 9157+0000abd0@11022
 9158+0000ebf0@11023
 9159+0000ebd4@11024
 9160+0000eb54@11025
 9161+00006bf4@11026
 9162+0000ebf4@11027
 9163+0000fbf4@11028
 9164+00007bf6@11030
 9165+0000fbf6@11031
 9166+0000f17a@11032
 9167+0000b1fa@11033
 9168+000031fa@11035
 9169+0000a17a@11036
 9170+0000afc2@11037
 9171+00002f40@11040
 9172+0000afe4@11041
 9173+0000efe4@11042
 9174+0000ef64@11043
 9175+00006fe4@11044
 9176+0000efe4@11045
 9177+0000ffe4@11046
 9178+0000ff64@11047
 9179+0000ffe4@11048
 9180+00007fe6@11049
 9181+0000ffe6@11050
 9182+0000b346@11051
 9183+0000b3c6@11052
 9184+00003346@11054
 9185+0000a3e6@11055
 9186+0000abe2@11056
 9187+00002b62@11058
 9188+0000abe0@11059
 9189+0000ebe4@11060
 9190+0000eb64@11062
 9191+00006be4@11063
 9192+0000ebe4@11064
 9193+0000fbe4@11065
 9194+0000fb64@11066
 9195+0000fbe4@11067
 9196+00007be6@11068
 9197+0000ff7e@11069
 9198+0000bf9e@11070
 9199+00003f9e@11072
 9200+0000af1e@11073
 9201+0000ab02@11074
 9202+0000ab82@11075
 9203+00002b00@11077
 9204+0000ab80@11078
 9205+0000eba4@11079
 9206+0000eb24@11081
 9207+0000eba4@11082
 9208+0000fb24@11084
 9209+0000fba4@11085
 9210+00007ba6@11086
 9211+0000fba6@11087
 9212+0000ff3e@11088
 9213+0000bfbe@11089
 9214+00003fbe@11091
 9215+0000af3e@11092
 9216+0000ab82@11093
 9217+0000ab80@11096
 9218+0000aba4@11097
 9219+0000eba4@11098
 9220+0000eb24@11099
 9221+00006ba4@11100
 9222+0000eba4@11101
 9223+0000fba4@11102
 9224+0000fb24@11103
 9225+0000fba4@11104
 9226+00007ba6@11105
 9227+0000fba6@11106
 9228+0000f91e@11107
 9229+0000b99e@11108
 9230+0000a91e@11110
 9231+0000abc2@11111
 9232+00002b42@11114
 9233+0000abc0@11115
 9234+0000ebe0@11116
 9235+0000ebc4@11117
 9236+0000eb44@11118
 9237+00006bc4@11119
 9238+0000ebe4@11120
 9239+0000fbe4@11121
 9240+0000fb44@11122
 9241+00007be6@11123
 9242+0000fbe6@11124
 9243+0000fb1e@11125
 9244+0000f99e@11126
 9245+0000799e@11128
 9246+0000f91c@11129
 9247+0000fbc0@11130
 9248+0000ebc0@11131
 9249+00006b40@11133
 9250+0000ebc0@11134
 9251+0000ebe4@11135
 9252+00006be4@11137
 9253+0000ebe4@11138
 9254+0000fb64@11140
 9255+0000fbe4@11141
 9256+00007be6@11142
 9257+0000fbe6@11143
 9258+0000f91e@11144
 9259+0000b99e@11145
 9260+0000399e@11147
 9261+0000a99e@11148
 9262+0000abd2@11149
 9263+00002bd2@11151
 9264+0000abd0@11152
 9265+0000abf0@11153
 9266+0000ebf4@11154
 9267+0000eb74@11155
 9268+00006bf4@11156
 9269+0000ebf4@11157
 9270+0000fbf4@11158
 9271+0000fb54@11159
 9272+0000fbf4@11160
 9273+00007bf6@11161
 9274+0000fbf6@11162
 9275+0000bb1e@11163
 9276+0000bb9e@11164
 9277+00003b9e@11165
 9278+0000ab9e@11166
 9279+0000abe2@11167
 9280+00002b60@11170
 9281+0000abe0@11171
 9282+0000ebe4@11172
 9283+0000eb64@11174
 9284+00006be4@11175
 9285+0000ebe4@11176
 9286+0000fbe4@11177
 9287+00007be6@11179
 9288+0000fbe6@11180
 9289+0000f17e@11181
 9290+0000b1fe@11182
 9291+000031fe@11184
 9292+0000a17e@11185
 9293+0000afc2@11186
 9294+00002f40@11189
 9295+0000afe4@11190
 9296+0000efe4@11191
 9297+00006fe4@11193
 9298+0000efe4@11194
 9299+0000ff64@11196
 9300+0000ffe4@11197
 9301+00007fe6@11198
 9302+0000ffe6@11199
 9303+0000b346@11200
 9304+0000b3c6@11201
 9305+00002346@11203
 9306+0000abe6@11204
 9307+0000abe2@11205
 9308+00002b62@11207
 9309+0000abe0@11208
 9310+0000ebe4@11209
 9311+0000eb64@11211
 9312+00006be4@11212
 9313+0000ebe4@11213
 9314+0000fbe4@11214
 9315+0000fb64@11215
 9316+0000fbe4@11216
 9317+00007be6@11217
 9318+0000ff7e@11218
 9319+0000b79e@11219
 9320+0000379e@11221
 9321+0000a71e@11222
 9322+0000a992@11223
 9323+00002910@11226
 9324+0000a990@11227
 9325+0000ebb4@11228
 9326+0000eb94@11229
 9327+0000eb34@11230
 9328+0000e9b4@11231
 9329+0000fb34@11233
 9330+0000fbb4@11234
 9331+00007bb6@11235
 9332+0000fbb6@11236
 9333+0000f73e@11237
 9334+0000b7be@11238
 9335+000037be@11240
 9336+0000a73e@11241
 9337+0000a992@11242
 9338+0000a990@11245
 9339+0000abb4@11246
 9340+0000ebb4@11247
 9341+0000eb34@11248
 9342+00006bb4@11249
 9343+0000ebb4@11250
 9344+0000fb94@11251
 9345+0000fb34@11252
 9346+0000fbb4@11253
 9347+00007bb6@11254
 9348+0000fbb6@11255
 9349+0000b922@11256
 9350+0000b9a2@11257
 9351+0000a9a2@11259
 9352+0000abc2@11260
 9353+00002b42@11263
 9354+0000abc0@11264
 9355+0000ebe0@11265
 9356+0000ebe4@11266
 9357+0000eb64@11267
 9358+00006be4@11268
 9359+0000ebe4@11269
 9360+0000fbe4@11270
 9361+0000fb44@11271
 9362+00007be6@11272
 9363+0000fbe6@11273
 9364+0000fb62@11274
 9365+0000f9a2@11275
 9366+000079a2@11277
 9367+0000e922@11278
 9368+0000ebc2@11279
 9369+00006b40@11282
 9370+0000ebc0@11283
 9371+0000ebe4@11284
 9372+0000a9ec@11285
 9373+000029ec@11286
 9374+0000a9ec@11287
 9375+0000b96c@11289
 9376+0000b9ec@11290
 9377+000079ee@11291
 9378+0000f9ee@11292
 9379+0000fb3e@11293
 9380+0000bbbe@11294
 9381+00003bbe@11296
 9382+0000abbe@11297
 9383+0000abe2@11298
 9384+00002be2@11300
 9385+0000abe0@11301
 9386+0000ebe4@11303
 9387+0000eb64@11304
 9388+00006be4@11305
 9389+0000ebe4@11306
 9390+0000fbe4@11307
 9391+0000fb64@11308
 9392+0000fbe4@11309
 9393+00007be6@11310
 9394+0000fbe6@11311
 9395+0000b91e@11312
 9396+0000b99e@11313
 9397+0000399e@11314
 9398+0000a91e@11315
 9399+0000abd2@11316
 9400+00002b50@11319
 9401+0000abd0@11320
 9402+0000ebf4@11321
 9403+0000ebd4@11322
 9404+0000eb54@11323
 9405+00006bf4@11324
 9406+0000ebf4@11325
 9407+0000fbf4@11326
 9408+00007bf6@11328
 9409+0000fbf6@11329
 9410+0000fb42@11330
 9411+0000b3c2@11331
 9412+000033c2@11333
 9413+0000a342@11334
 9414+0000afc2@11335
 9415+00002f40@11338
 9416+0000afe4@11339
 9417+0000efe4@11340
 9418+0000ef64@11341
 9419+00006fe4@11342
 9420+0000efe4@11343
 9421+0000efc0@11344
 9422+0000ff64@11345
 9423+0000ffe4@11346
 9424+00007fe6@11347
 9425+0000ffe6@11348
 9426+0000b346@11349
 9427+0000b3c6@11350
 9428+00002346@11352
 9429+0000abe6@11353
 9430+0000abe2@11354
 9431+00002b62@11356
 9432+0000abe0@11357
 9433+0000ebe4@11358
 9434+0000eb64@11360
 9435+00006be4@11361
 9436+0000ebe4@11362
 9437+0000fbe4@11363
 9438+0000fb64@11364
 9439+0000fbe4@11365
 9440+00007be6@11366
 9441+0000ff7e@11367
 9442+0000bf9e@11368
 9443+00003f9e@11370
 9444+0000af1e@11371
 9445+0000aba2@11372
 9446+00002b20@11375
 9447+0000aba0@11376
 9448+0000eba4@11377
 9449+0000eb24@11379
 9450+0000eba4@11380
 9451+0000fb24@11382
 9452+0000fba4@11383
 9453+00007ba6@11384
 9454+0000fba6@11385
 9455+0000f53e@11386
 9456+0000b5be@11387
 9457+000035be@11389
 9458+0000a53e@11390
 9459+0000a182@11391
 9460+0000a100@11394
 9461+0000a3a4@11395
 9462+0000e3a4@11396
 9463+0000e324@11397
 9464+000063a4@11398
 9465+0000e3a4@11399
 9466+0000f184@11400
 9467+0000f324@11401
 9468+0000f3a4@11402
 9469+000073a6@11403
 9470+0000f3a6@11404
 9471+0000f926@11405
 9472+0000b9a6@11406
 9473+0000a926@11408
 9474+0000abe2@11409
 9475+0000abc2@11410
 9476+00002b42@11412
 9477+0000abc0@11413
 9478+0000ebe0@11414
 9479+0000ebc4@11415
 9480+0000eb44@11416
 9481+00006be4@11417
 9482+0000ebe4@11418
 9483+0000fbe4@11419
 9484+0000fb44@11420
 9485+00007be6@11421
 9486+0000fbe6@11422
 9487+0000fb66@11423
 9488+0000f9a6@11424
 9489+000079a6@11426
 9490+0000f926@11427
 9491+0000ebc2@11428
 9492+00006b40@11431
 9493+0000ebc0@11432
 9494+0000ebe4@11433
 9495+0000a5e0@11434
 9496+000025e0@11435
 9497+0000a5e0@11436
 9498+0000b560@11438
 9499+0000b5e0@11439
 9500+000075e2@11440
 9501+0000f5e2@11441
 9502+0000f91e@11442
 9503+0000b99e@11443
 9504+0000399e@11445
 9505+0000a99e@11446
 9506+0000abd2@11447
 9507+00002bd2@11449
 9508+0000abd0@11450
 9509+0000abf4@11451
 9510+0000ebf4@11452
 9511+0000eb74@11453
 9512+00006bf4@11454
 9513+0000ebf4@11455
 9514+0000fbf4@11456
 9515+0000fb54@11457
 9516+0000fbf4@11458
 9517+00007bf6@11459
 9518+0000fbf6@11460
 9519+0000b91e@11461
 9520+0000b99e@11462
 9521+0000399e@11463
 9522+0000a91e@11464
 9523+0000abd2@11465
 9524+00002b50@11468
 9525+0000abd0@11469
 9526+0000ebf4@11470
 9527+0000eb74@11472
 9528+00006bf4@11473
 9529+0000ebf4@11474
 9530+0000fbf4@11475
 9531+00007bf6@11477
 9532+0000fbf6@11478
 9533+0000fb46@11479
 9534+0000b3c6@11480
 9535+000033c6@11482
 9536+0000b346@11483
 9537+0000afc2@11484
 9538+00002f40@11487
 9539+0000afe4@11488
 9540+0000efe4@11489
 9541+0000ef64@11490
 9542+00006fe4@11491
 9543+0000efe4@11492
 9544+0000efc0@11493
 9545+0000ff44@11494
 9546+0000ffe4@11495
 9547+00007fe6@11496
 9548+0000ffe6@11497
 9549+0000b346@11498
 9550+0000b3c6@11499
 9551+00002346@11501
 9552+0000abe6@11502
 9553+0000abe2@11503
 9554+00002b62@11505
 9555+0000abe0@11506
 9556+0000ebe4@11507
 9557+0000eb64@11509
 9558+00006be4@11510
 9559+0000ebe4@11511
 9560+0000fbe4@11512
 9561+0000fb64@11513
 9562+0000fbe4@11514
 9563+00007be6@11515
 9564+0000ff7e@11516
 9565+0000b5be@11517
 9566+000035be@11519
 9567+0000a53e@11520
 9568+0000a102@11521
 9569+0000a182@11522
 9570+00002100@11524
 9571+0000a180@11525
 9572+0000e3a4@11526
 9573+0000e324@11528
 9574+0000e3a4@11529
 9575+0000f324@11531
 9576+0000f3a4@11532
 9577+000073a6@11533
 9578+0000f3a6@11534
 9579+0000f53e@11535
 9580+0000b5be@11536
 9581+000035be@11538
 9582+0000a53e@11539
 9583+0000a182@11540
 9584+0000a100@11543
 9585+0000a3a4@11544
 9586+0000e3a4@11545
 9587+0000e324@11546
 9588+000063a4@11547
 9589+0000e3a4@11548
 9590+0000f184@11549
 9591+0000f104@11550
 9592+0000f3a4@11551
 9593+000073a6@11552
 9594+0000f3a6@11553
 9595+0000f92a@11554
 9596+0000b9aa@11555
 9597+0000a92a@11557
 9598+0000abc2@11558
 9599+00002b42@11561
 9600+0000abc0@11562
 9601+0000ebe0@11563
 9602+0000ebe4@11564
 9603+0000eb64@11565
 9604+00006be4@11566
 9605+0000ebe4@11567
 9606+0000fbe4@11568
 9607+0000fb64@11569
 9608+00007be6@11570
 9609+0000fbe6@11571
 9610+0000fb6e@11572
 9611+0000f9aa@11573
 9612+000079aa@11575
 9613+0000e92a@11576
 9614+0000ebc2@11577
 9615+00006b40@11580
 9616+0000ebc0@11581
 9617+0000ebe4@11582
 9618+0000a5e0@11583
 9619+000025e0@11584
 9620+0000a5e0@11585
 9621+0000b560@11587
 9622+0000b5e0@11588
 9623+000075e2@11589
 9624+0000f5e2@11590
 9625+0000f91e@11591
 9626+0000b99e@11592
 9627+0000399e@11594
 9628+0000a99e@11595
 9629+0000abd2@11596
 9630+00002bd2@11598
 9631+0000abd0@11599
 9632+0000abf4@11600
 9633+0000ebf4@11601
 9634+0000eb74@11602
 9635+00006bf4@11603
 9636+0000ebf4@11604
 9637+0000fbf4@11605
 9638+0000fb54@11606
 9639+0000fbf4@11607
 9640+00007bf6@11608
 9641+0000fbf6@11609
 9642+0000b91e@11610
 9643+0000b99e@11611
 9644+0000399e@11612
 9645+0000a91e@11613
 9646+0000abd2@11614
 9647+00002b50@11617
 9648+0000abd0@11618
 9649+0000ebf4@11619
 9650+0000ebd4@11620
 9651+0000eb54@11621
 9652+00006bf4@11622
 9653+0000ebf4@11623
 9654+0000fbf4@11624
 9655+00007bf6@11626
 9656+0000fbf6@11627
 9657+0000fb5a@11628
 9658+0000b3ca@11629
 9659+000033ca@11631
 9660+0000a34a@11632
 9661+0000afc2@11633
 9662+00002f40@11636
 9663+0000afe4@11637
 9664+0000efe4@11638
 9665+0000ef64@11639
 9666+00006fe4@11640
 9667+0000efe4@11641
 9668+0000ffc0@11642
 9669+0000ff64@11643
 9670+0000ffe4@11644
 9671+00007fe6@11645
 9672+0000ffe6@11646
 9673+0000b346@11647
 9674+0000b3c6@11648
 9675+00002346@11650
 9676+0000abe6@11651
 9677+0000abe2@11652
 9678+00002b62@11654
 9679+0000abe0@11655
 9680+0000ebe4@11656
 9681+0000eb64@11658
 9682+00006be4@11659
 9683+0000ebe4@11660
 9684+0000fbe4@11661
 9685+0000fb64@11662
 9686+0000fbe4@11663
 9687+00007be6@11664
 9688+0000ff7e@11665
 9689+0000b5be@11666
 9690+000035be@11668
 9691+0000a53e@11669
 9692+0000a102@11670
 9693+0000a182@11671
 9694+00002100@11673
 9695+0000a180@11674
 9696+0000e3a4@11675
 9697+0000e184@11676
 9698+0000e324@11677
 9699+0000e1a4@11678
 9700+0000e3a4@11679
 9701+0000f324@11680
 9702+0000f3a4@11681
 9703+000073a6@11682
 9704+0000f3a6@11683
 9705+0000f53e@11684
 9706+0000b5be@11685
 9707+000035be@11687
 9708+0000a53e@11688
 9709+0000a182@11689
 9710+0000a180@11692
 9711+0000a3a4@11693
 9712+0000e3a4@11694
 9713+0000e324@11695
 9714+000061a4@11696
 9715+0000e3a4@11697
 9716+0000f384@11698
 9717+0000f324@11699
 9718+0000f3a4@11700
 9719+000073a6@11701
 9720+0000f3a6@11702
 9721+0000f92e@11703
 9722+0000b9ae@11704
 9723+000039ae@11705
 9724+0000a92e@11706
 9725+0000abc2@11707
 9726+00002b42@11710
 9727+0000abc0@11711
 9728+0000ebe0@11712
 9729+0000ebe4@11713
 9730+0000eb64@11714
 9731+00006be4@11715
 9732+0000ebe4@11716
 9733+0000fbe4@11717
 9734+0000fb44@11718
 9735+00007be6@11719
 9736+0000fbe6@11720
 9737+0000fb2e@11721
 9738+0000f9ae@11722
 9739+000079ae@11724
 9740+0000f92c@11725
 9741+0000fbc0@11726
 9742+0000ebc0@11727
 9743+00006b40@11729
 9744+0000ebc0@11730
 9745+0000ebe4@11731
 9746+00006be4@11733
 9747+0000ebe4@11734
 9748+0000fb64@11736
 9749+0000fbe4@11737
 9750+00007be6@11738
 9751+0000fbe6@11739
 9752+0000f91e@11740
 9753+0000b99e@11741
 9754+0000399e@11743
 9755+0000a99e@11744
 9756+0000abd2@11745
 9757+00002bd2@11747
 9758+0000abd0@11748
 9759+0000abf4@11749
 9760+0000ebf4@11750
 9761+0000eb74@11751
 9762+00006bf4@11752
 9763+0000ebf4@11753
 9764+0000fbf4@11754
 9765+0000fb54@11755
 9766+0000fbf4@11756
 9767+00007bf6@11757
 9768+0000fbf6@11758
 9769+0000b91e@11759
 9770+0000b99e@11760
 9771+0000399e@11761
 9772+0000a91e@11762
 9773+0000abd2@11763
 9774+00002b50@11766
 9775+0000abd0@11767
 9776+0000ebf4@11768
 9777+0000ebd4@11769
 9778+0000eb74@11770
 9779+00006bf4@11771
 9780+0000ebf4@11772
 9781+0000fbf4@11773
 9782+00007bf6@11775
 9783+0000fbf6@11776
 9784+0000f35e@11777
 9785+0000b3ce@11778
 9786+000033ce@11780
 9787+0000a34e@11781
 9788+0000afc2@11782
 9789+00002f40@11785
 9790+0000afe4@11786
 9791+0000efe4@11787
 9792+0000ef64@11788
 9793+00006fe4@11789
 9794+0000efe4@11790
 9795+0000efc4@11791
 9796+0000ff64@11792
 9797+0000ffe4@11793
 9798+00007fe6@11794
 9799+0000ffe6@11795
 9800+0000b346@11796
 9801+0000b3c6@11797
 9802+00002346@11799
 9803+0000abe6@11800
 9804+0000abe2@11801
 9805+00002b62@11803
 9806+0000abe0@11804
 9807+0000ebe4@11805
 9808+0000eb64@11807
 9809+00006be4@11808
 9810+0000ebe4@11809
 9811+0000fbe4@11810
 9812+0000fb64@11811
 9813+0000fbe4@11812
 9814+0000fbe6@11813
 9815+0000ff7e@11814
 9816+0000b5be@11815
 9817+000035be@11817
 9818+0000a53e@11818
 9819+0000a102@11819
 9820+0000a182@11820
 9821+00002100@11822
 9822+0000a180@11823
 9823+0000e3a4@11824
 9824+0000e1a4@11825
 9825+0000e324@11826
 9826+0000e3a4@11827
 9827+0000f324@11829
 9828+0000f3a4@11830
 9829+000073a6@11831
 9830+0000f3a6@11832
 9831+0000f53e@11833
 9832+0000b5be@11834
 9833+000035be@11836
 9834+0000a53e@11837
 9835+0000a182@11838
 9836+0000a180@11841
 9837+0000a3a4@11842
 9838+0000e3a4@11843
 9839+0000e324@11844
 9840+000061a4@11845
 9841+0000e3a4@11846
 9842+0000f384@11847
 9843+0000f304@11848
 9844+0000f3a4@11849
 9845+000073a6@11850
 9846+0000f3a6@11851
 9847+0000f932@11852
 9848+0000b9b2@11853
 9849+000039b2@11854
 9850+0000a9b2@11855
 9851+0000abc2@11856
 9852+00002b42@11859
 9853+0000abc0@11860
 9854+0000ebe0@11861
 9855+0000ebc4@11862
 9856+0000eb44@11863
 9857+00006bc4@11864
 9858+0000ebe4@11865
 9859+0000fbe4@11866
 9860+0000fbc4@11867
 9861+00007be6@11868
 9862+0000fbe6@11869
 9863+0000fb72@11870
 9864+0000f9b2@11871
 9865+000079b2@11873
 9866+0000e932@11874
 9867+0000ebc2@11875
 9868+00006b40@11878
 9869+0000ebc0@11879
 9870+0000ebe4@11880
 9871+0000a5e0@11881
 9872+000025e0@11882
 9873+0000a5e0@11883
 9874+0000b560@11885
 9875+0000b5e0@11886
 9876+000075e2@11887
 9877+0000f5e2@11888
 9878+0000f91e@11889
 9879+0000b99e@11890
 9880+0000399e@11892
 9881+0000a99e@11893
 9882+0000abd2@11894
 9883+00002bd2@11896
 9884+0000ab50@11897
 9885+0000abf4@11898
 9886+0000ebf4@11899
 9887+0000eb74@11900
 9888+00006bf4@11901
 9889+0000ebf4@11902
 9890+0000fbf4@11903
 9891+0000fb54@11904
 9892+0000fbf4@11905
 9893+00007bf6@11906
 9894+0000fbf6@11907
 9895+0000b91e@11908
 9896+0000b99e@11909
 9897+0000399e@11910
 9898+0000a91e@11911
 9899+0000abd2@11912
 9900+00002b50@11915
 9901+0000abd0@11916
 9902+0000ebf4@11917
 9903+0000ebd4@11918
 9904+0000eb54@11919
 9905+00006bf4@11920
 9906+0000ebf4@11921
 9907+0000fbf4@11922
 9908+00007bf6@11924
 9909+0000fbf6@11925
 9910+0000f352@11926
 9911+0000b3d2@11927
 9912+000033d2@11929
 9913+0000a352@11930
 9914+0000afc2@11931
 9915+00002f40@11934
 9916+0000afe4@11935
 9917+0000efe4@11936
 9918+0000ef64@11937
 9919+00006fe4@11938
 9920+0000efe4@11939
 9921+0000efc0@11940
 9922+0000ff44@11941
 9923+0000ffe4@11942
 9924+00007fe6@11943
 9925+0000ffe6@11944
 9926+0000b346@11945
 9927+0000b3c6@11946
 9928+00002346@11948
 9929+0000abe6@11949
 9930+0000abe2@11950
 9931+00002b62@11952
 9932+0000abe0@11953
 9933+0000ebe4@11954
 9934+0000eb64@11956
 9935+00006be4@11957
 9936+0000ebe4@11958
 9937+0000fbe4@11959
 9938+0000fb64@11960
 9939+0000fbe4@11961
 9940+0000fbe6@11962
 9941+0000ff7e@11963
 9942+0000b5be@11964
 9943+000035be@11966
 9944+0000a53e@11967
 9945+0000a102@11968
 9946+0000a182@11969
 9947+00002100@11971
 9948+0000a180@11972
 9949+0000e3a4@11973
 9950+0000e1a4@11974
 9951+0000e304@11975
 9952+0000e1a4@11976
 9953+0000e3a4@11977
 9954+0000f324@11978
 9955+0000f3a4@11979
 9956+000073a6@11980
 9957+0000f3a6@11981
 9958+0000f53e@11982
 9959+0000b5be@11983
 9960+000035be@11985
 9961+0000a53e@11986
 9962+0000a182@11987
 9963+0000a180@11990
 9964+0000a3a4@11991
 9965+0000e3a4@11992
 9966+0000e324@11993
 9967+000063a4@11994
 9968+0000e3a4@11995
 9969+0000f184@11996
 9970+0000f304@11997
 9971+0000f3a4@11998
 9972+000073a6@11999
 9973+0000f3a6@12000
 9974+0000f936@12001
 9975+0000b9b6@12002
 9976+000039b6@12003
 9977+0000a936@12004
 9978+0000abc2@12005
 9979+00002b42@12008
 9980+0000abc0@12009
 9981+0000ebe0@12010
 9982+0000ebc4@12011
 9983+0000eb44@12012
 9984+00006be4@12013
 9985+0000ebe4@12014
 9986+0000fbe4@12015
 9987+0000fb64@12016
 9988+00007be6@12017
 9989+0000fbe6@12018
 9990+0000fb76@12019
 9991+0000f9b6@12020
 9992+000079b6@12022
 9993+0000e936@12023
 9994+0000ebc2@12024
 9995+00006b40@12027
 9996+0000ebc0@12028
 9997+0000ebe4@12029
 9998+0000a5e0@12030
 9999+000025e0@12031
10000+0000a5e0@12032
10001+0000b560@12034
10002+0000b5e0@12035
10003+000075e2@12036
10004+0000f5e2@12037
10005+0000f91e@12038
10006+0000b99e@12039
10007+0000399e@12041
10008+0000a99e@12042
10009+0000abd2@12043
10010+00002bd2@12045
10011+0000abd0@12046
10012+0000abf4@12047
10013+0000ebf4@12048
10014+0000eb74@12049
10015+00006bf4@12050
10016+0000ebf4@12051
10017+0000fbf4@12052
10018+0000fb54@12053
10019+0000fbf4@12054
10020+00007bf6@12055
10021+0000fbf6@12056
10022+0000b33e@12057
10023+0000b3be@12058
10024+000033be@12059
10025+0000a33e@12060
10026+0000abd2@12061
10027+00002b50@12064
10028+0000abd0@12065
10029+0000ebf4@12066
10030+0000eb54@12068
10031+00006bf4@12069
10032+0000ebf4@12070
10033+0000fbf4@12071
10034+00007bf6@12073
10035+0000fbf6@12074
10036+0000f356@12075
10037+0000b3d6@12076
10038+000033d6@12078
10039+0000a356@12079
10040+0000afc2@12080
10041+00002f40@12083
10042+0000afe4@12084
10043+0000efe4@12085
10044+0000ef64@12086
10045+00006fe4@12087
10046+0000efe4@12088
10047+0000ffc4@12089
10048+0000ff44@12090
10049+0000ffe4@12091
10050+00007fe6@12092
10051+0000ffe6@12093
10052+0000b346@12094
10053+0000b3c6@12095
10054+000033c6@12097
10055+0000abe6@12098
10056+0000abe2@12099
10057+00002b62@12101
10058+0000abe0@12102
10059+0000ebe4@12103
10060+0000eb64@12105
10061+00006be4@12106
10062+0000ebe4@12107
10063+0000fbe4@12108
10064+0000fb64@12109
10065+0000fbe4@12110
10066+0000fbe6@12111
10067+0000ff7e@12112
10068+0000b5be@12113
10069+000035be@12115
10070+0000a53e@12116
10071+0000a102@12117
10072+0000a182@12118
10073+00002100@12120
10074+0000a180@12121
10075+0000e3a4@12122
10076+0000e1a4@12125
10077+0000f324@12127
10078+0000f3a4@12128
10079+000073a6@12129
10080+0000f3a6@12130
10081+0000f53e@12131
10082+0000b5be@12132
10083+000035be@12134
10084+0000a53e@12135
10085+0000a182@12136
10086+0000a180@12139
10087+0000a3a4@12140
10088+0000e3a4@12141
10089+0000e324@12142
10090+000063a4@12143
10091+0000e3a4@12144
10092+0000f384@12145
10093+0000f304@12146
10094+0000f3a4@12147
10095+000073a6@12148
10096+0000f3a6@12149
10097+0000f93a@12150
10098+0000b9ba@12151
10099+000039ba@12152
10100+0000a93a@12153
10101+0000abc2@12154
10102+00002b42@12157
10103+0000abc0@12158
10104+0000ebe0@12159
10105+0000ebe4@12160
10106+0000eb64@12161
10107+00006be4@12162
10108+0000ebe4@12163
10109+0000fbe4@12164
10110+0000fb64@12165
10111+00007be6@12166
10112+0000fbe6@12167
10113+0000fb7a@12168
10114+0000f9ba@12169
10115+000079ba@12171
10116+0000e93a@12172
10117+0000ebc2@12173
10118+00006b40@12176
10119+0000ebc0@12177
10120+0000ebe4@12178
10121+0000a3a4@12179
10122+000023a4@12180
10123+0000a3a4@12181
10124+0000b324@12183
10125+0000b3a4@12184
10126+000073a6@12185
10127+0000f3a6@12186
10128+0000f9fe@12187
10129+0000b9fe@12188
10130+0000397e@12190
10131+0000a9fe@12191
10132+0000a182@12192
10133+00002182@12194
10134+0000a180@12195
10135+0000a184@12196
10136+0000e380@12197
10137+0000e324@12198
10138+00006184@12199
10139+0000e3a4@12200
10140+0000f3a4@12201
10141+0000f104@12202
10142+0000f3a4@12203
10143+000073a6@12204
10144+0000f3a6@12205
10145+0000f11e@12206
10146+0000b19e@12207
10147+0000319e@12208
10148+0000a11e@12209
10149+0000a182@12210
10150+00002100@12213
10151+0000a180@12214
10152+0000e3a4@12215
10153+0000e384@12216
10154+0000e304@12217
10155+000061a4@12218
10156+0000e3a4@12219
10157+0000f3a4@12220
10158+000073a6@12222
10159+0000f3a6@12223
10160+0000f37a@12224
10161+0000b3da@12225
10162+000033da@12227
10163+0000a35a@12228
10164+0000afc2@12229
10165+00002f40@12232
10166+0000afe4@12233
10167+0000efe4@12234
10168+0000ef64@12235
10169+00006fe4@12236
10170+0000efe4@12237
10171+0000efc0@12238
10172+0000ff64@12239
10173+0000ffe4@12240
10174+00007fe6@12241
10175+0000ffe6@12242
10176+0000b346@12243
10177+0000b3c6@12244
10178+0000a346@12246
10179+0000abe6@12247
10180+0000abe2@12248
10181+00002b62@12250
10182+0000abe0@12251
10183+0000ebe4@12252
10184+0000eb64@12254
10185+00006be4@12255
10186+0000ebe4@12256
10187+0000fbe4@12257
10188+0000fb64@12258
10189+0000fbe4@12259
10190+0000fbe6@12260
10191+0000ff7e@12261
10192+0000b5be@12262
10193+000035be@12264
10194+0000a53e@12265
10195+0000a102@12266
10196+0000a182@12267
10197+00002100@12269
10198+0000a180@12270
10199+0000e3a4@12271
10200+0000e384@12272
10201+0000e324@12273
10202+0000e3a4@12274
10203+0000f324@12276
10204+0000f3a4@12277
10205+000073a6@12278
10206+0000f3a6@12279
10207+0000f53e@12280
10208+0000b5be@12281
10209+000035be@12283
10210+0000a53e@12284
10211+0000a182@12285
10212+0000a182@12288
+9716, -0
   1@@ -0,0 +1,9716 @@
   2+;Size: 9708
   3+;Rate: 50000000
   4+;Channels: 16
   5+;EnabledChannels: 65535
   6+;TriggerPosition: 119
   7+;Compressed: true
   8+;AbsoluteLength: 12287
   9+;CursorEnabled: true
  10+0000e08a@0
  11+0000e00a@1
  12+0000600a@2
  13+0000e088@3
  14+0000a080@5
  15+0000a000@6
  16+00002000@7
  17+0000a080@8
  18+0000b080@9
  19+00003002@11
  20+0000f002@12
  21+0000f082@13
  22+0000f002@15
  23+00007002@16
  24+0000e082@17
  25+0000e08a@18
  26+0000e00a@20
  27+00006008@21
  28+0000e088@22
  29+0000a080@24
  30+00002000@25
  31+0000a000@26
  32+0000a080@27
  33+0000b080@28
  34+0000b000@29
  35+00007002@30
  36+0000f082@31
  37+0000f002@34
  38+00007002@35
  39+0000e082@36
  40+0000e08a@37
  41+0000600a@39
  42+0000e008@40
  43+0000e088@41
  44+0000a088@42
  45+0000a000@43
  46+00002000@44
  47+0000a080@45
  48+0000b080@46
  49+0000b000@48
  50+00007002@49
  51+0000f082@50
  52+00007002@53
  53+0000e002@54
  54+0000e08a@55
  55+0000e00a@57
  56+00006008@58
  57+0000e088@59
  58+0000a080@61
  59+0000a000@62
  60+00002000@63
  61+0000a080@64
  62+0000b080@65
  63+00003002@67
  64+0000f002@68
  65+0000f082@69
  66+0000f002@71
  67+00007082@72
  68+0000e082@73
  69+0000e08a@74
  70+0000e00a@75
  71+0000e08a@76
  72+00006088@77
  73+0000e088@78
  74+0000e008@79
  75+0000a000@80
  76+00002080@81
  77+0000a080@82
  78+0000b000@83
  79+0000b080@85
  80+00007082@86
  81+0000f082@87
  82+0000f002@88
  83+0000f082@90
  84+00007082@91
  85+0000e08a@92
  86+0000e00a@93
  87+0000608a@95
  88+0000e088@96
  89+0000e008@97
  90+0000a008@98
  91+0000a080@99
  92+00002080@100
  93+0000a080@101
  94+0000b000@102
  95+0000b080@104
  96+00007082@105
  97+0000f282@106
  98+0000f202@107
  99+00007282@109
 100+0000e282@110
 101+0000ea72@111
 102+0000eaf2@113
 103+00006af0@114
 104+0000eaf0@115
 105+0000e040@116
 106+0000e0c0@118
 107+0000c0c0@119
 108+0000d040@121
 109+000070c2@123
 110+0000f0c2@124
 111+0000f202@125
 112+0000f282@127
 113+00007282@128
 114+0000e282@129
 115+0000ea76@130
 116+0000eaf6@132
 117+0000eaf4@133
 118+0000ee7c@134
 119+00004efc@137
 120+0000cefc@138
 121+0000de7c@139
 122+0000defc@141
 123+00007efe@142
 124+0000fefe@143
 125+0000f202@144
 126+0000f282@146
 127+0000e282@147
 128+0000ea7a@148
 129+0000eafa@149
 130+00006afa@151
 131+0000ea78@152
 132+0000e0c0@153
 133+00004040@156
 134+0000c040@157
 135+0000d0c0@158
 136+000070c2@160
 137+0000f042@161
 138+0000f202@162
 139+0000f282@163
 140+00007202@165
 141+0000e202@166
 142+0000eafe@167
 143+00006a7c@170
 144+0000ea7c@171
 145+0000eefc@172
 146+00006efc@174
 147+0000ce7c@175
 148+0000defc@177
 149+00007e7e@179
 150+0000fe7e@180
 151+0000f206@181
 152+0000f286@182
 153+00007206@184
 154+0000e206@185
 155+0000eaf2@186
 156+00006af2@188
 157+0000ea70@189
 158+0000eac0@190
 159+0000e0c0@191
 160+00004040@193
 161+0000c040@194
 162+0000d0c0@195
 163+00007042@198
 164+0000f042@199
 165+0000f286@200
 166+00007286@202
 167+0000e206@203
 168+0000ea76@204
 169+0000eaf6@205
 170+00006a74@207
 171+0000ea74@208
 172+0000eefc@209
 173+00004e7c@212
 174+0000ce7c@213
 175+0000defc@214
 176+00007efe@216
 177+0000fe7e@217
 178+0000f286@218
 179+00007206@221
 180+0000e206@222
 181+0000eafa@223
 182+00006a78@226
 183+0000eaf8@227
 184+0000e0c0@228
 185+0000e040@229
 186+000040c0@230
 187+0000c0c0@231
 188+0000d040@233
 189+000070c2@235
 190+0000f0c2@236
 191+0000f386@237
 192+0000f306@238
 193+0000f386@240
 194+0000ebfe@241
 195+0000eb7e@243
 196+00006b7e@244
 197+0000ebfc@245
 198+0000effc@246
 199+0000ef7c@247
 200+00004ffc@249
 201+0000cffc@250
 202+0000dffc@251
 203+0000df7c@252
 204+0000fffe@254
 205+0000f386@256
 206+0000f306@257
 207+00007386@258
 208+0000f384@259
 209+0000fbfc@260
 210+0000eb7c@261
 211+00006bfc@263
 212+0000ebfc@264
 213+0000eb7c@266
 214+0000ebfc@268
 215+0000fbfc@270
 216+0000fb7c@271
 217+00007bfe@272
 218+0000fbfe@273
 219+0000f38a@274
 220+0000f30a@275
 221+0000738a@277
 222+0000e38a@278
 223+0000ebf2@279
 224+0000eb72@280
 225+0000ebf0@282
 226+0000e1c0@284
 227+0000e140@285
 228+000041c0@286
 229+0000c1c0@287
 230+0000d1c0@288
 231+0000d140@289
 232+000071c2@291
 233+0000f1c2@292
 234+0000f38a@293
 235+0000f30a@294
 236+0000730a@295
 237+0000e38a@296
 238+0000ebf6@297
 239+0000eb76@299
 240+00006b76@300
 241+0000ebf4@301
 242+0000effc@302
 243+0000ef7c@303
 244+0000effc@304
 245+00004ffc@305
 246+0000cffc@306
 247+0000df7c@307
 248+0000dffc@308
 249+00007ffe@309
 250+0000ff7e@310
 251+0000fffe@311
 252+0000f38a@312
 253+0000730a@314
 254+0000e38a@315
 255+0000ebfa@316
 256+0000eb7a@318
 257+00006bf8@319
 258+0000ebf8@320
 259+0000e140@321
 260+0000e1c0@322
 261+000061c0@323
 262+0000c1c0@324
 263+0000c140@325
 264+0000d1c0@326
 265+000071c2@328
 266+0000f142@329
 267+0000f38a@330
 268+0000730a@333
 269+0000e38a@334
 270+0000ebfe@335
 271+00006bfe@337
 272+0000ebfc@338
 273+0000effc@339
 274+0000ef7c@340
 275+0000effc@341
 276+00004ffc@342
 277+0000cffc@343
 278+0000df7c@344
 279+0000dffc@345
 280+00007ffe@347
 281+0000fffe@348
 282+0000f38e@349
 283+0000738e@351
 284+0000e38e@352
 285+0000ebf2@353
 286+0000eb72@355
 287+00006bf0@356
 288+0000ebf0@357
 289+0000e140@358
 290+0000e1c0@360
 291+000041c0@361
 292+0000c1c0@362
 293+0000d1c0@363
 294+000071c2@365
 295+0000f142@366
 296+0000f38e@367
 297+0000730e@370
 298+0000e38e@371
 299+0000ebf6@372
 300+0000eb76@374
 301+00006bf4@375
 302+0000effc@376
 303+00004ffc@379
 304+0000cffc@380
 305+0000cf7c@381
 306+0000dffc@382
 307+00007ffe@384
 308+0000ff7e@385
 309+0000f30e@386
 310+0000f38e@387
 311+0000e30e@389
 312+0000ebfe@390
 313+0000ebfa@391
 314+00006bfa@393
 315+0000ebf8@394
 316+0000e1c0@395
 317+0000e140@396
 318+0000e1c0@397
 319+000041c0@398
 320+0000c1c0@399
 321+0000d140@400
 322+0000d1c0@401
 323+0000f1c2@403
 324+0000f3ce@404
 325+0000f38e@405
 326+0000730e@407
 327+0000e38e@408
 328+0000ebfe@409
 329+0000eb7e@411
 330+00006bfc@412
 331+0000ebfc@413
 332+0000effc@414
 333+0000ef7c@415
 334+0000effc@416
 335+0000cffc@417
 336+0000cf7c@418
 337+0000dffc@419
 338+00007ffe@421
 339+0000ff7e@422
 340+0000f312@423
 341+0000f392@424
 342+00007312@426
 343+0000e392@427
 344+0000ebf2@428
 345+0000ebf0@431
 346+0000e140@433
 347+0000e1c0@434
 348+000041c0@435
 349+0000c1c0@436
 350+0000d140@437
 351+0000d1c0@438
 352+000071c2@440
 353+0000f142@441
 354+0000f392@442
 355+00007392@444
 356+0000e392@445
 357+0000ebf6@446
 358+0000eb76@448
 359+00006bf6@449
 360+0000ebf4@450
 361+0000effc@451
 362+0000ef7c@452
 363+0000effc@453
 364+00004ffc@454
 365+0000cffc@455
 366+0000df7c@456
 367+0000dffc@457
 368+00007ffe@458
 369+0000ff7e@459
 370+0000fffe@460
 371+0000f392@461
 372+00007312@463
 373+0000e392@464
 374+0000ebfa@465
 375+0000eb7a@467
 376+00006bf8@468
 377+0000ebf8@469
 378+0000e140@470
 379+0000e1c0@471
 380+000061c0@472
 381+0000c1c0@473
 382+0000c140@474
 383+0000d1c0@475
 384+000071c2@477
 385+0000f142@478
 386+0000f392@479
 387+00007312@482
 388+0000e392@483
 389+0000ebfe@484
 390+00006bfe@486
 391+0000ebfc@487
 392+0000effc@488
 393+0000ef7c@489
 394+0000effc@490
 395+00004ffc@491
 396+0000cffc@492
 397+0000df7c@493
 398+0000dffc@494
 399+00007ffe@496
 400+0000fffe@497
 401+0000f396@498
 402+00007396@500
 403+0000e396@501
 404+0000ebf2@502
 405+0000eb72@504
 406+00006bf0@505
 407+0000ebf0@506
 408+0000e140@507
 409+0000e1c0@509
 410+000041c0@510
 411+0000c1c0@511
 412+0000d1c0@512
 413+000071c2@514
 414+0000f142@515
 415+0000f396@516
 416+00007316@519
 417+0000e396@520
 418+0000ebf6@521
 419+0000eb76@523
 420+00006bf4@524
 421+0000effc@525
 422+00004ffc@528
 423+0000cffc@529
 424+0000df7c@530
 425+0000dffc@531
 426+00007ffe@533
 427+0000ff7e@534
 428+0000f316@535
 429+0000f396@536
 430+0000e316@538
 431+0000ebfe@539
 432+0000ebfa@540
 433+00006bfa@542
 434+0000ebf8@543
 435+0000e1c0@544
 436+0000e140@545
 437+0000e1c0@546
 438+000041c0@547
 439+0000c1c0@548
 440+0000d140@549
 441+0000d1c0@550
 442+0000f1c2@552
 443+0000f3d6@553
 444+0000f396@554
 445+00007316@556
 446+0000e396@557
 447+0000ebfe@558
 448+0000eb7e@560
 449+00006bfc@561
 450+0000ebfc@562
 451+0000effc@563
 452+0000ef7c@564
 453+0000effc@565
 454+0000cffc@566
 455+0000cf7c@567
 456+0000dffc@568
 457+00007ffe@570
 458+0000ff7e@571
 459+0000f39a@572
 460+0000731a@575
 461+0000e39a@576
 462+0000ebf2@577
 463+0000ebf0@580
 464+0000e140@582
 465+0000e1c0@583
 466+000041c0@584
 467+0000c1c0@585
 468+0000d140@586
 469+0000d1c0@587
 470+000071c2@589
 471+0000f142@590
 472+0000f39a@591
 473+0000739a@593
 474+0000e39a@594
 475+0000ebf6@595
 476+0000eb76@597
 477+00006bf6@598
 478+0000ebf4@599
 479+0000effc@600
 480+0000ef7c@601
 481+0000effc@602
 482+00004ffc@603
 483+0000cffc@604
 484+0000df7c@605
 485+0000dffc@606
 486+00007ffe@607
 487+0000ff7e@608
 488+0000fbfe@609
 489+0000f39a@610
 490+0000731a@612
 491+0000e39a@613
 492+0000ebfa@614
 493+0000eb7a@616
 494+00006bf8@617
 495+0000ebf8@618
 496+0000e140@619
 497+0000e1c0@620
 498+000061c0@621
 499+0000c1c0@622
 500+0000c140@623
 501+0000d1c0@624
 502+000071c2@626
 503+0000f142@627
 504+0000f39a@628
 505+0000731a@631
 506+0000e39a@632
 507+0000ebfe@633
 508+00006bfe@635
 509+0000ebfc@636
 510+0000effc@637
 511+0000ef7c@638
 512+0000effc@639
 513+00004ffc@640
 514+0000cffc@641
 515+0000df7c@642
 516+0000dffc@643
 517+00007ffe@645
 518+0000fffe@646
 519+0000f39e@647
 520+0000739e@649
 521+0000e39e@650
 522+0000ebf2@651
 523+0000eb72@653
 524+00006bf0@654
 525+0000ebf0@655
 526+0000e140@656
 527+0000e1c0@658
 528+000041c0@659
 529+0000c1c0@660
 530+0000d1c0@661
 531+000071c2@663
 532+0000f142@664
 533+0000f39e@665
 534+0000731e@668
 535+0000e39e@669
 536+0000ebf6@670
 537+0000eb76@672
 538+00006bf4@673
 539+0000effc@674
 540+00004ffc@677
 541+0000cffc@678
 542+0000cf7c@679
 543+0000dffc@680
 544+00007ffe@682
 545+0000ff7e@683
 546+0000f39e@684
 547+0000e39e@687
 548+0000ebfe@688
 549+0000ebfa@689
 550+0000eb7a@690
 551+00006bfa@691
 552+0000ebf8@692
 553+0000e1c0@693
 554+0000e140@694
 555+0000e1c0@695
 556+000041c0@696
 557+0000c1c0@697
 558+0000d140@698
 559+0000d1c0@699
 560+0000f1c2@701
 561+0000f35e@702
 562+0000f39e@703
 563+0000731e@705
 564+0000e39e@706
 565+0000ebfe@707
 566+0000eb7e@709
 567+00006bfc@710
 568+0000ebfc@711
 569+0000effc@712
 570+0000ef7c@713
 571+0000effc@714
 572+0000cffc@715
 573+0000cf7c@716
 574+0000dffc@717
 575+00007ffe@719
 576+0000ff7e@720
 577+0000f322@721
 578+0000f3a2@722
 579+00007322@724
 580+0000e3a2@725
 581+0000ebf2@726
 582+0000ebf0@729
 583+0000e140@731
 584+0000e1c0@732
 585+000041c0@733
 586+0000c1c0@734
 587+0000d140@735
 588+0000d1c0@736
 589+000071c2@738
 590+0000f142@739
 591+0000f3a2@740
 592+000073a2@742
 593+0000e3a2@743
 594+0000ebf6@744
 595+0000eb76@746
 596+00006bf6@747
 597+0000ebf4@748
 598+0000effc@749
 599+0000ef7c@750
 600+0000effc@751
 601+00004ffc@752
 602+0000cffc@753
 603+0000dffc@754
 604+00007ffe@756
 605+0000ff7e@757
 606+0000fff6@758
 607+0000f3a2@759
 608+00007322@761
 609+0000e3a2@762
 610+0000ebfa@763
 611+0000eb7a@765
 612+00006bf8@766
 613+0000ebf8@767
 614+0000e140@768
 615+0000e1c0@769
 616+000061c0@770
 617+0000c1c0@771
 618+0000c140@772
 619+0000d1c0@773
 620+000071c2@775
 621+0000f142@776
 622+0000f3a2@777
 623+00007322@780
 624+0000e3a2@781
 625+0000ebfe@782
 626+00006bfe@784
 627+0000ebfc@785
 628+0000effc@786
 629+0000ef7c@787
 630+0000effc@788
 631+00004ffc@789
 632+0000cffc@790
 633+0000df7c@791
 634+0000dffc@792
 635+00007ffe@794
 636+0000fffe@795
 637+0000f3a6@796
 638+000073a6@798
 639+0000e3a6@799
 640+0000ebf2@800
 641+0000eb72@802
 642+00006bf0@803
 643+0000ebf0@804
 644+0000e140@805
 645+0000e1c0@807
 646+000041c0@808
 647+0000c1c0@809
 648+0000d1c0@810
 649+000071c2@812
 650+0000f142@813
 651+0000f3a6@814
 652+00007326@817
 653+0000e3a6@818
 654+0000ebf6@819
 655+0000eb76@821
 656+00006bf4@822
 657+0000effc@823
 658+0000ef7c@824
 659+0000effc@825
 660+00004ffc@826
 661+0000cffc@827
 662+0000df7c@828
 663+0000dffc@829
 664+00007ffe@831
 665+0000ff7e@832
 666+0000f326@833
 667+0000f3a6@834
 668+0000e3a6@836
 669+0000ebfe@837
 670+0000ebfa@838
 671+00006bfa@840
 672+0000ebf8@841
 673+0000e1c0@842
 674+0000e140@843
 675+0000e1c0@844
 676+000041c0@845
 677+0000c1c0@846
 678+0000d140@847
 679+0000d1c0@848
 680+0000f1c2@850
 681+0000f3e6@851
 682+0000f3a6@852
 683+00007326@854
 684+0000f3a4@855
 685+0000fbf8@856
 686+0000ebf8@857
 687+0000eb78@858
 688+00006bf8@859
 689+0000ebf8@860
 690+0000effc@861
 691+0000eb7c@862
 692+0000effc@863
 693+0000ebfc@864
 694+0000eb7c@865
 695+0000fffc@866
 696+00007bfe@868
 697+0000ff7e@869
 698+0000f3a6@870
 699+00007326@873
 700+0000e3a6@874
 701+0000ebfe@875
 702+0000ebfc@878
 703+0000effc@879
 704+0000ef7c@880
 705+0000effc@881
 706+00004ffc@882
 707+0000cffc@883
 708+0000df7c@884
 709+0000dffc@885
 710+00007ffe@887
 711+0000ff7e@888
 712+0000f3aa@889
 713+0000e3aa@892
 714+0000ebf2@893
 715+0000eb72@895
 716+00006bf2@896
 717+0000ebf0@897
 718+0000e1c0@898
 719+0000e140@899
 720+0000e1c0@900
 721+000041c0@901
 722+0000c1c0@902
 723+0000d140@903
 724+0000d1c0@904
 725+000071c2@905
 726+0000f142@906
 727+0000f36a@907
 728+0000f3aa@908
 729+0000732a@910
 730+0000e3aa@911
 731+0000ebf6@912
 732+0000eb76@914
 733+00006bf4@915
 734+0000ebf4@916
 735+0000effc@917
 736+00006ffc@919
 737+0000cffc@920
 738+0000cf7c@921
 739+0000dffc@922
 740+00007ffe@924
 741+0000ff7e@925
 742+0000f32a@926
 743+0000f3aa@927
 744+0000732a@929
 745+0000e3aa@930
 746+0000ebfa@931
 747+00006bfa@933
 748+0000ebf8@934
 749+0000e9c0@935
 750+0000e140@936
 751+0000e1c0@937
 752+000041c0@938
 753+0000c1c0@939
 754+0000d140@940
 755+0000d1c0@941
 756+000071c2@943
 757+0000f1c2@944
 758+0000f3aa@945
 759+000073aa@947
 760+0000e3aa@948
 761+0000ebfe@949
 762+0000eb7e@951
 763+00006bfc@952
 764+0000ebfc@953
 765+0000effc@954
 766+0000ef7c@955
 767+0000effc@956
 768+00004ffc@957
 769+0000cffc@958
 770+0000dffc@959
 771+00007ffe@961
 772+0000ff7e@962
 773+0000f3ae@963
 774+0000732e@966
 775+0000e3ae@967
 776+0000ebf2@968
 777+0000eb72@970
 778+00006bf0@971
 779+0000ebf0@972
 780+0000e1c0@973
 781+000041c0@975
 782+0000c1c0@976
 783+0000d140@977
 784+0000d1c0@978
 785+000071c2@980
 786+0000f142@981
 787+0000f3ae@982
 788+0000e3ae@985
 789+0000ebfe@986
 790+0000ebf6@987
 791+0000eb76@988
 792+00006bf6@989
 793+0000ebf4@990
 794+0000effc@991
 795+0000ef7c@992
 796+0000effc@993
 797+00004ffc@994
 798+0000cffc@995
 799+0000df7c@996
 800+0000dffc@997
 801+0000fffe@999
 802+0000f3ae@1001
 803+000073ae@1003
 804+0000e3ae@1004
 805+0000ebfa@1005
 806+0000eb7a@1007
 807+00006bf8@1008
 808+0000ebf8@1009
 809+0000e140@1010
 810+0000e1c0@1011
 811+0000c1c0@1013
 812+0000c140@1014
 813+0000d1c0@1015
 814+000071c2@1017
 815+0000f142@1018
 816+0000f3ae@1019
 817+0000732e@1022
 818+0000e3ae@1023
 819+0000ebfe@1024
 820+0000ebfc@1027
 821+0000effc@1028
 822+0000ef7c@1029
 823+0000effc@1030
 824+00004ffc@1031
 825+0000cffc@1032
 826+0000df7c@1033
 827+0000dffc@1034
 828+00007ffe@1036
 829+0000ff7e@1037
 830+0000f3b2@1038
 831+000073b2@1040
 832+0000e3b2@1041
 833+0000ebf2@1042
 834+0000eb72@1044
 835+00006bf2@1045
 836+0000ebf0@1046
 837+0000e1c0@1047
 838+0000e140@1048
 839+0000e1c0@1049
 840+000041c0@1050
 841+0000c1c0@1051
 842+0000d140@1052
 843+0000d1c0@1053
 844+000071c2@1054
 845+0000f142@1055
 846+0000f372@1056
 847+0000f3b2@1057
 848+00007332@1059
 849+0000e3b2@1060
 850+0000ebf6@1061
 851+0000eb76@1063
 852+00006bf4@1064
 853+0000ebf4@1065
 854+0000effc@1066
 855+00006ffc@1068
 856+0000cffc@1069
 857+0000cf7c@1070
 858+0000dffc@1071
 859+00007ffe@1073
 860+0000ff7e@1074
 861+0000f332@1075
 862+0000f3b2@1076
 863+00007332@1078
 864+0000e3b2@1079
 865+0000ebfa@1080
 866+00006bfa@1082
 867+0000ebf8@1083
 868+0000e9c0@1084
 869+0000e140@1085
 870+0000e1c0@1086
 871+000041c0@1087
 872+0000c1c0@1088
 873+0000d140@1089
 874+0000d1c0@1090
 875+000071c2@1092
 876+0000f1c2@1093
 877+0000f3b2@1094
 878+000073b2@1096
 879+0000e3b2@1097
 880+0000ebfe@1098
 881+0000eb7e@1100
 882+00006bfc@1101
 883+0000ebfc@1102
 884+0000effc@1103
 885+0000ef7c@1104
 886+0000effc@1105
 887+00004ffc@1106
 888+0000cffc@1107
 889+0000dffc@1108
 890+00007ffe@1110
 891+0000ff7e@1111
 892+0000f3b6@1112
 893+00007336@1115
 894+0000e3b6@1116
 895+0000ebf2@1117
 896+0000eb72@1119
 897+00006bf0@1120
 898+0000ebf0@1121
 899+0000e1c0@1122
 900+000041c0@1124
 901+0000c1c0@1125
 902+0000d140@1126
 903+0000d1c0@1127
 904+000071c2@1129
 905+0000f142@1130
 906+0000f3b6@1131
 907+0000e3b6@1134
 908+0000ebf6@1135
 909+0000eb76@1137
 910+00006bf6@1138
 911+0000ebf4@1139
 912+0000effc@1140
 913+0000ef7c@1141
 914+0000effc@1142
 915+00004ffc@1143
 916+0000cffc@1144
 917+0000df7c@1145
 918+0000dffc@1146
 919+0000fffe@1148
 920+0000f3b6@1150
 921+000073b6@1152
 922+0000e3b6@1153
 923+0000ebfa@1154
 924+0000eb7a@1156
 925+00006bf8@1157
 926+0000ebf8@1158
 927+0000e140@1159
 928+0000e1c0@1160
 929+0000c1c0@1162
 930+0000c140@1163
 931+0000d1c0@1164
 932+000071c2@1166
 933+0000f142@1167
 934+0000f3b6@1168
 935+00007336@1171
 936+0000e3b6@1172
 937+0000ebfe@1173
 938+0000ebfc@1176
 939+0000effc@1177
 940+0000ef7c@1178
 941+0000effc@1179
 942+00004ffc@1180
 943+0000cffc@1181
 944+0000df7c@1182
 945+0000dffc@1183
 946+00007ffe@1185
 947+0000ff7e@1186
 948+0000f3ba@1187
 949+000073ba@1189
 950+0000e3ba@1190
 951+0000ebf2@1191
 952+0000eb72@1193
 953+00006bf2@1194
 954+0000ebf0@1195
 955+0000e1c0@1196
 956+0000e140@1197
 957+0000e1c0@1198
 958+000041c0@1199
 959+0000c1c0@1200
 960+0000d1c0@1201
 961+000071c2@1203
 962+0000f142@1204
 963+0000f37a@1205
 964+0000f3ba@1206
 965+0000733a@1208
 966+0000e3ba@1209
 967+0000ebf6@1210
 968+0000eb76@1212
 969+00006bf4@1213
 970+0000ebf4@1214
 971+0000effc@1215
 972+00006ffc@1217
 973+0000cffc@1218
 974+0000cf7c@1219
 975+0000dffc@1220
 976+00007ffe@1222
 977+0000ff7e@1223
 978+0000f3ba@1224
 979+0000733a@1227
 980+0000e3ba@1228
 981+0000ebfa@1229
 982+00006bfa@1231
 983+0000ebf8@1232
 984+0000e9c0@1233
 985+0000e140@1234
 986+0000e1c0@1235
 987+000041c0@1236
 988+0000c1c0@1237
 989+0000d140@1238
 990+0000d1c0@1239
 991+000071c2@1241
 992+0000f1c2@1242
 993+0000f3ba@1243
 994+000073ba@1245
 995+0000e3ba@1246
 996+0000ebfe@1247
 997+0000eb7e@1249
 998+00006bfc@1250
 999+0000ebfc@1251
1000+0000effc@1252
1001+0000ef7c@1253
1002+0000effc@1254
1003+00004ffc@1255
1004+0000cffc@1256
1005+0000dffc@1257
1006+00007ffe@1259
1007+0000ff7e@1260
1008+0000f3be@1261
1009+0000733e@1264
1010+0000e3be@1265
1011+0000ebf2@1266
1012+0000eb72@1268
1013+00006bf0@1269
1014+0000ebf0@1270
1015+0000e1c0@1271
1016+000041c0@1273
1017+0000c1c0@1274
1018+0000d140@1275
1019+0000d1c0@1276
1020+000071c2@1278
1021+0000f142@1279
1022+0000f3be@1280
1023+0000e3be@1283
1024+0000ebfe@1284
1025+0000ebf6@1285
1026+0000eb76@1286
1027+00006bf6@1287
1028+0000ebf4@1288
1029+0000effc@1289
1030+0000ef7c@1290
1031+0000effc@1291
1032+00004ffc@1292
1033+0000cffc@1293
1034+0000df7c@1294
1035+0000dffc@1295
1036+0000fffe@1297
1037+0000f3be@1299
1038+0000733e@1301
1039+0000e3be@1302
1040+0000ebfa@1303
1041+0000eb7a@1305
1042+00006bf8@1306
1043+0000ebf8@1307
1044+0000e140@1308
1045+0000e1c0@1309
1046+0000c1c0@1311
1047+0000c140@1312
1048+0000d1c0@1313
1049+000071c2@1315
1050+0000f142@1316
1051+0000f3be@1317
1052+0000733e@1320
1053+0000e3be@1321
1054+0000ebfe@1322
1055+0000ebfc@1325
1056+0000effc@1326
1057+0000ef7c@1327
1058+0000effc@1328
1059+00004ffc@1329
1060+0000cffc@1330
1061+0000df7c@1331
1062+0000dffc@1332
1063+00007ffe@1334
1064+0000ff7e@1335
1065+0000f582@1336
1066+00007582@1338
1067+0000e582@1339
1068+0000ebf2@1340
1069+0000eb72@1342
1070+00006bf2@1343
1071+0000ebf0@1344
1072+0000e1c0@1345
1073+0000e140@1346
1074+0000e1c0@1347
1075+000041c0@1348
1076+0000c1c0@1349
1077+0000d1c0@1350
1078+000071c2@1352
1079+0000f142@1353
1080+0000f502@1354
1081+0000f582@1355
1082+00007502@1357
1083+0000e582@1358
1084+0000ebf6@1359
1085+0000eb76@1361
1086+00006bf4@1362
1087+0000ebf4@1363
1088+0000effc@1364
1089+00006ffc@1366
1090+0000cffc@1367
1091+0000cf7c@1368
1092+0000dffc@1369
1093+00007ffe@1371
1094+0000ff7e@1372
1095+0000f502@1373
1096+0000f582@1374
1097+00007502@1376
1098+0000e582@1377
1099+0000ebfa@1378
1100+00006bfa@1380
1101+0000ebf8@1381
1102+0000e9c0@1382
1103+0000e140@1383
1104+0000e1c0@1384
1105+000041c0@1385
1106+0000c1c0@1386
1107+0000d140@1387
1108+0000d1c0@1388
1109+000071c2@1390
1110+0000f1c2@1391
1111+0000f582@1392
1112+00007582@1394
1113+0000e582@1395
1114+0000ebfe@1396
1115+0000eb7e@1398
1116+00006bfc@1399
1117+0000ebfc@1400
1118+0000effc@1401
1119+0000ef7c@1402
1120+0000effc@1403
1121+00004ffc@1404
1122+0000cffc@1405
1123+0000dffc@1406
1124+00007ffe@1408
1125+0000ff7e@1409
1126+0000fd86@1410
1127+0000f586@1411
1128+00007506@1413
1129+0000e586@1414
1130+0000ebf2@1415
1131+0000eb72@1417
1132+00006bf0@1418
1133+0000ebf0@1419
1134+0000e1c0@1420
1135+000041c0@1422
1136+0000c1c0@1423
1137+0000d140@1424
1138+0000d1c0@1425
1139+000071c2@1427
1140+0000f142@1428
1141+0000f586@1429
1142+0000e586@1432
1143+0000e7f6@1433
1144+0000ebf6@1434
1145+00006bf6@1436
1146+0000ebf4@1437
1147+0000effc@1438
1148+0000ef7c@1439
1149+0000effc@1440
1150+00004ffc@1441
1151+0000cffc@1442
1152+0000df7c@1443
1153+0000dffc@1444
1154+0000fffe@1446
1155+0000f586@1448
1156+00007586@1450
1157+0000f584@1451
1158+0000fbf4@1452
1159+0000ebf4@1453
1160+0000eb74@1454
1161+00006bf4@1455
1162+0000ebf4@1456
1163+0000eb74@1458
1164+0000ebf4@1459
1165+0000eb74@1461
1166+0000fbf4@1462
1167+00007bf6@1464
1168+0000fb76@1465
1169+0000f506@1466
1170+0000f586@1467
1171+00007506@1469
1172+0000e586@1470
1173+0000ebfa@1471
1174+0000ebf8@1474
1175+0000e140@1476
1176+0000e1c0@1477
1177+000041c0@1478
1178+0000c1c0@1479
1179+0000d140@1480
1180+0000d1c0@1481
1181+000071c2@1483
1182+0000f142@1484
1183+0000f586@1485
1184+00007586@1487
1185+0000e586@1488
1186+0000ebfe@1489
1187+0000eb7e@1491
1188+00006bfe@1492
1189+0000ebfc@1493
1190+0000effc@1494
1191+0000ef7c@1495
1192+0000effc@1496
1193+00004ffc@1497
1194+0000cffc@1498
1195+0000dffc@1499
1196+00007ffe@1501
1197+0000ff7e@1502
1198+0000ff9e@1503
1199+0000f58a@1504
1200+0000750a@1506
1201+0000e58a@1507
1202+0000ebf2@1508
1203+0000eb72@1510
1204+00006bf0@1511
1205+0000ebf0@1512
1206+0000e140@1513
1207+0000e1c0@1514
1208+000061c0@1515
1209+0000c1c0@1516
1210+0000c140@1517
1211+0000d1c0@1518
1212+000071c2@1520
1213+0000f142@1521
1214+0000f58a@1522
1215+0000750a@1525
1216+0000e58a@1526
1217+0000ebf6@1527
1218+00006bf6@1529
1219+0000ebf4@1530
1220+0000effc@1531
1221+0000ef7c@1532
1222+0000effc@1533
1223+00004ffc@1534
1224+0000cffc@1535
1225+0000df7c@1536
1226+0000dffc@1537
1227+00007ffe@1539
1228+0000fffe@1540
1229+0000f58a@1541
1230+0000758a@1543
1231+0000e58a@1544
1232+0000ebfa@1545
1233+0000eb7a@1547
1234+00006bf8@1548
1235+0000ebf8@1549
1236+0000e140@1550
1237+0000e1c0@1552
1238+000041c0@1553
1239+0000c1c0@1554
1240+0000d1c0@1555
1241+000071c2@1557
1242+0000f142@1558
1243+0000f58a@1559
1244+0000750a@1562
1245+0000e58a@1563
1246+0000ebfe@1564
1247+0000eb7e@1566
1248+00006bfc@1567
1249+0000effc@1568
1250+0000ef7c@1569
1251+0000effc@1570
1252+00004ffc@1571
1253+0000cffc@1572
1254+0000df7c@1573
1255+0000dffc@1574
1256+00007ffe@1576
1257+0000ff7e@1577
1258+0000f58e@1578
1259+0000e58e@1581
1260+0000effa@1582
1261+0000ebf2@1583
1262+0000eb72@1584
1263+00006bf2@1585
1264+0000ebf0@1586
1265+0000e1c0@1587
1266+0000e140@1588
1267+0000e1c0@1589
1268+000041c0@1590
1269+0000c1c0@1591
1270+0000d140@1592
1271+0000d1c0@1593
1272+0000f1c2@1595
1273+0000f54e@1596
1274+0000f58e@1597
1275+0000750e@1599
1276+0000e58e@1600
1277+0000ebf6@1601
1278+0000eb76@1603
1279+00006bf4@1604
1280+0000ebf4@1605
1281+0000effc@1606
1282+0000ef7c@1607
1283+0000effc@1608
1284+0000cffc@1609
1285+0000cf7c@1610
1286+0000dffc@1611
1287+00007ffe@1613
1288+0000ff7e@1614
1289+0000f58e@1615
1290+0000750e@1618
1291+0000e58e@1619
1292+0000ebfa@1620
1293+0000ebf8@1623
1294+0000e140@1625
1295+0000e1c0@1626
1296+000041c0@1627
1297+0000c1c0@1628
1298+0000d140@1629
1299+0000d1c0@1630
1300+000071c2@1632
1301+0000f142@1633
1302+0000f58e@1634
1303+0000758e@1636
1304+0000e58e@1637
1305+0000ebfe@1638
1306+0000eb7e@1640
1307+00006bfe@1641
1308+0000ebfc@1642
1309+0000effc@1643
1310+0000ef7c@1644
1311+0000effc@1645
1312+00004ffc@1646
1313+0000cffc@1647
1314+0000dffc@1648
1315+00007ffe@1650
1316+0000ff7e@1651
1317+0000ffbe@1652
1318+0000f592@1653
1319+00007512@1655
1320+0000e592@1656
1321+0000ebf2@1657
1322+0000eb72@1659
1323+00006bf0@1660
1324+0000ebf0@1661
1325+0000e140@1662
1326+0000e1c0@1663
1327+000061c0@1664
1328+0000c1c0@1665
1329+0000c140@1666
1330+0000d1c0@1667
1331+000071c2@1669
1332+0000f142@1670
1333+0000f592@1671
1334+00007512@1674
1335+0000e592@1675
1336+0000ebf6@1676
1337+00006bf6@1678
1338+0000ebf4@1679
1339+0000effc@1680
1340+0000ef7c@1681
1341+0000effc@1682
1342+00004ffc@1683
1343+0000cffc@1684
1344+0000df7c@1685
1345+0000dffc@1686
1346+00007ffe@1688
1347+0000fffe@1689
1348+0000f592@1690
1349+00007592@1692
1350+0000e592@1693
1351+0000ebfa@1694
1352+0000eb7a@1696
1353+00006bf8@1697
1354+0000ebf8@1698
1355+0000e140@1699
1356+0000e1c0@1701
1357+000041c0@1702
1358+0000c1c0@1703
1359+0000d1c0@1704
1360+000071c2@1706
1361+0000f142@1707
1362+0000f592@1708
1363+00007512@1711
1364+0000e592@1712
1365+0000ebfe@1713
1366+0000eb7e@1715
1367+00006bfc@1716
1368+0000effc@1717
1369+0000ef7c@1718
1370+0000effc@1719
1371+00004ffc@1720
1372+0000cffc@1721
1373+0000df7c@1722
1374+0000dffc@1723
1375+00007ffe@1725
1376+0000ff7e@1726
1377+0000f596@1727
1378+0000e596@1730
1379+0000eff6@1731
1380+0000ebf2@1732
1381+0000eb72@1733
1382+00006bf2@1734
1383+0000ebf0@1735
1384+0000e1c0@1736
1385+0000e140@1737
1386+0000e1c0@1738
1387+000041c0@1739
1388+0000c1c0@1740
1389+0000d140@1741
1390+0000d1c0@1742
1391+0000f1c0@1743
1392+0000f1c2@1744
1393+0000f556@1745
1394+0000f596@1746
1395+00007516@1748
1396+0000e596@1749
1397+0000ebf6@1750
1398+0000eb76@1752
1399+00006bf4@1753
1400+0000ebf4@1754
1401+0000effc@1755
1402+0000ef7c@1756
1403+0000effc@1757
1404+0000cffc@1758
1405+0000cf7c@1759
1406+0000dffc@1760
1407+00007ffe@1762
1408+0000ff7e@1763
1409+0000f516@1764
1410+0000f596@1765
1411+00007516@1767
1412+0000e596@1768
1413+0000ebfa@1769
1414+00006bfa@1771
1415+0000ebf8@1772
1416+0000e140@1774
1417+0000e1c0@1775
1418+000041c0@1776
1419+0000c1c0@1777
1420+0000d140@1778
1421+0000d1c0@1779
1422+000071c2@1781
1423+0000f142@1782
1424+0000f596@1783
1425+00007596@1785
1426+0000e596@1786
1427+0000ebfe@1787
1428+0000eb7e@1789
1429+00006bfe@1790
1430+0000ebfc@1791
1431+0000effc@1792
1432+0000ef7c@1793
1433+0000effc@1794
1434+00004ffc@1795
1435+0000cffc@1796
1436+0000dffc@1797
1437+00007ffe@1799
1438+0000ff7e@1800
1439+0000ffbe@1801
1440+0000f59a@1802
1441+0000751a@1804
1442+0000e59a@1805
1443+0000ebf2@1806
1444+0000eb72@1808
1445+00006bf0@1809
1446+0000ebf0@1810
1447+0000e140@1811
1448+0000e1c0@1812
1449+000061c0@1813
1450+0000c1c0@1814
1451+0000c140@1815
1452+0000d1c0@1816
1453+000071c2@1818
1454+0000f142@1819
1455+0000f59a@1820
1456+0000751a@1823
1457+0000e59a@1824
1458+0000ebf6@1825
1459+00006bf6@1827
1460+0000ebf4@1828
1461+0000effc@1829
1462+0000ef7c@1830
1463+0000effc@1831
1464+00004ffc@1832
1465+0000cffc@1833
1466+0000df7c@1834
1467+0000dffc@1835
1468+00007ffe@1837
1469+0000fffe@1838
1470+0000f59a@1839
1471+0000759a@1841
1472+0000e59a@1842
1473+0000ebfa@1843
1474+0000eb7a@1845
1475+00006bf8@1846
1476+0000ebf8@1847
1477+0000e140@1848
1478+0000e1c0@1850
1479+000041c0@1851
1480+0000c1c0@1852
1481+0000d1c0@1853
1482+000071c2@1855
1483+0000f142@1856
1484+0000f59a@1857
1485+0000751a@1860
1486+0000e59a@1861
1487+0000ebfe@1862
1488+0000eb7e@1864
1489+00006bfc@1865
1490+0000effc@1866
1491+0000ef7c@1867
1492+0000effc@1868
1493+00004ffc@1869
1494+0000cffc@1870
1495+0000df7c@1871
1496+0000dffc@1872
1497+00007ffe@1874
1498+0000ff7e@1875
1499+0000f59e@1876
1500+0000e59e@1879
1501+0000eff2@1880
1502+0000ebf2@1881
1503+0000eb72@1882
1504+00006bf2@1883
1505+0000ebf0@1884
1506+0000e1c0@1885
1507+0000e140@1886
1508+0000e1c0@1887
1509+000041c0@1888
1510+0000c1c0@1889
1511+0000d140@1890
1512+0000d1c0@1891
1513+0000f1c0@1892
1514+0000f1c2@1893
1515+0000f55e@1894
1516+0000f59e@1895
1517+0000751e@1897
1518+0000e59e@1898
1519+0000ebf6@1899
1520+0000eb76@1901
1521+00006bf4@1902
1522+0000ebf4@1903
1523+0000effc@1904
1524+0000ef7c@1905
1525+0000effc@1906
1526+0000cffc@1907
1527+0000cf7c@1908
1528+0000dffc@1909
1529+00007ffe@1911
1530+0000ff7e@1912
1531+0000f59e@1913
1532+0000751e@1916
1533+0000e59e@1917
1534+0000ebfa@1918
1535+00006bfa@1920
1536+0000ebf8@1921
1537+0000e140@1923
1538+0000e1c0@1924
1539+000041c0@1925
1540+0000c1c0@1926
1541+0000d140@1927
1542+0000d1c0@1928
1543+000071c2@1930
1544+0000f142@1931
1545+0000f59e@1932
1546+0000759e@1934
1547+0000e59e@1935
1548+0000ebfe@1936
1549+0000eb7e@1938
1550+00006bfe@1939
1551+0000ebfc@1940
1552+0000effc@1941
1553+0000ef7c@1942
1554+0000effc@1943
1555+00004ffc@1944
1556+0000cffc@1945
1557+0000dffc@1946
1558+00007ffe@1948
1559+0000ff7e@1949
1560+0000ffe6@1950
1561+0000f5a2@1951
1562+00007522@1953
1563+0000e5a2@1954
1564+0000ebf2@1955
1565+0000eb72@1957
1566+00006bf0@1958
1567+0000ebf0@1959
1568+0000e1c0@1960
1569+000061c0@1962
1570+0000c1c0@1963
1571+0000c140@1964
1572+0000d1c0@1965
1573+000071c2@1967
1574+0000f142@1968
1575+0000f5a2@1969
1576+00007522@1972
1577+0000e5a2@1973
1578+0000ebf6@1974
1579+00006bf6@1976
1580+0000ebf4@1977
1581+0000effc@1978
1582+0000ef7c@1979
1583+0000effc@1980
1584+00004ffc@1981
1585+0000cffc@1982
1586+0000df7c@1983
1587+0000dffc@1984
1588+00007ffe@1986
1589+0000fffe@1987
1590+0000f5a2@1988
1591+000075a2@1990
1592+0000e5a2@1991
1593+0000ebfa@1992
1594+0000eb7a@1994
1595+00006bf8@1995
1596+0000ebf8@1996
1597+0000e140@1997
1598+0000e1c0@1999
1599+000041c0@2000
1600+0000c1c0@2001
1601+0000d1c0@2002
1602+000071c2@2004
1603+0000f142@2005
1604+0000f5a2@2006
1605+00007522@2009
1606+0000e5a2@2010
1607+0000ebfe@2011
1608+0000eb7e@2013
1609+00006bfc@2014
1610+0000effc@2015
1611+0000ef7c@2016
1612+0000effc@2017
1613+00004ffc@2018
1614+0000cffc@2019
1615+0000df7c@2020
1616+0000dffc@2021
1617+00007ffe@2023
1618+0000ff7e@2024
1619+0000f5a6@2025
1620+0000e5a6@2028
1621+0000eff2@2029
1622+0000ebf2@2030
1623+0000eb72@2031
1624+00006bf2@2032
1625+0000ebf0@2033
1626+0000e1c0@2034
1627+0000e140@2035
1628+0000e1c0@2036
1629+000041c0@2037
1630+0000c1c0@2038
1631+0000d140@2039
1632+0000d1c0@2040
1633+0000f1c0@2041
1634+0000f1c2@2042
1635+0000f566@2043
1636+0000f5a6@2044
1637+00007526@2046
1638+0000f5a4@2047
1639+0000fbf0@2048
1640+0000ebf0@2049
1641+0000eb70@2050
1642+00006bf0@2051
1643+0000ebf0@2052
1644+0000ef7c@2053
1645+0000ebfc@2054
1646+0000effc@2055
1647+0000ebfc@2056
1648+0000eb7c@2057
1649+0000fffc@2058
1650+00007bfe@2060
1651+0000ff7e@2061
1652+0000f5a6@2062
1653+00007526@2065
1654+0000e5a6@2066
1655+0000ebf6@2067
1656+00006bf6@2069
1657+0000ebf4@2070
1658+0000effc@2071
1659+0000ef7c@2072
1660+0000effc@2073
1661+00004ffc@2074
1662+0000cffc@2075
1663+0000df7c@2076
1664+0000dffc@2077
1665+00007ffe@2079
1666+0000ff7e@2080
1667+0000f5a6@2081
1668+000075a6@2083
1669+0000e5a6@2084
1670+0000ebfa@2085
1671+0000eb7a@2087
1672+00006bfa@2088
1673+0000ebf8@2089
1674+0000e140@2090
1675+0000e1c0@2092
1676+000041c0@2093
1677+0000c1c0@2094
1678+0000d1c0@2095
1679+000071c2@2097
1680+0000f142@2098
1681+0000f526@2099
1682+0000f5a6@2100
1683+00007526@2102
1684+0000e5a6@2103
1685+0000ebfe@2104
1686+0000eb7e@2106
1687+00006bfc@2107
1688+0000ebfc@2108
1689+0000effc@2109
1690+00006ffc@2111
1691+0000cffc@2112
1692+0000cf7c@2113
1693+0000dffc@2114
1694+00007ffe@2116
1695+0000ff7e@2117
1696+0000f52a@2118
1697+0000f5aa@2119
1698+0000752a@2121
1699+0000e5aa@2122
1700+0000ebf2@2123
1701+00006bf2@2125
1702+0000ebf0@2126
1703+0000e1c0@2127
1704+0000e140@2128
1705+0000e1c0@2129
1706+000041c0@2130
1707+0000c1c0@2131
1708+0000d140@2132
1709+0000d1c0@2133
1710+000071c2@2135
1711+0000f1c2@2136
1712+0000f5aa@2137
1713+000075aa@2139
1714+0000e5aa@2140
1715+0000ebf6@2141
1716+0000eb76@2143
1717+00006bf4@2144
1718+0000ebf4@2145
1719+0000effc@2146
1720+0000ef7c@2147
1721+0000effc@2148
1722+00004ffc@2149
1723+0000cffc@2150
1724+0000dffc@2151
1725+00007ffe@2153
1726+0000ff7e@2154
1727+0000f5aa@2155
1728+0000752a@2158
1729+0000e5aa@2159
1730+0000ebfa@2160
1731+0000eb7a@2162
1732+00006bf8@2163
1733+0000ebf8@2164
1734+0000e1c0@2165
1735+000041c0@2167
1736+0000c1c0@2168
1737+0000d140@2169
1738+0000d1c0@2170
1739+000071c2@2172
1740+0000f142@2173
1741+0000f5aa@2174
1742+0000e5aa@2177
1743+0000effe@2178
1744+0000ebfe@2179
1745+0000eb7e@2180
1746+00006bfe@2181
1747+0000ebfc@2182
1748+0000effc@2183
1749+0000ef7c@2184
1750+0000effc@2185
1751+00004ffc@2186
1752+0000cffc@2187
1753+0000df7c@2188
1754+0000dffc@2189
1755+0000fffc@2190
1756+0000fffe@2191
1757+0000f5ae@2193
1758+0000752e@2195
1759+0000e5ae@2196
1760+0000ebf2@2197
1761+0000eb72@2199
1762+00006bf0@2200
1763+0000ebf0@2201
1764+0000e140@2202
1765+0000e1c0@2203
1766+0000c1c0@2205
1767+0000c140@2206
1768+0000d1c0@2207
1769+000071c2@2209
1770+0000f142@2210
1771+0000f5ae@2211
1772+0000752e@2214
1773+0000e5ae@2215
1774+0000ebf6@2216
1775+00006bf6@2218
1776+0000ebf4@2219
1777+0000effc@2220
1778+0000ef7c@2221
1779+0000effc@2222
1780+00004ffc@2223
1781+0000cffc@2224
1782+0000df7c@2225
1783+0000dffc@2226
1784+00007ffe@2228
1785+0000ff7e@2229
1786+0000f5ae@2230
1787+000075ae@2232
1788+0000e5ae@2233
1789+0000effa@2234
1790+0000ebfa@2235
1791+0000eb7a@2236
1792+00006bfa@2237
1793+0000ebf8@2238
1794+0000e140@2239
1795+0000e1c0@2241
1796+000041c0@2242
1797+0000c1c0@2243
1798+0000d1c0@2244
1799+000071c2@2246
1800+0000f142@2247
1801+0000f52e@2248
1802+0000f5ae@2249
1803+0000752e@2251
1804+0000e5ae@2252
1805+0000ebfe@2253
1806+0000eb7e@2255
1807+00006bfc@2256
1808+0000ebfc@2257
1809+0000effc@2258
1810+00006ffc@2260
1811+0000cffc@2261
1812+0000cf7c@2262
1813+0000dffc@2263
1814+00007ffe@2265
1815+0000ff7e@2266
1816+0000f532@2267
1817+0000f5b2@2268
1818+00007532@2270
1819+0000e5f2@2271
1820+0000ebf2@2272
1821+00006bf2@2274
1822+0000ebf0@2275
1823+0000e1c0@2276
1824+0000e140@2277
1825+0000e1c0@2278
1826+000041c0@2279
1827+0000c1c0@2280
1828+0000d140@2281
1829+0000d1c0@2282
1830+000071c2@2284
1831+0000f5f2@2285
1832+0000f5b2@2286
1833+000075b2@2288
1834+0000e5b2@2289
1835+0000ebf6@2290
1836+0000eb76@2292
1837+00006bf4@2293
1838+0000ebf4@2294
1839+0000effc@2295
1840+0000ef7c@2296
1841+0000effc@2297
1842+00004ffc@2298
1843+0000cffc@2299
1844+0000dffc@2300
1845+00007ffe@2302
1846+0000ff7e@2303
1847+0000f5b2@2304
1848+00007532@2307
1849+0000e5b2@2308
1850+0000ebfa@2309
1851+0000eb7a@2311
1852+00006bf8@2312
1853+0000ebf8@2313
1854+0000e1c0@2314
1855+000041c0@2316
1856+0000c1c0@2317
1857+0000d140@2318
1858+0000d1c0@2319
1859+000071c2@2321
1860+0000f142@2322
1861+0000f5b2@2323
1862+0000e5b2@2326
1863+0000effe@2327
1864+0000ebfe@2328
1865+0000eb7e@2329
1866+00006bfe@2330
1867+0000ebfc@2331
1868+0000effc@2332
1869+0000ef7c@2333
1870+0000effc@2334
1871+00004ffc@2335
1872+0000cffc@2336
1873+0000df7c@2337
1874+0000dffc@2338
1875+0000fffc@2339
1876+0000fffe@2340
1877+0000f5b6@2342
1878+00007536@2344
1879+0000e5b6@2345
1880+0000ebf2@2346
1881+0000eb72@2348
1882+00006bf0@2349
1883+0000ebf0@2350
1884+0000e140@2351
1885+0000e1c0@2352
1886+0000c1c0@2354
1887+0000c140@2355
1888+0000d1c0@2356
1889+000071c2@2358
1890+0000f142@2359
1891+0000f5b6@2360
1892+00007536@2363
1893+0000e5b6@2364
1894+0000ebf6@2365
1895+00006bf6@2367
1896+0000ebf4@2368
1897+0000effc@2369
1898+0000ef7c@2370
1899+0000effc@2371
1900+00004ffc@2372
1901+0000cffc@2373
1902+0000df7c@2374
1903+0000dffc@2375
1904+00007ffe@2377
1905+0000fffe@2378
1906+0000f5b6@2379
1907+000075b6@2381
1908+0000e5b6@2382
1909+0000effa@2383
1910+0000ebfa@2384
1911+0000eb7a@2385
1912+00006bfa@2386
1913+0000ebf8@2387
1914+0000e140@2388
1915+0000e1c0@2390
1916+000041c0@2391
1917+0000c1c0@2392
1918+0000d1c0@2393
1919+000071c2@2395
1920+0000f142@2396
1921+0000f576@2397
1922+0000f5b6@2398
1923+00007536@2400
1924+0000e5b6@2401
1925+0000ebfe@2402
1926+0000eb7e@2404
1927+00006bfc@2405
1928+0000ebfc@2406
1929+0000effc@2407
1930+00006ffc@2409
1931+0000cffc@2410
1932+0000cf7c@2411
1933+0000dffc@2412
1934+00007ffe@2414
1935+0000ff7e@2415
1936+0000f5ba@2416
1937+0000753a@2419
1938+0000e5fa@2420
1939+0000ebf2@2421
1940+0000eb72@2422
1941+00006bf2@2423
1942+0000ebf0@2424
1943+0000e1c0@2425
1944+0000e140@2426
1945+0000e1c0@2427
1946+000041c0@2428
1947+0000c1c0@2429
1948+0000d140@2430
1949+0000d1c0@2431
1950+000071c2@2433
1951+0000f1d2@2434
1952+0000f5ba@2435
1953+000075ba@2437
1954+0000e5ba@2438
1955+0000ebf6@2439
1956+0000eb76@2441
1957+00006bf4@2442
1958+0000ebf4@2443
1959+0000effc@2444
1960+0000ef7c@2445
1961+0000effc@2446
1962+00004ffc@2447
1963+0000cffc@2448
1964+0000dffc@2449
1965+00007ffe@2451
1966+0000ff7e@2452
1967+0000f5ba@2453
1968+0000753a@2456
1969+0000e5ba@2457
1970+0000ebfa@2458
1971+0000eb7a@2460
1972+0000ebf8@2461
1973+0000e1c0@2463
1974+000041c0@2465
1975+0000c1c0@2466
1976+0000d140@2467
1977+0000d1c0@2468
1978+000071c2@2470
1979+0000f142@2471
1980+0000f5ba@2472
1981+0000e5ba@2475
1982+0000effe@2476
1983+0000ebfe@2477
1984+0000eb7e@2478
1985+00006bfe@2479
1986+0000ebfc@2480
1987+0000effc@2481
1988+0000ef7c@2482
1989+0000effc@2483
1990+00004ffc@2484
1991+0000cffc@2485
1992+0000df7c@2486
1993+0000dffc@2487
1994+0000fffc@2488
1995+0000fffe@2489
1996+0000f5be@2491
1997+0000753e@2493
1998+0000e5be@2494
1999+0000ebf2@2495
2000+0000eb72@2497
2001+00006bf0@2498
2002+0000ebf0@2499
2003+0000e140@2500
2004+0000e1c0@2501
2005+0000c1c0@2503
2006+0000c140@2504
2007+0000d1c0@2505
2008+000071c2@2507
2009+0000f142@2508
2010+0000f5be@2509
2011+0000753e@2512
2012+0000e5be@2513
2013+0000ebf6@2514
2014+00006bf6@2516
2015+0000ebf4@2517
2016+0000effc@2518
2017+0000ef7c@2519
2018+0000effc@2520
2019+00004ffc@2521
2020+0000cffc@2522
2021+0000df7c@2523
2022+0000dffc@2524
2023+00007ffe@2526
2024+0000fffe@2527
2025+0000f5be@2528
2026+000075be@2530
2027+0000e5be@2531
2028+0000effa@2532
2029+0000ebfa@2533
2030+0000eb7a@2534
2031+00006bfa@2535
2032+0000ebf8@2536
2033+0000e140@2537
2034+0000e1c0@2539
2035+000041c0@2540
2036+0000c1c0@2541
2037+0000d1c0@2542
2038+000071c2@2544
2039+0000f142@2545
2040+0000f57e@2546
2041+0000f5be@2547
2042+0000753e@2549
2043+0000e5be@2550
2044+0000ebfe@2551
2045+0000eb7e@2553
2046+00006bfc@2554
2047+0000ebfc@2555
2048+0000effc@2556
2049+00006ffc@2558
2050+0000cffc@2559
2051+0000cf7c@2560
2052+0000dffc@2561
2053+00007ffe@2563
2054+0000ff7e@2564
2055+0000f702@2565
2056+0000f782@2566
2057+00007702@2568
2058+0000e782@2569
2059+0000ebf2@2570
2060+00006bf2@2572
2061+0000ebf0@2573
2062+0000e1c0@2574
2063+0000e140@2575
2064+0000e1c0@2576
2065+000041c0@2577
2066+0000c1c0@2578
2067+0000d140@2579
2068+0000d1c0@2580
2069+000071c2@2582
2070+0000f5c2@2583
2071+0000f782@2584
2072+00007782@2586
2073+0000e782@2587
2074+0000ebf6@2588
2075+0000eb76@2590
2076+00006bf4@2591
2077+0000ebf4@2592
2078+0000effc@2593
2079+0000ef7c@2594
2080+0000effc@2595
2081+00004ffc@2596
2082+0000cffc@2597
2083+0000dffc@2598
2084+00007ffe@2600
2085+0000ff7e@2601
2086+0000ff82@2602
2087+0000f782@2603
2088+00007702@2605
2089+0000e782@2606
2090+0000ebfa@2607
2091+0000eb7a@2609
2092+0000ebf8@2610
2093+0000e140@2612
2094+0000e1c0@2613
2095+000041c0@2614
2096+0000c1c0@2615
2097+0000d140@2616
2098+0000d1c0@2617
2099+000071c2@2619
2100+0000f142@2620
2101+0000f782@2621
2102+0000e782@2624
2103+0000ebfe@2625
2104+0000eb7e@2627
2105+00006bfe@2628
2106+0000ebfc@2629
2107+0000effc@2630
2108+0000ef7c@2631
2109+0000effc@2632
2110+00004ffc@2633
2111+0000cffc@2634
2112+0000df7c@2635
2113+0000dffc@2636
2114+0000fffc@2637
2115+0000fffe@2638
2116+0000f782@2640
2117+00007702@2642
2118+0000f780@2643
2119+0000fbfe@2644
2120+0000ebfc@2645
2121+0000eb7c@2646
2122+00006bfc@2647
2123+0000ebfc@2648
2124+0000eb7c@2650
2125+0000ebfc@2651
2126+0000eb7c@2653
2127+0000fbfc@2654
2128+00007bfe@2656
2129+0000fb7e@2657
2130+0000f706@2658
2131+0000f786@2659
2132+00007706@2661
2133+0000e786@2662
2134+0000ebf2@2663
2135+00006bf2@2665
2136+0000ebf0@2666
2137+0000ebc0@2667
2138+0000e140@2668
2139+0000e1c0@2669
2140+000041c0@2670
2141+0000c1c0@2671
2142+0000d140@2672
2143+0000d1c0@2673
2144+000071c2@2675
2145+0000f1c2@2676
2146+0000f786@2677
2147+00007786@2679
2148+0000e786@2680
2149+0000ebf6@2681
2150+0000eb76@2683
2151+00006bf6@2684
2152+0000ebf4@2685
2153+0000effc@2686
2154+0000ef7c@2687
2155+0000effc@2688
2156+00004ffc@2689
2157+0000cffc@2690
2158+0000dffc@2691
2159+00007ffe@2693
2160+0000ff7e@2694
2161+0000ff86@2695
2162+0000f786@2696
2163+00007706@2698
2164+0000e786@2699
2165+0000ebfa@2700
2166+0000eb7a@2702
2167+00006bf8@2703
2168+0000ebf8@2704
2169+0000e1c0@2705
2170+000061c0@2707
2171+0000c1c0@2708
2172+0000c140@2709
2173+0000d1c0@2710
2174+000071c2@2712
2175+0000f142@2713
2176+0000f786@2714
2177+00007706@2717
2178+0000e786@2718
2179+0000ebfe@2719
2180+00006bfe@2721
2181+0000ebfc@2722
2182+0000effc@2723
2183+0000ef7c@2724
2184+0000effc@2725
2185+00004ffc@2726
2186+0000cffc@2727
2187+0000df7c@2728
2188+0000dffc@2729
2189+00007ffe@2731
2190+0000fffe@2732
2191+0000f78a@2733
2192+0000778a@2735
2193+0000e78a@2736
2194+0000ebf2@2737
2195+0000eb72@2739
2196+00006bf0@2740
2197+0000ebf0@2741
2198+0000e140@2742
2199+0000e1c0@2744
2200+000041c0@2745
2201+0000c1c0@2746
2202+0000d1c0@2747
2203+000071c2@2749
2204+0000f142@2750
2205+0000f78a@2751
2206+0000770a@2754
2207+0000e78a@2755
2208+0000ebf6@2756
2209+0000eb76@2758
2210+0000ebf4@2759
2211+0000effc@2760
2212+0000ef7c@2761
2213+0000effc@2762
2214+00004ffc@2763
2215+0000cffc@2764
2216+0000df7c@2765
2217+0000dffc@2766
2218+00007ffe@2768
2219+0000ff7e@2769
2220+0000f78a@2770
2221+0000e78a@2773
2222+0000ebfa@2774
2223+0000eb7a@2776
2224+00006bfa@2777
2225+0000ebf8@2778
2226+0000e1c0@2779
2227+0000e140@2780
2228+0000e1c0@2781
2229+000041c0@2782
2230+0000c1c0@2783
2231+0000d140@2784
2232+0000d1c0@2785
2233+0000f1c0@2786
2234+0000f1c2@2787
2235+0000f74a@2788
2236+0000f78a@2789
2237+0000770a@2791
2238+0000e78a@2792
2239+0000ebfe@2793
2240+0000eb7e@2795
2241+00006bfc@2796
2242+0000ebfc@2797
2243+0000effc@2798
2244+0000ef7c@2799
2245+0000effc@2800
2246+0000cffc@2801
2247+0000cf7c@2802
2248+0000dffc@2803
2249+00007ffe@2805
2250+0000ff7e@2806
2251+0000f70e@2807
2252+0000f78e@2808
2253+0000770e@2810
2254+0000e78e@2811
2255+0000ebf2@2812
2256+00006bf2@2814
2257+0000ebf0@2815
2258+0000ebc0@2816
2259+0000e140@2817
2260+0000e1c0@2818
2261+000041c0@2819
2262+0000c1c0@2820
2263+0000d140@2821
2264+0000d1c0@2822
2265+000071c2@2824
2266+0000f1c2@2825
2267+0000f78e@2826
2268+0000778e@2828
2269+0000e78e@2829
2270+0000ebf6@2830
2271+0000eb76@2832
2272+00006bf4@2833
2273+0000ebf4@2834
2274+0000effc@2835
2275+0000ef7c@2836
2276+0000effc@2837
2277+00004ffc@2838
2278+0000cffc@2839
2279+0000dffc@2840
2280+00007ffe@2842
2281+0000ff7e@2843
2282+0000ff8e@2844
2283+0000f78e@2845
2284+0000770e@2847
2285+0000e78e@2848
2286+0000ebfa@2849
2287+0000eb7a@2851
2288+00006bf8@2852
2289+0000ebf8@2853
2290+0000e1c0@2854
2291+000061c0@2856
2292+0000c1c0@2857
2293+0000c140@2858
2294+0000d1c0@2859
2295+000071c2@2861
2296+0000f142@2862
2297+0000f78e@2863
2298+0000770e@2866
2299+0000e7ae@2867
2300+0000ebfe@2868
2301+00006bfe@2870
2302+0000ebfc@2871
2303+0000effc@2872
2304+0000ef7c@2873
2305+0000effc@2874
2306+00004ffc@2875
2307+0000cffc@2876
2308+0000df7c@2877
2309+0000dffc@2878
2310+00007ffe@2880
2311+0000fffe@2881
2312+0000f792@2882
2313+00007792@2884
2314+0000e792@2885
2315+0000ebf2@2886
2316+0000eb72@2888
2317+00006bf0@2889
2318+0000ebf0@2890
2319+0000e140@2891
2320+0000e1c0@2893
2321+000041c0@2894
2322+0000c1c0@2895
2323+0000d1c0@2896
2324+000071c2@2898
2325+0000f142@2899
2326+0000f792@2900
2327+00007712@2903
2328+0000e792@2904
2329+0000ebf6@2905
2330+0000eb76@2907
2331+0000ebf4@2908
2332+0000effc@2909
2333+0000ef7c@2910
2334+0000effc@2911
2335+00004ffc@2912
2336+0000cffc@2913
2337+0000df7c@2914
2338+0000dffc@2915
2339+00007ffe@2917
2340+0000ff7e@2918
2341+0000f792@2919
2342+0000e792@2922
2343+0000ebfa@2923
2344+0000eb7a@2925
2345+00006bfa@2926
2346+0000ebf8@2927
2347+0000e1c0@2928
2348+0000e140@2929
2349+0000e1c0@2930
2350+000041c0@2931
2351+0000c1c0@2932
2352+0000d140@2933
2353+0000d1c0@2934
2354+0000f1c0@2935
2355+0000f142@2936
2356+0000f752@2937
2357+0000f792@2938
2358+00007712@2940
2359+0000e792@2941
2360+0000ebfe@2942
2361+0000eb7e@2944
2362+00006bfc@2945
2363+0000ebfc@2946
2364+0000effc@2947
2365+0000ef7c@2948
2366+0000effc@2949
2367+0000cffc@2950
2368+0000cf7c@2951
2369+0000dffc@2952
2370+00007ffe@2954
2371+0000ff7e@2955
2372+0000f716@2956
2373+0000f796@2957
2374+00007716@2959
2375+0000e796@2960
2376+0000ebf2@2961
2377+00006bf2@2963
2378+0000ebf0@2964
2379+0000ebc0@2965
2380+0000e140@2966
2381+0000e1c0@2967
2382+000041c0@2968
2383+0000c1c0@2969
2384+0000d140@2970
2385+0000d1c0@2971
2386+000071c2@2973
2387+0000f1c2@2974
2388+0000f796@2975
2389+00007796@2977
2390+0000e796@2978
2391+0000ebf6@2979
2392+0000eb76@2981
2393+00006bf4@2982
2394+0000ebf4@2983
2395+0000effc@2984
2396+0000ef7c@2985
2397+0000effc@2986
2398+00004ffc@2987
2399+0000cffc@2988
2400+0000dffc@2989
2401+00007ffe@2991
2402+0000ff7e@2992
2403+0000ff96@2993
2404+0000f796@2994
2405+00007716@2996
2406+0000e796@2997
2407+0000ebfa@2998
2408+0000eb7a@3000
2409+00006bf8@3001
2410+0000ebf8@3002
2411+0000e1c0@3003
2412+000041c0@3005
2413+0000c1c0@3006
2414+0000c140@3007
2415+0000d1c0@3008
2416+000071c2@3010
2417+0000f142@3011
2418+0000f796@3012
2419+00007716@3015
2420+0000e796@3016
2421+0000ebfe@3017
2422+00006bfe@3019
2423+0000ebfc@3020
2424+0000effc@3021
2425+0000ef7c@3022
2426+0000effc@3023
2427+00004ffc@3024
2428+0000cffc@3025
2429+0000df7c@3026
2430+0000dffc@3027
2431+00007ffe@3029
2432+0000fffe@3030
2433+0000f79a@3031
2434+0000779a@3033
2435+0000e79a@3034
2436+0000ebf2@3035
2437+0000eb72@3037
2438+00006bf0@3038
2439+0000ebf0@3039
2440+0000e140@3040
2441+0000e1c0@3042
2442+000041c0@3043
2443+0000c1c0@3044
2444+0000d1c0@3045
2445+000071c2@3047
2446+0000f142@3048
2447+0000f79a@3049
2448+0000771a@3052
2449+0000e79a@3053
2450+0000ebf6@3054
2451+0000eb76@3056
2452+0000ebf4@3057
2453+0000effc@3058
2454+0000ef7c@3059
2455+0000effc@3060
2456+00004ffc@3061
2457+0000cffc@3062
2458+0000df7c@3063
2459+0000dffc@3064
2460+00007ffe@3066
2461+0000ff7e@3067
2462+0000f79a@3068
2463+0000e79a@3071
2464+0000ebfa@3072
2465+0000eb7a@3074
2466+00006bfa@3075
2467+0000ebf8@3076
2468+0000e1c0@3077
2469+0000e140@3078
2470+0000e1c0@3079
2471+000041c0@3080
2472+0000c1c0@3081
2473+0000d140@3082
2474+0000d1c0@3083
2475+0000f1c0@3084
2476+0000f1c2@3085
2477+0000f75a@3086
2478+0000f79a@3087
2479+0000771a@3089
2480+0000e79a@3090
2481+0000ebfe@3091
2482+0000eb7e@3093
2483+00006bfc@3094
2484+0000ebfc@3095
2485+0000effc@3096
2486+0000ef7c@3097
2487+0000effc@3098
2488+0000cffc@3099
2489+0000cf7c@3100
2490+0000dffc@3101
2491+00007ffe@3103
2492+0000ff7e@3104
2493+0000f79e@3105
2494+0000771e@3108
2495+0000e79e@3109
2496+0000ebf2@3110
2497+00006bf2@3112
2498+0000ebf0@3113
2499+0000ebc0@3114
2500+0000e140@3115
2501+0000e1c0@3116
2502+000041c0@3117
2503+0000c1c0@3118
2504+0000d140@3119
2505+0000d1c0@3120
2506+000071c2@3122
2507+0000f1c2@3123
2508+0000f79e@3124
2509+0000779e@3126
2510+0000e79e@3127
2511+0000ebf6@3128
2512+0000eb76@3130
2513+00006bf4@3131
2514+0000ebf4@3132
2515+0000effc@3133
2516+0000ef7c@3134
2517+0000effc@3135
2518+00004ffc@3136
2519+0000cffc@3137
2520+0000dffc@3138
2521+00007ffe@3140
2522+0000ff7e@3141
2523+0000ff9e@3142
2524+0000f79e@3143
2525+0000771e@3145
2526+0000e79e@3146
2527+0000ebfa@3147
2528+0000eb7a@3149
2529+00006bf8@3150
2530+0000ebf8@3151
2531+0000e1c0@3152
2532+000041c0@3154
2533+0000c1c0@3155
2534+0000c140@3156
2535+0000d1c0@3157
2536+000071c2@3159
2537+0000f142@3160
2538+0000f79e@3161
2539+0000771e@3164
2540+0000e7fe@3165
2541+0000ebfe@3166
2542+00006bfe@3168
2543+0000ebfc@3169
2544+0000effc@3170
2545+0000ef7c@3171
2546+0000effc@3172
2547+00004ffc@3173
2548+0000cffc@3174
2549+0000df7c@3175
2550+0000dffc@3176
2551+00007ffe@3178
2552+0000fffe@3179
2553+0000f6a2@3180
2554+000076a2@3182
2555+0000e6a2@3183
2556+0000eaf2@3184
2557+0000ea72@3186
2558+00006a70@3187
2559+0000eaf0@3188
2560+0000e0c0@3189
2561+0000e040@3191
2562+0000c040@3192
2563+0000c0c0@3193
2564+0000d0c0@3194
2565+00007042@3196
2566+0000f0c2@3197
2567+0000f6a2@3198
2568+0000f622@3200
2569+00007622@3201
2570+0000e6a2@3202
2571+0000eaf6@3203
2572+0000ea76@3205
2573+0000ea74@3206
2574+0000eefc@3207
2575+00004e7c@3210
2576+0000cefc@3211
2577+0000defc@3212
2578+0000de7c@3214
2579+00007e7e@3215
2580+0000fefe@3216
2581+0000f6a2@3217
2582+0000f622@3219
2583+0000e622@3220
2584+0000eafa@3221
2585+00006a7a@3224
2586+0000eaf8@3225
2587+0000e0c0@3226
2588+0000e040@3228
2589+00004040@3229
2590+0000c0c0@3230
2591+0000d0c0@3231
2592+00007040@3233
2593+0000f042@3234
2594+0000f6e2@3235
2595+0000f6a2@3236
2596+0000f622@3237
2597+00007622@3238
2598+0000e6a2@3239
2599+0000eafe@3240
2600+0000ea7e@3242
2601+00006a7c@3243
2602+0000eafc@3244
2603+0000eefc@3245
2604+00006e7c@3247
2605+0000ce7c@3248
2606+0000cefc@3249
2607+0000defc@3250
2608+0000de7c@3251
2609+00007e7e@3252
2610+0000fefe@3253
2611+0000f6a6@3254
2612+0000f626@3256
2613+000076a6@3257
2614+0000e6a6@3258
2615+0000eaf2@3259
2616+0000ea72@3260
2617+00006af2@3261
2618+0000eaf0@3262
2619+0000eac0@3263
2620+0000e040@3264
2621+000040c0@3266
2622+0000c0c0@3267
2623+0000d040@3268
2624+0000d0c0@3270
2625+000070c2@3271
2626+0000f0c2@3272
2627+0000f626@3273
2628+000076a6@3275
2629+0000e6a6@3276
2630+0000ea76@3277
2631+0000eaf6@3279
2632+00006af4@3280
2633+0000eaf4@3281
2634+0000ee7c@3282
2635+0000eefc@3284
2636+00004efc@3285
2637+0000cefc@3286
2638+0000de7c@3287
2639+00007efe@3289
2640+0000fefe@3290
2641+0000fea6@3291
2642+0000f626@3292
2643+0000f6a6@3293
2644+000076a6@3294
2645+0000e6a6@3295
2646+0000ea7a@3296
2647+0000eafa@3298
2648+00006af8@3299
2649+0000eaf8@3300
2650+0000e040@3301
2651+000040c0@3303
2652+0000c0c0@3304
2653+0000c040@3305
2654+0000d040@3306
2655+0000d0c0@3307
2656+000070c2@3308
2657+0000f0c2@3309
2658+0000f626@3310
2659+0000f6a6@3312
2660+000076a6@3313
2661+0000e6ae@3314
2662+0000ea7e@3315
2663+00006afe@3317
2664+0000eafc@3318
2665+0000ee7c@3319
2666+0000eefc@3321
2667+00004efc@3322
2668+0000cefc@3323
2669+0000de7c@3324
2670+0000defc@3326
2671+00007efe@3327
2672+0000fefe@3328
2673+0000f62a@3329
2674+000076aa@3331
2675+0000e6aa@3332
2676+0000ea72@3333
2677+0000eaf2@3334
2678+00006af0@3336
2679+0000ea70@3337
2680+0000e0c0@3338
2681+0000c040@3341
2682+0000d0c0@3343
2683+00007042@3345
2684+0000f042@3346
2685+0000f6aa@3347
2686+0000762a@3350
2687+0000e62a@3351
2688+0000eaf6@3352
2689+0000ea74@3355
2690+0000ee7c@3356
2691+0000eefc@3357
2692+00004efc@3359
2693+0000ce7c@3360
2694+0000defc@3361
2695+00007e7e@3364
2696+0000fe7e@3365
2697+0000f6aa@3366
2698+0000e62a@3369
2699+0000ea7a@3370
2700+0000eafa@3371
2701+00006a7a@3373
2702+0000ea78@3374
2703+0000e040@3375
2704+0000e0c0@3376
2705+00004040@3378
2706+0000c040@3379
2707+0000d0c0@3380
2708+0000f0c0@3382
2709+0000f042@3383
2710+0000f66a@3384
2711+0000f6aa@3385
2712+0000762a@3387
2713+0000e62a@3388
2714+0000eafe@3389
2715+00006a7c@3392
2716+0000ea7c@3393
2717+0000eefc@3394
2718+00006efc@3396
2719+0000ce7c@3397
2720+0000defc@3399
2721+00007e7e@3401
2722+0000fe7e@3402
2723+0000f62e@3403
2724+0000f6ae@3404
2725+0000762e@3406
2726+0000e62e@3407
2727+0000eaf2@3408
2728+00006af2@3410
2729+0000eaf0@3411
2730+0000eac0@3412
2731+0000e0c0@3413
2732+0000e040@3414
2733+000040c0@3415
2734+0000c0c0@3416
2735+0000d0c0@3417
2736+0000d040@3418
2737+000070c2@3420
2738+0000f0c2@3421
2739+0000f7ae@3422
2740+0000f72e@3423
2741+0000772e@3424
2742+0000e7ae@3425
2743+0000ebf6@3426
2744+0000eb76@3428
2745+00006b74@3429
2746+0000ebf4@3430
2747+0000effc@3431
2748+0000ef7c@3432
2749+00004ffc@3434
2750+0000cffc@3435
2751+0000dffc@3436
2752+0000df7c@3437
2753+00007f7e@3438
2754+0000fffe@3439
2755+0000ffae@3440
2756+0000f72e@3441
2757+000077ac@3443
2758+0000f7ac@3444
2759+0000fbf4@3445
2760+0000eb74@3446
2761+00006bf4@3448
2762+0000ebf4@3449
2763+0000eb74@3451
2764+00006b74@3452
2765+0000ebf4@3453
2766+0000fb74@3455
2767+00007bf6@3457
2768+0000fbf6@3458
2769+0000f7ae@3459
2770+0000f72e@3460
2771+000077ae@3462
2772+0000e7fe@3463
2773+0000ebfa@3464
2774+0000eb7a@3465
2775+00006b7a@3466
2776+0000ebf8@3467
2777+0000e1c0@3468
2778+0000e140@3469
2779+000041c0@3471
2780+0000c1c0@3472
2781+0000d1c0@3473
2782+0000d140@3474
2783+000071c2@3476
2784+0000f7ee@3477
2785+0000f7ae@3478
2786+0000f72e@3479
2787+000077ae@3480
2788+0000e7ae@3481
2789+0000ebfe@3482
2790+0000eb7e@3483
2791+00006bfc@3485
2792+0000ebfc@3486
2793+0000effc@3487
2794+0000ef7c@3488
2795+0000effc@3489
2796+0000cffc@3490
2797+0000dffc@3492
2798+00007ffe@3494
2799+0000ff7e@3495
2800+0000f7b2@3496
2801+00007732@3499
2802+0000e7b2@3500
2803+0000ebf2@3501
2804+0000eb72@3503
2805+0000ebf0@3504
2806+0000e1c0@3506
2807+000041c0@3508
2808+0000c1c0@3509
2809+0000d140@3510
2810+0000d1c0@3511
2811+000071c2@3513
2812+0000f142@3514
2813+0000f7b2@3515
2814+0000e7b2@3518
2815+0000ebf6@3519
2816+0000eb76@3521
2817+00006bf6@3522
2818+0000ebf4@3523
2819+0000effc@3524
2820+0000ef7c@3525
2821+0000effc@3526
2822+00004ffc@3527
2823+0000cffc@3528
2824+0000df7c@3529
2825+0000dffc@3530
2826+0000fffc@3531
2827+0000ff7e@3532
2828+0000fffe@3533
2829+0000f7b2@3534
2830+00007732@3536
2831+0000e7b2@3537
2832+0000ebfa@3538
2833+0000eb7a@3540
2834+00006bf8@3541
2835+0000ebf8@3542
2836+0000e140@3543
2837+0000e1c0@3544
2838+0000c1c0@3546
2839+0000c140@3547
2840+0000d1c0@3548
2841+000071c2@3550
2842+0000f142@3551
2843+0000f7b2@3552
2844+00007732@3555
2845+0000e7b2@3556
2846+0000ebfe@3557
2847+00006bfe@3559
2848+0000ebfc@3560
2849+0000effc@3561
2850+0000ef7c@3562
2851+0000effc@3563
2852+00004ffc@3564
2853+0000cffc@3565
2854+0000df7c@3566
2855+0000dffc@3567
2856+00007ffe@3569
2857+0000fffe@3570
2858+0000f7b6@3571
2859+000077b6@3573
2860+0000e7b6@3574
2861+0000ebf2@3575
2862+0000eb72@3577
2863+00006bf0@3578
2864+0000ebf0@3579
2865+0000e140@3580
2866+0000e1c0@3582
2867+000041c0@3583
2868+0000c1c0@3584
2869+0000d1c0@3585
2870+000071c2@3587
2871+0000f142@3588
2872+0000f736@3589
2873+0000f7b6@3590
2874+00007736@3592
2875+0000e7b6@3593
2876+0000ebf6@3594
2877+0000eb76@3596
2878+00006bf4@3597
2879+0000effc@3598
2880+00004ffc@3601
2881+0000cffc@3602
2882+0000cf7c@3603
2883+0000dffc@3604
2884+00007ffe@3606
2885+0000ff7e@3607
2886+0000f7b6@3608
2887+00006736@3611
2888+0000e7f6@3612
2889+0000ebfa@3613
2890+0000eb7a@3614
2891+00006bfa@3615
2892+0000ebf8@3616
2893+0000e1c0@3617
2894+0000e140@3618
2895+0000e1c0@3619
2896+000041c0@3620
2897+0000c1c0@3621
2898+0000d140@3622
2899+0000d1c0@3623
2900+000071c2@3625
2901+0000f5f6@3626
2902+0000f7b6@3627
2903+00007736@3629
2904+0000e7b6@3630
2905+0000ebfe@3631
2906+0000eb7e@3633
2907+00006bfc@3634
2908+0000ebfc@3635
2909+0000effc@3636
2910+0000ef7c@3637
2911+0000effc@3638
2912+0000cffc@3639
2913+0000dffc@3641
2914+00007ffe@3643
2915+0000ff7e@3644
2916+0000f7ba@3645
2917+0000773a@3648
2918+0000e7ba@3649
2919+0000ebf2@3650
2920+0000ebf0@3653
2921+0000e1c0@3655
2922+000041c0@3657
2923+0000c1c0@3658
2924+0000d140@3659
2925+0000d1c0@3660
2926+000071c2@3662
2927+0000f142@3663
2928+0000f7ba@3664
2929+0000e7ba@3667
2930+0000effe@3668
2931+0000ebf6@3669
2932+0000eb76@3670
2933+00006bf6@3671
2934+0000ebf4@3672
2935+0000effc@3673
2936+0000ef7c@3674
2937+0000effc@3675
2938+00004ffc@3676
2939+0000cffc@3677
2940+0000df7c@3678
2941+0000dffc@3679
2942+0000fffc@3680
2943+0000fffe@3681
2944+0000f7ba@3683
2945+0000773a@3685
2946+0000e7ba@3686
2947+0000ebfa@3687
2948+0000eb7a@3689
2949+00006bf8@3690
2950+0000ebf8@3691
2951+0000e140@3692
2952+0000e1c0@3693
2953+0000c1c0@3695
2954+0000c140@3696
2955+0000d1c0@3697
2956+000071c2@3699
2957+0000f142@3700
2958+0000f7ba@3701
2959+0000773a@3704
2960+0000e7ba@3705
2961+0000ebfe@3706
2962+00006bfe@3708
2963+0000ebfc@3709
2964+0000effc@3710
2965+0000ef7c@3711
2966+0000effc@3712
2967+00004ffc@3713
2968+0000cffc@3714
2969+0000df7c@3715
2970+0000dffc@3716
2971+00007ffe@3718
2972+0000fffe@3719
2973+0000f7be@3720
2974+000077be@3722
2975+0000e7be@3723
2976+0000ebf2@3724
2977+0000eb72@3726
2978+00006bf0@3727
2979+0000ebf0@3728
2980+0000e140@3729
2981+0000e1c0@3731
2982+000041c0@3732
2983+0000c1c0@3733
2984+0000d1c0@3734
2985+000071c2@3736
2986+0000f142@3737
2987+0000f73e@3738
2988+0000f7be@3739
2989+0000773e@3741
2990+0000e7be@3742
2991+0000ebf6@3743
2992+0000eb76@3745
2993+00006bf4@3746
2994+0000effc@3747
2995+00004ffc@3750
2996+0000cffc@3751
2997+0000cf7c@3752
2998+0000dffc@3753
2999+00007ffe@3755
3000+0000ff7e@3756
3001+0000f7be@3757
3002+0000673e@3760
3003+0000e7fe@3761
3004+0000ebfa@3762
3005+0000eb7a@3763
3006+00006bfa@3764
3007+0000ebf8@3765
3008+0000e1c0@3766
3009+0000e140@3767
3010+0000e1c0@3768
3011+000041c0@3769
3012+0000c1c0@3770
3013+0000d140@3771
3014+0000d1c0@3772
3015+000071c2@3774
3016+0000f57e@3775
3017+0000f7be@3776
3018+0000773e@3778
3019+0000e7be@3779
3020+0000ebfe@3780
3021+0000eb7e@3782
3022+00006bfc@3783
3023+0000ebfc@3784
3024+0000effc@3785
3025+0000ef7c@3786
3026+0000effc@3787
3027+0000cffc@3788
3028+0000dffc@3790
3029+00007ffe@3792
3030+0000ff7e@3793
3031+0000f982@3794
3032+00007902@3797
3033+0000e982@3798
3034+0000ebf2@3799
3035+0000eb72@3801
3036+0000ebf0@3802
3037+0000e1c0@3804
3038+000041c0@3806
3039+0000c1c0@3807
3040+0000d140@3808
3041+0000d1c0@3809
3042+000071c2@3811
3043+0000f142@3812
3044+0000f982@3813
3045+0000e982@3816
3046+0000ebf6@3817
3047+0000eb76@3819
3048+00006bf6@3820
3049+0000ebf4@3821
3050+0000effc@3822
3051+0000ef7c@3823
3052+0000effc@3824
3053+00004ffc@3825
3054+0000cffc@3826
3055+0000df7c@3827
3056+0000dffc@3828
3057+00007ffc@3829
3058+0000ff7e@3830
3059+0000fffe@3831
3060+0000f982@3832
3061+00007902@3834
3062+0000e982@3835
3063+0000ebfa@3836
3064+0000eb7a@3838
3065+00006bf8@3839
3066+0000ebf8@3840
3067+0000e140@3841
3068+0000e1c0@3842
3069+000061c0@3843
3070+0000c1c0@3844
3071+0000c140@3845
3072+0000d1c0@3846
3073+000071c2@3848
3074+0000f142@3849
3075+0000f982@3850
3076+00007902@3853
3077+0000e982@3854
3078+0000fbfe@3855
3079+0000ebfe@3856
3080+00006bfe@3857
3081+0000ebfc@3858
3082+0000effc@3859
3083+0000ef7c@3860
3084+0000effc@3861
3085+00004ffc@3862
3086+0000cffc@3863
3087+0000df7c@3864
3088+0000dffc@3865
3089+00007ffe@3867
3090+0000fffe@3868
3091+0000f986@3869
3092+00007986@3871
3093+0000e986@3872
3094+0000ebf2@3873
3095+0000eb72@3875
3096+00006bf0@3876
3097+0000ebf0@3877
3098+0000e140@3878
3099+0000e1c0@3880
3100+000041c0@3881
3101+0000c1c0@3882
3102+0000d1c0@3883
3103+000071c2@3885
3104+0000f142@3886
3105+0000f906@3887
3106+0000f986@3888
3107+00007906@3890
3108+0000e986@3891
3109+0000ebf6@3892
3110+0000eb76@3894
3111+00006bf4@3895
3112+0000effc@3896
3113+00004ffc@3899
3114+0000cffc@3900
3115+0000cf7c@3901
3116+0000dffc@3902
3117+00007ffe@3904
3118+0000ff7e@3905
3119+0000f906@3906
3120+0000f986@3907
3121+00006906@3909
3122+0000e9f6@3910
3123+0000ebfa@3911
3124+00006bfa@3913
3125+0000ebf8@3914
3126+0000e1c0@3915
3127+0000e140@3916
3128+0000e1c0@3917
3129+000041c0@3918
3130+0000c1c0@3919
3131+0000d140@3920
3132+0000d1c0@3921
3133+000071c2@3923
3134+0000f9c6@3924
3135+0000f986@3925
3136+00007906@3927
3137+0000e986@3928
3138+0000ebfe@3929
3139+0000eb7e@3931
3140+00006bfc@3932
3141+0000ebfc@3933
3142+0000effc@3934
3143+0000ef7c@3935
3144+0000effc@3936
3145+0000cffc@3937
3146+0000dffc@3939
3147+00007ffe@3941
3148+0000ff7e@3942
3149+0000f98a@3943
3150+0000790a@3946
3151+0000e98a@3947
3152+0000ebf2@3948
3153+0000eb72@3950
3154+0000ebf0@3951
3155+0000e1c0@3953
3156+000041c0@3955
3157+0000c1c0@3956
3158+0000d140@3957
3159+0000d1c0@3958
3160+000071c2@3960
3161+0000f142@3961
3162+0000f98a@3962
3163+0000e98a@3965
3164+0000ebf6@3966
3165+0000eb76@3968
3166+00006bf6@3969
3167+0000ebf4@3970
3168+0000effc@3971
3169+0000ef7c@3972
3170+0000effc@3973
3171+00004ffc@3974
3172+0000cffc@3975
3173+0000df7c@3976
3174+0000dffc@3977
3175+00007ffc@3978
3176+0000ff7e@3979
3177+0000fffe@3980
3178+0000f98a@3981
3179+0000790a@3983
3180+0000e98a@3984
3181+0000ebfa@3985
3182+0000eb7a@3987
3183+00006bf8@3988
3184+0000ebf8@3989
3185+0000e140@3990
3186+0000e1c0@3991
3187+000061c0@3992
3188+0000c1c0@3993
3189+0000c140@3994
3190+0000d1c0@3995
3191+000071c2@3997
3192+0000f142@3998
3193+0000f98a@3999
3194+0000790a@4002
3195+0000e98a@4003
3196+0000ebfe@4004
3197+00006bfe@4006
3198+0000ebfc@4007
3199+0000effc@4008
3200+0000ef7c@4009
3201+0000effc@4010
3202+00004ffc@4011
3203+0000cffc@4012
3204+0000df7c@4013
3205+0000dffc@4014
3206+00007ffe@4016
3207+0000fffe@4017
3208+0000f98e@4018
3209+0000798e@4020
3210+0000e98e@4021
3211+0000ebf2@4022
3212+0000eb72@4024
3213+00006bf0@4025
3214+0000ebf0@4026
3215+0000e140@4027
3216+0000e1c0@4029
3217+000041c0@4030
3218+0000c1c0@4031
3219+0000d1c0@4032
3220+000071c2@4034
3221+0000f142@4035
3222+0000f90e@4036
3223+0000f98e@4037
3224+0000790c@4039
3225+0000f98c@4040
3226+0000fbf0@4041
3227+0000ebf0@4042
3228+0000eb70@4043
3229+00006bf0@4044
3230+0000effc@4045
3231+0000ebfc@4046
3232+00006ffc@4048
3233+0000ebfc@4049
3234+0000fb7c@4050
3235+0000fffc@4051
3236+00007bfe@4053
3237+0000ff7e@4054
3238+0000f98e@4055
3239+0000690e@4058
3240+0000ebfe@4059
3241+0000ebf6@4060
3242+00006bf6@4062
3243+0000ebf4@4063
3244+0000effc@4064
3245+0000ef7c@4065
3246+0000effc@4066
3247+00004ffc@4067
3248+0000cffc@4068
3249+0000df7c@4069
3250+0000dffc@4070
3251+00007ffe@4072
3252+0000fffe@4073
3253+0000f98e@4074
3254+0000798e@4076
3255+0000e98e@4077
3256+0000ebfa@4078
3257+0000eb7a@4080
3258+00006bf8@4081
3259+0000ebf8@4082
3260+0000e140@4083
3261+0000e1c0@4084
3262+0000c1c0@4086
3263+0000d1c0@4088
3264+000071c2@4090
3265+0000f142@4091
3266+0000f98e@4092
3267+0000790e@4095
3268+0000e98e@4096
3269+0000ebfe@4097
3270+0000eb7e@4099
3271+0000ebfc@4100
3272+0000effc@4101
3273+0000ef7c@4102
3274+0000effc@4103
3275+00004ffc@4104
3276+0000cffc@4105
3277+0000df7c@4106
3278+0000dffc@4107
3279+00007ffe@4109
3280+0000ff7e@4110
3281+0000f992@4111
3282+0000e992@4114
3283+0000ebf2@4115
3284+0000eb72@4117
3285+00006bf2@4118
3286+0000ebf0@4119
3287+0000e1c0@4120
3288+0000e140@4121
3289+0000e1c0@4122
3290+000041c0@4123
3291+0000c1c0@4124
3292+0000d140@4125
3293+0000d1c0@4126
3294+000071c0@4127
3295+0000f142@4128
3296+0000f952@4129
3297+0000f992@4130
3298+00007912@4132
3299+0000e992@4133
3300+0000ebf6@4134
3301+0000eb76@4136
3302+00006bf4@4137
3303+0000ebf4@4138
3304+0000effc@4139
3305+00006ffc@4141
3306+0000cffc@4142
3307+0000cf7c@4143
3308+0000dffc@4144
3309+00007ffe@4146
3310+0000ff7e@4147
3311+0000f912@4148
3312+0000f992@4149
3313+00007912@4151
3314+0000e992@4152
3315+0000ebfa@4153
3316+00006bfa@4155
3317+0000ebf8@4156
3318+0000ebc0@4157
3319+0000e140@4158
3320+0000e1c0@4159
3321+000041c0@4160
3322+0000c1c0@4161
3323+0000d140@4162
3324+0000d1c0@4163
3325+000071c2@4165
3326+0000f1c2@4166
3327+0000f992@4167
3328+00007992@4169
3329+0000e992@4170
3330+0000ebfe@4171
3331+0000eb7e@4173
3332+00006bfc@4174
3333+0000ebfc@4175
3334+0000effc@4176
3335+0000ef7c@4177
3336+0000effc@4178
3337+00004ffc@4179
3338+0000cffc@4180
3339+0000dffc@4181
3340+00007ffe@4183
3341+0000ff7e@4184
3342+0000f996@4185
3343+00007916@4188
3344+0000e996@4189
3345+0000ebf2@4190
3346+0000eb72@4192
3347+00006bf0@4193
3348+0000ebf0@4194
3349+0000e1c0@4195
3350+000041c0@4197
3351+0000c1c0@4198
3352+0000c140@4199
3353+0000d1c0@4200
3354+000071c2@4202
3355+0000f142@4203
3356+0000f996@4204
3357+00006916@4207
3358+0000ebf6@4208
3359+00006bf6@4211
3360+0000ebf4@4212
3361+0000effc@4213
3362+0000ef7c@4214
3363+0000effc@4215
3364+00004ffc@4216
3365+0000cffc@4217
3366+0000df7c@4218
3367+0000dffc@4219
3368+00007ffe@4221
3369+0000fffe@4222
3370+0000f996@4223
3371+00007996@4225
3372+0000e996@4226
3373+0000ebfa@4227
3374+0000eb7a@4229
3375+00006bf8@4230
3376+0000ebf8@4231
3377+0000e140@4232
3378+0000e1c0@4233
3379+0000c1c0@4235
3380+0000d1c0@4237
3381+000071c2@4239
3382+0000f142@4240
3383+0000f996@4241
3384+00007916@4244
3385+0000e996@4245
3386+0000ebfe@4246
3387+0000eb7e@4248
3388+0000ebfc@4249
3389+0000effc@4250
3390+0000ef7c@4251
3391+0000effc@4252
3392+00004ffc@4253
3393+0000cffc@4254
3394+0000df7c@4255
3395+0000dffc@4256
3396+00007ffe@4258
3397+0000ff7e@4259
3398+0000f99a@4260
3399+0000e99a@4263
3400+0000ebf2@4264
3401+0000eb72@4266
3402+00006bf2@4267
3403+0000ebf0@4268
3404+0000e1c0@4269
3405+0000e140@4270
3406+0000e1c0@4271
3407+000041c0@4272
3408+0000c1c0@4273
3409+0000d140@4274
3410+0000d1c0@4275
3411+000071c0@4276
3412+0000f142@4277
3413+0000f95a@4278
3414+0000f99a@4279
3415+0000791a@4281
3416+0000e99a@4282
3417+0000ebf6@4283
3418+0000eb76@4285
3419+00006bf4@4286
3420+0000ebf4@4287
3421+0000effc@4288
3422+00006ffc@4290
3423+0000cffc@4291
3424+0000cf7c@4292
3425+0000dffc@4293
3426+00007ffe@4295
3427+0000ff7e@4296
3428+0000f91a@4297
3429+0000f99a@4298
3430+0000791a@4300
3431+0000e99a@4301
3432+0000ebfa@4302
3433+00006bfa@4304
3434+0000ebf8@4305
3435+0000ebc0@4306
3436+0000e140@4307
3437+0000e1c0@4308
3438+000041c0@4309
3439+0000c1c0@4310
3440+0000d140@4311
3441+0000d1c0@4312
3442+000071c2@4314
3443+0000f1c2@4315
3444+0000f99a@4316
3445+0000799a@4318
3446+0000e99a@4319
3447+0000ebfe@4320
3448+0000eb7e@4322
3449+00006bfc@4323
3450+0000ebfc@4324
3451+0000effc@4325
3452+0000ef7c@4326
3453+0000effc@4327
3454+00004ffc@4328
3455+0000cffc@4329
3456+0000dffc@4330
3457+00007ffe@4332
3458+0000ff7e@4333
3459+0000f99e@4334
3460+0000791e@4337
3461+0000e99e@4338
3462+0000ebf2@4339
3463+0000eb72@4341
3464+00006bf0@4342
3465+0000ebf0@4343
3466+0000e1c0@4344
3467+000041c0@4346
3468+0000c1c0@4347
3469+0000c140@4348
3470+0000d1c0@4349
3471+000071c2@4351
3472+0000f142@4352
3473+0000f99e@4353
3474+0000691e@4356
3475+0000ebfe@4357
3476+0000ebf6@4358
3477+00006bf6@4360
3478+0000ebf4@4361
3479+0000effc@4362
3480+0000ef7c@4363
3481+0000effc@4364
3482+00004ffc@4365
3483+0000cffc@4366
3484+0000df7c@4367
3485+0000dffc@4368
3486+00007ffe@4370
3487+0000fffe@4371
3488+0000f99e@4372
3489+0000799e@4374
3490+0000e99e@4375
3491+0000ebfa@4376
3492+0000eb7a@4378
3493+00006bf8@4379
3494+0000ebf8@4380
3495+0000e140@4381
3496+0000e1c0@4382
3497+0000c1c0@4384
3498+0000d1c0@4386
3499+000071c2@4388
3500+0000f142@4389
3501+0000f99e@4390
3502+0000791e@4393
3503+0000e99e@4394
3504+0000ebfe@4395
3505+0000eb7e@4397
3506+0000ebfc@4398
3507+0000effc@4399
3508+0000ef7c@4400
3509+0000effc@4401
3510+00004ffc@4402
3511+0000cffc@4403
3512+0000df7c@4404
3513+0000dffc@4405
3514+00007ffe@4407
3515+0000ff7e@4408
3516+0000f9a2@4409
3517+0000e9a2@4412
3518+0000ebf2@4413
3519+0000eb72@4415
3520+00006bf2@4416
3521+0000ebf0@4417
3522+0000e1c0@4418
3523+0000e140@4419
3524+0000e1c0@4420
3525+000041c0@4421
3526+0000c1c0@4422
3527+0000d140@4423
3528+0000d1c0@4424
3529+000071c0@4425
3530+0000f142@4426
3531+0000f962@4427
3532+0000f9a2@4428
3533+00007922@4430
3534+0000e9a2@4431
3535+0000ebf6@4432
3536+0000eb76@4434
3537+00006bf4@4435
3538+0000ebf4@4436
3539+0000effc@4437
3540+00006ffc@4439
3541+0000cffc@4440
3542+0000cf7c@4441
3543+0000dffc@4442
3544+00007ffe@4444
3545+0000ff7e@4445
3546+0000f922@4446
3547+0000f9a2@4447
3548+00007922@4449
3549+0000e9a2@4450
3550+0000ebfa@4451
3551+00006bfa@4453
3552+0000ebf8@4454
3553+0000ebc0@4455
3554+0000e140@4456
3555+0000e1c0@4457
3556+000041c0@4458
3557+0000c1c0@4459
3558+0000d140@4460
3559+0000d1c0@4461
3560+000071c2@4463
3561+0000f1c2@4464
3562+0000f9a2@4465
3563+000079a2@4467
3564+0000e9a2@4468
3565+0000ebfe@4469
3566+0000eb7e@4471
3567+00006bfc@4472
3568+0000ebfc@4473
3569+0000effc@4474
3570+0000ef7c@4475
3571+0000effc@4476
3572+00004ffc@4477
3573+0000cffc@4478
3574+0000dffc@4479
3575+00007ffe@4481
3576+0000ff7e@4482
3577+0000f9a6@4483
3578+00007926@4486
3579+0000e9a6@4487
3580+0000ebf2@4488
3581+0000eb72@4490
3582+00006bf0@4491
3583+0000ebf0@4492
3584+0000e1c0@4493
3585+000041c0@4495
3586+0000c1c0@4496
3587+0000c140@4497
3588+0000d1c0@4498
3589+000071c2@4500
3590+0000f142@4501
3591+0000f9a6@4502
3592+00007926@4505
3593+0000ebf6@4506
3594+00006bf6@4509
3595+0000ebf4@4510
3596+0000effc@4511
3597+0000ef7c@4512
3598+0000effc@4513
3599+00004ffc@4514
3600+0000cffc@4515
3601+0000df7c@4516
3602+0000dffc@4517
3603+00007ffe@4519
3604+0000fffe@4520
3605+0000f9a6@4521
3606+000079a6@4523
3607+0000e9a6@4524
3608+0000ebfa@4525
3609+0000eb7a@4527
3610+00006bf8@4528
3611+0000ebf8@4529
3612+0000e140@4530
3613+0000e1c0@4531
3614+0000c1c0@4533
3615+0000d1c0@4535
3616+000071c2@4537
3617+0000f142@4538
3618+0000f9a6@4539
3619+00007926@4542
3620+0000e9a6@4543
3621+0000ebfe@4544
3622+0000eb7e@4546
3623+0000ebfc@4547
3624+0000effc@4548
3625+0000ef7c@4549
3626+0000effc@4550
3627+00004ffc@4551
3628+0000cffc@4552
3629+0000df7c@4553
3630+0000dffc@4554
3631+00007ffe@4556
3632+0000ff7e@4557
3633+0000f9aa@4558
3634+0000e9aa@4561
3635+0000ebf2@4562
3636+0000eb72@4564
3637+00006bf2@4565
3638+0000ebf0@4566
3639+0000e1c0@4567
3640+0000e140@4568
3641+0000e1c0@4569
3642+000041c0@4570
3643+0000c1c0@4571
3644+0000d140@4572
3645+0000d1c0@4573
3646+000071c2@4574
3647+0000f142@4575
3648+0000f96a@4576
3649+0000f9aa@4577
3650+0000792a@4579
3651+0000e9aa@4580
3652+0000ebf6@4581
3653+0000eb76@4583
3654+00006bf4@4584
3655+0000ebf4@4585
3656+0000effc@4586
3657+00006ffc@4588
3658+0000cffc@4589
3659+0000cf7c@4590
3660+0000dffc@4591
3661+00007ffe@4593
3662+0000ff7e@4594
3663+0000f92a@4595
3664+0000f9aa@4596
3665+0000792a@4598
3666+0000e9aa@4599
3667+0000ebfa@4600
3668+00006bfa@4602
3669+0000ebf8@4603
3670+0000ebc0@4604
3671+0000e140@4605
3672+0000e1c0@4606
3673+000041c0@4607
3674+0000c1c0@4608
3675+0000d140@4609
3676+0000d1c0@4610
3677+000071c2@4612
3678+0000f1c2@4613
3679+0000f9aa@4614
3680+000079aa@4616
3681+0000e9aa@4617
3682+0000ebfe@4618
3683+0000eb7e@4620
3684+00006bfc@4621
3685+0000ebfc@4622
3686+0000effc@4623
3687+0000ef7c@4624
3688+0000effc@4625
3689+00004ffc@4626
3690+0000cffc@4627
3691+0000dffc@4628
3692+00007ffe@4630
3693+0000ff7e@4631
3694+0000f9aa@4632
3695+00007928@4635
3696+0000f9a8@4636
3697+0000fbfc@4637
3698+0000ebfc@4638
3699+0000eb7c@4639
3700+00006bfc@4640
3701+0000ebfc@4641
3702+00006bfc@4644
3703+0000ebfc@4645
3704+0000fb7c@4646
3705+0000fbfc@4647
3706+00007bfe@4649
3707+0000fb7e@4650
3708+0000f9ae@4651
3709+0000692e@4654
3710+0000ebfe@4655
3711+0000ebf2@4656
3712+0000eb72@4657
3713+00006bf2@4658
3714+0000ebf0@4659
3715+0000e1c0@4660
3716+0000e140@4661
3717+0000e1c0@4662
3718+000041c0@4663
3719+0000c1c0@4664
3720+0000d140@4665
3721+0000d1c0@4666
3722+000071c2@4668
3723+0000f96e@4669
3724+0000f9ae@4670
3725+0000792e@4672
3726+0000e9ae@4673
3727+0000ebf6@4674
3728+0000eb76@4676
3729+00006bf4@4677
3730+0000ebf4@4678
3731+0000effc@4679
3732+0000ef7c@4680
3733+0000effc@4681
3734+0000cffc@4682
3735+0000cf7c@4683
3736+0000dffc@4684
3737+00007ffe@4686
3738+0000ff7e@4687
3739+0000f9ae@4688
3740+0000792e@4691
3741+0000e9ae@4692
3742+0000ebfa@4693
3743+0000ebf8@4696
3744+0000e140@4698
3745+0000e1c0@4699
3746+000041c0@4700
3747+0000c1c0@4701
3748+0000d140@4702
3749+0000d1c0@4703
3750+000071c2@4705
3751+0000f142@4706
3752+0000f9ae@4707
3753+000079ae@4709
3754+0000e9ae@4710
3755+0000ebfe@4711
3756+0000eb7e@4713
3757+00006bfe@4714
3758+0000ebfc@4715
3759+0000effc@4716
3760+0000ef7c@4717
3761+0000effc@4718
3762+00004ffc@4719
3763+0000cffc@4720
3764+0000dffc@4721
3765+00007ffe@4723
3766+0000ff7e@4724
3767+0000fffe@4725
3768+0000f9b2@4726
3769+00007932@4728
3770+0000e9b2@4729
3771+0000ebf2@4730
3772+0000eb72@4732
3773+00006bf0@4733
3774+0000ebf0@4734
3775+0000e140@4735
3776+0000e1c0@4736
3777+000061c0@4737
3778+0000c1c0@4738
3779+0000c140@4739
3780+0000d1c0@4740
3781+000071c2@4742
3782+0000f142@4743
3783+0000f9b2@4744
3784+00007932@4747
3785+0000e9b2@4748
3786+0000ebf6@4749
3787+00006bf6@4751
3788+0000ebf4@4752
3789+0000effc@4753
3790+0000ef7c@4754
3791+0000effc@4755
3792+00004ffc@4756
3793+0000cffc@4757
3794+0000df7c@4758
3795+0000dffc@4759
3796+00007ffe@4761
3797+0000fffe@4762
3798+0000f9b2@4763
3799+000079b2@4765
3800+0000e9b2@4766
3801+0000ebfa@4767
3802+0000eb7a@4769
3803+00006bf8@4770
3804+0000ebf8@4771
3805+0000e140@4772
3806+0000e1c0@4774
3807+000041c0@4775
3808+0000c1c0@4776
3809+0000d1c0@4777
3810+000071c2@4779
3811+0000f142@4780
3812+0000f9b2@4781
3813+00007932@4784
3814+0000e9b2@4785
3815+0000ebfe@4786
3816+0000eb7e@4788
3817+00006bfc@4789
3818+0000effc@4790
3819+00004ffc@4793
3820+0000cffc@4794
3821+0000cf7c@4795
3822+0000dffc@4796
3823+00007ffe@4798
3824+0000ff7e@4799
3825+0000f936@4800
3826+0000f9b6@4801
3827+0000e936@4803
3828+0000ebf6@4804
3829+0000ebf2@4805
3830+0000eb72@4806
3831+00006bf2@4807
3832+0000ebf0@4808
3833+0000e1c0@4809
3834+0000e140@4810
3835+0000e1c0@4811
3836+000041c0@4812
3837+0000c1c0@4813
3838+0000d140@4814
3839+0000d1c0@4815
3840+0000f1c2@4817
3841+0000f976@4818
3842+0000f9b6@4819
3843+00007936@4821
3844+0000e9b6@4822
3845+0000ebf6@4823
3846+0000eb76@4825
3847+00006bf4@4826
3848+0000ebf4@4827
3849+0000effc@4828
3850+0000ef7c@4829
3851+0000effc@4830
3852+0000cffc@4831
3853+0000cf7c@4832
3854+0000dffc@4833
3855+00007ffe@4835
3856+0000ff7e@4836
3857+0000f9b6@4837
3858+00007936@4840
3859+0000e9b6@4841
3860+0000ebfa@4842
3861+0000ebf8@4845
3862+0000e140@4847
3863+0000e1c0@4848
3864+000041c0@4849
3865+0000c1c0@4850
3866+0000d140@4851
3867+0000d1c0@4852
3868+000071c2@4854
3869+0000f142@4855
3870+0000f9b6@4856
3871+000079b6@4858
3872+0000e9b6@4859
3873+0000ebfe@4860
3874+0000eb7e@4862
3875+00006bfe@4863
3876+0000ebfc@4864
3877+0000effc@4865
3878+0000ef7c@4866
3879+0000effc@4867
3880+00004ffc@4868
3881+0000cffc@4869
3882+0000dffc@4870
3883+00007ffe@4872
3884+0000ff7e@4873
3885+0000fbfe@4874
3886+0000f9ba@4875
3887+0000793a@4877
3888+0000e9ba@4878
3889+0000ebf2@4879
3890+0000eb72@4881
3891+00006bf0@4882
3892+0000ebf0@4883
3893+0000e140@4884
3894+0000e1c0@4885
3895+000061c0@4886
3896+0000c1c0@4887
3897+0000c140@4888
3898+0000d1c0@4889
3899+000071c2@4891
3900+0000f142@4892
3901+0000f9ba@4893
3902+0000793a@4896
3903+0000e9ba@4897
3904+0000ebf6@4898
3905+00006bf6@4900
3906+0000ebf4@4901
3907+0000effc@4902
3908+0000ef7c@4903
3909+0000effc@4904
3910+00004ffc@4905
3911+0000cffc@4906
3912+0000df7c@4907
3913+0000dffc@4908
3914+00007ffe@4910
3915+0000fffe@4911
3916+0000f9ba@4912
3917+000079ba@4914
3918+0000e9ba@4915
3919+0000ebfa@4916
3920+0000eb7a@4918
3921+00006bf8@4919
3922+0000ebf8@4920
3923+0000e140@4921
3924+0000e1c0@4923
3925+000041c0@4924
3926+0000c1c0@4925
3927+0000d1c0@4926
3928+000071c2@4928
3929+0000f142@4929
3930+0000f9fa@4930
3931+0000f9ba@4931
3932+0000793a@4933
3933+0000e9ba@4934
3934+0000ebfe@4935
3935+0000eb7e@4937
3936+00006bfc@4938
3937+0000effc@4939
3938+00004ffc@4942
3939+0000cffc@4943
3940+0000cf7c@4944
3941+0000dffc@4945
3942+00007ffe@4947
3943+0000ff7e@4948
3944+0000f9be@4949
3945+0000e93e@4952
3946+0000ebfe@4953
3947+0000ebf2@4954
3948+0000eb72@4955
3949+00006bf2@4956
3950+0000ebf0@4957
3951+0000e1c0@4958
3952+0000e140@4959
3953+0000e1c0@4960
3954+000041c0@4961
3955+0000c1c0@4962
3956+0000d140@4963
3957+0000d1c0@4964
3958+0000f1c2@4966
3959+0000f97e@4967
3960+0000f9be@4968
3961+0000793e@4970
3962+0000e9be@4971
3963+0000ebf6@4972
3964+0000eb76@4974
3965+00006bf4@4975
3966+0000ebf4@4976
3967+0000effc@4977
3968+0000ef7c@4978
3969+0000effc@4979
3970+0000cffc@4980
3971+0000cf7c@4981
3972+0000dffc@4982
3973+00007ffe@4984
3974+0000ff7e@4985
3975+0000f9be@4986
3976+0000793e@4989
3977+0000e9be@4990
3978+0000ebfa@4991
3979+0000ebf8@4994
3980+0000e140@4996
3981+0000e1c0@4997
3982+000041c0@4998
3983+0000c1c0@4999
3984+0000d140@5000
3985+0000d1c0@5001
3986+000071c2@5003
3987+0000f142@5004
3988+0000f9be@5005
3989+000079be@5007
3990+0000e9be@5008
3991+0000ebfe@5009
3992+0000eb7e@5011
3993+00006bfe@5012
3994+0000ebfc@5013
3995+0000effc@5014
3996+0000ef7c@5015
3997+0000effc@5016
3998+00004ffc@5017
3999+0000cffc@5018
4000+0000dffc@5019
4001+00007ffe@5021
4002+0000ff7e@5022
4003+0000fffe@5023
4004+0000fb82@5024
4005+00007b02@5026
4006+0000eb82@5027
4007+0000ebf2@5028
4008+0000eb72@5030
4009+00006bf0@5031
4010+0000ebf0@5032
4011+0000e140@5033
4012+0000e1c0@5034
4013+000061c0@5035
4014+0000c1c0@5036
4015+0000c140@5037
4016+0000d1c0@5038
4017+000071c2@5040
4018+0000f142@5041
4019+0000fb82@5042
4020+00007b02@5045
4021+0000eb82@5046
4022+0000ebf6@5047
4023+00006bf6@5049
4024+0000ebf4@5050
4025+0000effc@5051
4026+0000ef7c@5052
4027+0000effc@5053
4028+00004ffc@5054
4029+0000cffc@5055
4030+0000df7c@5056
4031+0000dffc@5057
4032+00007ffe@5059
4033+0000fffe@5060
4034+0000fb82@5061
4035+00007b82@5063
4036+0000eb82@5064
4037+0000ebfa@5065
4038+0000eb7a@5067
4039+00006bf8@5068
4040+0000ebf8@5069
4041+0000e140@5070
4042+0000e1c0@5072
4043+000041c0@5073
4044+0000c1c0@5074
4045+0000d1c0@5075
4046+000071c2@5077
4047+0000f142@5078
4048+0000fb02@5079
4049+0000fb82@5080
4050+00007b02@5082
4051+0000eb82@5083
4052+0000ebfe@5084
4053+0000eb7e@5085
4054+00006bfc@5087
4055+0000effc@5088
4056+00004ffc@5091
4057+0000cffc@5092
4058+0000df7c@5093
4059+0000dffc@5094
4060+00007ffe@5096
4061+0000ff7e@5097
4062+0000fb86@5098
4063+0000eb86@5101
4064+0000ebf6@5102
4065+0000ebf2@5103
4066+0000eb72@5104
4067+00006bf2@5105
4068+0000ebf0@5106
4069+0000e1c0@5107
4070+0000e140@5108
4071+0000e1c0@5109
4072+000041c0@5110
4073+0000c1c0@5111
4074+0000d140@5112
4075+0000d1c0@5113
4076+0000f1c2@5115
4077+0000fbc6@5116
4078+0000fb86@5117
4079+00007b06@5119
4080+0000eb86@5120
4081+0000ebf6@5121
4082+0000eb76@5123
4083+00006bf4@5124
4084+0000ebf4@5125
4085+0000effc@5126
4086+0000ef7c@5127
4087+0000effc@5128
4088+0000cffc@5129
4089+0000cf7c@5130
4090+0000dffc@5131
4091+00007ffe@5133
4092+0000ff7e@5134
4093+0000fb06@5135
4094+0000fb86@5136
4095+00007b06@5138
4096+0000eb86@5139
4097+0000ebfa@5140
4098+0000ebf8@5143
4099+0000e140@5145
4100+0000e1c0@5146
4101+000041c0@5147
4102+0000c1c0@5148
4103+0000d140@5149
4104+0000d1c0@5150
4105+000071c2@5152
4106+0000f142@5153
4107+0000fb86@5154
4108+00007b86@5156
4109+0000eb86@5157
4110+0000ebfe@5158
4111+0000eb7e@5160
4112+00006bfe@5161
4113+0000ebfc@5162
4114+0000effc@5163
4115+0000ef7c@5164
4116+0000effc@5165
4117+00004ffc@5166
4118+0000cffc@5167
4119+0000dffc@5168
4120+00007ffe@5170
4121+0000ff7e@5171
4122+0000fffe@5172
4123+0000fb8a@5173
4124+00007b0a@5175
4125+0000eb8a@5176
4126+0000ebf2@5177
4127+0000eb72@5179
4128+00006bf0@5180
4129+0000ebf0@5181
4130+0000e140@5182
4131+0000e1c0@5183
4132+000061c0@5184
4133+0000c1c0@5185
4134+0000c140@5186
4135+0000d1c0@5187
4136+000071c2@5189
4137+0000f142@5190
4138+0000fb8a@5191
4139+00007b0a@5194
4140+0000eb8a@5195
4141+0000ebf6@5196
4142+00006bf6@5198
4143+0000ebf4@5199
4144+0000effc@5200
4145+0000ef7c@5201
4146+0000effc@5202
4147+00004ffc@5203
4148+0000cffc@5204
4149+0000df7c@5205
4150+0000dffc@5206
4151+00007ffe@5208
4152+0000fffe@5209
4153+0000fb8a@5210
4154+00007b8a@5212
4155+0000eb8a@5213
4156+0000ebfa@5214
4157+0000eb7a@5216
4158+00006bf8@5217
4159+0000ebf8@5218
4160+0000e140@5219
4161+0000e1c0@5221
4162+000041c0@5222
4163+0000c1c0@5223
4164+0000d1c0@5224
4165+000071c2@5226
4166+0000f142@5227
4167+0000fb0a@5228
4168+0000fb8a@5229
4169+00007b08@5231
4170+0000fb88@5232
4171+0000fbf8@5233
4172+0000ebf8@5234
4173+0000eb78@5235
4174+00006bf8@5236
4175+0000effc@5237
4176+0000eb7c@5238
4177+0000ebfc@5239
4178+00006bfc@5240
4179+0000ebfc@5241
4180+0000fb78@5242
4181+0000fffc@5243
4182+00007bfe@5245
4183+0000ff7e@5246
4184+0000fb8a@5247
4185+0000eb8a@5250
4186+0000ebfe@5251
4187+00006bfe@5254
4188+0000ebfc@5255
4189+0000effc@5256
4190+0000ef7c@5257
4191+0000effc@5258
4192+00004ffc@5259
4193+0000cffc@5260
4194+0000df7c@5261
4195+0000dffc@5262
4196+0000fffe@5264
4197+0000fb8e@5266
4198+00007b8e@5268
4199+0000eb8e@5269
4200+0000ebf2@5270
4201+0000eb72@5272
4202+00006bf0@5273
4203+0000ebf0@5274
4204+0000e140@5275
4205+0000e1c0@5276
4206+0000c1c0@5278
4207+0000d1c0@5280
4208+000071c2@5282
4209+0000f142@5283
4210+0000fb8e@5284
4211+00007b0e@5287
4212+0000eb8e@5288
4213+0000ebf6@5289
4214+0000ebf4@5292
4215+0000effc@5293
4216+0000ef7c@5294
4217+0000effc@5295
4218+00004ffc@5296
4219+0000cffc@5297
4220+0000df7c@5298
4221+0000dffc@5299
4222+00007ffe@5301
4223+0000ff7e@5302
4224+0000fb8e@5303
4225+0000eb8e@5306
4226+0000ebfa@5307
4227+0000eb7a@5309
4228+00006bfa@5310
4229+0000ebf8@5311
4230+0000e140@5312
4231+0000e1c0@5314
4232+000041c0@5315
4233+0000c1c0@5316
4234+0000d140@5317
4235+0000d1c0@5318
4236+000071c2@5319
4237+0000f142@5320
4238+0000fb0e@5321
4239+0000fb8e@5322
4240+00007b0e@5324
4241+0000eb8e@5325
4242+0000ebfe@5326
4243+0000eb7e@5328
4244+00006bfc@5329
4245+0000ebfc@5330
4246+0000effc@5331
4247+00006ffc@5333
4248+0000cffc@5334
4249+0000cf7c@5335
4250+0000dffc@5336
4251+00007ffe@5338
4252+0000ff7e@5339
4253+0000fb12@5340
4254+0000fb92@5341
4255+00007b12@5343
4256+0000eb92@5344
4257+0000ebf2@5345
4258+00006bf2@5347
4259+0000ebf0@5348
4260+0000e9c0@5349
4261+0000e140@5350
4262+0000e1c0@5351
4263+000041c0@5352
4264+0000c1c0@5353
4265+0000d140@5354
4266+0000d1c0@5355
4267+000071c2@5357
4268+0000f1c2@5358
4269+0000fb92@5359
4270+00007b92@5361
4271+0000eb92@5362
4272+0000ebf6@5363
4273+0000eb76@5365
4274+00006bf4@5366
4275+0000ebf4@5367
4276+0000effc@5368
4277+0000ef7c@5369
4278+0000effc@5370
4279+00004ffc@5371
4280+0000cffc@5372
4281+0000dffc@5373
4282+00007ffe@5375
4283+0000ff7e@5376
4284+0000ff92@5377
4285+0000fb92@5378
4286+00007b12@5380
4287+0000eb92@5381
4288+0000ebfa@5382
4289+0000eb7a@5384
4290+00006bf8@5385
4291+0000ebf8@5386
4292+0000e1c0@5387
4293+000041c0@5389
4294+0000c1c0@5390
4295+0000d140@5391
4296+0000d1c0@5392
4297+000071c2@5394
4298+0000f142@5395
4299+0000fb92@5396
4300+0000eb92@5399
4301+0000ebfe@5400
4302+00006bfe@5403
4303+0000ebfc@5404
4304+0000effc@5405
4305+0000ef7c@5406
4306+0000effc@5407
4307+00004ffc@5408
4308+0000cffc@5409
4309+0000df7c@5410
4310+0000dffc@5411
4311+0000fffe@5413
4312+0000fb96@5415
4313+00007b96@5417
4314+0000eb96@5418
4315+0000ebf2@5419
4316+0000eb72@5421
4317+00006bf0@5422
4318+0000ebf0@5423
4319+0000e140@5424
4320+0000e1c0@5425
4321+0000c1c0@5427
4322+0000c140@5428
4323+0000d1c0@5429
4324+000071c2@5431
4325+0000f142@5432
4326+0000fb96@5433
4327+00007b16@5436
4328+0000eb96@5437
4329+0000ebf6@5438
4330+0000ebf4@5441
4331+0000effc@5442
4332+0000ef7c@5443
4333+0000effc@5444
4334+00004ffc@5445
4335+0000cffc@5446
4336+0000df7c@5447
4337+0000dffc@5448
4338+00007ffe@5450
4339+0000ff7e@5451
4340+0000fb96@5452
4341+0000eb96@5455
4342+0000ebfa@5456
4343+0000eb7a@5458
4344+00006bfa@5459
4345+0000ebf8@5460
4346+0000e140@5461
4347+0000e1c0@5463
4348+000041c0@5464
4349+0000c1c0@5465
4350+0000d140@5466
4351+0000d1c0@5467
4352+000071c2@5468
4353+0000f142@5469
4354+0000fb16@5470
4355+0000fb96@5471
4356+00007b16@5473
4357+0000eb96@5474
4358+0000ebfe@5475
4359+0000eb7e@5477
4360+00006bfc@5478
4361+0000ebfc@5479
4362+0000effc@5480
4363+00006ffc@5482
4364+0000cffc@5483
4365+0000cf7c@5484
4366+0000dffc@5485
4367+00007ffe@5487
4368+0000ff7e@5488
4369+0000fb1a@5489
4370+0000fb9a@5490
4371+00007b1a@5492
4372+0000eb9a@5493
4373+0000ebf2@5494
4374+00006bf2@5496
4375+0000ebf0@5497
4376+0000e9c0@5498
4377+0000e140@5499
4378+0000e1c0@5500
4379+000041c0@5501
4380+0000c1c0@5502
4381+0000d140@5503
4382+0000d1c0@5504
4383+000071c2@5506
4384+0000f1c2@5507
4385+0000fb9a@5508
4386+00007b9a@5510
4387+0000eb9a@5511
4388+0000ebf6@5512
4389+0000eb76@5514
4390+00006bf4@5515
4391+0000ebf4@5516
4392+0000effc@5517
4393+0000ef7c@5518
4394+0000effc@5519
4395+00004ffc@5520
4396+0000cffc@5521
4397+0000dffc@5522
4398+00007ffe@5524
4399+0000ff7e@5525
4400+0000fb9a@5526
4401+00007b1a@5529
4402+0000eb9a@5530
4403+0000ebfa@5531
4404+0000eb7a@5533
4405+00006bf8@5534
4406+0000ebf8@5535
4407+0000e1c0@5536
4408+000041c0@5538
4409+0000c1c0@5539
4410+0000d140@5540
4411+0000d1c0@5541
4412+000071c2@5543
4413+0000f142@5544
4414+0000fb9a@5545
4415+0000eb9a@5548
4416+0000ebfe@5549
4417+00006bfe@5552
4418+0000ebfc@5553
4419+0000effc@5554
4420+0000ef7c@5555
4421+0000effc@5556
4422+00004ffc@5557
4423+0000cffc@5558
4424+0000df7c@5559
4425+0000dffc@5560
4426+0000fffe@5562
4427+0000fb9e@5564
4428+00007b9e@5566
4429+0000eb9e@5567
4430+0000ebf2@5568
4431+0000eb72@5570
4432+00006bf0@5571
4433+0000ebf0@5572
4434+0000e140@5573
4435+0000e1c0@5574
4436+0000c1c0@5576
4437+0000c140@5577
4438+0000d1c0@5578
4439+000071c2@5580
4440+0000f142@5581
4441+0000fb9e@5582
4442+00007b1e@5585
4443+0000eb9e@5586
4444+0000ebf6@5587
4445+0000ebf4@5590
4446+0000effc@5591
4447+0000ef7c@5592
4448+0000effc@5593
4449+00004ffc@5594
4450+0000cffc@5595
4451+0000df7c@5596
4452+0000dffc@5597
4453+00007ffe@5599
4454+0000ff7e@5600
4455+0000fb9e@5601
4456+00007b9e@5603
4457+0000eb9e@5604
4458+0000ebfa@5605
4459+0000eb7a@5607
4460+00006bfa@5608
4461+0000ebf8@5609
4462+0000e140@5610
4463+0000e1c0@5612
4464+000041c0@5613
4465+0000c1c0@5614
4466+0000d1c0@5615
4467+000071c2@5617
4468+0000f142@5618
4469+0000fb1e@5619
4470+0000fb9e@5620
4471+00007b1e@5622
4472+0000eb9e@5623
4473+0000ebfe@5624
4474+0000eb7e@5626
4475+00006bfc@5627
4476+0000ebfc@5628
4477+0000effc@5629
4478+00006ffc@5631
4479+0000cffc@5632
4480+0000cf7c@5633
4481+0000dffc@5634
4482+00007ffe@5636
4483+0000ff7e@5637
4484+0000fb22@5638
4485+0000fba2@5639
4486+00007b22@5641
4487+0000eba2@5642
4488+0000ebf2@5643
4489+00006bf2@5645
4490+0000ebf0@5646
4491+0000e9c0@5647
4492+0000e140@5648
4493+0000e1c0@5649
4494+000041c0@5650
4495+0000c1c0@5651
4496+0000d140@5652
4497+0000d1c0@5653
4498+000071c2@5655
4499+0000f1c2@5656
4500+0000fba2@5657
4501+00007ba2@5659
4502+0000eba2@5660
4503+0000ebf6@5661
4504+0000eb76@5663
4505+00006bf4@5664
4506+0000ebf4@5665
4507+0000effc@5666
4508+0000ef7c@5667
4509+0000effc@5668
4510+00004ffc@5669
4511+0000cffc@5670
4512+0000dffc@5671
4513+00007ffe@5673
4514+0000ff7e@5674
4515+0000ffa2@5675
4516+0000fba2@5676
4517+00007b22@5678
4518+0000eba2@5679
4519+0000ebfa@5680
4520+0000eb7a@5682
4521+00006bf8@5683
4522+0000ebf8@5684
4523+0000e1c0@5685
4524+000041c0@5687
4525+0000c1c0@5688
4526+0000c140@5689
4527+0000d1c0@5690
4528+000071c2@5692
4529+0000f142@5693
4530+0000fba2@5694
4531+0000eba2@5697
4532+0000ebfe@5698
4533+00006bfe@5701
4534+0000ebfc@5702
4535+0000effc@5703
4536+0000ef7c@5704
4537+0000effc@5705
4538+00004ffc@5706
4539+0000cffc@5707
4540+0000df7c@5708
4541+0000dffc@5709
4542+0000fffe@5711
4543+0000fba6@5713
4544+00007ba6@5715
4545+0000eba6@5716
4546+0000ebf2@5717
4547+0000eb72@5719
4548+00006bf0@5720
4549+0000ebf0@5721
4550+0000e140@5722
4551+0000e1c0@5723
4552+0000c1c0@5725
4553+0000c140@5726
4554+0000d1c0@5727
4555+000071c2@5729
4556+0000f142@5730
4557+0000fba6@5731
4558+00007b26@5734
4559+0000eba6@5735
4560+0000ebf6@5736
4561+0000ebf4@5739
4562+0000effc@5740
4563+0000ef7c@5741
4564+0000effc@5742
4565+00004ffc@5743
4566+0000cffc@5744
4567+0000df7c@5745
4568+0000dffc@5746
4569+00007ffe@5748
4570+0000ff7e@5749
4571+0000fba6@5750
4572+00007ba6@5752
4573+0000eba6@5753
4574+0000ebfa@5754
4575+0000eb7a@5756
4576+00006bfa@5757
4577+0000ebf8@5758
4578+0000e140@5759
4579+0000e1c0@5761
4580+000041c0@5762
4581+0000c1c0@5763
4582+0000d1c0@5764
4583+000071c2@5766
4584+0000f142@5767
4585+0000fb26@5768
4586+0000fba6@5769
4587+00007b26@5771
4588+0000eba6@5772
4589+0000ebfe@5773
4590+0000eb7e@5775
4591+00006bfc@5776
4592+0000ebfc@5777
4593+0000effc@5778
4594+00006ffc@5780
4595+0000cffc@5781
4596+0000cf7c@5782
4597+0000dffc@5783
4598+00007ffe@5785
4599+0000ff7e@5786
4600+0000fb2a@5787
4601+0000fbaa@5788
4602+00007b2a@5790
4603+0000ebaa@5791
4604+0000ebf2@5792
4605+00006bf2@5794
4606+0000ebf0@5795
4607+0000e9c0@5796
4608+0000e140@5797
4609+0000e1c0@5798
4610+000041c0@5799
4611+0000c1c0@5800
4612+0000d140@5801
4613+0000d1c0@5802
4614+000071c2@5804
4615+0000f1c2@5805
4616+0000fbaa@5806
4617+00007baa@5808
4618+0000ebaa@5809
4619+0000ebf6@5810
4620+0000eb76@5812
4621+00006bf4@5813
4622+0000ebf4@5814
4623+0000effc@5815
4624+0000ef7c@5816
4625+0000effc@5817
4626+00004ffc@5818
4627+0000cffc@5819
4628+0000dffc@5820
4629+00007ffe@5822
4630+0000ff7e@5823
4631+0000fbaa@5824
4632+00007b28@5827
4633+0000fba8@5828
4634+0000fbf4@5829
4635+0000ebf4@5830
4636+0000eb74@5831
4637+00006bf4@5832
4638+0000ebf4@5833
4639+00006bf4@5836
4640+0000ebf4@5837
4641+0000fb74@5838
4642+0000fbf4@5839
4643+00007bf6@5841
4644+0000fb76@5842
4645+0000fbaa@5843
4646+0000ebaa@5846
4647+0000ebfa@5847
4648+0000eb7a@5849
4649+00006bfa@5850
4650+0000ebf8@5851
4651+0000e1c0@5852
4652+0000e140@5853
4653+0000e1c0@5854
4654+000041c0@5855
4655+0000c1c0@5856
4656+0000d140@5857
4657+0000d1c0@5858
4658+0000f1c2@5860
4659+0000fb6a@5861
4660+0000fbaa@5862
4661+00007b2a@5864
4662+0000ebaa@5865
4663+0000ebfe@5866
4664+0000eb7e@5868
4665+00006bfc@5869
4666+0000ebfc@5870
4667+0000effc@5871
4668+0000ef7c@5872
4669+0000effc@5873
4670+0000cffc@5874
4671+0000cf7c@5875
4672+0000dffc@5876
4673+00007ffe@5878
4674+0000ff7e@5879
4675+0000fbae@5880
4676+00007b2e@5883
4677+0000ebae@5884
4678+0000ebf2@5885
4679+0000ebf0@5888
4680+0000e140@5890
4681+0000e1c0@5891
4682+000041c0@5892
4683+0000c1c0@5893
4684+0000d140@5894
4685+0000d1c0@5895
4686+000071c2@5897
4687+0000f142@5898
4688+0000fbae@5899
4689+00007bae@5901
4690+0000ebae@5902
4691+0000ebf6@5903
4692+0000eb76@5905
4693+00006bf6@5906
4694+0000ebf4@5907
4695+0000effc@5908
4696+0000ef7c@5909
4697+0000effc@5910
4698+00004ffc@5911
4699+0000cffc@5912
4700+0000dffc@5913
4701+00007ffe@5915
4702+0000ff7e@5916
4703+0000fbbe@5917
4704+0000fbae@5918
4705+00007b2e@5920
4706+0000fbae@5921
4707+0000ebfa@5922
4708+0000eb7a@5924
4709+00006bf8@5925
4710+0000ebf8@5926
4711+0000e1c0@5927
4712+000061c0@5929
4713+0000c1c0@5930
4714+0000c140@5931
4715+0000d1c0@5932
4716+000071c2@5934
4717+0000f142@5935
4718+0000fbae@5936
4719+00007b2e@5939
4720+0000ebae@5940
4721+0000ebfe@5941
4722+00006bfe@5943
4723+0000ebfc@5944
4724+0000effc@5945
4725+0000ef7c@5946
4726+0000effc@5947
4727+00004ffc@5948
4728+0000cffc@5949
4729+0000df7c@5950
4730+0000dffc@5951
4731+00007ffe@5953
4732+0000fffe@5954
4733+0000fbb2@5955
4734+00007bb2@5957
4735+0000ebb2@5958
4736+0000ebf2@5959
4737+0000eb72@5961
4738+00006bf0@5962
4739+0000ebf0@5963
4740+0000e140@5964
4741+0000e1c0@5966
4742+000041c0@5967
4743+0000c1c0@5968
4744+0000d1c0@5969
4745+000071c2@5971
4746+0000f142@5972
4747+0000fbb2@5973
4748+00007b32@5976
4749+0000ebb2@5977
4750+0000ebf6@5978
4751+0000eb76@5980
4752+00006bf4@5981
4753+0000effc@5982
4754+0000ef7c@5983
4755+0000effc@5984
4756+00004ffc@5985
4757+0000cffc@5986
4758+0000df7c@5987
4759+0000dffc@5988
4760+00007ffe@5990
4761+0000ff7e@5991
4762+0000fbb2@5992
4763+0000ebb2@5995
4764+0000ebfa@5996
4765+0000eb7a@5998
4766+00006bfa@5999
4767+0000ebf8@6000
4768+0000e1c0@6001
4769+0000e140@6002
4770+0000e1c0@6003
4771+000041c0@6004
4772+0000c1c0@6005
4773+0000d140@6006
4774+0000d1c0@6007
4775+0000f1c2@6009
4776+0000fb72@6010
4777+0000fbb2@6011
4778+00007b32@6013
4779+0000ebb2@6014
4780+0000ebfe@6015
4781+0000eb7e@6017
4782+00006bfc@6018
4783+0000ebfc@6019
4784+0000effc@6020
4785+0000ef7c@6021
4786+0000effc@6022
4787+0000cffc@6023
4788+0000cf7c@6024
4789+0000dffc@6025
4790+00007ffe@6027
4791+0000ff7e@6028
4792+0000fbb6@6029
4793+00007b36@6032
4794+0000ebb6@6033
4795+0000ebf2@6034
4796+0000ebf0@6037
4797+0000e140@6039
4798+0000e1c0@6040
4799+000041c0@6041
4800+0000c1c0@6042
4801+0000d140@6043
4802+0000d1c0@6044
4803+000071c2@6046
4804+0000f142@6047
4805+0000fbb6@6048
4806+00007bb6@6050
4807+0000ebb6@6051
4808+0000ebf6@6052
4809+0000eb76@6054
4810+00006bf6@6055
4811+0000ebf4@6056
4812+0000effc@6057
4813+0000ef7c@6058
4814+0000effc@6059
4815+00004ffc@6060
4816+0000cffc@6061
4817+0000dffc@6062
4818+00007ffe@6064
4819+0000ff7e@6065
4820+0000fbbe@6066
4821+0000fbb6@6067
4822+00007b36@6069
4823+0000fbb6@6070
4824+0000ebfa@6071
4825+0000eb7a@6073
4826+00006bf8@6074
4827+0000ebf8@6075
4828+0000e1c0@6076
4829+000061c0@6078
4830+0000c1c0@6079
4831+0000c140@6080
4832+0000d1c0@6081
4833+000071c2@6083
4834+0000f142@6084
4835+0000fbb6@6085
4836+00007b36@6088
4837+0000ebb6@6089
4838+0000ebfe@6090
4839+00006bfe@6092
4840+0000ebfc@6093
4841+0000effc@6094
4842+0000ef7c@6095
4843+0000effc@6096
4844+00004ffc@6097
4845+0000cffc@6098
4846+0000df7c@6099
4847+0000dffc@6100
4848+00007ffe@6102
4849+0000fffe@6103
4850+0000fbba@6104
4851+00007bba@6106
4852+0000ebba@6107
4853+0000ebf2@6108
4854+0000eb72@6110
4855+00006bf0@6111
4856+0000ebf0@6112
4857+0000e140@6113
4858+0000e1c0@6115
4859+000041c0@6116
4860+0000c1c0@6117
4861+0000d1c0@6118
4862+000071c2@6120
4863+0000f142@6121
4864+0000fbba@6122
4865+00007b3a@6125
4866+0000ebba@6126
4867+0000ebf6@6127
4868+0000eb76@6129
4869+00006bf4@6130
4870+0000effc@6131
4871+0000ef7c@6132
4872+0000effc@6133
4873+00004ffc@6134
4874+0000cffc@6135
4875+0000df7c@6136
4876+0000dffc@6137
4877+00007ffe@6139
4878+0000ff7e@6140
4879+0000fbba@6141
4880+0000ebba@6144
4881+0000ebfa@6145
4882+0000eb7a@6147
4883+00006bfa@6148
4884+0000ebf8@6149
4885+0000e1c0@6150
4886+0000e140@6151
4887+0000e1c0@6152
4888+000041c0@6153
4889+0000c1c0@6154
4890+0000d140@6155
4891+0000d1c0@6156
4892+0000f1c2@6158
4893+0000fb7a@6159
4894+0000fbba@6160
4895+00007b3a@6162
4896+0000ebba@6163
4897+0000ebfe@6164
4898+0000eb7e@6166
4899+00006bfc@6167
4900+0000ebfc@6168
4901+0000effc@6169
4902+0000ef7c@6170
4903+0000effc@6171
4904+0000cffc@6172
4905+0000cf7c@6173
4906+0000dffc@6174
4907+00007ffe@6176
4908+0000ff7e@6177
4909+0000fbbe@6178
4910+00007b3e@6181
4911+0000ebbe@6182
4912+0000ebf2@6183
4913+0000ebf0@6186
4914+0000e140@6188
4915+0000e1c0@6189
4916+000041c0@6190
4917+0000c1c0@6191
4918+0000d140@6192
4919+0000d1c0@6193
4920+000071c2@6195
4921+0000f142@6196
4922+0000fbbe@6197
4923+00007bbe@6199
4924+0000ebbe@6200
4925+0000ebf6@6201
4926+0000eb76@6203
4927+00006bf6@6204
4928+0000ebf4@6205
4929+0000effc@6206
4930+0000ef7c@6207
4931+0000effc@6208
4932+00004ffc@6209
4933+0000cffc@6210
4934+0000dffc@6211
4935+00007ffe@6213
4936+0000ff7e@6214
4937+0000fbbe@6215
4938+00007b3e@6218
4939+0000ebbe@6219
4940+0000ebfa@6220
4941+0000eb7a@6222
4942+00006bf8@6223
4943+0000ebf8@6224
4944+0000e1c0@6225
4945+000061c0@6227
4946+0000c1c0@6228
4947+0000c140@6229
4948+0000d1c0@6230
4949+000071c2@6232
4950+0000f142@6233
4951+0000fbbe@6234
4952+00007b3e@6237
4953+0000ebbe@6238
4954+0000ebfe@6239
4955+00006bfe@6241
4956+0000ebfc@6242
4957+0000effc@6243
4958+0000ef7c@6244
4959+0000effc@6245
4960+00004ffc@6246
4961+0000cffc@6247
4962+0000df7c@6248
4963+0000dffc@6249
4964+00007ffe@6251
4965+0000fffe@6252
4966+0000fd82@6253
4967+00007d82@6255
4968+0000ed82@6256
4969+0000ebf2@6257
4970+0000eb72@6259
4971+00006bf0@6260
4972+0000ebf0@6261
4973+0000e140@6262
4974+0000e1c0@6264
4975+000041c0@6265
4976+0000c1c0@6266
4977+0000d1c0@6267
4978+000071c2@6269
4979+0000f142@6270
4980+0000fd02@6271
4981+0000fd82@6272
4982+00007d02@6274
4983+0000ed82@6275
4984+0000ebf6@6276
4985+0000eb76@6278
4986+00006bf4@6279
4987+0000effc@6280
4988+0000ef7c@6281
4989+0000effc@6282
4990+00004ffc@6283
4991+0000cffc@6284
4992+0000df7c@6285
4993+0000dffc@6286
4994+00007ffe@6288
4995+0000ff7e@6289
4996+0000fd82@6290
4997+0000ed82@6293
4998+0000effa@6294
4999+0000ebfa@6295
5000+0000eb7a@6296
5001+00006bfa@6297
5002+0000ebf8@6298
5003+0000e1c0@6299
5004+0000e140@6300
5005+0000e1c0@6301
5006+000041c0@6302
5007+0000c1c0@6303
5008+0000d140@6304
5009+0000d1c0@6305
5010+0000f1c0@6306
5011+0000f1c2@6307
5012+0000fdc2@6308
5013+0000fd82@6309
5014+00007d02@6311
5015+0000ed82@6312
5016+0000ebfe@6313
5017+0000eb7e@6315
5018+00006bfc@6316
5019+0000ebfc@6317
5020+0000effc@6318
5021+0000ef7c@6319
5022+0000effc@6320
5023+0000cffc@6321
5024+0000cf7c@6322
5025+0000dffc@6323
5026+00007ffe@6325
5027+0000ff7e@6326
5028+0000fd06@6327
5029+0000fd86@6328
5030+00007d06@6330
5031+0000ed86@6331
5032+0000ebf2@6332
5033+0000ebf0@6335
5034+0000e140@6337
5035+0000e1c0@6338
5036+000041c0@6339
5037+0000c1c0@6340
5038+0000d140@6341
5039+0000d1c0@6342
5040+000071c2@6344
5041+0000f142@6345
5042+0000fd86@6346
5043+00007d86@6348
5044+0000ed86@6349
5045+0000ebf6@6350
5046+0000eb76@6352
5047+00006bf6@6353
5048+0000ebf4@6354
5049+0000effc@6355
5050+0000ef7c@6356
5051+0000effc@6357
5052+00004ffc@6358
5053+0000cffc@6359
5054+0000dffc@6360
5055+00007ffe@6362
5056+0000ff7e@6363
5057+0000ff86@6364
5058+0000fc86@6365
5059+00007c06@6367
5060+0000ec86@6368
5061+0000eafa@6369
5062+0000ea7a@6371
5063+00006a78@6372
5064+0000eaf8@6373
5065+0000e0c0@6374
5066+00006040@6376
5067+0000c040@6377
5068+0000c0c0@6378
5069+0000d0c0@6379
5070+0000d040@6380
5071+00007042@6381
5072+0000f0c2@6382
5073+0000fc86@6383
5074+0000fc06@6385
5075+00007c06@6386
5076+0000ec86@6387
5077+0000eafe@6388
5078+00006a7e@6390
5079+0000ea7c@6391
5080+0000eefc@6392
5081+0000ee7c@6394
5082+00004e7c@6395
5083+0000cefc@6396
5084+0000defc@6397
5085+0000de7c@6399
5086+00007e7e@6400
5087+0000fefe@6401
5088+0000fc8a@6402
5089+00007c0a@6404
5090+0000ec8a@6405
5091+0000eaf2@6406
5092+0000ea72@6408
5093+00006a70@6409
5094+0000eaf0@6410
5095+0000e0c0@6411
5096+0000e040@6413
5097+00004040@6414
5098+0000c0c0@6415
5099+0000d0c0@6416
5100+00007042@6418
5101+0000f042@6419
5102+0000fc8a@6420
5103+0000fc0a@6422
5104+00007c0a@6423
5105+0000ec8a@6424
5106+0000eaf6@6425
5107+0000ea76@6427
5108+00006a74@6428
5109+0000eefc@6429
5110+00004e7c@6432
5111+0000cefc@6433
5112+0000defc@6434
5113+0000de7c@6436
5114+00007e7e@6437
5115+0000fefe@6438
5116+0000fc8a@6439
5117+0000ec8a@6442
5118+0000eefa@6443
5119+0000eafa@6444
5120+00006afa@6446
5121+0000eaf8@6447
5122+0000e040@6448
5123+0000e0c0@6450
5124+000040c0@6451
5125+0000c0c0@6452
5126+0000d040@6453
5127+0000f0c0@6455
5128+0000f0c2@6456
5129+0000fc4a@6457
5130+0000fc0a@6458
5131+0000fc8a@6459
5132+00007c8a@6460
5133+0000ec8a@6461
5134+0000eafe@6462
5135+0000ea7e@6463
5136+0000eafe@6464
5137+00006afc@6465
5138+0000eafc@6466
5139+0000ee7c@6467
5140+0000eefc@6469
5141+0000cefc@6470
5142+0000de7c@6472
5143+00007efe@6474
5144+0000fefe@6475
5145+0000fc0e@6476
5146+0000fc8e@6478
5147+00007c8e@6479
5148+0000ec8e@6480
5149+0000ea72@6481
5150+0000eaf2@6483
5151+0000eaf0@6484
5152+0000e040@6486
5153+000040c0@6488
5154+0000c0c0@6489
5155+0000d040@6490
5156+0000d0c0@6492
5157+000070c2@6493
5158+0000f0c2@6494
5159+0000fc0e@6495
5160+00007c8e@6497
5161+0000ec8e@6498
5162+0000eaf6@6499
5163+0000ea76@6500
5164+0000eaf6@6501
5165+00006af6@6502
5166+0000eaf4@6503
5167+0000ee7c@6504
5168+0000eefc@6506
5169+00004efc@6507
5170+0000cefc@6508
5171+0000de7c@6509
5172+00007efe@6511
5173+0000fefe@6512
5174+0000fe8e@6513
5175+0000fc0e@6514
5176+0000fc8e@6515
5177+00007c8e@6516
5178+0000ec8e@6517
5179+0000eafa@6518
5180+00006af8@6521
5181+0000ea78@6522
5182+0000e0c0@6523
5183+000060c0@6525
5184+0000c040@6526
5185+0000d0c0@6528
5186+00007042@6530
5187+0000f042@6531
5188+0000fc8e@6532
5189+00007c0e@6535
5190+0000ec0e@6536
5191+0000eafe@6537
5192+00006afe@6539
5193+0000ea7c@6540
5194+0000ee7c@6541
5195+0000eefc@6542
5196+00004e7c@6544
5197+0000ce7c@6545
5198+0000defc@6546
5199+00007e7e@6549
5200+0000fe7e@6550
5201+0000fc92@6551
5202+00007c92@6553
5203+0000ec12@6554
5204+0000eaf2@6555
5205+00006a70@6558
5206+0000ea70@6559
5207+0000e0c0@6560
5208+00004040@6563
5209+0000c040@6564
5210+0000d0c0@6565
5211+00007042@6567
5212+0000f042@6568
5213+0000fc12@6569
5214+0000fc92@6570
5215+00007c12@6572
5216+0000ec12@6573
5217+0000eaf6@6574
5218+00006a74@6577
5219+0000ee7c@6578
5220+0000eefc@6579
5221+00004efc@6581
5222+0000ce7c@6582
5223+0000de7c@6583
5224+0000defc@6584
5225+00007e7e@6586
5226+0000fe7e@6587
5227+0000fc92@6588
5228+0000ec12@6591
5229+0000ee7a@6592
5230+0000eafa@6593
5231+00006a7a@6595
5232+0000eaf8@6596
5233+0000e0c0@6597
5234+0000e040@6599
5235+000040c0@6600
5236+0000c0c0@6601
5237+0000d0c0@6602
5238+0000d040@6603
5239+0000f040@6604
5240+0000f0c2@6605
5241+0000fcd2@6606
5242+0000fd12@6607
5243+00007d92@6609
5244+0000ed92@6610
5245+0000ebfe@6611
5246+0000eb7e@6612
5247+00006bfc@6614
5248+0000ebfc@6615
5249+0000effc@6616
5250+0000ef7c@6617
5251+0000cffc@6619
5252+0000dffc@6621
5253+0000df7c@6622
5254+00007ffe@6623
5255+0000fffe@6624
5256+0000fd92@6625
5257+0000fd12@6626
5258+00007d90@6628
5259+0000fd90@6629
5260+0000fbfc@6630
5261+0000eb7c@6631
5262+00006b7c@6632
5263+0000ebfc@6633
5264+0000eb7c@6635
5265+00006bfc@6637
5266+0000ebfc@6638
5267+0000fbfc@6639
5268+0000fb7c@6640
5269+00007bfe@6642
5270+0000fbfe@6643
5271+0000fd96@6644
5272+0000fd16@6645
5273+00007d16@6646
5274+0000ed96@6647
5275+0000ebf2@6648
5276+0000eb72@6650
5277+00006b72@6651
5278+0000ebf0@6652
5279+0000e1c0@6653
5280+0000e140@6654
5281+000041c0@6656
5282+0000c1c0@6657
5283+0000d1c0@6658
5284+0000d140@6659
5285+00007142@6660
5286+0000f1c2@6661
5287+0000fd96@6662
5288+0000fd16@6663
5289+00007d96@6665
5290+0000ed96@6666
5291+0000ebf6@6667
5292+0000eb76@6668
5293+00006bf4@6670
5294+0000ebf4@6671
5295+0000effc@6672
5296+00006ffc@6674
5297+0000cffc@6675
5298+0000cf7c@6676
5299+0000dffc@6677
5300+00007ffe@6679
5301+0000ff7e@6680
5302+0000fd16@6681
5303+0000fd96@6682
5304+00007d16@6684
5305+0000ed96@6685
5306+0000ebfa@6686
5307+00006bfa@6688
5308+0000ebf8@6689
5309+0000e9c0@6690
5310+0000e140@6691
5311+0000e1c0@6692
5312+000041c0@6693
5313+0000c1c0@6694
5314+0000d140@6695
5315+0000d1c0@6696
5316+000071c2@6698
5317+0000f5c6@6699
5318+0000fd96@6700
5319+00007d96@6702
5320+0000ed96@6703
5321+0000ebfe@6704
5322+0000eb7e@6706
5323+00006bfc@6707
5324+0000ebfc@6708
5325+0000effc@6709
5326+0000ef7c@6710
5327+0000effc@6711
5328+00004ffc@6712
5329+0000cffc@6713
5330+0000dffc@6714
5331+00007ffe@6716
5332+0000ff7e@6717
5333+0000fd9a@6718
5334+00007d1a@6721
5335+0000ed9a@6722
5336+0000ebf2@6723
5337+0000eb72@6725
5338+00006bf0@6726
5339+0000ebf0@6727
5340+0000e1c0@6728
5341+000041c0@6730
5342+0000c1c0@6731
5343+0000d140@6732
5344+0000d1c0@6733
5345+000071c2@6735
5346+0000f142@6736
5347+0000fd9a@6737
5348+0000ed9a@6740
5349+0000effe@6741
5350+0000ebf6@6742
5351+0000eb76@6743
5352+00006bf6@6744
5353+0000ebf4@6745
5354+0000effc@6746
5355+0000ef7c@6747
5356+0000effc@6748
5357+00004ffc@6749
5358+0000cffc@6750
5359+0000df7c@6751
5360+0000dffc@6752
5361+0000fffc@6753
5362+0000fffe@6754
5363+0000fd9a@6756
5364+00007d1a@6758
5365+0000ed9a@6759
5366+0000ebfa@6760
5367+0000eb7a@6762
5368+00006bf8@6763
5369+0000ebf8@6764
5370+0000e140@6765
5371+0000e1c0@6766
5372+0000c1c0@6768
5373+0000c140@6769
5374+0000d1c0@6770
5375+000071c2@6772
5376+0000f142@6773
5377+0000fd9a@6774
5378+00007d1a@6777
5379+0000ed9a@6778
5380+0000ebfe@6779
5381+00006bfe@6781
5382+0000ebfc@6782
5383+0000effc@6783
5384+0000ef7c@6784
5385+0000effc@6785
5386+00004ffc@6786
5387+0000cffc@6787
5388+0000df7c@6788
5389+0000dffc@6789
5390+00007ffe@6791
5391+0000fffe@6792
5392+0000fd9e@6793
5393+00007d9e@6795
5394+0000ed9e@6796
5395+0000ebf2@6797
5396+0000eb72@6799
5397+00006bf2@6800
5398+0000ebf0@6801
5399+0000e140@6802
5400+0000e1c0@6804
5401+000041c0@6805
5402+0000c1c0@6806
5403+0000d1c0@6807
5404+000071c2@6809
5405+0000f142@6810
5406+0000fd1e@6811
5407+0000fd9e@6812
5408+00007d1e@6814
5409+0000ed9e@6815
5410+0000ebf6@6816
5411+0000eb76@6818
5412+00006bf4@6819
5413+0000ebf4@6820
5414+0000effc@6821
5415+00006ffc@6823
5416+0000cffc@6824
5417+0000cf7c@6825
5418+0000dffc@6826
5419+00007ffe@6828
5420+0000ff7e@6829
5421+0000fd9e@6830
5422+00007d1e@6833
5423+0000ed9e@6834
5424+0000ebfa@6835
5425+00006bfa@6837
5426+0000ebf8@6838
5427+0000e1c0@6839
5428+0000e140@6840
5429+0000e1c0@6841
5430+000041c0@6842
5431+0000c1c0@6843
5432+0000d140@6844
5433+0000d1c0@6845
5434+000071c2@6847
5435+0000f1ce@6848
5436+0000fd9e@6849
5437+00007d1e@6851
5438+0000ed9e@6852
5439+0000ebfe@6853
5440+0000eb7e@6855
5441+00006bfc@6856
5442+0000ebfc@6857
5443+0000effc@6858
5444+0000ef7c@6859
5445+0000effc@6860
5446+00004ffc@6861
5447+0000cffc@6862
5448+0000dffc@6863
5449+00007ffe@6865
5450+0000ff7e@6866
5451+0000fda2@6867
5452+00007d22@6870
5453+0000eda2@6871
5454+0000ebf2@6872
5455+0000eb72@6874
5456+00006bf0@6875
5457+0000ebf0@6876
5458+0000e1c0@6877
5459+000041c0@6879
5460+0000c1c0@6880
5461+0000d140@6881
5462+0000d1c0@6882
5463+000071c2@6884
5464+0000f142@6885
5465+0000fda2@6886
5466+0000eda2@6889
5467+0000eff6@6890
5468+0000ebf6@6891
5469+0000eb76@6892
5470+00006bf6@6893
5471+0000ebf4@6894
5472+0000effc@6895
5473+0000ef7c@6896
5474+0000effc@6897
5475+00004ffc@6898
5476+0000cffc@6899
5477+0000df7c@6900
5478+0000dffc@6901
5479+0000fffc@6902
5480+0000ff7e@6903
5481+0000fffe@6904
5482+0000fda2@6905
5483+00007d22@6907
5484+0000eda2@6908
5485+0000ebfa@6909
5486+0000eb7a@6911
5487+00006bf8@6912
5488+0000ebf8@6913
5489+0000e140@6914
5490+0000e1c0@6915
5491+0000c1c0@6917
5492+0000c140@6918
5493+0000d1c0@6919
5494+000071c2@6921
5495+0000f142@6922
5496+0000fda2@6923
5497+00007d22@6926
5498+0000eda2@6927
5499+0000ebfe@6928
5500+00006bfe@6930
5501+0000ebfc@6931
5502+0000effc@6932
5503+0000ef7c@6933
5504+0000effc@6934
5505+00004ffc@6935
5506+0000cffc@6936
5507+0000df7c@6937
5508+0000dffc@6938
5509+00007ffe@6940
5510+0000ff7e@6941
5511+0000fda6@6942
5512+00007da6@6944
5513+0000eda6@6945
5514+0000ebf2@6946
5515+0000eb72@6948
5516+00006bf2@6949
5517+0000ebf0@6950
5518+0000e140@6951
5519+0000e1c0@6953
5520+000041c0@6954
5521+0000c1c0@6955
5522+0000d1c0@6956
5523+000071c2@6958
5524+0000f142@6959
5525+0000fd26@6960
5526+0000fda6@6961
5527+00007d26@6963
5528+0000eda6@6964
5529+0000ebf6@6965
5530+0000eb76@6967
5531+00006bf4@6968
5532+0000ebf4@6969
5533+0000effc@6970
5534+00006ffc@6972
5535+0000cffc@6973
5536+0000cf7c@6974
5537+0000dffc@6975
5538+00007ffe@6977
5539+0000ff7e@6978
5540+0000fd26@6979
5541+0000fda6@6980
5542+00007d26@6982
5543+0000eda6@6983
5544+0000ebfa@6984
5545+00006bfa@6986
5546+0000ebf8@6987
5547+0000e1c0@6988
5548+0000e140@6989
5549+0000e1c0@6990
5550+000041c0@6991
5551+0000c1c0@6992
5552+0000d140@6993
5553+0000d1c0@6994
5554+000071c2@6996
5555+0000f5c6@6997
5556+0000fda6@6998
5557+00007da6@7000
5558+0000eda6@7001
5559+0000ebfe@7002
5560+0000eb7e@7004
5561+00006bfc@7005
5562+0000ebfc@7006
5563+0000effc@7007
5564+0000ef7c@7008
5565+0000effc@7009
5566+00004ffc@7010
5567+0000cffc@7011
5568+0000dffc@7012
5569+00007ffe@7014
5570+0000ff7e@7015
5571+0000fdaa@7016
5572+00007d2a@7019
5573+0000edaa@7020
5574+0000ebf2@7021
5575+0000eb72@7023
5576+0000ebf0@7024
5577+0000e1c0@7026
5578+000041c0@7028
5579+0000c1c0@7029
5580+0000d140@7030
5581+0000d1c0@7031
5582+000071c2@7033
5583+0000f142@7034
5584+0000fdaa@7035
5585+0000edaa@7038
5586+0000effe@7039
5587+0000ebf6@7040
5588+0000eb76@7041
5589+00006bf6@7042
5590+0000ebf4@7043
5591+0000effc@7044
5592+0000ef7c@7045
5593+0000effc@7046
5594+00004ffc@7047
5595+0000cffc@7048
5596+0000df7c@7049
5597+0000dffc@7050
5598+0000fffc@7051
5599+0000fffe@7052
5600+0000fdaa@7054
5601+00007d2a@7056
5602+0000edaa@7057
5603+0000ebfa@7058
5604+0000eb7a@7060
5605+00006bf8@7061
5606+0000ebf8@7062
5607+0000e140@7063
5608+0000e1c0@7064
5609+0000c1c0@7066
5610+0000c140@7067
5611+0000d1c0@7068
5612+000071c2@7070
5613+0000f142@7071
5614+0000fdaa@7072
5615+00007d2a@7075
5616+0000edaa@7076
5617+0000ebfe@7077
5618+00006bfe@7079
5619+0000ebfc@7080
5620+0000effc@7081
5621+0000ef7c@7082
5622+0000effc@7083
5623+00004ffc@7084
5624+0000cffc@7085
5625+0000df7c@7086
5626+0000dffc@7087
5627+00007ffe@7089
5628+0000fffe@7090
5629+0000fdae@7091
5630+00007dae@7093
5631+0000edae@7094
5632+0000ebf2@7095
5633+0000eb72@7097
5634+00006bf2@7098
5635+0000ebf0@7099
5636+0000e140@7100
5637+0000e1c0@7102
5638+000041c0@7103
5639+0000c1c0@7104
5640+0000d1c0@7105
5641+000071c2@7107
5642+0000f142@7108
5643+0000fd2e@7109
5644+0000fdae@7110
5645+00007d2e@7112
5646+0000edae@7113
5647+0000ebf6@7114
5648+0000eb76@7116
5649+00006bf4@7117
5650+0000ebf4@7118
5651+0000effc@7119
5652+00004ffc@7121
5653+0000cffc@7122
5654+0000cf7c@7123
5655+0000dffc@7124
5656+00007ffe@7126
5657+0000ff7e@7127
5658+0000fdae@7128
5659+00006d2e@7131
5660+0000edae@7132
5661+0000ebfa@7133
5662+00006bfa@7135
5663+0000ebf8@7136
5664+0000e1c0@7137
5665+0000e140@7138
5666+0000e1c0@7139
5667+000041c0@7140
5668+0000c1c0@7141
5669+0000d140@7142
5670+0000d1c0@7143
5671+000071c2@7145
5672+0000f5ce@7146
5673+0000fdae@7147
5674+00007d2e@7149
5675+0000edae@7150
5676+0000ebfe@7151
5677+0000eb7e@7153
5678+00006bfc@7154
5679+0000ebfc@7155
5680+0000effc@7156
5681+0000ef7c@7157
5682+0000effc@7158
5683+00004ffc@7159
5684+0000cffc@7160
5685+0000dffc@7161
5686+00007ffe@7163
5687+0000ff7e@7164
5688+0000fdb2@7165
5689+00007d32@7168
5690+0000edb2@7169
5691+0000ebf2@7170
5692+0000eb72@7172
5693+0000ebf0@7173
5694+0000e1c0@7175
5695+000041c0@7177
5696+0000c1c0@7178
5697+0000d140@7179
5698+0000d1c0@7180
5699+000071c2@7182
5700+0000f142@7183
5701+0000fdb2@7184
5702+0000edb2@7187
5703+0000ebf6@7188
5704+0000eb76@7190
5705+00006bf6@7191
5706+0000ebf4@7192
5707+0000effc@7193
5708+0000ef7c@7194
5709+0000effc@7195
5710+00004ffc@7196
5711+0000cffc@7197
5712+0000df7c@7198
5713+0000dffc@7199
5714+0000fffc@7200
5715+0000fffe@7201
5716+0000fdb2@7203
5717+00007d32@7205
5718+0000edb2@7206
5719+0000ebfa@7207
5720+0000eb7a@7209
5721+00006bf8@7210
5722+0000ebf8@7211
5723+0000e140@7212
5724+0000e1c0@7213
5725+0000c1c0@7215
5726+0000c140@7216
5727+0000d1c0@7217
5728+000071c2@7219
5729+0000f142@7220
5730+0000fdb2@7221
5731+00007d30@7224
5732+0000fdb0@7225
5733+0000fbf8@7226
5734+0000ebf8@7227
5735+00006bf8@7228
5736+0000ebf8@7229
5737+0000eb7c@7231
5738+0000ebfc@7232
5739+00006bfc@7233
5740+0000effc@7234
5741+0000ff78@7235
5742+0000fffc@7236
5743+00007ffe@7238
5744+0000ff7e@7239
5745+0000fdb2@7240
5746+00007db2@7242
5747+0000edb2@7243
5748+0000ebfe@7244
5749+0000eb7e@7246
5750+00006bfc@7247
5751+0000ebfc@7248
5752+0000effc@7249
5753+0000ef7c@7250
5754+0000effc@7251
5755+00004ffc@7252
5756+0000cffc@7253
5757+0000dffc@7254
5758+00007ffe@7256
5759+0000ff7e@7257
5760+0000fdb6@7258
5761+00007d36@7261
5762+0000fdb6@7262
5763+0000ebf2@7263
5764+0000eb72@7265
5765+00006bf0@7266
5766+0000ebf0@7267
5767+0000e1c0@7268
5768+000061c0@7270
5769+0000c1c0@7271
5770+0000c140@7272
5771+0000d1c0@7273
5772+000071c2@7275
5773+0000f142@7276
5774+0000fdb6@7277
5775+00007d36@7280
5776+0000edf6@7281
5777+0000ebf6@7282
5778+00006bf6@7284
5779+0000ebf4@7285
5780+0000effc@7286
5781+0000ef7c@7287
5782+0000effc@7288
5783+00004ffc@7289
5784+0000cffc@7290
5785+0000df7c@7291
5786+0000dffc@7292
5787+00007ffe@7294
5788+0000fffe@7295
5789+0000fdb6@7296
5790+00007db6@7298
5791+0000edb6@7299
5792+0000ebfa@7300
5793+0000eb7a@7302
5794+00006bf8@7303
5795+0000ebf8@7304
5796+0000e140@7305
5797+0000e1c0@7307
5798+000041c0@7308
5799+0000c1c0@7309
5800+0000d1c0@7310
5801+000071c2@7312
5802+0000f142@7313
5803+0000fdb6@7314
5804+00007d36@7317
5805+0000edb6@7318
5806+0000ebfe@7319
5807+0000eb7e@7321
5808+0000ebfc@7322
5809+0000effc@7323
5810+0000ef7c@7324
5811+0000effc@7325
5812+00004ffc@7326
5813+0000cffc@7327
5814+0000df7c@7328
5815+0000dffc@7329
5816+00007ffe@7331
5817+0000ff7e@7332
5818+0000fdba@7333
5819+0000edba@7336
5820+0000eff2@7337
5821+0000ebf2@7338
5822+0000eb72@7339
5823+00006bf2@7340
5824+0000ebf0@7341
5825+0000e1c0@7342
5826+0000e140@7343
5827+0000e1c0@7344
5828+000041c0@7345
5829+0000c1c0@7346
5830+0000d140@7347
5831+0000d1c0@7348
5832+0000f1c0@7349
5833+0000f1c2@7350
5834+0000fd7a@7351
5835+0000fdba@7352
5836+00007d3a@7354
5837+0000edba@7355
5838+0000ebf6@7356
5839+0000eb76@7358
5840+00006bf4@7359
5841+0000ebf4@7360
5842+0000effc@7361
5843+0000ef7c@7362
5844+0000effc@7363
5845+0000cffc@7364
5846+0000cf7c@7365
5847+0000dffc@7366
5848+00007ffe@7368
5849+0000ff7e@7369
5850+0000fdba@7370
5851+00007d3a@7373
5852+0000edba@7374
5853+0000ebfa@7375
5854+00006bfa@7377
5855+0000ebf8@7378
5856+0000ebe8@7379
5857+0000e140@7380
5858+0000e1c0@7381
5859+000041c0@7382
5860+0000c1c0@7383
5861+0000d140@7384
5862+0000d1c0@7385
5863+000071c2@7387
5864+0000f1c2@7388
5865+0000fdba@7389
5866+00007dba@7391
5867+0000edba@7392
5868+0000ebfe@7393
5869+0000eb7e@7395
5870+00006bfc@7396
5871+0000ebfc@7397
5872+0000effc@7398
5873+0000ef7c@7399
5874+0000effc@7400
5875+00004ffc@7401
5876+0000cffc@7402
5877+0000dffc@7403
5878+00007ffe@7405
5879+0000ff7e@7406
5880+0000fdbe@7407
5881+00007d3e@7410
5882+0000fdbe@7411
5883+0000ebf2@7412
5884+0000eb72@7414
5885+00006bf0@7415
5886+0000ebf0@7416
5887+0000e1c0@7417
5888+000061c0@7419
5889+0000c1c0@7420
5890+0000c140@7421
5891+0000d1c0@7422
5892+000071c2@7424
5893+0000f142@7425
5894+0000fdbe@7426
5895+00007d3e@7429
5896+0000edfe@7430
5897+0000ebf6@7431
5898+0000eb76@7432
5899+00006bf6@7433
5900+0000ebf4@7434
5901+0000effc@7435
5902+0000ef7c@7436
5903+0000effc@7437
5904+00004ffc@7438
5905+0000cffc@7439
5906+0000df7c@7440
5907+0000dffc@7441
5908+00007ffe@7443
5909+0000fffe@7444
5910+0000fdbe@7445
5911+00007dbe@7447
5912+0000edbe@7448
5913+0000ebfa@7449
5914+0000eb7a@7451
5915+00006bf8@7452
5916+0000ebf8@7453
5917+0000e140@7454
5918+0000e1c0@7456
5919+000041c0@7457
5920+0000c1c0@7458
5921+0000d1c0@7459
5922+000071c2@7461
5923+0000f142@7462
5924+0000fdbe@7463
5925+00007d3e@7466
5926+0000edbe@7467
5927+0000ebfe@7468
5928+0000eb7e@7470
5929+0000ebfc@7471
5930+0000effc@7472
5931+0000ef7c@7473
5932+0000effc@7474
5933+00004ffc@7475
5934+0000cffc@7476
5935+0000df7c@7477
5936+0000dffc@7478
5937+00007ffe@7480
5938+0000ff7e@7481
5939+0000ff82@7482
5940+0000ef82@7485
5941+0000ebf2@7486
5942+0000eb72@7488
5943+00006bf2@7489
5944+0000ebf0@7490
5945+0000e1c0@7491
5946+0000e140@7492
5947+0000e1c0@7493
5948+000041c0@7494
5949+0000c1c0@7495
5950+0000d140@7496
5951+0000d1c0@7497
5952+0000f1c0@7498
5953+0000f1c2@7499
5954+0000ff42@7500
5955+0000ff82@7501
5956+00007f02@7503
5957+0000ef82@7504
5958+0000ebf6@7505
5959+0000eb76@7507
5960+00006bf4@7508
5961+0000ebf4@7509
5962+0000effc@7510
5963+0000cffc@7513
5964+0000cf7c@7514
5965+0000dffc@7515
5966+00007ffe@7517
5967+0000ff7e@7518
5968+0000ff02@7519
5969+0000ff82@7520
5970+00007f02@7522
5971+0000ef82@7523
5972+0000ebfa@7524
5973+00006bfa@7526
5974+0000ebf8@7527
5975+0000ebc8@7528
5976+0000e140@7529
5977+0000e1c0@7530
5978+000041c0@7531
5979+0000c1c0@7532
5980+0000d140@7533
5981+0000d1c0@7534
5982+000071c2@7536
5983+0000f1c2@7537
5984+0000ff82@7538
5985+00007f82@7540
5986+0000ef82@7541
5987+0000ebfe@7542
5988+0000eb7e@7544
5989+00006bfc@7545
5990+0000ebfc@7546
5991+0000effc@7547
5992+0000ef7c@7548
5993+0000effc@7549
5994+00004ffc@7550
5995+0000cffc@7551
5996+0000dffc@7552
5997+00007ffe@7554
5998+0000ff7e@7555
5999+0000ff86@7556
6000+00007f06@7559
6001+0000ef86@7560
6002+0000ebf2@7561
6003+0000eb72@7563
6004+00006bf0@7564
6005+0000ebf0@7565
6006+0000e1c0@7566
6007+000041c0@7568
6008+0000c1c0@7569
6009+0000c140@7570
6010+0000d1c0@7571
6011+000071c2@7573
6012+0000f142@7574
6013+0000ff86@7575
6014+00007f06@7578
6015+0000efb6@7579
6016+0000ebf6@7580
6017+00006bf6@7582
6018+0000ebf4@7583
6019+0000effc@7584
6020+0000ef7c@7585
6021+0000effc@7586
6022+00004ffc@7587
6023+0000cffc@7588
6024+0000df7c@7589
6025+0000dffc@7590
6026+00007ffe@7592
6027+0000fffe@7593
6028+0000ff86@7594
6029+00007f86@7596
6030+0000ef86@7597
6031+0000ebfa@7598
6032+0000eb7a@7600
6033+00006bf8@7601
6034+0000ebf8@7602
6035+0000e140@7603
6036+0000e1c0@7605
6037+000041c0@7606
6038+0000c1c0@7607
6039+0000d1c0@7608
6040+000071c2@7610
6041+0000f142@7611
6042+0000ff86@7612
6043+00007f06@7615
6044+0000ef86@7616
6045+0000ebfe@7617
6046+0000eb7e@7619
6047+0000ebfc@7620
6048+0000effc@7621
6049+0000ef7c@7622
6050+0000effc@7623
6051+00004ffc@7624
6052+0000cffc@7625
6053+0000df7c@7626
6054+0000dffc@7627
6055+00007ffe@7629
6056+0000ff7e@7630
6057+0000ff8a@7631
6058+0000ef8a@7634
6059+0000ebf2@7635
6060+0000eb72@7637
6061+00006bf2@7638
6062+0000ebf0@7639
6063+0000e1c0@7640
6064+0000e140@7641
6065+0000e1c0@7642
6066+000041c0@7643
6067+0000c1c0@7644
6068+0000d140@7645
6069+0000d1c0@7646
6070+0000f1c0@7647
6071+0000f1c2@7648
6072+0000ff4a@7649
6073+0000ff8a@7650
6074+00007f0a@7652
6075+0000ef8a@7653
6076+0000ebf6@7654
6077+0000eb76@7656
6078+00006bf4@7657
6079+0000ebf4@7658
6080+0000effc@7659
6081+0000cffc@7662
6082+0000cf7c@7663
6083+0000dffc@7664
6084+00007ffe@7666
6085+0000ff7e@7667
6086+0000ff0a@7668
6087+0000ff8a@7669
6088+00007f0a@7671
6089+0000ef8a@7672
6090+0000ebfa@7673
6091+00006bfa@7675
6092+0000ebf8@7676
6093+0000ebc0@7677
6094+0000e140@7678
6095+0000e1c0@7679
6096+000041c0@7680
6097+0000c1c0@7681
6098+0000d140@7682
6099+0000d1c0@7683
6100+000071c2@7685
6101+0000f1c2@7686
6102+0000ff8a@7687
6103+00007f8a@7689
6104+0000ef8a@7690
6105+0000ebfe@7691
6106+0000eb7e@7693
6107+00006bfc@7694
6108+0000ebfc@7695
6109+0000effc@7696
6110+0000ef7c@7697
6111+0000effc@7698
6112+00004ffc@7699
6113+0000cffc@7700
6114+0000dffc@7701
6115+00007ffe@7703
6116+0000ff7e@7704
6117+0000ff8e@7705
6118+00007f0e@7708
6119+0000ff8e@7709
6120+0000ebf2@7710
6121+0000eb72@7712
6122+00006bf0@7713
6123+0000ebf0@7714
6124+0000e1c0@7715
6125+000041c0@7717
6126+0000c1c0@7718
6127+0000c140@7719
6128+0000d1c0@7720
6129+000071c2@7722
6130+0000f142@7723
6131+0000ff8e@7724
6132+00007f0e@7727
6133+0000efee@7728
6134+0000ebf6@7729
6135+00006bf6@7731
6136+0000ebf4@7732
6137+0000effc@7733
6138+0000ef7c@7734
6139+0000effc@7735
6140+00004ffc@7736
6141+0000cffc@7737
6142+0000df7c@7738
6143+0000dffc@7739
6144+00007ffe@7741
6145+0000fffe@7742
6146+0000ff8e@7743
6147+00007f8e@7745
6148+0000ef8e@7746
6149+0000ebfa@7747
6150+0000eb7a@7749
6151+00006bf8@7750
6152+0000ebf8@7751
6153+0000e140@7752
6154+0000e1c0@7753
6155+000041c0@7755
6156+0000c1c0@7756
6157+0000d1c0@7757
6158+000071c2@7759
6159+0000f142@7760
6160+0000ff8e@7761
6161+00007f0e@7764
6162+0000ef8e@7765
6163+0000ebfe@7766
6164+0000eb7e@7768
6165+0000ebfc@7769
6166+0000effc@7770
6167+0000ef7c@7771
6168+0000effc@7772
6169+00004ffc@7773
6170+0000cffc@7774
6171+0000df7c@7775
6172+0000dffc@7776
6173+00007ffe@7778
6174+0000ff7e@7779
6175+0000ff92@7780
6176+0000ef92@7783
6177+0000ebf2@7784
6178+0000eb72@7786
6179+00006bf2@7787
6180+0000ebf0@7788
6181+0000e1c0@7789
6182+0000e140@7790
6183+0000e1c0@7791
6184+000041c0@7792
6185+0000c1c0@7793
6186+0000d140@7794
6187+0000d1c0@7795
6188+0000f1c0@7796
6189+0000f142@7797
6190+0000ff52@7798
6191+0000ff92@7799
6192+00007f12@7801
6193+0000ef92@7802
6194+0000ebf6@7803
6195+0000eb76@7805
6196+00006bf4@7806
6197+0000ebf4@7807
6198+0000effc@7808
6199+0000cffc@7811
6200+0000cf7c@7812
6201+0000dffc@7813
6202+00007ffe@7815
6203+0000ff7e@7816
6204+0000ff12@7817
6205+0000ff92@7818
6206+00007f10@7820
6207+0000ff90@7821
6208+0000fbf4@7822
6209+0000ebf4@7823
6210+00006bf4@7824
6211+0000ebf4@7825
6212+0000eb74@7827
6213+0000ebf4@7828
6214+00006bf4@7829
6215+0000ebf4@7830
6216+0000fb74@7831
6217+0000fbf4@7832
6218+00007bf6@7834
6219+0000fbf6@7835
6220+0000ff92@7836
6221+00007f92@7838
6222+0000ef92@7839
6223+0000ebfa@7840
6224+0000eb7a@7842
6225+00006bf8@7843
6226+0000ebf8@7844
6227+0000e140@7845
6228+0000e1c0@7847
6229+000041c0@7848
6230+0000c1c0@7849
6231+0000d1c0@7850
6232+000071c2@7852
6233+0000f142@7853
6234+0000ff12@7854
6235+0000ff92@7855
6236+00007f12@7857
6237+0000ef92@7858
6238+0000ebfe@7859
6239+0000eb7e@7860
6240+00006bfc@7862
6241+0000effc@7863
6242+00004ffc@7866
6243+0000cffc@7867
6244+0000cf7c@7868
6245+0000dffc@7869
6246+00007ffe@7871
6247+0000ff7e@7872
6248+0000ff96@7873
6249+00006f16@7876
6250+0000eff6@7877
6251+0000ebf2@7878
6252+0000eb72@7879
6253+00006bf2@7880
6254+0000ebf0@7881
6255+0000e1c0@7882
6256+0000e140@7883
6257+0000e1c0@7884
6258+000041c0@7885
6259+0000c1c0@7886
6260+0000d140@7887
6261+0000d1c0@7888
6262+000071c2@7890
6263+0000f5d6@7891
6264+0000ff96@7892
6265+00007f16@7894
6266+0000ef96@7895
6267+0000ebf6@7896
6268+0000eb76@7898
6269+00006bf4@7899
6270+0000ebf4@7900
6271+0000effc@7901
6272+0000ef7c@7902
6273+0000effc@7903
6274+0000cffc@7904
6275+0000dffc@7906
6276+00007ffe@7908
6277+0000ff7e@7909
6278+0000ff96@7910
6279+00007f16@7913
6280+0000ef96@7914
6281+0000ebfa@7915
6282+0000eb7a@7917
6283+0000ebf8@7918
6284+0000e1c0@7920
6285+000041c0@7922
6286+0000c1c0@7923
6287+0000d140@7924
6288+0000d1c0@7925
6289+000071c2@7927
6290+0000f142@7928
6291+0000ff96@7929
6292+0000ef96@7932
6293+0000ebfe@7933
6294+0000eb7e@7935
6295+00006bfe@7936
6296+0000ebfc@7937
6297+0000effc@7938
6298+0000ef7c@7939
6299+0000effc@7940
6300+00004ffc@7941
6301+0000cffc@7942
6302+0000df7c@7943
6303+0000dffc@7944
6304+0000fffc@7945
6305+0000ff7e@7946
6306+0000fffe@7947
6307+0000ff9a@7948
6308+00007f1a@7950
6309+0000ef9a@7951
6310+0000ebf2@7952
6311+0000eb72@7954
6312+00006bf0@7955
6313+0000ebf0@7956
6314+0000e140@7957
6315+0000e1c0@7958
6316+0000c1c0@7960
6317+0000c140@7961
6318+0000d1c0@7962
6319+000071c2@7964
6320+0000f142@7965
6321+0000ff9a@7966
6322+00007f1a@7969
6323+0000ef9a@7970
6324+0000ebf6@7971
6325+00006bf6@7973
6326+0000ebf4@7974
6327+0000effc@7975
6328+0000ef7c@7976
6329+0000effc@7977
6330+00004ffc@7978
6331+0000cffc@7979
6332+0000df7c@7980
6333+0000dffc@7981
6334+00007ffe@7983
6335+0000fffe@7984
6336+0000ff9a@7985
6337+00007f9a@7987
6338+0000ef9a@7988
6339+0000ebfa@7989
6340+0000eb7a@7991
6341+00006bf8@7992
6342+0000ebf8@7993
6343+0000e140@7994
6344+0000e1c0@7996
6345+000041c0@7997
6346+0000c1c0@7998
6347+0000d1c0@7999
6348+000071c2@8001
6349+0000f142@8002
6350+0000ff1a@8003
6351+0000ff9a@8004
6352+00007f1a@8006
6353+0000ef9a@8007
6354+0000ebfe@8008
6355+0000eb7e@8010
6356+00006bfc@8011
6357+0000effc@8012
6358+00004ffc@8015
6359+0000cffc@8016
6360+0000cf7c@8017
6361+0000dffc@8018
6362+00007ffe@8020
6363+0000ff7e@8021
6364+0000ff9e@8022
6365+00007f1e@8025
6366+0000effe@8026
6367+0000ebf2@8027
6368+0000eb72@8028
6369+00006bf2@8029
6370+0000ebf0@8030
6371+0000e1c0@8031
6372+0000e140@8032
6373+0000e1c0@8033
6374+000041c0@8034
6375+0000c1c0@8035
6376+0000d140@8036
6377+0000d1c0@8037
6378+000071c2@8039
6379+0000f5de@8040
6380+0000ff9e@8041
6381+00007f1e@8043
6382+0000ef9e@8044
6383+0000ebf6@8045
6384+0000eb76@8047
6385+00006bf4@8048
6386+0000ebf4@8049
6387+0000effc@8050
6388+0000ef7c@8051
6389+0000effc@8052
6390+0000cffc@8053
6391+0000dffc@8055
6392+00007ffe@8057
6393+0000ff7e@8058
6394+0000ff9e@8059
6395+00007f1e@8062
6396+0000ef9e@8063
6397+0000ebfa@8064
6398+0000ebf8@8067
6399+0000e1c0@8069
6400+000041c0@8071
6401+0000c1c0@8072
6402+0000d140@8073
6403+0000d1c0@8074
6404+000071c2@8076
6405+0000f142@8077
6406+0000ff9e@8078
6407+0000ef9e@8081
6408+0000ebfe@8082
6409+0000eb7e@8084
6410+00006bfe@8085
6411+0000ebfc@8086
6412+0000effc@8087
6413+0000ef7c@8088
6414+0000effc@8089
6415+00004ffc@8090
6416+0000cffc@8091
6417+0000df7c@8092
6418+0000dffc@8093
6419+0000fffc@8094
6420+0000ff7e@8095
6421+0000fffe@8096
6422+0000ffa2@8097
6423+00007f22@8099
6424+0000efa2@8100
6425+0000ebf2@8101
6426+0000eb72@8103
6427+00006bf0@8104
6428+0000ebf0@8105
6429+0000e140@8106
6430+0000e1c0@8107
6431+0000c1c0@8109
6432+0000c140@8110
6433+0000d1c0@8111
6434+000071c2@8113
6435+0000f142@8114
6436+0000ffa2@8115
6437+00007f22@8118
6438+0000efa2@8119
6439+0000ebf6@8120
6440+00006bf6@8122
6441+0000ebf4@8123
6442+0000effc@8124
6443+0000ef7c@8125
6444+0000effc@8126
6445+00004ffc@8127
6446+0000cffc@8128
6447+0000df7c@8129
6448+0000dffc@8130
6449+00007ffe@8132
6450+0000fffe@8133
6451+0000ffa2@8134
6452+00007fa2@8136
6453+0000efa2@8137
6454+0000ebfa@8138
6455+0000eb7a@8140
6456+00006bf8@8141
6457+0000ebf8@8142
6458+0000e140@8143
6459+0000e1c0@8145
6460+000041c0@8146
6461+0000c1c0@8147
6462+0000d1c0@8148
6463+000071c2@8150
6464+0000f142@8151
6465+0000ff22@8152
6466+0000ffa2@8153
6467+00007f22@8155
6468+0000efa2@8156
6469+0000ebfe@8157
6470+0000eb7e@8158
6471+00006bfc@8160
6472+0000effc@8161
6473+00004ffc@8164
6474+0000cffc@8165
6475+0000cf7c@8166
6476+0000dffc@8167
6477+00007ffe@8169
6478+0000ff7e@8170
6479+0000ffa6@8171
6480+00006f26@8174
6481+0000eff6@8175
6482+0000ebf2@8176
6483+0000eb72@8177
6484+00006bf2@8178
6485+0000ebf0@8179
6486+0000e1c0@8180
6487+0000e140@8181
6488+0000e1c0@8182
6489+000041c0@8183
6490+0000c1c0@8184
6491+0000d140@8185
6492+0000d1c0@8186
6493+000071c2@8188
6494+0000f5e6@8189
6495+0000ffa6@8190
6496+00007f26@8192
6497+0000efa6@8193
6498+0000ebf6@8194
6499+0000eb76@8196
6500+00006bf4@8197
6501+0000ebf4@8198
6502+0000effc@8199
6503+0000ef7c@8200
6504+0000effc@8201
6505+0000cffc@8202
6506+0000dffc@8204
6507+00007ffe@8206
6508+0000ff7e@8207
6509+0000ffa6@8208
6510+00007f26@8211
6511+0000efa6@8212
6512+0000ebfa@8213
6513+0000ebf8@8216
6514+0000e1c0@8218
6515+000041c0@8220
6516+0000c1c0@8221
6517+0000d140@8222
6518+0000d1c0@8223
6519+000071c2@8225
6520+0000f142@8226
6521+0000ffa6@8227
6522+0000efa6@8230
6523+0000ebfe@8231
6524+0000eb7e@8233
6525+00006bfe@8234
6526+0000ebfc@8235
6527+0000effc@8236
6528+0000ef7c@8237
6529+0000effc@8238
6530+00004ffc@8239
6531+0000cffc@8240
6532+0000df7c@8241
6533+0000dffc@8242
6534+0000fffc@8243
6535+0000ff7e@8244
6536+0000fffe@8245
6537+0000ffaa@8246
6538+00007f2a@8248
6539+0000efaa@8249
6540+0000ebf2@8250
6541+0000eb72@8252
6542+00006bf0@8253
6543+0000ebf0@8254
6544+0000e140@8255
6545+0000e1c0@8256
6546+000061c0@8257
6547+0000c1c0@8258
6548+0000c140@8259
6549+0000d1c0@8260
6550+000071c2@8262
6551+0000f142@8263
6552+0000ffaa@8264
6553+00007f2a@8267
6554+0000efaa@8268
6555+0000ebf6@8269
6556+00006bf6@8271
6557+0000ebf4@8272
6558+0000effc@8273
6559+0000ef7c@8274
6560+0000effc@8275
6561+00004ffc@8276
6562+0000cffc@8277
6563+0000df7c@8278
6564+0000dffc@8279
6565+00007ffe@8281
6566+0000fffe@8282
6567+0000ffaa@8283
6568+00007faa@8285
6569+0000efaa@8286
6570+0000ebfa@8287
6571+0000eb7a@8289
6572+00006bf8@8290
6573+0000ebf8@8291
6574+0000e140@8292
6575+0000e1c0@8294
6576+000041c0@8295
6577+0000c1c0@8296
6578+0000d1c0@8297
6579+000071c2@8299
6580+0000f142@8300
6581+0000ff2a@8301
6582+0000ffaa@8302
6583+00007f2a@8304
6584+0000efaa@8305
6585+0000ebfe@8306
6586+0000eb7e@8308
6587+00006bfc@8309
6588+0000effc@8310
6589+00004ffc@8313
6590+0000cffc@8314
6591+0000cf7c@8315
6592+0000dffc@8316
6593+00007ffe@8318
6594+0000ff7e@8319
6595+0000ffae@8320
6596+00006f2e@8323
6597+0000effe@8324
6598+0000ebf2@8325
6599+0000eb72@8326
6600+00006bf2@8327
6601+0000ebf0@8328
6602+0000e1c0@8329
6603+0000e140@8330
6604+0000e1c0@8331
6605+000041c0@8332
6606+0000c1c0@8333
6607+0000d140@8334
6608+0000d1c0@8335
6609+000071c2@8337
6610+0000f56e@8338
6611+0000ffae@8339
6612+00007f2e@8341
6613+0000efae@8342
6614+0000ebf6@8343
6615+0000eb76@8345
6616+00006bf4@8346
6617+0000ebf4@8347
6618+0000effc@8348
6619+0000ef7c@8349
6620+0000effc@8350
6621+0000cffc@8351
6622+0000dffc@8353
6623+00007ffe@8355
6624+0000ff7e@8356
6625+0000ffae@8357
6626+00007f2e@8360
6627+0000efae@8361
6628+0000ebfa@8362
6629+0000ebf8@8365
6630+0000e1c0@8367
6631+000041c0@8369
6632+0000c1c0@8370
6633+0000d140@8371
6634+0000d1c0@8372
6635+000071c2@8374
6636+0000f142@8375
6637+0000ffae@8376
6638+0000efae@8379
6639+0000ebfe@8380
6640+0000eb7e@8382
6641+00006bfe@8383
6642+0000ebfc@8384
6643+0000effc@8385
6644+0000ef7c@8386
6645+0000effc@8387
6646+00004ffc@8388
6647+0000cffc@8389
6648+0000df7c@8390
6649+0000dffc@8391
6650+00007ffc@8392
6651+0000ff7e@8393
6652+0000fffe@8394
6653+0000ffb2@8395
6654+00007f32@8397
6655+0000efb2@8398
6656+0000ebf2@8399
6657+0000eb72@8401
6658+00006bf0@8402
6659+0000ebf0@8403
6660+0000e140@8404
6661+0000e1c0@8405
6662+000061c0@8406
6663+0000c1c0@8407
6664+0000c140@8408
6665+0000d1c0@8409
6666+000071c2@8411
6667+0000f142@8412
6668+0000ffb2@8413
6669+00007f30@8416
6670+0000ffb0@8417
6671+0000fbf0@8418
6672+0000ebf0@8419
6673+00006bf0@8420
6674+0000ebf0@8421
6675+0000ebf8@8422
6676+0000eb7c@8423
6677+0000ebfc@8424
6678+00006bfc@8425
6679+0000effc@8426
6680+0000ff7c@8427
6681+0000fffc@8428
6682+00007ffe@8430
6683+0000fffe@8431
6684+0000ffb2@8432
6685+00007fb2@8434
6686+0000efb2@8435
6687+0000ebf6@8436
6688+0000eb76@8438
6689+00006bf4@8439
6690+0000ebf4@8440
6691+0000effc@8441
6692+0000ef7c@8442
6693+0000effc@8443
6694+00004ffc@8444
6695+0000cffc@8445
6696+0000dffc@8446
6697+00007ffe@8448
6698+0000ff7e@8449
6699+0000ffb2@8450
6700+00007f32@8453
6701+0000ffb2@8454
6702+0000ebfa@8455
6703+0000eb7a@8457
6704+00006bf8@8458
6705+0000ebf8@8459
6706+0000e1c0@8460
6707+000041c0@8462
6708+0000c1c0@8463
6709+0000c140@8464
6710+0000d1c0@8465
6711+000071c2@8467
6712+0000f142@8468
6713+0000ffb2@8469
6714+00007f32@8472
6715+0000effe@8473
6716+0000ebfe@8474
6717+00006bfe@8476
6718+0000ebfc@8477
6719+0000effc@8478
6720+0000ef7c@8479
6721+0000effc@8480
6722+00004ffc@8481
6723+0000cffc@8482
6724+0000df7c@8483
6725+0000dffc@8484
6726+00007ffe@8486
6727+0000fffe@8487
6728+0000ffb6@8488
6729+00007fb6@8490
6730+0000efb6@8491
6731+0000ebf2@8492
6732+0000eb72@8494
6733+00006bf0@8495
6734+0000ebf0@8496
6735+0000e140@8497
6736+0000e1c0@8498
6737+0000c1c0@8500
6738+0000d1c0@8502
6739+000071c2@8504
6740+0000f142@8505
6741+0000ffb6@8506
6742+00007f36@8509
6743+0000efb6@8510
6744+0000ebf6@8511
6745+0000ebf4@8514
6746+0000effc@8515
6747+0000ef7c@8516
6748+0000effc@8517
6749+00004ffc@8518
6750+0000cffc@8519
6751+0000df7c@8520
6752+0000dffc@8521
6753+00007ffe@8523
6754+0000ff7e@8524
6755+0000ffb6@8525
6756+0000efb6@8528
6757+0000ebfa@8529
6758+0000eb7a@8531
6759+00006bfa@8532
6760+0000ebf8@8533
6761+0000e1c0@8534
6762+0000e140@8535
6763+0000e1c0@8536
6764+000041c0@8537
6765+0000c1c0@8538
6766+0000d140@8539
6767+0000d1c0@8540
6768+000071c0@8541
6769+0000f142@8542
6770+0000ff76@8543
6771+0000ffb6@8544
6772+00007f36@8546
6773+0000efb6@8547
6774+0000ebfe@8548
6775+0000eb7e@8550
6776+00006bfc@8551
6777+0000ebfc@8552
6778+0000effc@8553
6779+00006ffc@8555
6780+0000cffc@8556
6781+0000cf7c@8557
6782+0000dffc@8558
6783+00007ffe@8560
6784+0000ff7e@8561
6785+0000ffba@8562
6786+00007f3a@8565
6787+0000efba@8566
6788+0000ebf2@8567
6789+00006bf2@8569
6790+0000ebf0@8570
6791+0000ebc0@8571
6792+0000e140@8572
6793+0000e1c0@8573
6794+000041c0@8574
6795+0000c1c0@8575
6796+0000d140@8576
6797+0000d1c0@8577
6798+000071c2@8579
6799+0000f1c2@8580
6800+0000ffba@8581
6801+00007fba@8583
6802+0000efba@8584
6803+0000ebf6@8585
6804+0000eb76@8587
6805+00006bf4@8588
6806+0000ebf4@8589
6807+0000effc@8590
6808+0000ef7c@8591
6809+0000effc@8592
6810+00004ffc@8593
6811+0000cffc@8594
6812+0000dffc@8595
6813+00007ffe@8597
6814+0000ff7e@8598
6815+0000ffba@8599
6816+00007f3a@8602
6817+0000efba@8603
6818+0000ebfa@8604
6819+0000eb7a@8606
6820+00006bf8@8607
6821+0000ebf8@8608
6822+0000e1c0@8609
6823+000041c0@8611
6824+0000c1c0@8612
6825+0000c140@8613
6826+0000d1c0@8614
6827+000071c2@8616
6828+0000f142@8617
6829+0000ffba@8618
6830+00007f3a@8621
6831+0000effe@8622
6832+0000ebfe@8623
6833+00006bfe@8625
6834+0000ebfc@8626
6835+0000effc@8627
6836+0000ef7c@8628
6837+0000effc@8629
6838+00004ffc@8630
6839+0000cffc@8631
6840+0000df7c@8632
6841+0000dffc@8633
6842+00007ffe@8635
6843+0000fffe@8636
6844+0000ffbe@8637
6845+00007fbe@8639
6846+0000efbe@8640
6847+0000ebf2@8641
6848+0000eb72@8643
6849+00006bf0@8644
6850+0000ebf0@8645
6851+0000e140@8646
6852+0000e1c0@8647
6853+0000c1c0@8649
6854+0000d1c0@8651
6855+000071c2@8653
6856+0000f142@8654
6857+0000ffbe@8655
6858+00007f3e@8658
6859+0000efbe@8659
6860+0000ebf6@8660
6861+0000ebf4@8663
6862+0000effc@8664
6863+0000ef7c@8665
6864+0000effc@8666
6865+00004ffc@8667
6866+0000cffc@8668
6867+0000df7c@8669
6868+0000dffc@8670
6869+00007ffe@8672
6870+0000ff7e@8673
6871+0000ffbe@8674
6872+0000efbe@8677
6873+0000ebfa@8678
6874+0000eb7a@8680
6875+00006bfa@8681
6876+0000ebf8@8682
6877+0000e1c0@8683
6878+0000e140@8684
6879+0000e1c0@8685
6880+000041c0@8686
6881+0000c1c0@8687
6882+0000d140@8688
6883+0000d1c0@8689
6884+000071c0@8690
6885+0000f142@8691
6886+0000ff3e@8692
6887+0000ffbe@8693
6888+00007f3e@8695
6889+0000efbe@8696
6890+0000ebfe@8697
6891+0000eb7e@8699
6892+00006bfc@8700
6893+0000ebfc@8701
6894+0000effc@8702
6895+00006ffc@8704
6896+0000cffc@8705
6897+0000cf7c@8706
6898+0000dffc@8707
6899+00007ffe@8709
6900+0000ff7e@8710
6901+0000f142@8711
6902+0000f1c2@8712
6903+00007142@8714
6904+0000e1c2@8715
6905+0000ebf2@8716
6906+00006bf2@8718
6907+0000ebf0@8719
6908+0000ebc0@8720
6909+0000e140@8721
6910+0000e1c0@8722
6911+000041c0@8723
6912+0000c1c0@8724
6913+0000d140@8725
6914+0000d1c0@8726
6915+000071c2@8728
6916+0000f1c2@8729
6917+000071c2@8732
6918+0000e1c2@8733
6919+0000ebf6@8734
6920+0000eb76@8736
6921+00006bf4@8737
6922+0000ebf4@8738
6923+0000effc@8739
6924+0000ef7c@8740
6925+0000effc@8741
6926+00004ffc@8742
6927+0000cffc@8743
6928+0000dffc@8744
6929+00007ffe@8746
6930+0000ff7e@8747
6931+0000f1c2@8748
6932+00007142@8751
6933+0000e1c2@8752
6934+0000ebfa@8753
6935+0000eb7a@8755
6936+00006bf8@8756
6937+0000ebf8@8757
6938+0000e1c0@8758
6939+000041c0@8760
6940+0000c1c0@8761
6941+0000c140@8762
6942+0000d1c0@8763
6943+000071c2@8765
6944+0000f142@8766
6945+0000f1c2@8767
6946+00006142@8770
6947+0000e1fe@8771
6948+0000ebfe@8772
6949+00006bfe@8774
6950+0000ebfc@8775
6951+0000effc@8776
6952+0000ef7c@8777
6953+0000effc@8778
6954+00004ffc@8779
6955+0000cffc@8780
6956+0000df7c@8781
6957+0000dffc@8782
6958+00007ffe@8784
6959+0000fffe@8785
6960+0000f1c6@8786
6961+000071c6@8788
6962+0000e1c6@8789
6963+0000ebf2@8790
6964+0000eb72@8792
6965+00006bf0@8793
6966+0000ebf0@8794
6967+0000e140@8795
6968+0000e1c0@8796
6969+0000c1c0@8798
6970+0000d1c0@8800
6971+000071c2@8802
6972+0000f142@8803
6973+0000f1c6@8804
6974+00007146@8807
6975+0000e1c6@8808
6976+0000ebf6@8809
6977+0000ebf4@8812
6978+0000effc@8813
6979+0000ef7c@8814
6980+0000effc@8815
6981+00004ffc@8816
6982+0000cffc@8817
6983+0000df7c@8818
6984+0000dffc@8819
6985+00007ffe@8821
6986+0000ff7e@8822
6987+0000f1c6@8823
6988+0000e1c6@8826
6989+0000ebfa@8827
6990+0000eb7a@8829
6991+00006bfa@8830
6992+0000ebf8@8831
6993+0000e1c0@8832
6994+0000e140@8833
6995+0000e1c0@8834
6996+000041c0@8835
6997+0000c1c0@8836
6998+0000d140@8837
6999+0000d1c0@8838
7000+000071c0@8839
7001+0000f142@8840
7002+0000f1c6@8841
7003+00007146@8844
7004+0000e1c6@8845
7005+0000ebfe@8846
7006+0000eb7e@8848
7007+00006bfc@8849
7008+0000ebfc@8850
7009+0000effc@8851
7010+00006ffc@8853
7011+0000cffc@8854
7012+0000cf7c@8855
7013+0000dffc@8856
7014+00007ffe@8858
7015+0000ff7e@8859
7016+0000f14a@8860
7017+0000f1ca@8861
7018+0000714a@8863
7019+0000e1ca@8864
7020+0000ebf2@8865
7021+00006bf2@8867
7022+0000ebf0@8868
7023+0000ebc0@8869
7024+0000e140@8870
7025+0000e1c0@8871
7026+000041c0@8872
7027+0000c1c0@8873
7028+0000d140@8874
7029+0000d1c0@8875
7030+000071c2@8877
7031+0000f1c2@8878
7032+0000f1ca@8879
7033+000071ca@8881
7034+0000e1ca@8882
7035+0000ebfe@8883
7036+0000ebf6@8884
7037+0000eb76@8885
7038+00006bf4@8886
7039+0000ebf4@8887
7040+0000effc@8888
7041+0000ef7c@8889
7042+0000effc@8890
7043+00004ffc@8891
7044+0000cffc@8892
7045+0000dffc@8893
7046+00007ffe@8895
7047+0000ff7e@8896
7048+0000f1ce@8897
7049+0000f1ca@8898
7050+0000714a@8900
7051+0000e1ca@8901
7052+0000ebfa@8902
7053+0000eb7a@8904
7054+00006bf8@8905
7055+0000ebf8@8906
7056+0000e1c0@8907
7057+000041c0@8909
7058+0000c1c0@8910
7059+0000c140@8911
7060+0000d1c0@8912
7061+000071c2@8914
7062+0000f142@8915
7063+0000f1ca@8916
7064+0000614a@8919
7065+0000e1fe@8920
7066+0000ebfe@8921
7067+00006bfe@8923
7068+0000ebfc@8924
7069+0000effc@8925
7070+0000ef7c@8926
7071+0000effc@8927
7072+00004ffc@8928
7073+0000cffc@8929
7074+0000df7c@8930
7075+0000dffc@8931
7076+00007ffe@8933
7077+0000fffe@8934
7078+0000f1ce@8935
7079+0000714e@8937
7080+0000e1ce@8938
7081+0000ebf2@8939
7082+0000eb72@8941
7083+00006bf0@8942
7084+0000ebf0@8943
7085+0000e140@8944
7086+0000e1c0@8945
7087+0000c1c0@8947
7088+0000d1c0@8949
7089+000071c2@8951
7090+0000f142@8952
7091+0000f1ce@8953
7092+0000714e@8956
7093+0000e1ce@8957
7094+0000ebf6@8958
7095+0000ebf4@8961
7096+0000effc@8962
7097+0000ef7c@8963
7098+0000effc@8964
7099+00004ffc@8965
7100+0000cffc@8966
7101+0000df7c@8967
7102+0000dffc@8968
7103+00007ffe@8970
7104+0000ff7e@8971
7105+0000f1ce@8972
7106+0000e1ce@8975
7107+0000ebfa@8976
7108+0000eb7a@8978
7109+00006bfa@8979
7110+0000ebf8@8980
7111+0000e1c0@8981
7112+0000e140@8982
7113+0000e1c0@8983
7114+000041c0@8984
7115+0000c1c0@8985
7116+0000d140@8986
7117+0000d1c0@8987
7118+000071c2@8988
7119+0000f142@8989
7120+0000f1ce@8990
7121+0000714e@8993
7122+0000e1ce@8994
7123+0000ebfe@8995
7124+0000eb7e@8997
7125+00006bfc@8998
7126+0000ebfc@8999
7127+0000effc@9000
7128+00006ffc@9002
7129+0000cffc@9003
7130+0000cf7c@9004
7131+0000dffc@9005
7132+00007ffe@9007
7133+0000ff7e@9008
7134+0000f1ce@9009
7135+0000714c@9012
7136+0000f1cc@9013
7137+0000fbfc@9014
7138+0000ebfc@9015
7139+00006bfc@9016
7140+0000ebfc@9017
7141+0000eb7c@9019
7142+0000ebfc@9020
7143+00006bfc@9021
7144+0000ebfc@9022
7145+0000fb7c@9023
7146+0000fbfc@9024
7147+00007bfe@9026
7148+0000fbfe@9027
7149+0000f1d2@9028
7150+000071d2@9030
7151+0000e1d2@9031
7152+0000ebf2@9032
7153+0000eb72@9034
7154+00006bf0@9035
7155+0000ebf0@9036
7156+0000e140@9037
7157+0000e1c0@9039
7158+000041c0@9040
7159+0000c1c0@9041
7160+0000d1c0@9042
7161+000071c2@9044
7162+0000f142@9045
7163+0000f1d2@9046
7164+00007152@9049
7165+0000e1d2@9050
7166+0000ebf6@9051
7167+0000eb76@9053
7168+00006bf4@9054
7169+0000effc@9055
7170+00004ffc@9058
7171+0000cffc@9059
7172+0000cf7c@9060
7173+0000dffc@9061
7174+00007ffe@9063
7175+0000ff7e@9064
7176+0000f152@9065
7177+0000f1d2@9066
7178+00006152@9068
7179+0000e3fa@9069
7180+0000ebfa@9070
7181+00006bfa@9072
7182+0000ebf8@9073
7183+0000e1c0@9074
7184+0000e140@9075
7185+0000e1c0@9076
7186+000041c0@9077
7187+0000c1c0@9078
7188+0000d140@9079
7189+0000d1c0@9080
7190+000071c2@9082
7191+0000f1d2@9083
7192+00007152@9086
7193+0000e1d2@9087
7194+0000ebfe@9088
7195+0000eb7e@9090
7196+00006bfc@9091
7197+0000ebfc@9092
7198+0000effc@9093
7199+0000ef7c@9094
7200+0000effc@9095
7201+0000cffc@9096
7202+0000cf7c@9097
7203+0000dffc@9098
7204+00007ffe@9100
7205+0000ff7e@9101
7206+0000f1d6@9102
7207+00007156@9105
7208+0000e1d6@9106
7209+0000ebf2@9107
7210+0000ebf0@9110
7211+0000e1c0@9112
7212+000041c0@9114
7213+0000c1c0@9115
7214+0000d140@9116
7215+0000d1c0@9117
7216+000071c2@9119
7217+0000f142@9120
7218+0000f1d6@9121
7219+0000e1d6@9124
7220+0000ebf6@9125
7221+0000eb76@9127
7222+00006bf6@9128
7223+0000ebf4@9129
7224+0000effc@9130
7225+0000ef7c@9131
7226+0000effc@9132
7227+00004ffc@9133
7228+0000cffc@9134
7229+0000df7c@9135
7230+0000dffc@9136
7231+00007ffe@9137
7232+0000ff7e@9138
7233+0000fbfe@9139
7234+0000f1d6@9140
7235+00007156@9142
7236+0000e1d6@9143
7237+0000ebfa@9144
7238+0000eb7a@9146
7239+00006bf8@9147
7240+0000ebf8@9148
7241+0000e1c0@9149
7242+000061c0@9151
7243+0000c1c0@9152
7244+0000c140@9153
7245+0000d1c0@9154
7246+000071c2@9156
7247+0000f142@9157
7248+0000f1d6@9158
7249+00007156@9161
7250+0000e1d6@9162
7251+0000ebfe@9163
7252+00006bfe@9165
7253+0000ebfc@9166
7254+0000effc@9167
7255+0000ef7c@9168
7256+0000effc@9169
7257+00004ffc@9170
7258+0000cffc@9171
7259+0000df7c@9172
7260+0000dffc@9173
7261+00007ffe@9175
7262+0000fffe@9176
7263+0000f1da@9177
7264+000071da@9179
7265+0000e1da@9180
7266+0000ebf2@9181
7267+0000eb72@9183
7268+00006bf0@9184
7269+0000ebf0@9185
7270+0000e140@9186
7271+0000e1c0@9188
7272+000041c0@9189
7273+0000c1c0@9190
7274+0000d1c0@9191
7275+000071c2@9193
7276+0000f142@9194
7277+0000f1da@9195
7278+0000715a@9198
7279+0000e1da@9199
7280+0000ebf6@9200
7281+0000eb76@9202
7282+00006bf4@9203
7283+0000effc@9204
7284+00004ffc@9207
7285+0000cffc@9208
7286+0000cf7c@9209
7287+0000dffc@9210
7288+00007ffe@9212
7289+0000ff7e@9213
7290+0000f1da@9214
7291+0000e15a@9217
7292+0000e3fa@9218
7293+0000ebfa@9219
7294+00006bfa@9221
7295+0000ebf8@9222
7296+0000e1c0@9223
7297+0000e140@9224
7298+0000e1c0@9225
7299+000041c0@9226
7300+0000c1c0@9227
7301+0000d140@9228
7302+0000d1c0@9229
7303+0000f1c2@9231
7304+0000f1da@9232
7305+0000715a@9235
7306+0000e1da@9236
7307+0000ebfe@9237
7308+0000eb7e@9239
7309+00006bfc@9240
7310+0000ebfc@9241
7311+0000effc@9242
7312+0000ef7c@9243
7313+0000effc@9244
7314+0000cffc@9245
7315+0000cf7c@9246
7316+0000dffc@9247
7317+00007ffe@9249
7318+0000ff7e@9250
7319+0000f1de@9251
7320+0000715e@9254
7321+0000e1de@9255
7322+0000ebf2@9256
7323+0000ebf0@9259
7324+0000e1c0@9261
7325+000041c0@9263
7326+0000c1c0@9264
7327+0000d140@9265
7328+0000d1c0@9266
7329+000071c2@9268
7330+0000f142@9269
7331+0000f1de@9270
7332+000071de@9272
7333+0000e1de@9273
7334+0000ebf6@9274
7335+0000eb76@9276
7336+00006bf6@9277
7337+0000ebf4@9278
7338+0000effc@9279
7339+0000ef7c@9280
7340+0000effc@9281
7341+00004ffc@9282
7342+0000cffc@9283
7343+0000df7c@9284
7344+0000dffc@9285
7345+00007ffe@9286
7346+0000fffe@9287
7347+0000fbfe@9288
7348+0000f1de@9289
7349+0000715e@9291
7350+0000f1de@9292
7351+0000ebfa@9293
7352+0000eb7a@9295
7353+00006bf8@9296
7354+0000ebf8@9297
7355+0000e1c0@9298
7356+000061c0@9300
7357+0000c1c0@9301
7358+0000c140@9302
7359+0000d1c0@9303
7360+000071c2@9305
7361+0000f142@9306
7362+0000f1de@9307
7363+0000715e@9310
7364+0000e1de@9311
7365+0000ebfe@9312
7366+00006bfe@9314
7367+0000ebfc@9315
7368+0000effc@9316
7369+0000ef7c@9317
7370+0000effc@9318
7371+00004ffc@9319
7372+0000cffc@9320
7373+0000df7c@9321
7374+0000dffc@9322
7375+00007ffe@9324
7376+0000fffe@9325
7377+0000f1e2@9326
7378+000071e2@9328
7379+0000e1e2@9329
7380+0000ebf2@9330
7381+0000eb72@9332
7382+00006bf0@9333
7383+0000ebf0@9334
7384+0000e140@9335
7385+0000e1c0@9337
7386+000041c0@9338
7387+0000c1c0@9339
7388+0000d1c0@9340
7389+000071c2@9342
7390+0000f142@9343
7391+0000f1e2@9344
7392+00007162@9347
7393+0000e1e2@9348
7394+0000ebf6@9349
7395+0000eb76@9351
7396+00006bf4@9352
7397+0000effc@9353
7398+00004ffc@9356
7399+0000cffc@9357
7400+0000cf7c@9358
7401+0000dffc@9359
7402+00007ffe@9361
7403+0000ff7e@9362
7404+0000f1e2@9363
7405+00006162@9366
7406+0000e3fa@9367
7407+0000ebfa@9368
7408+00006bfa@9370
7409+0000ebf8@9371
7410+0000e1c0@9372
7411+0000e140@9373
7412+0000e1c0@9374
7413+000041c0@9375
7414+0000c1c0@9376
7415+0000d140@9377
7416+0000d1c0@9378
7417+0000f1c2@9380
7418+0000f1e2@9381
7419+00007162@9384
7420+0000e1e2@9385
7421+0000ebfe@9386
7422+0000eb7e@9388
7423+00006bfc@9389
7424+0000ebfc@9390
7425+0000effc@9391
7426+0000ef7c@9392
7427+0000effc@9393
7428+0000cffc@9394
7429+0000cf7c@9395
7430+0000dffc@9396
7431+00007ffe@9398
7432+0000ff7e@9399
7433+0000f1e6@9400
7434+00007166@9403
7435+0000e1e6@9404
7436+0000ebf2@9405
7437+0000ebf0@9408
7438+0000e1c0@9410
7439+000041c0@9412
7440+0000c1c0@9413
7441+0000d140@9414
7442+0000d1c0@9415
7443+000071c2@9417
7444+0000f142@9418
7445+0000f1e6@9419
7446+000071e6@9421
7447+0000e1e6@9422
7448+0000ebf6@9423
7449+0000eb76@9425
7450+00006bf6@9426
7451+0000ebf4@9427
7452+0000effc@9428
7453+0000ef7c@9429
7454+0000effc@9430
7455+00004ffc@9431
7456+0000cffc@9432
7457+0000df7c@9433
7458+0000dffc@9434
7459+00007ffe@9435
7460+0000ff7e@9436
7461+0000fbfe@9437
7462+0000f1e6@9438
7463+00007166@9440
7464+0000e1e6@9441
7465+0000ebfa@9442
7466+0000eb7a@9444
7467+00006bf8@9445
7468+0000ebf8@9446
7469+0000e1c0@9447
7470+000061c0@9449
7471+0000c1c0@9450
7472+0000c140@9451
7473+0000d1c0@9452
7474+000071c2@9454
7475+0000f142@9455
7476+0000f1e6@9456
7477+00007166@9459
7478+0000e1e6@9460
7479+0000ebfe@9461
7480+00006bfe@9463
7481+0000ebfc@9464
7482+0000effc@9465
7483+0000ef7c@9466
7484+0000effc@9467
7485+00004ffc@9468
7486+0000cffc@9469
7487+0000df7c@9470
7488+0000dffc@9471
7489+00007ffe@9473
7490+0000fffe@9474
7491+0000f1ea@9475
7492+000071ea@9477
7493+0000e1ea@9478
7494+0000ebf2@9479
7495+0000eb72@9481
7496+00006bf0@9482
7497+0000ebf0@9483
7498+0000e140@9484
7499+0000e1c0@9486
7500+000041c0@9487
7501+0000c1c0@9488
7502+0000d1c0@9489
7503+000071c2@9491
7504+0000f142@9492
7505+0000f1ea@9493
7506+0000716a@9496
7507+0000e1ea@9497
7508+0000ebf6@9498
7509+0000eb76@9500
7510+00006bf4@9501
7511+0000effc@9502
7512+00004ffc@9505
7513+0000cffc@9506
7514+0000cf7c@9507
7515+0000dffc@9508
7516+00007ffe@9510
7517+0000ff7e@9511
7518+0000f1ea@9512
7519+0000e16a@9515
7520+0000e3fa@9516
7521+0000ebfa@9517
7522+00006bfa@9519
7523+0000ebf8@9520
7524+0000e1c0@9521
7525+0000e140@9522
7526+0000e1c0@9523
7527+000041c0@9524
7528+0000c1c0@9525
7529+0000d140@9526
7530+0000d1c0@9527
7531+0000f1c2@9529
7532+0000f1ea@9530
7533+0000716a@9533
7534+0000e1ea@9534
7535+0000ebfe@9535
7536+0000eb7e@9537
7537+00006bfc@9538
7538+0000ebfc@9539
7539+0000effc@9540
7540+0000ef7c@9541
7541+0000effc@9542
7542+0000cffc@9543
7543+0000cf7c@9544
7544+0000dffc@9545
7545+00007ffe@9547
7546+0000ff7e@9548
7547+0000f0ee@9549
7548+0000706e@9552
7549+0000e0ee@9553
7550+0000eaf2@9554
7551+0000ea72@9556
7552+0000ea70@9557
7553+0000eaf0@9558
7554+0000e0c0@9559
7555+0000e040@9560
7556+00004040@9561
7557+0000c0c0@9562
7558+0000d0c0@9563
7559+0000d040@9565
7560+00007042@9566
7561+0000f0c2@9567
7562+0000f0ee@9568
7563+0000706e@9570
7564+0000e06e@9571
7565+0000eaf6@9572
7566+0000ea76@9574
7567+00006a76@9575
7568+0000eaf4@9576
7569+0000eefc@9577
7570+0000ee7c@9579
7571+00004e7c@9580
7572+0000cefc@9581
7573+0000defc@9582
7574+00007e7e@9584
7575+0000fe7e@9585
7576+0000fafe@9586
7577+0000f0ee@9587
7578+0000f06e@9588
7579+0000706e@9589
7580+0000e0ee@9590
7581+0000eafa@9591
7582+0000ea7a@9593
7583+00006a78@9594
7584+0000eaf8@9595
7585+0000e0c0@9596
7586+00006040@9598
7587+0000c040@9599
7588+0000c0c0@9600
7589+0000d0c0@9601
7590+0000d040@9602
7591+00007042@9603
7592+0000f0c2@9604
7593+0000f0ee@9605
7594+0000f06e@9607
7595+0000706e@9608
7596+0000e0ee@9609
7597+0000eafe@9610
7598+00006a7e@9612
7599+0000ea7c@9613
7600+0000eefc@9614
7601+0000ee7c@9616
7602+00004e7c@9617
7603+0000cefc@9618
7604+0000defc@9619
7605+0000de7c@9621
7606+00007e7e@9622
7607+0000fefe@9623
7608+0000f0f2@9624
7609+000070f2@9626
7610+0000e0f2@9627
7611+0000eaf2@9628
7612+0000ea72@9629
7613+0000eaf2@9630
7614+00006af0@9631
7615+0000eaf0@9632
7616+0000e040@9633
7617+0000e0c0@9635
7618+000040c0@9636
7619+0000c0c0@9637
7620+0000d040@9638
7621+000070c2@9640
7622+0000f0c2@9641
7623+0000f072@9642
7624+0000f0f2@9644
7625+000070f2@9645
7626+0000e0f2@9646
7627+0000ea76@9647
7628+0000eaf6@9649
7629+00006af4@9650
7630+0000eefc@9651
7631+0000ee7c@9652
7632+00004efc@9654
7633+0000cefc@9655
7634+0000de7c@9656
7635+0000defc@9658
7636+00007efe@9659
7637+0000fefe@9660
7638+0000f072@9661
7639+0000f0f2@9663
7640+0000e2fa@9665
7641+0000ea7a@9666
7642+00006afa@9668
7643+0000eaf8@9669
7644+0000e040@9670
7645+0000e140@9671
7646+0000e1c0@9672
7647+000041c0@9673
7648+0000c1c0@9674
7649+0000d140@9675
7650+0000d1c0@9677
7651+0000f1c2@9678
7652+0000f1f2@9679
7653+0000f172@9680
7654+000071f2@9682
7655+0000e1f2@9683
7656+0000eb7e@9684
7657+0000ebfe@9686
7658+00006bfc@9687
7659+0000ebfc@9688
7660+0000ef7c@9689
7661+0000effc@9691
7662+0000cffc@9692
7663+0000df7c@9694
7664+00007ffe@9696
7665+0000fffe@9697
7666+0000f176@9698
7667+0000f1f6@9700
7668+000071f6@9701
7669+0000e1f6@9702
7670+0000ebf2@9703
7671+0000ebf0@9706
7672+0000e1c0@9708
7673+00004140@9710
7674+0000c1c0@9711
7675+0000d1c0@9712
7676+0000d140@9714
7677+000071c2@9715
7678+0000f1c2@9716
7679+0000f1f6@9717
7680+000071f6@9719
7681+0000e1f6@9720
7682+0000eb76@9721
7683+0000ebf6@9722
7684+00006bf6@9724
7685+0000eb74@9725
7686+0000effc@9726
7687+00004f7c@9729
7688+0000cffc@9730
7689+0000dffc@9731
7690+00007ffe@9733
7691+0000fffe@9734
7692+0000fbfe@9735
7693+0000f1f6@9736
7694+000071f6@9738
7695+0000e1f6@9739
7696+0000eb7a@9740
7697+0000ebfa@9741
7698+00006bf8@9743
7699+0000ebf8@9744
7700+0000e1c0@9745
7701+000061c0@9747
7702+0000c1c0@9748
7703+0000d1c0@9750
7704+0000d140@9751
7705+000071c2@9752
7706+0000f1c2@9753
7707+0000f1f6@9754
7708+0000f176@9755
7709+0000f1f6@9756
7710+000071f6@9757
7711+0000e1f6@9758
7712+0000ebfe@9759
7713+00006bfe@9761
7714+0000eb7c@9762
7715+0000effc@9763
7716+00004f7c@9766
7717+0000cffc@9767
7718+0000dffc@9768
7719+0000df7c@9770
7720+00007ffe@9771
7721+0000fffe@9772
7722+0000f17a@9773
7723+0000f1fa@9774
7724+000071fa@9775
7725+0000e1fa@9776
7726+0000eb72@9777
7727+0000ebf2@9778
7728+00006bf0@9780
7729+0000eb70@9781
7730+0000e1c0@9782
7731+00004140@9785
7732+0000c1c0@9786
7733+0000d1c0@9787
7734+0000d140@9788
7735+000071c2@9789
7736+0000f1c2@9790
7737+0000f1fa@9791
7738+0000f17a@9792
7739+0000f1fa@9793
7740+000071fa@9794
7741+0000e1fa@9795
7742+0000eb76@9796
7743+0000ebf6@9797
7744+00006bf4@9799
7745+0000effc@9800
7746+00004f7c@9803
7747+0000cffc@9804
7748+0000dffc@9806
7749+0000df7c@9807
7750+00007ffe@9808
7751+0000fffe@9809
7752+0000f17a@9810
7753+0000f1fa@9812
7754+0000f1f8@9813
7755+0000fbfc@9814
7756+0000fbf4@9815
7757+0000ebf4@9816
7758+00006bf4@9817
7759+0000eb74@9818
7760+0000ebf4@9819
7761+00006b74@9822
7762+0000ebf4@9823
7763+0000fbf4@9824
7764+0000fb74@9826
7765+0000fbf6@9827
7766+0000fbfe@9828
7767+0000f17a@9829
7768+0000f1fa@9830
7769+000071fa@9831
7770+0000e1fa@9832
7771+0000eb7a@9833
7772+0000ebfa@9834
7773+00006bf8@9836
7774+0000eb78@9837
7775+0000e1c0@9838
7776+0000c1c0@9841
7777+0000d1c0@9843
7778+0000d140@9844
7779+000071c2@9845
7780+0000f1c2@9846
7781+0000f1fa@9847
7782+0000f17a@9848
7783+0000f1fa@9849
7784+000071fa@9850
7785+0000e1fa@9851
7786+0000ebfe@9852
7787+0000ebfc@9855
7788+0000effc@9856
7789+00004f7c@9859
7790+0000cffc@9860
7791+0000dffc@9861
7792+0000df7c@9863
7793+00007ffe@9864
7794+0000fffe@9865
7795+0000f17e@9866
7796+0000f1fe@9867
7797+0000e1fe@9869
7798+0000eb72@9870
7799+0000ebf2@9872
7800+00006bf2@9873
7801+0000eb70@9874
7802+0000e1c0@9875
7803+00004140@9878
7804+0000c1c0@9879
7805+0000d1c0@9880
7806+000071c2@9882
7807+0000f1c2@9883
7808+0000f1fe@9884
7809+0000f17e@9885
7810+0000f1fe@9886
7811+000071fe@9887
7812+0000e1fe@9888
7813+0000eb76@9889
7814+0000ebf6@9890
7815+00006bf4@9892
7816+0000ebf4@9893
7817+0000effc@9894
7818+00006ffc@9896
7819+0000cffc@9897
7820+0000dffc@9899
7821+0000df7c@9900
7822+00007ffe@9901
7823+0000fffe@9902
7824+0000f1fe@9903
7825+0000f17e@9904
7826+0000f1fe@9905
7827+000071fe@9906
7828+0000e1fe@9907
7829+0000ebfa@9908
7830+00006bfa@9910
7831+0000eb78@9911
7832+0000e9c0@9912
7833+0000e1c0@9913
7834+00004140@9915
7835+0000c1c0@9916
7836+0000d1c0@9917
7837+0000d140@9919
7838+000071c2@9920
7839+0000f1c6@9921
7840+0000f17e@9922
7841+0000f1fe@9923
7842+000071fe@9924
7843+0000e1fe@9925
7844+0000eb7e@9926
7845+0000ebfe@9927
7846+00006bfc@9929
7847+0000eb7c@9930
7848+0000effc@9931
7849+00004f7c@9934
7850+0000cffc@9935
7851+0000dffc@9936
7852+0000df7c@9937
7853+00007ffe@9938
7854+0000fffe@9939
7855+0000f3c2@9940
7856+0000f342@9941
7857+0000f3c2@9942
7858+000073c2@9943
7859+0000e3c2@9944
7860+0000eb72@9945
7861+0000ebf2@9946
7862+00006bf0@9948
7863+0000ebf0@9949
7864+0000e1c0@9950
7865+000041c0@9952
7866+0000c1c0@9953
7867+0000d1c0@9955
7868+0000d140@9956
7869+000071c2@9957
7870+0000f1c2@9958
7871+0000f3c2@9959
7872+0000f342@9960
7873+0000f3c2@9961
7874+0000eb76@9963
7875+0000ebf6@9964
7876+00006bf6@9966
7877+0000eb74@9967
7878+0000effc@9968
7879+00004f7c@9971
7880+0000cffc@9972
7881+0000dffc@9973
7882+0000df7c@9975
7883+0000fffe@9976
7884+0000f3c2@9978
7885+000073c2@9980
7886+0000e3c2@9981
7887+0000eb7a@9982
7888+0000ebfa@9983
7889+00006bf8@9985
7890+0000eb78@9986
7891+0000e1c0@9987
7892+0000c1c0@9990
7893+0000d1c0@9992
7894+0000d140@9993
7895+000071c2@9994
7896+0000f1c2@9995
7897+0000f3c2@9996
7898+0000f342@9997
7899+0000f3c2@9998
7900+000073c2@9999
7901+0000e3c2@10000
7902+0000eb7e@10001
7903+0000ebfe@10002
7904+0000ebfc@10004
7905+0000effc@10005
7906+00004f7c@10008
7907+0000cffc@10009
7908+0000dffc@10010
7909+0000df7c@10012
7910+00007ffe@10013
7911+0000fffe@10014
7912+0000f346@10015
7913+0000f3c6@10016
7914+0000e3c6@10018
7915+0000eb72@10019
7916+0000ebf2@10020
7917+00006bf2@10022
7918+0000eb70@10023
7919+0000e1c0@10024
7920+00004140@10027
7921+0000c1c0@10028
7922+0000d1c0@10029
7923+000071c2@10031
7924+0000f1c2@10032
7925+0000f3c6@10033
7926+0000f346@10034
7927+0000f3c6@10035
7928+000073c6@10036
7929+0000e3c6@10037
7930+0000eb76@10038
7931+0000ebf6@10039
7932+00006bf4@10041
7933+0000ebf4@10042
7934+0000effc@10043
7935+00006ffc@10045
7936+0000cffc@10046
7937+0000dffc@10048
7938+0000df7c@10049
7939+00007ffe@10050
7940+0000fffe@10051
7941+0000f346@10052
7942+0000f3c6@10054
7943+000073c6@10055
7944+0000e3c6@10056
7945+0000ebfa@10057
7946+00006bfa@10059
7947+0000eb78@10060
7948+0000e9c0@10061
7949+0000e1c0@10062
7950+00004140@10064
7951+0000c1c0@10065
7952+0000d1c0@10066
7953+0000d140@10068
7954+000071c2@10069
7955+0000f1c6@10070
7956+0000f3c6@10071
7957+000073c6@10073
7958+0000e3c6@10074
7959+0000eb7e@10075
7960+0000ebfe@10076
7961+00006bfc@10078
7962+0000eb7c@10079
7963+0000effc@10080
7964+00004f7c@10083
7965+0000cffc@10084
7966+0000dffc@10085
7967+00007ffe@10087
7968+0000fffe@10088
7969+0000f3ca@10089
7970+0000f34a@10090
7971+0000f3ca@10091
7972+000073ca@10092
7973+0000e3ca@10093
7974+0000eb72@10094
7975+0000ebf2@10095
7976+00006bf0@10097
7977+0000ebf0@10098
7978+0000e1c0@10099
7979+000041c0@10101
7980+0000c1c0@10102
7981+0000d1c0@10104
7982+0000d140@10105
7983+000071c2@10106
7984+0000f1c2@10107
7985+0000f3ca@10108
7986+0000f34a@10109
7987+0000f3ca@10110
7988+0000eb7e@10112
7989+0000ebf6@10113
7990+00006bf6@10115
7991+0000eb74@10116
7992+0000effc@10117
7993+00004f7c@10120
7994+0000cffc@10121
7995+0000dffc@10122
7996+0000df7c@10124
7997+0000fffe@10125
7998+0000f3ca@10127
7999+000073ca@10129
8000+0000e3ca@10130
8001+0000eb7a@10131
8002+0000ebfa@10132
8003+00006bf8@10134
8004+0000eb78@10135
8005+0000e1c0@10136
8006+0000c1c0@10139
8007+0000d1c0@10141
8008+0000d140@10142
8009+000071c2@10143
8010+0000f1c2@10144
8011+0000f3ca@10145
8012+0000f34a@10146
8013+0000f3ca@10147
8014+000073ca@10148
8015+0000e3ca@10149
8016+0000eb7e@10150
8017+0000ebfe@10151
8018+0000ebfc@10153
8019+0000effc@10154
8020+00004f7c@10157
8021+0000cffc@10158
8022+0000dffc@10159
8023+0000df7c@10161
8024+00007ffe@10162
8025+0000fffe@10163
8026+0000f34e@10164
8027+0000f3ce@10165
8028+0000e3ce@10167
8029+0000eb72@10168
8030+0000ebf2@10169
8031+00006bf2@10171
8032+0000eb70@10172
8033+0000e1c0@10173
8034+00004140@10176
8035+0000c1c0@10177
8036+0000d1c0@10178
8037+000071c2@10180
8038+0000f1c2@10181
8039+0000f3ce@10182
8040+0000f34e@10183
8041+0000f3ce@10184
8042+000073ce@10185
8043+0000e3ce@10186
8044+0000eb76@10187
8045+0000ebf6@10188
8046+00006bf4@10190
8047+0000ebf4@10191
8048+0000effc@10192
8049+00006ffc@10194
8050+0000cffc@10195
8051+0000dffc@10197
8052+0000df7c@10198
8053+00007ffe@10199
8054+0000fffe@10200
8055+0000f34e@10201
8056+0000f3ce@10203
8057+000073ce@10204
8058+0000e3ce@10205
8059+0000ebfa@10206
8060+00006bfa@10208
8061+0000eb78@10209
8062+0000e9c0@10210
8063+0000e1c0@10211
8064+00004140@10213
8065+0000c1c0@10214
8066+0000d1c0@10215
8067+0000d140@10217
8068+000071c2@10218
8069+0000f1c6@10219
8070+0000f34e@10220
8071+0000f3ce@10221
8072+000073ce@10222
8073+0000e3ce@10223
8074+0000eb7e@10224
8075+0000ebfe@10225
8076+00006bfc@10227
8077+0000eb7c@10228
8078+0000effc@10229
8079+00004f7c@10232
8080+0000cffc@10233
8081+0000dffc@10234
8082+00007ffe@10236
8083+0000fffe@10237
8084+0000f3d2@10238
8085+0000f352@10239
8086+0000f3d2@10240
8087+000073d2@10241
8088+0000e3d2@10242
8089+0000eb72@10243
8090+0000ebf2@10244
8091+00006bf0@10246
8092+0000ebf0@10247
8093+0000e1c0@10248
8094+000041c0@10250
8095+0000c1c0@10251
8096+0000d1c0@10253
8097+0000d140@10254
8098+000071c2@10255
8099+0000f1c2@10256
8100+0000f3d2@10257
8101+0000f352@10258
8102+0000f3d2@10259
8103+0000eb76@10261
8104+0000ebf6@10262
8105+00006bf6@10264
8106+0000eb74@10265
8107+0000effc@10266
8108+00004f7c@10269
8109+0000cffc@10270
8110+0000dffc@10271
8111+0000df7c@10273
8112+0000fffe@10274
8113+0000f3d2@10276
8114+000073d2@10278
8115+0000e3d2@10279
8116+0000eb7a@10280
8117+0000ebfa@10281
8118+00006bf8@10283
8119+0000eb78@10284
8120+0000e1c0@10285
8121+0000c1c0@10288
8122+0000d1c0@10290
8123+0000d140@10291
8124+000071c2@10292
8125+0000f1c2@10293
8126+0000f3d2@10294
8127+0000f352@10295
8128+0000f3d2@10296
8129+000073d2@10297
8130+0000e3d2@10298
8131+0000eb7e@10299
8132+0000ebfe@10300
8133+0000ebfc@10302
8134+0000effc@10303
8135+00004f7c@10306
8136+0000cffc@10307
8137+0000dffc@10308
8138+0000df7c@10310
8139+00007ffe@10311
8140+0000fffe@10312
8141+0000f356@10313
8142+0000f3d6@10314
8143+0000e3d6@10316
8144+0000eb72@10317
8145+0000ebf2@10318
8146+00006bf2@10320
8147+0000eb70@10321
8148+0000e1c0@10322
8149+00004140@10325
8150+0000c1c0@10326
8151+0000d1c0@10327
8152+000071c2@10329
8153+0000f1c2@10330
8154+0000f3d6@10331
8155+0000f356@10332
8156+0000f3d6@10333
8157+000073d6@10334
8158+0000e3d6@10335
8159+0000eb76@10336
8160+0000ebf6@10337
8161+00006bf4@10339
8162+0000ebf4@10340
8163+0000effc@10341
8164+00006ffc@10343
8165+0000cffc@10344
8166+0000dffc@10346
8167+0000df7c@10347
8168+00007ffe@10348
8169+0000fffe@10349
8170+0000f356@10350
8171+0000f3d6@10352
8172+000073d6@10353
8173+0000e3d6@10354
8174+0000ebfa@10355
8175+00006bfa@10357
8176+0000eb78@10358
8177+0000e9c0@10359
8178+0000e1c0@10360
8179+00004140@10362
8180+0000c1c0@10363
8181+0000d1c0@10364
8182+0000d140@10366
8183+000071c2@10367
8184+0000f1c6@10368
8185+0000f356@10369
8186+0000f3d6@10370
8187+000073d6@10371
8188+0000e3d6@10372
8189+0000eb7e@10373
8190+0000ebfe@10374
8191+00006bfc@10376
8192+0000eb7c@10377
8193+0000effc@10378
8194+00004f7c@10381
8195+0000cffc@10382
8196+0000dffc@10383
8197+0000df7c@10384
8198+00007ffe@10385
8199+0000fffe@10386
8200+0000f3da@10387
8201+0000f35a@10388
8202+0000f3da@10389
8203+000073da@10390
8204+0000e3da@10391
8205+0000eb72@10392
8206+0000ebf2@10393
8207+00006bf0@10395
8208+0000ebf0@10396
8209+0000e1c0@10397
8210+000041c0@10399
8211+0000c1c0@10400
8212+0000d1c0@10402
8213+0000d140@10403
8214+000071c2@10404
8215+0000f1c2@10405
8216+0000f3da@10406
8217+0000f35a@10407
8218+0000f3da@10408
8219+0000f3d8@10409
8220+0000fbf8@10410
8221+0000fbf0@10411
8222+0000ebf0@10412
8223+00006bf0@10413
8224+0000eb70@10414
8225+0000effc@10415
8226+0000ebfc@10416
8227+00006b7c@10418
8228+0000effc@10419
8229+0000fffc@10420
8230+0000ff7c@10422
8231+0000fffe@10423
8232+0000fbfe@10424
8233+0000f35a@10425
8234+0000f3da@10426
8235+000073da@10427
8236+0000e3da@10428
8237+0000eb76@10429
8238+0000ebf6@10430
8239+00006bf4@10432
8240+0000eb74@10433
8241+0000effc@10434
8242+0000cffc@10437
8243+0000dffc@10439
8244+0000df7c@10440
8245+00007ffe@10441
8246+0000fffe@10442
8247+0000f3da@10443
8248+0000f35a@10444
8249+0000f3da@10445
8250+000073da@10446
8251+0000e3da@10447
8252+0000ebfa@10448
8253+0000ebf8@10451
8254+0000e1c0@10453
8255+00004140@10455
8256+0000c1c0@10456
8257+0000d1c0@10457
8258+0000d140@10459
8259+000071c2@10460
8260+0000f1c2@10461
8261+0000f3da@10462
8262+000073da@10464
8263+0000e3da@10465
8264+0000eb7e@10466
8265+0000ebfe@10467
8266+00006bfe@10469
8267+0000eb7c@10470
8268+0000effc@10471
8269+00004f7c@10474
8270+0000cffc@10475
8271+0000dffc@10476
8272+00007ffe@10478
8273+0000fffe@10479
8274+0000fbde@10480
8275+0000f3de@10481
8276+000073de@10483
8277+0000e3de@10484
8278+0000eb72@10485
8279+0000ebf2@10486
8280+00006bf0@10488
8281+0000ebf0@10489
8282+0000e1c0@10490
8283+000061c0@10492
8284+0000c1c0@10493
8285+0000d1c0@10495
8286+0000d140@10496
8287+000071c2@10497
8288+0000f1c2@10498
8289+0000f3de@10499
8290+0000f35e@10500
8291+0000f3de@10501
8292+000073de@10502
8293+0000e3de@10503
8294+0000ebf6@10504
8295+00006bf6@10506
8296+0000eb74@10507
8297+0000effc@10508
8298+00004f7c@10511
8299+0000cffc@10512
8300+0000dffc@10513
8301+0000df7c@10515
8302+00007ffe@10516
8303+0000fffe@10517
8304+0000f35e@10518
8305+0000f3de@10519
8306+000073de@10520
8307+0000e3de@10521
8308+0000eb7a@10522
8309+0000ebfa@10523
8310+00006bf8@10525
8311+0000eb78@10526
8312+0000e1c0@10527
8313+00004140@10530
8314+0000c1c0@10531
8315+0000d1c0@10532
8316+0000d140@10533
8317+000071c2@10534
8318+0000f1c2@10535
8319+0000f3de@10536
8320+0000f35e@10537
8321+0000f3de@10538
8322+000073de@10539
8323+0000e3de@10540
8324+0000eb7e@10541
8325+0000ebfe@10542
8326+00006bfc@10544
8327+0000effc@10545
8328+00004f7c@10548
8329+0000cffc@10549
8330+0000dffc@10550
8331+0000df7c@10552
8332+00007ffe@10553
8333+0000fffe@10554
8334+0000f362@10555
8335+0000f3e2@10557
8336+0000e3e2@10558
8337+0000eb72@10559
8338+0000ebf2@10560
8339+00006bf2@10562
8340+0000eb70@10563
8341+0000e1c0@10564
8342+00004140@10567
8343+0000c1c0@10568
8344+0000d1c0@10569
8345+0000f1c0@10571
8346+0000f1c2@10572
8347+0000f3e2@10573
8348+0000f362@10574
8349+0000f3e2@10575
8350+000073e2@10576
8351+0000e3e2@10577
8352+0000eb76@10578
8353+0000ebf6@10579
8354+00006bf4@10581
8355+0000eb74@10582
8356+0000effc@10583
8357+0000cffc@10586
8358+0000dffc@10588
8359+0000df7c@10589
8360+00007ffe@10590
8361+0000fffe@10591
8362+0000f3e2@10592
8363+0000f362@10593
8364+0000f3e2@10594
8365+000073e2@10595
8366+0000e3e2@10596
8367+0000eb7a@10597
8368+0000ebfa@10598
8369+0000ebf8@10600
8370+0000e1c0@10602
8371+00004140@10604
8372+0000c1c0@10605
8373+0000d1c0@10606
8374+0000d140@10608
8375+000071c2@10609
8376+0000f1c2@10610
8377+0000f3e2@10611
8378+0000f362@10612
8379+000073e2@10613
8380+0000e3e2@10614
8381+0000eb7e@10615
8382+0000ebfe@10616
8383+00006bfe@10618
8384+0000eb7c@10619
8385+0000effc@10620
8386+00004f7c@10623
8387+0000cffc@10624
8388+0000dffc@10625
8389+00007ffe@10627
8390+0000fffe@10628
8391+0000fbe6@10629
8392+0000f366@10630
8393+0000f3e6@10631
8394+000073e6@10632
8395+0000e3e6@10633
8396+0000eb72@10634
8397+0000ebf2@10635
8398+00006bf0@10637
8399+0000ebf0@10638
8400+0000e1c0@10639
8401+000061c0@10641
8402+0000c1c0@10642
8403+0000d1c0@10644
8404+0000d140@10645
8405+000071c2@10646
8406+0000f1c2@10647
8407+0000f3e6@10648
8408+0000f366@10649
8409+0000f3e6@10650
8410+000073e6@10651
8411+0000e3e6@10652
8412+0000ebf6@10653
8413+00006bf6@10655
8414+0000eb74@10656
8415+0000effc@10657
8416+00004f7c@10660
8417+0000cffc@10661
8418+0000dffc@10662
8419+0000df7c@10664
8420+00007ffe@10665
8421+0000fffe@10666
8422+0000f3e6@10667
8423+000073e6@10669
8424+0000e3e6@10670
8425+0000eb7a@10671
8426+0000ebfa@10672
8427+00006bf8@10674
8428+0000eb78@10675
8429+0000e1c0@10676
8430+00004140@10679
8431+0000c1c0@10680
8432+0000d1c0@10681
8433+0000d140@10682
8434+000071c2@10683
8435+0000f1c2@10684
8436+0000f3e6@10685
8437+0000f366@10686
8438+0000f3e6@10687
8439+000073e6@10688
8440+0000e3e6@10689
8441+0000eb7e@10690
8442+0000ebfe@10691
8443+00006bfc@10693
8444+0000effc@10694
8445+00004f7c@10697
8446+0000cffc@10698
8447+0000dffc@10699
8448+0000df7c@10701
8449+00007ffe@10702
8450+0000fffe@10703
8451+0000f36a@10704
8452+0000f3ea@10706
8453+0000e3ea@10707
8454+0000ebfa@10708
8455+0000ebf2@10709
8456+00006bf2@10711
8457+0000eb70@10712
8458+0000e1c0@10713
8459+00004140@10716
8460+0000c1c0@10717
8461+0000d1c0@10718
8462+0000f140@10720
8463+0000f1c2@10721
8464+0000f3ea@10722
8465+0000f36a@10723
8466+0000f3ea@10724
8467+000073ea@10725
8468+0000e3ea@10726
8469+0000eb76@10727
8470+0000ebf6@10728
8471+00006bf4@10730
8472+0000eb74@10731
8473+0000effc@10732
8474+0000cffc@10735
8475+0000dffc@10737
8476+0000df7c@10738
8477+00007ffe@10739
8478+0000fffe@10740
8479+0000f3ea@10741
8480+0000f36a@10742
8481+0000f3ea@10743
8482+000073ea@10744
8483+0000e3ea@10745
8484+0000ebfa@10746
8485+0000ebf8@10749
8486+0000e1c0@10751
8487+00004140@10753
8488+0000c1c0@10754
8489+0000d1c0@10755
8490+0000d140@10757
8491+000071c2@10758
8492+0000f1c2@10759
8493+0000f3ea@10760
8494+000073ea@10762
8495+0000e3ea@10763
8496+0000eb7e@10764
8497+0000ebfe@10765
8498+00006bfe@10767
8499+0000eb7c@10768
8500+0000effc@10769
8501+00004f7c@10772
8502+0000cffc@10773
8503+0000dffc@10774
8504+00007ffe@10776
8505+0000fffe@10777
8506+0000fbee@10778
8507+0000f36e@10779
8508+0000f3ee@10780
8509+000073ee@10781
8510+0000e3ee@10782
8511+0000eb72@10783
8512+0000ebf2@10784
8513+00006bf0@10786
8514+0000ebf0@10787
8515+0000e1c0@10788
8516+000061c0@10790
8517+0000c1c0@10791
8518+0000d1c0@10793
8519+0000d140@10794
8520+000071c2@10795
8521+0000f1c2@10796
8522+0000f3ee@10797
8523+0000f36e@10798
8524+0000f3ee@10799
8525+000073ee@10800
8526+0000e3ee@10801
8527+0000ebf6@10802
8528+00006bf6@10804
8529+0000eb74@10805
8530+0000effc@10806
8531+00004f7c@10809
8532+0000cffc@10810
8533+0000dffc@10811
8534+0000df7c@10813
8535+00007ffe@10814
8536+0000fffe@10815
8537+0000f36e@10816
8538+0000f3ee@10817
8539+000073ee@10818
8540+0000e3ee@10819
8541+0000eb7a@10820
8542+0000ebfa@10821
8543+00006bf8@10823
8544+0000eb78@10824
8545+0000e1c0@10825
8546+00004140@10828
8547+0000c1c0@10829
8548+0000d1c0@10830
8549+0000d140@10831
8550+000071c2@10832
8551+0000f1c2@10833
8552+0000f3ee@10834
8553+0000f36e@10835
8554+0000f3ee@10836
8555+000073ee@10837
8556+0000e3ee@10838
8557+0000eb7e@10839
8558+0000ebfe@10840
8559+00006bfc@10842
8560+0000effc@10843
8561+00004f7c@10846
8562+0000cffc@10847
8563+0000dffc@10848
8564+0000df7c@10850
8565+00007ffe@10851
8566+0000fffe@10852
8567+0000f372@10853
8568+0000f3f2@10855
8569+0000e3f2@10856
8570+0000ebf2@10857
8571+00006bf2@10860
8572+0000eb70@10861
8573+0000e1c0@10862
8574+00004140@10865
8575+0000c1c0@10866
8576+0000d1c0@10867
8577+0000f1c0@10869
8578+0000f1c2@10870
8579+0000f3f2@10871
8580+0000f372@10872
8581+0000f3f2@10873
8582+000073f2@10874
8583+0000e3f2@10875
8584+0000eb76@10876
8585+0000ebf6@10877
8586+00006bf4@10879
8587+0000eb74@10880
8588+0000effc@10881
8589+0000cffc@10884
8590+0000dffc@10886
8591+0000df7c@10887
8592+00007ffe@10888
8593+0000fffe@10889
8594+0000f3f2@10890
8595+0000f372@10891
8596+0000f3f2@10892
8597+000073f2@10893
8598+0000e3f2@10894
8599+0000ebfa@10895
8600+0000eb78@10898
8601+0000ebf8@10899
8602+0000e1c0@10900
8603+00004140@10902
8604+0000c1c0@10903
8605+0000d1c0@10904
8606+0000d140@10906
8607+000071c2@10907
8608+0000f1c2@10908
8609+0000f3f2@10909
8610+000073f2@10911
8611+0000e3f2@10912
8612+0000eb7e@10913
8613+0000ebfe@10914
8614+00006bfe@10916
8615+0000eb7c@10917
8616+0000effc@10918
8617+00004f7c@10921
8618+0000cffc@10922
8619+0000dffc@10923
8620+00007ffe@10925
8621+0000fffe@10926
8622+0000fbf6@10927
8623+0000f376@10928
8624+0000f3f6@10929
8625+000073f6@10930
8626+0000e3f6@10931
8627+0000eb72@10932
8628+0000ebf2@10933
8629+00006bf0@10935
8630+0000ebf0@10936
8631+0000e1c0@10937
8632+000061c0@10939
8633+0000c1c0@10940
8634+0000d1c0@10942
8635+0000d140@10943
8636+000071c2@10944
8637+0000f1c2@10945
8638+0000f3f6@10946
8639+0000f376@10947
8640+0000f3f6@10948
8641+000073f6@10949
8642+0000e3f6@10950
8643+0000ebf6@10951
8644+00006bf6@10953
8645+0000eb74@10954
8646+0000effc@10955
8647+00004f7c@10958
8648+0000cffc@10959
8649+0000dffc@10960
8650+0000df7c@10962
8651+00007ffe@10963
8652+0000fffe@10964
8653+0000f376@10965
8654+0000f3f6@10966
8655+000073f6@10967
8656+0000e3f6@10968
8657+0000eb7a@10969
8658+0000ebfa@10970
8659+00006bf8@10972
8660+0000eb78@10973
8661+0000e1c0@10974
8662+00004140@10977
8663+0000c1c0@10978
8664+0000d1c0@10979
8665+0000d140@10980
8666+000071c2@10981
8667+0000f1c2@10982
8668+0000f3f6@10983
8669+0000f376@10984
8670+0000f3f6@10985
8671+000073f6@10986
8672+0000e3f6@10987
8673+0000eb7e@10988
8674+0000ebfe@10989
8675+00006bfc@10991
8676+0000effc@10992
8677+00004f7c@10995
8678+0000cffc@10996
8679+0000dffc@10997
8680+0000df7c@10999
8681+00007ffe@11000
8682+0000fffe@11001
8683+0000f376@11002
8684+0000f3f6@11004
8685+0000f3f4@11005
8686+0000fb7c@11006
8687+0000fbfc@11007
8688+0000ebfc@11008
8689+00006bfc@11009
8690+0000eb7c@11010
8691+0000ebfc@11011
8692+00006b7c@11014
8693+0000ebfc@11015
8694+0000fbfc@11016
8695+0000fb7c@11018
8696+0000fbfe@11019
8697+0000f37a@11021
8698+0000f3fa@11022
8699+000073fa@11023
8700+0000e3fa@11024
8701+0000eb72@11025
8702+0000ebf2@11026
8703+00006bf0@11028
8704+0000eb70@11029
8705+0000e1c0@11030
8706+0000c1c0@11033
8707+0000d1c0@11035
8708+0000d140@11036
8709+000071c2@11037
8710+0000f1c2@11038
8711+0000f3fa@11039
8712+0000f37a@11040
8713+0000f3fa@11041
8714+000073fa@11042
8715+0000e3fa@11043
8716+0000ebf6@11044
8717+0000eb74@11047
8718+0000ef7c@11048
8719+0000effc@11049
8720+00004f7c@11051
8721+0000cffc@11052
8722+0000dffc@11053
8723+0000df7c@11055
8724+00007ffe@11056
8725+0000fffe@11057
8726+0000f37a@11058
8727+0000f3fa@11059
8728+000073fa@11060
8729+0000e3fa@11061
8730+0000eb7a@11062
8731+0000ebfa@11063
8732+00006bfa@11065
8733+0000eb78@11066
8734+0000e1c0@11067
8735+00004140@11070
8736+0000c1c0@11071
8737+0000d1c0@11072
8738+000071c2@11074
8739+0000f1c2@11075
8740+0000f3fa@11076
8741+0000f37a@11077
8742+0000f3fa@11078
8743+000073fa@11079
8744+0000e3fa@11080
8745+0000eb7e@11081
8746+0000ebfe@11082
8747+00006bfc@11084
8748+0000ebfc@11085
8749+0000effc@11086
8750+00006ffc@11088
8751+0000cffc@11089
8752+0000dffc@11091
8753+0000df7c@11092
8754+00007ffe@11093
8755+0000fffe@11094
8756+0000f3fe@11095
8757+0000f37e@11096
8758+0000f3fe@11097
8759+000073fe@11098
8760+0000e3fe@11099
8761+0000ebf2@11100
8762+00006bf2@11102
8763+0000eb70@11103
8764+0000e1c0@11104
8765+00004140@11107
8766+0000c1c0@11108
8767+0000d1c0@11109
8768+0000d140@11111
8769+000071c2@11112
8770+0000f1ce@11113
8771+0000f37e@11114
8772+0000f3fe@11115
8773+000073fe@11116
8774+0000e3fe@11117
8775+0000eb76@11118
8776+0000ebf6@11119
8777+00006bf4@11121
8778+0000eb74@11122
8779+0000effc@11123
8780+00004f7c@11126
8781+0000cffc@11127
8782+0000dffc@11128
8783+0000df7c@11129
8784+00007ffe@11130
8785+0000fffe@11131
8786+0000f3fe@11132
8787+0000f37e@11133
8788+0000f3fe@11134
8789+000073fe@11135
8790+0000e3fe@11136
8791+0000eb7a@11137
8792+0000ebfa@11138
8793+00006bf8@11140
8794+0000ebf8@11141
8795+0000e0c0@11142
8796+000040c0@11144
8797+0000c0c0@11145
8798+0000d0c0@11146
8799+0000d040@11148
8800+00007042@11149
8801+0000f0c2@11150
8802+0000f2fe@11151
8803+0000f27e@11153
8804+0000e27e@11154
8805+0000eafe@11155
8806+00006a7e@11158
8807+0000eafc@11159
8808+0000eefc@11160
8809+0000ee7c@11162
8810+00004e7c@11163
8811+0000cefc@11164
8812+0000defc@11165
8813+0000fe7c@11167
8814+0000fe7e@11168
8815+0000fefe@11169
8816+0000f4c2@11170
8817+0000f442@11171
8818+00007442@11172
8819+0000e4c2@11173
8820+0000eaf2@11174
8821+0000ea72@11176
8822+00006a70@11177
8823+0000eaf0@11178
8824+0000e0c0@11179
8825+0000e040@11181
8826+0000c040@11182
8827+0000c0c0@11183
8828+0000d0c0@11184
8829+0000d040@11185
8830+00007042@11186
8831+0000f0c2@11187
8832+0000f4c2@11188
8833+0000f442@11190
8834+00007442@11191
8835+0000e4c2@11192
8836+0000eaf6@11193
8837+00006a76@11195
8838+0000ea74@11196
8839+0000eefc@11197
8840+0000ee7c@11199
8841+00004e7c@11200
8842+0000cefc@11201
8843+0000defc@11202
8844+0000de7c@11204
8845+00007e7e@11205
8846+0000fefe@11206
8847+0000f4c2@11207
8848+00007442@11209
8849+0000e442@11210
8850+0000eafa@11211
8851+0000ea7a@11213
8852+00006a78@11214
8853+0000eaf8@11215
8854+0000e0c0@11216
8855+0000e040@11218
8856+000040c0@11219
8857+0000c0c0@11220
8858+0000d0c0@11221
8859+0000d040@11222
8860+000070c2@11223
8861+0000f0c2@11224
8862+0000f442@11225
8863+0000f4c2@11227
8864+000074c2@11228
8865+0000e4c2@11229
8866+0000eafe@11230
8867+0000ea7e@11231
8868+0000eafe@11232
8869+00006afc@11233
8870+0000eafc@11234
8871+0000ee7c@11235
8872+00006efc@11237
8873+0000cefc@11238
8874+0000ce7c@11239
8875+0000de7c@11240
8876+0000defc@11241
8877+00007efe@11242
8878+0000fefe@11243
8879+0000f446@11244
8880+0000f4c6@11246
8881+000074c6@11247
8882+0000e4c6@11248
8883+0000ea72@11249
8884+00006af2@11251
8885+0000eaf0@11252
8886+0000e0c0@11253
8887+0000e040@11254
8888+0000e0c0@11255
8889+000040c0@11256
8890+0000c0c0@11257
8891+0000d040@11258
8892+0000d0c0@11260
8893+000070c2@11261
8894+0000f4c6@11262
8895+0000f546@11263
8896+000075c6@11265
8897+0000e5c6@11266
8898+0000eb76@11267
8899+0000ebf6@11269
8900+00006bf4@11270
8901+0000ebf4@11271
8902+0000ef7c@11272
8903+0000effc@11274
8904+00004ffc@11275
8905+0000cffc@11276
8906+0000df7c@11277
8907+00007ffe@11279
8908+0000fffe@11280
8909+0000f546@11281
8910+0000f5c6@11283
8911+000075c6@11284
8912+0000e5c6@11285
8913+0000eb7a@11286
8914+0000ebfa@11288
8915+00006bf8@11289
8916+0000ebf8@11290
8917+0000e140@11291
8918+000041c0@11293
8919+0000c1c0@11294
8920+0000d140@11295
8921+0000d1c0@11296
8922+000071c2@11298
8923+0000f142@11299
8924+0000f5c6@11300
8925+0000e546@11303
8926+0000effe@11304
8927+0000ebfe@11305
8928+0000eb7e@11306
8929+00006bfe@11307
8930+0000ebfc@11308
8931+0000effc@11309
8932+0000ef7c@11310
8933+0000effc@11311
8934+00004ffc@11312
8935+0000cffc@11313
8936+0000df7c@11314
8937+0000dffc@11315
8938+0000fffc@11316
8939+0000fffe@11317
8940+0000f5ca@11319
8941+0000754a@11321
8942+0000e5ca@11322
8943+0000ebf2@11323
8944+0000eb72@11325
8945+00006bf0@11326
8946+0000ebf0@11327
8947+0000e140@11328
8948+0000e1c0@11329
8949+0000c1c0@11331
8950+0000c140@11332
8951+0000d1c0@11333
8952+000071c2@11335
8953+0000f142@11336
8954+0000f5ca@11337
8955+0000754a@11340
8956+0000e5ca@11341
8957+0000ebf6@11342
8958+00006bf6@11344
8959+0000ebf4@11345
8960+0000effc@11346
8961+0000ef7c@11347
8962+0000effc@11348
8963+00004ffc@11349
8964+0000cffc@11350
8965+0000df7c@11351
8966+0000dffc@11352
8967+00007ffe@11354
8968+0000fffe@11355
8969+0000f5ca@11356
8970+000075ca@11358
8971+0000e5ca@11359
8972+0000ebfa@11360
8973+0000eb7a@11362
8974+00006bfa@11363
8975+0000ebf8@11364
8976+0000e140@11365
8977+0000e1c0@11367
8978+000041c0@11368
8979+0000c1c0@11369
8980+0000d1c0@11370
8981+000071c2@11372
8982+0000f142@11373
8983+0000f5ca@11374
8984+0000754a@11377
8985+0000e5ca@11378
8986+0000ebfe@11379
8987+0000eb7e@11381
8988+00006bfc@11382
8989+0000ebfc@11383
8990+0000effc@11384
8991+00006ffc@11386
8992+0000cffc@11387
8993+0000cf7c@11388
8994+0000dffc@11389
8995+00007ffe@11391
8996+0000ff7e@11392
8997+0000f5ce@11393
8998+0000754e@11396
8999+0000e5ee@11397
9000+0000ebf2@11398
9001+0000eb72@11399
9002+00006bf2@11400
9003+0000ebf0@11401
9004+0000e1c0@11402
9005+0000e140@11403
9006+0000e1c0@11404
9007+000041c0@11405
9008+0000c1c0@11406
9009+0000d140@11407
9010+0000d1c0@11408
9011+000071c2@11410
9012+0000f5ce@11411
9013+0000754e@11414
9014+0000e5ce@11415
9015+0000ebf6@11416
9016+0000eb76@11418
9017+00006bf4@11419
9018+0000ebf4@11420
9019+0000effc@11421
9020+0000ef7c@11422
9021+0000effc@11423
9022+00004ffc@11424
9023+0000cffc@11425
9024+0000dffc@11426
9025+00007ffe@11428
9026+0000ff7e@11429
9027+0000f5ce@11430
9028+0000754e@11433
9029+0000e5ce@11434
9030+0000ebfa@11435
9031+0000eb7a@11437
9032+00006bf8@11438
9033+0000ebf8@11439
9034+0000e1c0@11440
9035+000041c0@11442
9036+0000c1c0@11443
9037+0000d140@11444
9038+0000d1c0@11445
9039+000071c2@11447
9040+0000f142@11448
9041+0000f5ce@11449
9042+0000e5ce@11452
9043+0000effe@11453
9044+0000ebfe@11454
9045+0000eb7e@11455
9046+00006bfe@11456
9047+0000ebfc@11457
9048+0000effc@11458
9049+0000ef7c@11459
9050+0000effc@11460
9051+00004ffc@11461
9052+0000cffc@11462
9053+0000df7c@11463
9054+0000dffc@11464
9055+0000fffc@11465
9056+0000fffe@11466
9057+0000f5d2@11468
9058+00007552@11470
9059+0000e5d2@11471
9060+0000ebf2@11472
9061+0000eb72@11474
9062+00006bf0@11475
9063+0000ebf0@11476
9064+0000e140@11477
9065+0000e1c0@11478
9066+0000c1c0@11480
9067+0000c140@11481
9068+0000d1c0@11482
9069+000071c2@11484
9070+0000f142@11485
9071+0000f5d2@11486
9072+00007552@11489
9073+0000e5d2@11490
9074+0000ebf6@11491
9075+00006bf6@11493
9076+0000ebf4@11494
9077+0000effc@11495
9078+0000ef7c@11496
9079+0000effc@11497
9080+00004ffc@11498
9081+0000cffc@11499
9082+0000df7c@11500
9083+0000dffc@11501
9084+00007ffe@11503
9085+0000fffe@11504
9086+0000f5d2@11505
9087+000075d2@11507
9088+0000e5d2@11508
9089+0000ebfa@11509
9090+0000eb7a@11511
9091+00006bfa@11512
9092+0000ebf8@11513
9093+0000e140@11514
9094+0000e1c0@11516
9095+000041c0@11517
9096+0000c1c0@11518
9097+0000d1c0@11519
9098+000071c2@11521
9099+0000f142@11522
9100+0000f5d2@11523
9101+00007552@11526
9102+0000e5d2@11527
9103+0000ebfe@11528
9104+0000eb7e@11530
9105+00006bfc@11531
9106+0000ebfc@11532
9107+0000effc@11533
9108+00006ffc@11535
9109+0000cffc@11536
9110+0000cf7c@11537
9111+0000dffc@11538
9112+00007ffe@11540
9113+0000ff7e@11541
9114+0000f5d6@11542
9115+00007556@11545
9116+0000e5d6@11546
9117+0000ebf2@11547
9118+0000eb72@11548
9119+00006bf2@11549
9120+0000ebf0@11550
9121+0000e1c0@11551
9122+0000e140@11552
9123+0000e1c0@11553
9124+000041c0@11554
9125+0000c1c0@11555
9126+0000d140@11556
9127+0000d1c0@11557
9128+000071c2@11559
9129+0000f5c6@11560
9130+0000f5d6@11561
9131+00007556@11563
9132+0000e5d6@11564
9133+0000ebf6@11565
9134+0000eb76@11567
9135+00006bf4@11568
9136+0000ebf4@11569
9137+0000effc@11570
9138+0000ef7c@11571
9139+0000effc@11572
9140+00004ffc@11573
9141+0000cffc@11574
9142+0000dffc@11575
9143+00007ffe@11577
9144+0000ff7e@11578
9145+0000f5d6@11579
9146+00007556@11582
9147+0000e5d6@11583
9148+0000ebfa@11584
9149+0000eb7a@11586
9150+0000ebf8@11587
9151+0000e1c0@11589
9152+000041c0@11591
9153+0000c1c0@11592
9154+0000d140@11593
9155+0000d1c0@11594
9156+000071c2@11596
9157+0000f142@11597
9158+0000f5d6@11598
9159+0000f5d4@11601
9160+0000fffc@11602
9161+0000fbf8@11603
9162+0000eb78@11604
9163+00006bf8@11605
9164+0000ebf8@11606
9165+0000effc@11607
9166+0000eb7c@11608
9167+0000effc@11609
9168+00006bfc@11610
9169+0000effc@11611
9170+0000ff7c@11612
9171+0000fffc@11613
9172+0000ff7e@11615
9173+0000fffe@11616
9174+0000f5d6@11617
9175+00007556@11619
9176+0000e5d6@11620
9177+0000ebfe@11621
9178+0000eb7e@11623
9179+00006bfc@11624
9180+0000ebfc@11625
9181+0000effc@11626
9182+0000ef7c@11627
9183+0000effc@11628
9184+0000cffc@11629
9185+0000cf7c@11630
9186+0000dffc@11631
9187+00007ffe@11633
9188+0000ff7e@11634
9189+0000f5da@11635
9190+0000755a@11638
9191+0000e5da@11639
9192+0000ebf2@11640
9193+00006bf2@11642
9194+0000ebf0@11643
9195+0000ebc0@11644
9196+0000e140@11645
9197+0000e1c0@11646
9198+000041c0@11647
9199+0000c1c0@11648
9200+0000d140@11649
9201+0000d1c0@11650
9202+000071c2@11652
9203+0000f1c2@11653
9204+0000f5da@11654
9205+000075da@11656
9206+0000e5da@11657
9207+0000eff6@11658
9208+0000ebf6@11659
9209+0000eb76@11660
9210+00006bf6@11661
9211+0000ebf4@11662
9212+0000effc@11663
9213+0000ef7c@11664
9214+0000effc@11665
9215+00004ffc@11666
9216+0000cffc@11667
9217+0000dffc@11668
9218+00007ffe@11670
9219+0000ff7e@11671
9220+0000fdfe@11672
9221+0000f5da@11673
9222+0000755a@11675
9223+0000e5da@11676
9224+0000ebfa@11677
9225+0000eb7a@11679
9226+00006bf8@11680
9227+0000ebf8@11681
9228+0000e1c0@11682
9229+000061c0@11684
9230+0000c1c0@11685
9231+0000c140@11686
9232+0000d1c0@11687
9233+000071c2@11689
9234+0000f142@11690
9235+0000f5da@11691
9236+0000755a@11694
9237+0000e5de@11695
9238+0000ebfe@11696
9239+00006bfe@11698
9240+0000ebfc@11699
9241+0000effc@11700
9242+0000ef7c@11701
9243+0000effc@11702
9244+00004ffc@11703
9245+0000cffc@11704
9246+0000df7c@11705
9247+0000dffc@11706
9248+00007ffe@11708
9249+0000fffe@11709
9250+0000f5de@11710
9251+000075de@11712
9252+0000e5de@11713
9253+0000ebf2@11714
9254+0000eb72@11716
9255+00006bf0@11717
9256+0000ebf0@11718
9257+0000e140@11719
9258+0000e1c0@11721
9259+000041c0@11722
9260+0000c1c0@11723
9261+0000d1c0@11724
9262+000071c2@11726
9263+0000f142@11727
9264+0000f5de@11728
9265+0000755e@11731
9266+0000e5de@11732
9267+0000ebf6@11733
9268+0000eb76@11735
9269+0000ebf4@11736
9270+0000effc@11737
9271+0000ef7c@11738
9272+0000effc@11739
9273+00004ffc@11740
9274+0000cffc@11741
9275+0000df7c@11742
9276+0000dffc@11743
9277+00007ffe@11745
9278+0000ff7e@11746
9279+0000f5de@11747
9280+0000e5de@11750
9281+0000effa@11751
9282+0000ebfa@11752
9283+0000eb7a@11753
9284+00006bfa@11754
9285+0000ebf8@11755
9286+0000e1c0@11756
9287+0000e140@11757
9288+0000e1c0@11758
9289+000041c0@11759
9290+0000c1c0@11760
9291+0000d140@11761
9292+0000d1c0@11762
9293+0000f1c0@11763
9294+0000f1c2@11764
9295+0000f55e@11765
9296+0000f5de@11766
9297+0000755e@11768
9298+0000e5de@11769
9299+0000ebfe@11770
9300+0000eb7e@11772
9301+00006bfc@11773
9302+0000ebfc@11774
9303+0000effc@11775
9304+0000ef7c@11776
9305+0000effc@11777
9306+0000cffc@11778
9307+0000cf7c@11779
9308+0000dffc@11780
9309+00007ffe@11782
9310+0000ff7e@11783
9311+0000f5e2@11784
9312+00007562@11787
9313+0000e5e2@11788
9314+0000ebf2@11789
9315+00006bf2@11791
9316+0000ebf0@11792
9317+0000ebc0@11793
9318+0000e140@11794
9319+0000e1c0@11795
9320+000041c0@11796
9321+0000c1c0@11797
9322+0000d140@11798
9323+0000d1c0@11799
9324+000071c2@11801
9325+0000f1c2@11802
9326+0000f5e2@11803
9327+000075e2@11805
9328+0000e5e2@11806
9329+0000ebf6@11807
9330+0000eb76@11809
9331+00006bf4@11810
9332+0000ebf4@11811
9333+0000effc@11812
9334+0000ef7c@11813
9335+0000effc@11814
9336+00004ffc@11815
9337+0000cffc@11816
9338+0000dffc@11817
9339+00007ffe@11819
9340+0000ff7e@11820
9341+0000ffe2@11821
9342+0000f5e2@11822
9343+00007562@11824
9344+0000e5e2@11825
9345+0000ebfa@11826
9346+0000eb7a@11828
9347+00006bf8@11829
9348+0000ebf8@11830
9349+0000e1c0@11831
9350+000061c0@11833
9351+0000c1c0@11834
9352+0000c140@11835
9353+0000d1c0@11836
9354+000071c2@11838
9355+0000f142@11839
9356+0000f5e2@11840
9357+00007562@11843
9358+0000e5ee@11844
9359+0000ebfe@11845
9360+00006bfe@11847
9361+0000ebfc@11848
9362+0000effc@11849
9363+0000ef7c@11850
9364+0000effc@11851
9365+00004ffc@11852
9366+0000cffc@11853
9367+0000df7c@11854
9368+0000dffc@11855
9369+00007ffe@11857
9370+0000fffe@11858
9371+0000f5e6@11859
9372+000075e6@11861
9373+0000e5e6@11862
9374+0000ebf2@11863
9375+0000eb72@11865
9376+00006bf0@11866
9377+0000ebf0@11867
9378+0000e140@11868
9379+0000e1c0@11870
9380+000041c0@11871
9381+0000c1c0@11872
9382+0000d1c0@11873
9383+000071c2@11875
9384+0000f142@11876
9385+0000f5e6@11877
9386+00007566@11880
9387+0000e5e6@11881
9388+0000ebf6@11882
9389+0000eb76@11884
9390+0000ebf4@11885
9391+0000effc@11886
9392+0000ef7c@11887
9393+0000effc@11888
9394+00004ffc@11889
9395+0000cffc@11890
9396+0000df7c@11891
9397+0000dffc@11892
9398+00007ffe@11894
9399+0000ff7e@11895
9400+0000f5e6@11896
9401+0000e5e6@11899
9402+0000effe@11900
9403+0000ebfa@11901
9404+0000eb7a@11902
9405+00006bfa@11903
9406+0000ebf8@11904
9407+0000e1c0@11905
9408+0000e140@11906
9409+0000e1c0@11907
9410+000041c0@11908
9411+0000c1c0@11909
9412+0000d140@11910
9413+0000d1c0@11911
9414+0000f1c0@11912
9415+0000f1c2@11913
9416+0000f5e6@11914
9417+00007566@11917
9418+0000e5e6@11918
9419+0000ebfe@11919
9420+0000eb7e@11921
9421+00006bfc@11922
9422+0000ebfc@11923
9423+0000effc@11924
9424+0000ef7c@11925
9425+0000effc@11926
9426+0000cffc@11927
9427+0000cf7c@11928
9428+0000dffc@11929
9429+00007ffe@11931
9430+0000ff7e@11932
9431+0000f5ea@11933
9432+0000756a@11936
9433+0000e5ea@11937
9434+0000ebf2@11938
9435+00006bf2@11940
9436+0000ebf0@11941
9437+0000ebc0@11942
9438+0000e140@11943
9439+0000e1c0@11944
9440+000041c0@11945
9441+0000c1c0@11946
9442+0000d140@11947
9443+0000d1c0@11948
9444+000071c2@11950
9445+0000f1c2@11951
9446+0000f5ea@11952
9447+000075ea@11954
9448+0000e5ea@11955
9449+0000effe@11956
9450+0000ebf6@11957
9451+0000eb76@11958
9452+00006bf4@11959
9453+0000ebf4@11960
9454+0000effc@11961
9455+0000ef7c@11962
9456+0000effc@11963
9457+00004ffc@11964
9458+0000cffc@11965
9459+0000dffc@11966
9460+00007ffe@11968
9461+0000ff7e@11969
9462+0000fdea@11970
9463+0000f5ea@11971
9464+0000756a@11973
9465+0000e5ea@11974
9466+0000ebfa@11975
9467+0000eb7a@11977
9468+00006bf8@11978
9469+0000ebf8@11979
9470+0000e1c0@11980
9471+000061c0@11982
9472+0000c1c0@11983
9473+0000c140@11984
9474+0000d1c0@11985
9475+000071c2@11987
9476+0000f142@11988
9477+0000f5ea@11989
9478+0000756a@11992
9479+0000e5ee@11993
9480+0000ebfe@11994
9481+00006bfe@11996
9482+0000ebfc@11997
9483+0000effc@11998
9484+0000ef7c@11999
9485+0000effc@12000
9486+00004ffc@12001
9487+0000cffc@12002
9488+0000df7c@12003
9489+0000dffc@12004
9490+00007ffe@12006
9491+0000fffe@12007
9492+0000f5ee@12008
9493+000075ee@12010
9494+0000e5ee@12011
9495+0000ebf2@12012
9496+0000eb72@12014
9497+00006bf0@12015
9498+0000ebf0@12016
9499+0000e140@12017
9500+0000e1c0@12019
9501+000041c0@12020
9502+0000c1c0@12021
9503+0000d1c0@12022
9504+000071c2@12024
9505+0000f142@12025
9506+0000f5ee@12026
9507+0000756e@12029
9508+0000e5ee@12030
9509+0000ebf6@12031
9510+0000eb76@12033
9511+0000ebf4@12034
9512+0000effc@12035
9513+0000ef7c@12036
9514+0000effc@12037
9515+00004ffc@12038
9516+0000cffc@12039
9517+0000df7c@12040
9518+0000dffc@12041
9519+00007ffe@12043
9520+0000ff7e@12044
9521+0000f5ee@12045
9522+0000e5ee@12048
9523+0000effa@12049
9524+0000ebfa@12050
9525+0000eb7a@12051
9526+00006bfa@12052
9527+0000ebf8@12053
9528+0000e1c0@12054
9529+0000e140@12055
9530+0000e1c0@12056
9531+000041c0@12057
9532+0000c1c0@12058
9533+0000d140@12059
9534+0000d1c0@12060
9535+0000f1c0@12061
9536+0000f142@12062
9537+0000f56e@12063
9538+0000f5ee@12064
9539+0000756e@12066
9540+0000e5ee@12067
9541+0000ebfe@12068
9542+0000eb7e@12070
9543+00006bfc@12071
9544+0000ebfc@12072
9545+0000effc@12073
9546+0000ef7c@12074
9547+0000effc@12075
9548+0000cffc@12076
9549+0000cf7c@12077
9550+0000dffc@12078
9551+00007ffe@12080
9552+0000ff7e@12081
9553+0000f5f2@12082
9554+00007572@12085
9555+0000e5f2@12086
9556+0000ebf2@12087
9557+00006bf2@12089
9558+0000ebf0@12090
9559+0000ebc0@12091
9560+0000e140@12092
9561+0000e1c0@12093
9562+000041c0@12094
9563+0000c1c0@12095
9564+0000d140@12096
9565+0000d1c0@12097
9566+000071c2@12099
9567+0000f1c2@12100
9568+0000f5f2@12101
9569+000075f2@12103
9570+0000e5f2@12104
9571+0000eff6@12105
9572+0000ebf6@12106
9573+0000eb76@12107
9574+00006bf4@12108
9575+0000ebf4@12109
9576+0000effc@12110
9577+0000ef7c@12111
9578+0000effc@12112
9579+00004ffc@12113
9580+0000cffc@12114
9581+0000dffc@12115
9582+00007ffe@12117
9583+0000ff7e@12118
9584+0000fdf2@12119
9585+0000f5f2@12120
9586+00007572@12122
9587+0000e5f2@12123
9588+0000ebfa@12124
9589+0000eb7a@12126
9590+00006bf8@12127
9591+0000ebf8@12128
9592+0000e1c0@12129
9593+000041c0@12131
9594+0000c1c0@12132
9595+0000c140@12133
9596+0000d1c0@12134
9597+000071c2@12136
9598+0000f142@12137
9599+0000f5f2@12138
9600+00007572@12141
9601+0000e5fe@12142
9602+0000ebfe@12143
9603+00006bfe@12145
9604+0000ebfc@12146
9605+0000effc@12147
9606+0000ef7c@12148
9607+0000effc@12149
9608+00004ffc@12150
9609+0000cffc@12151
9610+0000df7c@12152
9611+0000dffc@12153
9612+00007ffe@12155
9613+0000fffe@12156
9614+0000f5f6@12157
9615+000075f6@12159
9616+0000e5f6@12160
9617+0000ebf2@12161
9618+0000eb72@12163
9619+00006bf0@12164
9620+0000ebf0@12165
9621+0000e140@12166
9622+0000e1c0@12168
9623+000041c0@12169
9624+0000c1c0@12170
9625+0000d1c0@12171
9626+000071c2@12173
9627+0000f142@12174
9628+0000f5f6@12175
9629+00007576@12178
9630+0000e5f6@12179
9631+0000ebf6@12180
9632+0000eb76@12182
9633+0000ebf4@12183
9634+0000effc@12184
9635+0000ef7c@12185
9636+0000effc@12186
9637+00004ffc@12187
9638+0000cffc@12188
9639+0000df7c@12189
9640+0000dffc@12190
9641+00007ffe@12192
9642+0000ff7e@12193
9643+0000f5f6@12194
9644+0000f5f4@12197
9645+0000fff4@12198
9646+0000fbf4@12199
9647+0000eb74@12200
9648+00006bf4@12201
9649+0000ebf4@12202
9650+0000eb74@12204
9651+0000ebf4@12205
9652+00006bf4@12206
9653+0000ebf4@12207
9654+0000fb74@12208
9655+0000fbf4@12209
9656+0000fbf6@12211
9657+0000fff6@12212
9658+0000f5f6@12213
9659+00007576@12215
9660+0000e5f6@12216
9661+0000ebfa@12217
9662+0000eb7a@12219
9663+00006bf8@12220
9664+0000ebf8@12221
9665+0000e140@12222
9666+0000e1c0@12223
9667+0000c1c0@12225
9668+0000c140@12226
9669+0000d1c0@12227
9670+000071c2@12229
9671+0000f142@12230
9672+0000f5f6@12231
9673+00007576@12234
9674+0000e5f6@12235
9675+0000ebfe@12236
9676+00006bfe@12238
9677+0000ebfc@12239
9678+0000effc@12240
9679+0000ef7c@12241
9680+0000effc@12242
9681+00004ffc@12243
9682+0000cffc@12244
9683+0000df7c@12245
9684+0000dffc@12246
9685+00007ffe@12248
9686+0000fffe@12249
9687+0000f5fa@12250
9688+000075fa@12252
9689+0000e5fa@12253
9690+0000eff2@12254
9691+0000ebf2@12255
9692+0000eb72@12256
9693+00006bf2@12257
9694+0000ebf0@12258
9695+0000e140@12259
9696+0000e1c0@12261
9697+000041c0@12262
9698+0000c1c0@12263
9699+0000d1c0@12264
9700+000071c2@12266
9701+0000f142@12267
9702+0000f5fa@12268
9703+0000757a@12271
9704+0000e5fa@12272
9705+0000ebf6@12273
9706+0000eb76@12275
9707+00006bf4@12276
9708+0000ebf4@12277
9709+0000effc@12278
9710+00004ffc@12280
9711+0000cffc@12281
9712+0000cf7c@12282
9713+0000dffc@12283
9714+00007ffe@12285
9715+0000ff7e@12286
9716+0000f5fa@12287
9717+0000f5fa@12288
+642, -0
  1@@ -0,0 +1,642 @@
  2+info
  3+	prefix svp_
  4+	opcode_size 16
  5+	body svp_run_op
  6+	header svp.h
  7+	include svp_util.c
  8+	
  9+regs
 10+	internal 16 scratch2 x y pad0 st pad1 pc
 11+	a 32
 12+	scratch1 32
 13+	rom ptr16
 14+	stack 16 stack0 stack1 stack2 stack3 stack4 stack5
 15+	stackidx 8
 16+	p 32
 17+	external 16 pm0 pm1 pm2 xst pm4 ext5 pmc
 18+	pointers0 8 r0 r1 r2 r3 
 19+	pointers1 8 r4 r5 r6 r7
 20+	pm_address 32 5
 21+	pm_mode 8 5
 22+	
 23+	iram 16 1024
 24+	ram0 16 256
 25+	ram1 16 256
 26+	zflag 8
 27+	nflag 8
 28+	rpl 16
 29+	
 30+flags
 31+	register st
 32+	Z 13 zero zflag
 33+	N 15 sign nflag
 34+	R 0-2 none rpl
 35+	
 36+svp_pop
 37+	mov stack.stackidx dst
 38+	add 1 stackidx stackidx
 39+	switch stackidx
 40+	case 6
 41+	mov 0 stackidx
 42+	end
 43+	
 44+svp_push
 45+	arg src 16
 46+	sub 1 stackidx stackidx
 47+	switch stackidx
 48+	case 0xFF
 49+	mov 5 stackidx
 50+	end
 51+	mov src stack.stackidx
 52+	
 53+svp_ram_read
 54+	arg mode 16
 55+	arg banki 16
 56+	arg regi 16
 57+	local idx 16
 58+	
 59+	switch banki
 60+	case 0
 61+	meta bank ram0
 62+	meta reg pointers0.regi
 63+	
 64+	default
 65+	meta bank ram1
 66+	meta reg pointers1.regi
 67+	end
 68+	
 69+	mov reg idx
 70+	switch mode
 71+	case 0
 72+	meta modestr ""
 73+	
 74+	case 1
 75+	meta modestr +!
 76+	add 1 reg reg
 77+	
 78+	case 2
 79+	#loop decremenet
 80+	meta modestr -
 81+	
 82+	if rpl
 83+		local tmp 16
 84+		mov reg tmp
 85+		lsl 1 rpl rpl
 86+		sub 1 rpl rpl
 87+		local mask 16
 88+		not rpl mask
 89+		and reg mask reg
 90+		sub 1 tmp tmp
 91+		and rpl tmp tmp
 92+		or tmp reg reg
 93+	else
 94+		sub 1 reg reg
 95+	end
 96+	
 97+	case 3
 98+	#loop increment
 99+	meta modestr +
100+	
101+	and 7 st rpl
102+	if rpl
103+		local tmp 16
104+		mov reg tmp
105+		lsl 1 rpl rpl
106+		sub 1 rpl rpl
107+		local mask 16
108+		not rpl mask
109+		and reg mask reg
110+		add 1 tmp tmp
111+		and rpl tmp tmp
112+		or tmp reg reg
113+	else
114+		sub 1 reg reg
115+	end
116+	end
117+	
118+	and 255 idx idx
119+	meta val bank.idx
120+	
121+svp_read_ext
122+	arg regidxr 16
123+	switch regidxr
124+	case 7
125+	meta val a
126+	
127+	default
128+	#TODO: PMAR stuff
129+	meta val external.regidxr
130+	end
131+	
132+svp_write_ext
133+	arg regidxw 16
134+	switch regidxw
135+	case 7
136+	and 0xFFFF0000 a a
137+	or src a a
138+	
139+	default
140+	#TODO: PMAR stuff
141+	mov src external.regidxw
142+	end
143+	
144+svp_alu_op
145+	arg P 16
146+	arg param 32
147+	
148+	switch P
149+	case 1
150+	dis "sub %s" name
151+	sub param a a
152+	
153+	case 3
154+	dis "cmp %s" name
155+	cmp param a
156+	
157+	case 4
158+	dis "add %s" name
159+	add param a a
160+	
161+	case 5
162+	dis "and %s" name
163+	and param a a
164+	
165+	case 6
166+	dis "or %s" name
167+	or param a a
168+	
169+	case 7
170+	dis "eor %s" name
171+	xor param a a
172+	end
173+	update_flags ZN
174+	
175+svp_check_cond
176+	arg fval 16
177+	arg cond 16
178+	local invert 8
179+	switch cond
180+	case 0
181+	meta flag 1
182+	
183+	case 5
184+	meta flag zflag
185+	
186+	case 7
187+	meta flag nflag
188+	
189+	default
190+	meta flag 0
191+	end
192+	
193+	if fval
194+	meta istrue flag
195+	
196+	else
197+	lnot flag invert
198+	meta istrue invert
199+	
200+	end
201+	
202+PPP0000000000000 alu_n1
203+	invalid P 0
204+	invalid P 2
205+	meta name "-"
206+	svp_alu_op P 0xFFFF0000
207+	
208+PPP0000000000RRR alu_r
209+	invalid P 0
210+	invalid P 2
211+	local tmp 32 
212+	lsl internal.R 16 tmp
213+	meta name internal.R
214+	svp_alu_op P tmp
215+	
216+PPP0000000000011 alu_a
217+	invalid P 0
218+	invalid P 2
219+	svp_alu_op P a
220+	
221+PPP0000000000101 alu_stack
222+	invalid P 0
223+	invalid P 2
224+	local tmp 32
225+	meta dst tmp
226+	svp_pop
227+	meta name "stack"
228+	svp_alu_op P tmp
229+	
230+PPP0000000000111 alu_p
231+	invalid P 0
232+	invalid P 2
233+	meta name p
234+	svp_alu_op P p
235+	
236+PPP0000000001RRR alu_ext
237+	invalid P 0
238+	invalid P 2
239+	local tmp 32
240+	svp_read_ext R
241+	lsl val 16 tmp
242+	meta name val
243+	svp_alu_op P tmp
244+	
245+PPP0001B0000MMRR alu_ram
246+	invalid P 0
247+	invalid P 2
248+	svp_ram_read M B R
249+	local tmp 32
250+	lsl val 16 tmp
251+	
252+	switch P
253+	case 1
254+	dis "sub (%s%s)" reg modestr
255+	sub tmp a a
256+	
257+	case 3
258+	dis "cmp (%s%s)" reg modestr
259+	cmp tmp a
260+	
261+	case 4
262+	dis "add (%s%s)" reg modestr
263+	add tmp a a
264+	
265+	case 5
266+	dis "and (%s%s)" reg modestr
267+	and tmp a a
268+	
269+	case 6
270+	dis "or (%s%s)" reg modestr
271+	or tmp a a
272+	
273+	case 7
274+	dis "eor (%s%s)" reg modestr
275+	xor tmp a a
276+	end
277+	
278+	update_flags ZN
279+	
280+PPP0101B0000MMRR alu_ram_indirect
281+	invalid P 0
282+	invalid P 2
283+	svp_ram_read M B R
284+	svp_prog_ram_read val
285+	local tmp 32
286+	lsl scratch1 16 tmp
287+	
288+	switch P
289+	case 1
290+	dis "sub ((%s%s))" reg modestr
291+	sub tmp a a
292+	
293+	case 3
294+	dis "cmp ((%s%s))" reg modestr
295+	cmp tmp a
296+	
297+	case 4
298+	dis "add ((%s%s))" reg modestr
299+	add tmp a a
300+	
301+	case 5
302+	dis "and ((%s%s))" reg modestr
303+	and tmp a a
304+	
305+	case 6
306+	dis "or ((%s%s))" reg modestr
307+	or tmp a a
308+	
309+	case 7
310+	dis "eor ((%s%s))" reg modestr
311+	xor tmp a a
312+	end
313+	
314+	update_flags ZN
315+	
316+PPP0000000001111 alu_al
317+	invalid P 0
318+	invalid P 2
319+	local tmp 32
320+	lsl a 16 tmp
321+	
322+	meta name al
323+	svp_alu_op P tmp
324+	
325+PPP0011JAAAAAAAA alu_ram_direct
326+	invalid P 0
327+	invalid P 2
328+	if J
329+	meta src ram1.A
330+	else
331+	meta src ram0.A
332+	end
333+	svp_alu_op P src
334+	
335+PPP0010000000000 alu_immed
336+	invalid P 0
337+	invalid P 2
338+	svp_op_fetch
339+	svp_alu_op P scratch1
340+	
341+1001000FCCCC0OOO cond_mod
342+	svp_check_cond F C
343+	if istrue
344+
345+	switch O
346+	case 2
347+	asr a 1 a
348+	update_flags ZN
349+	
350+	case 3
351+	lsl a 1 a
352+	update_flags ZN
353+	
354+	case 6
355+	neg a a
356+	update_flags ZN
357+	
358+	case 7
359+	abs a a
360+	update_flags N
361+	end
362+	end
363+
364+000000000DDD0SSS ld_int_int
365+	dis "ld %s, %s" internal.D internal.S
366+	mov internal.S internal.D
367+	
368+000000000DDD0101 ld_int_stack
369+	dis "ld %s, stack" internal.D 
370+	meta dst internal.D
371+	svp_pop
372+	
373+0000000000110101 ld_a_stack
374+	dis "ld a, stack"
375+	local tmp 32
376+	meta dst tmp
377+	svp_pop
378+	lsl tmp 16 tmp
379+	and 0xFFFF a a
380+	or tmp a a
381+	
382+0000000001110101 ld_p_stack
383+	dis "ld p, stack"
384+	local tmp 32
385+	meta dst tmp
386+	svp_pop
387+	lsl tmp 16 tmp
388+	and 0xFFFF p p
389+	or tmp p p
390+	
391+0000000001010SSS ld_stack_int
392+	dis "ld stack, %s" internal.S
393+	svp_push internal.S
394+	
395+0000000001010011 ld_stack_a
396+	dis "ld stack, a"
397+	local tmp 32
398+	lsr a 16 tmp
399+	svp_push tmp
400+	
401+0000000001010111 ld_stack_p
402+	dis "ld stack, p"
403+	local tmp 32
404+	lsr p 16 tmp
405+	svp_push tmp
406+	
407+0000000000000000 ld_n1_n1
408+	#nop?
409+	dis "ld -, -"
410+	
411+0000000000000SSS ld_n1_int
412+	#nop?
413+	dis "nop??"
414+	
415+0000000000110111 ld_a_p
416+	dis "ld a, p"
417+	mov p a
418+	
419+0000000001110011 ld_p_a
420+	dis "ld p, a"
421+	mov a p
422+	
423+0000000000110011 ld_a_a
424+	dis "ld a, a"
425+	mov a a
426+	
427+0000000001110111 ld_p_p
428+	dis "ld p, p"
429+	mov p p
430+
431+000000000DDD0111 ld_int_p
432+	local tmp 32
433+	lsr p 16 tmp
434+	mov tmp internal.D
435+	dis "ld %s, p" internal.D
436+	
437+000000000DDD0111 ld_int_a
438+	local tmp 32
439+	lsr a 16 tmp
440+	mov tmp internal.D
441+	dis "ld %s, a" internal.D
442+	
443+0000000001110SSS ld_p_int
444+	local tmp 32
445+	lsl internal.S 16 tmp
446+	mov tmp p
447+	dis "ld p, %s" internal.S
448+	
449+0000000000110SSS ld_a_int
450+	local tmp 32
451+	lsl internal.S 16 tmp
452+	mov tmp a
453+	dis "ld a, %s" internal.S
454+	
455+000000000DDD0000 ld_int_n1
456+	dis "ld %s, -" internal.D
457+	mov 0xFFFF internal.D
458+	
459+0000000000110000 ld_a_n1
460+	dis "ld a, -"
461+	and 0xFFFF a a
462+	or 0xFFFF0000 a a
463+	
464+0000000001110000 ld_p_n1
465+	dis "ld p, -"
466+	and 0xFFFF p p
467+	or 0xFFFF0000 p p
468+
469+000000000DDD1SSS ld_int_ext
470+	svp_read_ext S
471+	dis "ld %s, %s" internal.D val
472+	mov val internal.D
473+	
474+0000000000111SSS ld_a_ext
475+	svp_read_ext S
476+	dis "ld a, %s" val
477+	local tmp 32
478+	lsl val 16 tmp
479+	and 0xFFFF a a
480+	or tmp a a
481+	
482+0000000001111SSS ld_p_ext
483+	svp_read_ext S
484+	dis "ld p, %s" val
485+	local tmp 32
486+	lsl val 16 tmp
487+	and 0xFFFF p p
488+	or tmp p p
489+	
490+000000001DDD0SSS ld_ext_int
491+	meta src internal.S
492+	svp_write_ext D
493+	switch D
494+	case 7
495+	dis "ld al, %s" src
496+	
497+	default
498+	dis "ld %s, %s" external.D src
499+	end
500+	
501+000000001DDD0011 ld_ext_a
502+	local tmp 32
503+	lsr a 16 tmp
504+	meta src tmp
505+	svp_write_ext D
506+	switch D
507+	case 7
508+	dis "ld al, a"
509+	
510+	default
511+	dis "ld %s, a" external.D
512+	end
513+	
514+000000001DDD0111 ld_ext_p
515+	local tmp 32
516+	lsr p 16 tmp
517+	meta src tmp
518+	svp_write_ext D
519+	switch D
520+	case 7
521+	dis "ld al, p"
522+	
523+	default
524+	dis "ld %s, p" external.D
525+	end
526+	
527+	
528+000000001DDD1SSS ld_ext_ext
529+	svp_read_ext S
530+	meta src val
531+	svp_write_ext D
532+	switch D
533+	case 7
534+	dis "ld al, %s" src
535+	default
536+	dis "ld %s, %s" external.D src
537+	end
538+	
539+0000001B0DDDMMPP ld_int_ram
540+	svp_ram_read M B P
541+	dis "ld %s, (%s%s)" internal.D reg modestr
542+	mov val internal.D
543+	
544+0000001B0011MMPP ld_a_ram
545+	svp_ram_read M B P
546+	dis "ld a, (%s%s)" reg modestr
547+	local tmp 32
548+	lsl val 16 tmp
549+	and 0xFFFF a a
550+	or tmp a a
551+	
552+0000001B0111MMPP ld_p_ram
553+	svp_ram_read M B P
554+	dis "ld p, (%s%s)" reg modestr
555+	local tmp 32
556+	lsl val 16 tmp
557+	and 0xFFFF p p
558+	or tmp p p
559+	
560+0000001B0101MMPP ld_stack_ram
561+	svp_ram_read M B P
562+	dis "ld stack, (%s%s)" reg modestr
563+	svp_push val
564+	
565+000010000DDD0000 ld_int_immed
566+	svp_op_fetch
567+	dis "ld %s, %X" internal.D scratch1
568+	mov scratch1 internal.D
569+	
570+0000100000000000 ld_n1_immed
571+	svp_op_fetch
572+	dis "ld -, %X" scratch1
573+
574+0000100000110000 ld_a_immed
575+	local tmp 32
576+	svp_op_fetch
577+	dis "ld a, %X" scratch1
578+	lsl 16 scratch1 tmp
579+	and 0xFFFF a a
580+	or tmp a a
581+	
582+0000100001010000 ld_stack_immed
583+	svp_op_fetch
584+	dis "ld stack, %X" scratch1
585+	svp_push scratch1
586+
587+0000100001110000 ld_p_immed
588+	local tmp 32
589+	svp_op_fetch
590+	dis "ld p, %X" scratch1
591+	lsl 16 scratch1 tmp
592+	and 0xFFFF p p
593+	or tmp p p
594+	
595+000010001DDD0000 ld_ext_immed
596+	svp_op_fetch
597+	dis "ld %s, %X", external.D, scratch1
598+	meta src scratch1
599+	svp_write_ext D
600+	switch D
601+	case 7
602+	dis "ld al, %X" scratch1
603+	
604+	default
605+	dis "ld %s, %X" external.D scratch1
606+	end
607+	
608+0100100FCCCC0000 call_cond
609+	svp_check_cond F C
610+	svp_op_fetch
611+	
612+	if istrue
613+	svp_push pc
614+	mov scratch1 pc
615+	end
616+	
617+0100110FCCCC0000 bra_cond
618+	svp_check_cond F C
619+	svp_op_fetch
620+	if istrue
621+	mov scratch1 pc
622+	end
623+	
624+svp_prog_ram_read
625+	arg src 16
626+	cycles 1
627+	cmp 1024 src
628+	
629+	if >=U
630+	add src src scratch1
631+	ocall prog_read_16
632+	
633+	else
634+	mov iram.src scratch1
635+	end
636+
637+svp_op_fetch
638+	svp_prog_ram_read pc
639+	add 1 pc pc
640+	
641+svp_run_op
642+	svp_op_fetch
643+	dispatch scratch1
+6, -0
1@@ -0,0 +1,6 @@
2+
3+void svp_prog_read_16(svp_context *context)
4+{
5+	uint16_t address = context->scratch1 >> 1;
6+	context->scratch1 = context->rom[address];
7+}
+65, -0
 1@@ -0,0 +1,65 @@
 2+#include <string.h>
 3+#include "system.h"
 4+#include "genesis.h"
 5+#include "sms.h"
 6+
 7+uint8_t safe_cmp(char *str, long offset, uint8_t *buffer, long filesize)
 8+{
 9+	long len = strlen(str);
10+	return filesize >= offset+len && !memcmp(str, buffer + offset, len);
11+}
12+
13+system_type detect_system_type(system_media *media)
14+{
15+	if (safe_cmp("SEGA", 0x100, media->buffer, media->size)) {
16+		//TODO: Differentiate between vanilla Genesis and Sega CD/32X games
17+		return SYSTEM_GENESIS;
18+	}
19+	if (safe_cmp("TMR SEGA", 0x1FF0, media->buffer, media->size)
20+		|| safe_cmp("TMR SEGA", 0x3FF0, media->buffer, media->size)
21+		|| safe_cmp("TMR SEGA", 0x7FF0, media->buffer, media->size)
22+	) {
23+		return SYSTEM_SMS;
24+	}
25+	//TODO: Detect Jaguar ROMs here
26+	
27+	//Header based detection failed, examine filename for clues
28+	if (media->extension) {
29+		if (!strcmp("md", media->extension) || !strcmp("gen", media->extension)) {
30+			return SYSTEM_GENESIS;
31+		}
32+		if (!strcmp("sms", media->extension)) {
33+			return SYSTEM_SMS;
34+		}
35+	}
36+	
37+	//More certain checks failed, look for a valid 68K reset vector
38+	if (media->size >= 8) {
39+		char *rom = media->buffer;
40+		uint32_t reset = rom[4] << 24 | rom[5] << 16 | rom[6] << 8 | rom[7];
41+		if (!(reset & 1) && reset < media->size) {
42+			//we have a valid looking reset vector, assume it's a Genesis ROM
43+			return SYSTEM_GENESIS;
44+		}
45+	}
46+	return SYSTEM_UNKNOWN;
47+}
48+
49+system_header *alloc_config_system(system_type stype, system_media *media, uint32_t opts, uint8_t force_region)
50+{
51+	void *lock_on = NULL;
52+	uint32_t lock_on_size = 0;
53+	if (media->chain) {
54+		lock_on = media->chain->buffer;
55+		lock_on_size = media->chain->size;
56+	}
57+	switch (stype)
58+	{
59+	case SYSTEM_GENESIS:
60+		return &(alloc_config_genesis(media->buffer, media->size, lock_on, lock_on_size, opts, force_region))->header;
61+	case SYSTEM_SMS:
62+		return &(alloc_configure_sms(media, opts, force_region))->header;
63+	default:
64+		return NULL;
65+	}
66+}
+87, -0
 1@@ -0,0 +1,87 @@
 2+#ifndef SYSTEM_H_
 3+#define SYSTEM_H_
 4+#include <stddef.h>
 5+#include <stdint.h>
 6+
 7+typedef struct system_header system_header;
 8+typedef struct system_media system_media;
 9+
10+typedef enum {
11+	SYSTEM_UNKNOWN,
12+	SYSTEM_GENESIS,
13+	SYSTEM_SMS
14+} system_type;
15+
16+typedef enum {
17+	DEBUGGER_NATIVE,
18+	DEBUGGER_GDB
19+} debugger_type;
20+
21+typedef void (*system_fun)(system_header *);
22+typedef uint16_t (*system_fun_r16)(system_header *);
23+typedef void (*system_str_fun)(system_header *, char *);
24+typedef uint8_t (*system_str_fun_r8)(system_header *, char *);
25+typedef void (*system_u32_fun)(system_header *, uint32_t);
26+typedef void (*system_u8_fun)(system_header *, uint8_t);
27+typedef uint8_t (*system_u8_fun_r8)(system_header *, uint8_t);
28+typedef void (*system_u8_u8_fun)(system_header *, uint8_t, uint8_t);
29+typedef void (*system_mabs_fun)(system_header *, uint8_t, uint16_t, uint16_t);
30+typedef void (*system_mrel_fun)(system_header *, uint8_t, int32_t, int32_t);
31+typedef uint8_t *(*system_ptrszt_fun_rptr8)(system_header *, size_t *);
32+typedef void (*system_ptr8_sizet_fun)(system_header *, uint8_t *, size_t);
33+
34+#include "arena.h"
35+#include "romdb.h"
36+
37+struct system_header {
38+	system_header           *next_context;
39+	system_str_fun          start_context;
40+	system_fun              resume_context;
41+	system_fun              load_save;
42+	system_fun              persist_save;
43+	system_u8_fun_r8        load_state;
44+	system_fun              request_exit;
45+	system_fun              soft_reset;
46+	system_fun              free_context;
47+	system_fun_r16          get_open_bus_value;
48+	system_u32_fun          set_speed_percent;
49+	system_fun              inc_debug_mode;
50+	system_u8_u8_fun        gamepad_down;
51+	system_u8_u8_fun        gamepad_up;
52+	system_u8_u8_fun        mouse_down;
53+	system_u8_u8_fun        mouse_up;
54+	system_mabs_fun         mouse_motion_absolute;
55+	system_mrel_fun         mouse_motion_relative;
56+	system_u8_fun           keyboard_down;
57+	system_u8_fun           keyboard_up;
58+	system_fun              config_updated;
59+	system_ptrszt_fun_rptr8 serialize;
60+	system_ptr8_sizet_fun   deserialize;
61+	rom_info                info;
62+	arena                   *arena;
63+	char                    *next_rom;
64+	char                    *save_dir;
65+	uint8_t                 enter_debugger;
66+	uint8_t                 should_exit;
67+	uint8_t                 save_state;
68+	uint8_t                 delayed_load_slot;
69+	uint8_t                 has_keyboard;
70+	debugger_type           debugger_type;
71+	system_type             type;
72+};
73+
74+struct system_media {
75+	void         *buffer;
76+	char         *dir;
77+	char         *name;
78+	char         *extension;
79+	system_media *chain;
80+	uint32_t     size;
81+};
82+
83+#define OPT_ADDRESS_LOG (1U << 31U)
84+
85+system_type detect_system_type(system_media *media);
86+system_header *alloc_config_system(system_type stype, system_media *media, uint32_t opts, uint8_t force_region);
87+
88+#endif //SYSTEM_H_
+44, -0
 1@@ -0,0 +1,44 @@
 2+#include <sys/types.h>
 3+#include <sys/stat.h>
 4+#include <fcntl.h>
 5+#include <unistd.h>
 6+#include <stdlib.h>
 7+#include "terminal.h"
 8+
 9+char buf[4096];
10+
11+void copy_data(int to, int from)
12+{
13+	ssize_t bytes = read(from, buf, sizeof(buf));
14+	while (bytes > 0)
15+	{
16+		ssize_t written = write(to, buf, bytes);
17+		if (written == -1) {
18+			exit(1);
19+		}
20+		bytes -= written;
21+	}
22+}
23+
24+int main(int argc, char **argv)
25+{
26+	//these will block so order is important
27+	int input_fd = open(INPUT_PATH, O_WRONLY);
28+	int output_fd = open(OUTPUT_PATH, O_RDONLY);
29+	fd_set read_fds;
30+	FD_ZERO(&read_fds);
31+	for (;;)
32+	{
33+		FD_SET(STDIN_FILENO, &read_fds);
34+		FD_SET(output_fd, &read_fds);
35+		select(output_fd+1, &read_fds, NULL, NULL, NULL);
36+		
37+		if (FD_ISSET(STDIN_FILENO, &read_fds)) {
38+			copy_data(input_fd, STDIN_FILENO);
39+		}
40+		if (FD_ISSET(output_fd, &read_fds)) {
41+			copy_data(STDOUT_FILENO, output_fd);
42+		}
43+	}
44+	return 0;
45+}
+71, -0
 1@@ -0,0 +1,71 @@
 2+#include <sys/types.h>
 3+#include <sys/stat.h>
 4+#include <unistd.h>
 5+#include <fcntl.h>
 6+#include <stdlib.h>
 7+#include <stdint.h>
 8+#include <signal.h>
 9+#include "util.h"
10+#include "terminal.h"
11+
12+pid_t child;
13+
14+void cleanup_terminal()
15+{
16+	kill(child, SIGKILL);
17+	unlink(INPUT_PATH);
18+	unlink(OUTPUT_PATH);
19+}
20+
21+static char init_done;
22+
23+void force_no_terminal()
24+{
25+	init_done = 1;
26+}
27+
28+void init_terminal()
29+{
30+	if (!init_done) {
31+		if (!(isatty(STDIN_FILENO) && isatty(STDOUT_FILENO))) {
32+#ifndef __APPLE__
33+			//check to see if x-terminal-emulator exists, just use xterm if it doesn't
34+			char *term = system("which x-terminal-emulator > /dev/null") ? "xterm" : "x-terminal-emulator";
35+#endif
36+			//get rid of FIFO's if they already exist
37+			unlink(INPUT_PATH);
38+			unlink(OUTPUT_PATH);
39+			//create FIFOs for talking to helper process in terminal app
40+			mkfifo(INPUT_PATH, 0666);
41+			mkfifo(OUTPUT_PATH, 0666);
42+
43+			//close existing file descriptors
44+			close(STDIN_FILENO);
45+			close(STDOUT_FILENO);
46+			close(STDERR_FILENO);
47+
48+			child = fork();
49+			if (child == -1) {
50+				//error, oh well
51+				warning("Failed to fork for terminal spawn");
52+			} else if (!child) {
53+				//child process, exec our terminal emulator
54+#ifdef __APPLE__
55+				execlp("open", "open", "./termhelper", NULL);
56+#else
57+				execlp(term, term, "-title", "BlastEm Debugger", "-e", "./termhelper", NULL);
58+#endif
59+			} else {
60+				//connect to the FIFOs, these will block so order is important
61+				open(INPUT_PATH, O_RDONLY);
62+				open(OUTPUT_PATH, O_WRONLY);
63+				atexit(cleanup_terminal);
64+				if (-1 == dup(STDOUT_FILENO)) {
65+					fatal_error("failed to dup STDOUT to STDERR after terminal fork");
66+				}
67+			}
68+		}
69+
70+		init_done = 1;
71+	}
72+}
+10, -0
 1@@ -0,0 +1,10 @@
 2+#ifndef TERMINAL_H_
 3+#define TERMINAL_H_
 4+
 5+void init_terminal();
 6+void force_no_terminal();
 7+
 8+#define INPUT_PATH "/tmp/blastem_input"
 9+#define OUTPUT_PATH "/tmp/blastem_output"
10+
11+#endif //TERMINAL_H_
A tern.c
+318, -0
  1@@ -0,0 +1,318 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "tern.h"
  8+#include <stddef.h>
  9+#include <stdlib.h>
 10+#include <string.h>
 11+#include <stdio.h>
 12+#include "util.h"
 13+
 14+tern_node * tern_insert(tern_node * head, char const * key, tern_val value, uint8_t valtype)
 15+{
 16+	tern_node ** cur = &head;
 17+	while(*key)
 18+	{
 19+		if (*cur) {
 20+			while(*cur && (*cur)->el != *key)
 21+			{
 22+				if (*key < (*cur)->el) {
 23+					cur = &(*cur)->left;
 24+				} else {
 25+					cur = &(*cur)->right;
 26+				}
 27+			}
 28+		}
 29+		if (!*cur) {
 30+			*cur = malloc(sizeof(tern_node));
 31+			(*cur)->left = NULL;
 32+			(*cur)->right = NULL;
 33+			(*cur)->straight.next = NULL;
 34+			(*cur)->el = *key;
 35+			(*cur)->valtype = TVAL_NONE;
 36+		}
 37+		cur = &((*cur)->straight.next);
 38+		key++;
 39+	}
 40+	while(*cur && (*cur)->el)
 41+	{
 42+		cur = &(*cur)->left;
 43+	}
 44+	if (!*cur) {
 45+		*cur = malloc(sizeof(tern_node));
 46+		(*cur)->left = NULL;
 47+		(*cur)->right = NULL;
 48+		(*cur)->el = 0;
 49+		(*cur)->valtype = TVAL_NONE;
 50+	}
 51+	if ((*cur)->valtype == TVAL_PTR) {
 52+		//not freeing tern nodes can also cause leaks, but handling freeing those here is problematic
 53+		//since updating a sub-tree may involve creating a new root node
 54+		free((*cur)->straight.value.ptrval);
 55+	}
 56+	(*cur)->straight.value = value;
 57+	(*cur)->valtype = valtype;
 58+	return head;
 59+}
 60+
 61+uint8_t tern_find(tern_node * head, char const * key, tern_val *ret)
 62+{
 63+	tern_node * cur = head;
 64+	while (cur)
 65+	{
 66+		if (cur->el == *key) {
 67+			if (*key) {
 68+				cur = cur->straight.next;
 69+				key++;
 70+			} else {
 71+				*ret = cur->straight.value;
 72+				return cur->valtype;
 73+			}
 74+		} else if (*key < cur->el) {
 75+			cur = cur->left;
 76+		} else {
 77+			cur = cur->right;
 78+		}
 79+	}
 80+	return TVAL_NONE;
 81+}
 82+
 83+tern_node * tern_find_prefix(tern_node * head, char const * key)
 84+{
 85+	tern_node * cur = head;
 86+	while (cur && *key)
 87+	{
 88+		if (cur->el == *key) {
 89+			cur = cur->straight.next;
 90+			key++;
 91+		} else if (*key < cur->el) {
 92+			cur = cur->left;
 93+		} else {
 94+			cur = cur->right;
 95+		}
 96+	}
 97+	return cur;
 98+}
 99+
100+intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def)
101+{
102+	tern_val ret;
103+	uint8_t valtype = tern_find(head, key, &ret);
104+	if (valtype == TVAL_INT) {
105+		return ret.intval;
106+	}
107+	return def;
108+}
109+
110+tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value)
111+{
112+	tern_val val;
113+	val.intval = value;
114+	return tern_insert(head, key, val, TVAL_INT);
115+}
116+
117+void * tern_find_ptr_default(tern_node * head, char const * key, void * def)
118+{
119+	tern_val ret;
120+	uint8_t valtype = tern_find(head, key, &ret);
121+	if (valtype == TVAL_PTR) {
122+		return ret.ptrval;
123+	}
124+	return def;
125+}
126+
127+void * tern_find_ptr(tern_node * head, char const * key)
128+{
129+	return tern_find_ptr_default(head, key, NULL);
130+}
131+
132+tern_node *tern_find_node(tern_node *head, char const *key)
133+{
134+	tern_val ret;
135+	uint8_t valtype = tern_find(head, key, &ret);
136+	if (valtype == TVAL_NODE) {
137+		return ret.ptrval;
138+	}
139+	return NULL;
140+}
141+
142+uint8_t tern_delete(tern_node **head, char const *key, tern_val *out)
143+{
144+	tern_node *cur = *head, **last = head;
145+	while (cur)
146+	{
147+		if (cur->el == *key) {
148+			if (*key) {
149+				last = &cur->straight.next;
150+				cur = cur->straight.next;
151+				key++;
152+			} else {
153+				break;
154+			}
155+		} else if (*key < cur->el) {
156+			last = &cur->left;
157+			cur = cur->left;
158+		} else {
159+			last = &cur->right;
160+			cur = cur->right;
161+		}
162+	}
163+	if (!cur) {
164+		return TVAL_NONE;
165+	}
166+	*last = cur->right;
167+	uint8_t valtype = cur->valtype;
168+	if (out) {
169+		*out = cur->straight.value;
170+	}
171+	free(cur);
172+	return valtype;
173+}
174+
175+tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype)
176+{
177+	tern_val ret;
178+	while (*key)
179+	{
180+		uint8_t valtype = tern_find(head, key, &ret);
181+		if (!valtype) {
182+			return def;
183+		}
184+		key = key + strlen(key) + 1;
185+		if (*key) {
186+			if (valtype != TVAL_NODE) {
187+				return def;
188+			}
189+			head = ret.ptrval;
190+		} else if (req_valtype && req_valtype != valtype) {
191+			return def;
192+		}
193+	}
194+	return ret;
195+}
196+
197+tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype)
198+{
199+	tern_val def;
200+	def.ptrval = NULL;
201+	return tern_find_path_default(head, key, def, valtype);
202+}
203+
204+tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value)
205+{
206+	tern_val val;
207+	val.ptrval = value;
208+	return tern_insert(head, key, val, TVAL_PTR);
209+}
210+
211+tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value)
212+{
213+	tern_val val;
214+	val.ptrval = value;
215+	return tern_insert(head, key, val, TVAL_NODE);
216+}
217+
218+tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint8_t valtype)
219+{
220+	const char *next_key = key + strlen(key) + 1;
221+	if (*next_key) {
222+		tern_node *child = tern_find_node(head, key);
223+		child = tern_insert_path(child, next_key, val, valtype);
224+		return tern_insert_node(head, key, child);
225+	} else {
226+		return tern_insert(head, key, val, valtype);
227+	}
228+}
229+
230+uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out)
231+{
232+	const char *next_key = key + strlen(key) + 1;
233+	if (*next_key) {
234+		tern_node *child = tern_find_node(*head, key);
235+		if (!child) {
236+			return TVAL_NONE;
237+		}
238+		tern_node *tmp = child;
239+		uint8_t valtype = tern_delete_path(&tmp, next_key, out);
240+		if (tmp != child) {
241+			*head = tern_insert_node(*head, key, tmp);
242+		}
243+		return valtype;
244+	} else {
245+		return tern_delete(head, key, out);
246+	}
247+}
248+
249+uint32_t tern_count(tern_node *head)
250+{
251+	uint32_t count = 0;
252+	if (head->left) {
253+		count += tern_count(head->left);
254+	}
255+	if (head->right) {
256+		count += tern_count(head->right);
257+	}
258+	if (!head->el) {
259+		count++;
260+	} else if (head->straight.next) {
261+		count += tern_count(head->straight.next);
262+	}
263+	return count;
264+}
265+
266+#define MAX_ITER_KEY 127
267+void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, int pos)
268+{
269+	if (!head->el) {
270+		keybuf[pos] = 0;
271+		fun(keybuf, head->straight.value, head->valtype, data);
272+	}
273+	if (head->left) {
274+		tern_foreach_int(head->left, fun, data, keybuf, pos);
275+	}
276+	if (head->el && head->straight.next) {
277+		if (pos == MAX_ITER_KEY) {
278+			fatal_error("tern_foreach_int: exceeded maximum key size");
279+		}
280+		keybuf[pos] = head->el;
281+		tern_foreach_int(head->straight.next, fun, data, keybuf, pos+1);
282+	}
283+	if (head->right) {
284+		tern_foreach_int(head->right, fun, data, keybuf, pos);
285+	}
286+}
287+
288+void tern_foreach(tern_node *head, iter_fun fun, void *data)
289+{
290+	//lame, but good enough for my purposes
291+	char key[MAX_ITER_KEY+1];
292+	tern_foreach_int(head, fun, data, key, 0);
293+}
294+
295+char * tern_int_key(uint32_t key, char * buf)
296+{
297+	char * cur = buf;
298+	while (key)
299+	{
300+		*(cur++) = (key & 0x7F) + 1;
301+		key >>= 7;
302+	}
303+	*cur = 0;
304+	return buf;
305+}
306+
307+void tern_free(tern_node *head)
308+{
309+	if (head->left) {
310+		tern_free(head->left);
311+	}
312+	if (head->right) {
313+		tern_free(head->right);
314+	}
315+	if (head->el) {
316+		tern_free(head->straight.next);
317+	}
318+	free(head);
319+}
A tern.h
+58, -0
 1@@ -0,0 +1,58 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef TERN_H_
 8+#define TERN_H_
 9+
10+#include <stdint.h>
11+
12+#define MAX_INT_KEY_SIZE (sizeof(uint32_t) + 2)
13+
14+typedef union {
15+	void     *ptrval;
16+	intptr_t intval;
17+} tern_val;
18+
19+typedef struct tern_node {
20+	struct tern_node *left;
21+	union {
22+		struct tern_node *next;
23+		tern_val         value;
24+	} straight;
25+	struct tern_node *right;
26+	char             el;
27+	uint8_t          valtype;
28+} tern_node;
29+
30+enum {
31+	TVAL_NONE=0,
32+	TVAL_INT,
33+	TVAL_PTR,
34+	TVAL_NODE
35+};
36+
37+typedef void (*iter_fun)(char *key, tern_val val, uint8_t valtype, void *data);
38+
39+tern_node * tern_insert(tern_node * head, char const * key, tern_val value, uint8_t valtype);
40+uint8_t tern_find(tern_node * head, char const * key, tern_val *ret);
41+tern_node * tern_find_prefix(tern_node * head, char const * key);
42+intptr_t tern_find_int(tern_node * head, char const * key, intptr_t def);
43+tern_node * tern_insert_int(tern_node * head, char const * key, intptr_t value);
44+void * tern_find_ptr_default(tern_node * head, char const * key, void * def);
45+void * tern_find_ptr(tern_node * head, char const * key);
46+tern_node *tern_find_node(tern_node *head, char const *key);
47+uint8_t tern_delete(tern_node **head, char const *key, tern_val *out);
48+tern_val tern_find_path_default(tern_node *head, char const *key, tern_val def, uint8_t req_valtype);
49+tern_val tern_find_path(tern_node *head, char const *key, uint8_t valtype);
50+uint8_t tern_delete_path(tern_node **head, char const *key, tern_val *out);
51+tern_node * tern_insert_ptr(tern_node * head, char const * key, void * value);
52+tern_node * tern_insert_node(tern_node *head, char const *key, tern_node *value);
53+tern_node *tern_insert_path(tern_node *head, char const *key, tern_val val, uint8_t valtype);
54+uint32_t tern_count(tern_node *head);
55+void tern_foreach(tern_node *head, iter_fun fun, void *data);
56+char * tern_int_key(uint32_t key, char * buf);
57+void tern_free(tern_node *head);
58+
59+#endif //TERN_H_
A test.c
+76, -0
 1@@ -0,0 +1,76 @@
 2+#include <stdint.h>
 3+#include <stdlib.h>
 4+#include <string.h>
 5+#include <stdio.h>
 6+#include "vdp.h"
 7+
 8+int headless = 1;
 9+uint16_t read_dma_value(uint32_t address)
10+{
11+	return 0;
12+}
13+
14+uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
15+{
16+	return 0;
17+}
18+
19+void render_alloc_surfaces(vdp_context * context)
20+{
21+	context->oddbuf = context->framebuf = malloc(512 * 256 * 4 * 2);
22+	memset(context->oddbuf, 0, 512 * 256 * 4 * 2);
23+	context->evenbuf = ((char *)context->oddbuf) + 512 * 256 * 4;
24+}
25+
26+int check_hint_time(vdp_context * v_context)
27+{
28+	uint32_t orig_hint_cycle = vdp_next_hint(v_context);
29+	uint32_t cur_hint_cycle;
30+	printf("hint cycle is %d at vcounter: %d, hslot: %d\n", orig_hint_cycle, v_context->vcounter, v_context->hslot);
31+	int res = 1;
32+	while ((cur_hint_cycle = vdp_next_hint(v_context)) > v_context->cycles)
33+	{
34+		if (cur_hint_cycle != orig_hint_cycle) {
35+			fprintf(stderr, "ERROR: hint cycle changed to %d at vcounter: %d, hslot: %d\n", cur_hint_cycle, v_context->vcounter, v_context->hslot);
36+			orig_hint_cycle = cur_hint_cycle;
37+			res = 0;
38+		}
39+		vdp_run_context(v_context, v_context->cycles + 1);
40+	}
41+	printf("hint fired at cycle: %d, vcounter: %d, hslot: %d\n", cur_hint_cycle, v_context->vcounter, v_context->hslot);
42+	vdp_int_ack(v_context, 4);
43+	return res;
44+}
45+
46+
47+int main(int argc, char ** argv)
48+{
49+	vdp_context v_context;
50+	init_vdp_context(&v_context, 0);
51+	vdp_control_port_write(&v_context, 0x8144);
52+	vdp_control_port_write(&v_context, 0x8C81);
53+	vdp_control_port_write(&v_context, 0x8A7F);
54+	vdp_control_port_write(&v_context, 0x8014);
55+	v_context.hint_counter = 0x7F;
56+	v_context.vcounter = 128;
57+	v_context.hslot = 165;
58+	//check single shot behavior
59+	int res = check_hint_time(&v_context);
60+	//check every line behavior
61+	while (v_context.vcounter < 225)
62+	{
63+		vdp_run_context(&v_context, v_context.cycles + 1);
64+	}
65+	vdp_control_port_write(&v_context, 0x8A00);
66+	int hint_count = 0;
67+	while (res && v_context.vcounter != 224)
68+	{
69+		res = res && check_hint_time(&v_context);
70+		hint_count++;
71+	}
72+	if (res && hint_count != 225) {
73+		fprintf(stderr, "ERROR: hint count should be 225 but was %d instead\n", hint_count);
74+		res = 0;
75+	}
76+	return 0;
77+}
+123, -0
  1@@ -0,0 +1,123 @@
  2+	dc.l $0, start
  3+	dc.l start
  4+	dc.l start
  5+	dc.l start
  6+	dc.l start
  7+	dc.l start
  8+	dc.l start
  9+	dc.l start
 10+	dc.l start
 11+	dc.l start
 12+	dc.l start
 13+	dc.l start
 14+	dc.l start
 15+	dc.l start
 16+	dc.l start
 17+	dc.l start
 18+	dc.l start
 19+	dc.l start
 20+	dc.l start
 21+	dc.l start
 22+	dc.l start
 23+	dc.l start
 24+	dc.l start
 25+	dc.l after
 26+	dc.l after
 27+	dc.l after
 28+	dc.l after
 29+	dc.l after
 30+	dc.l after
 31+	dc.l after
 32+	dc.l after
 33+	
 34+start:
 35+	bra after
 36+after:
 37+	abcd d0, d1
 38+	abcd -(a2), -(a3)
 39+	add.b #42, d1
 40+	add.w d3, d4
 41+	add.l d5, (a0)+
 42+	addq.w #5, d0
 43+	addx d6, d7
 44+	addx -(a4), -(a5)
 45+	and.w d5, d7
 46+	andi.l #5, (a0)+
 47+	andi #8, CCR
 48+	andi #9, CCR
 49+foo:
 50+	asl d0, d3
 51+	asr #3, d7
 52+	bne foo
 53+	bchg #5, d0
 54+	bclr #7, d0
 55+	bset #1, d0
 56+	bsr bar
 57+	btst #3, d0
 58+	chk.w #53, d7
 59+	clr d5
 60+	cmp d0, d1
 61+bar:
 62+	dbra d0, bar
 63+	divs.w d5, d7
 64+	divu.w d3, d4
 65+	eor.w d0, d6
 66+	eori.l #5, d2
 67+	eori #5, ccr
 68+	eori #2700, sr
 69+	exg d5, d6
 70+	ext d2
 71+	illegal
 72+	jmp (a0)
 73+	jsr (a5)
 74+	lea (a0, 8), a3
 75+	link.w a6, #32
 76+	lsl d0, d3
 77+	lsr #3, d7
 78+	move.b (a0)+, (32, a5)
 79+	moveq  #5, d0
 80+	move #89, ccr
 81+	move sr, d0
 82+	move #2700, sr
 83+	move a5, usp
 84+	movem.l d0-d3/a4/a6, -(a7)
 85+	movep.w d4, (40, a3)
 86+	muls.w d6, d7
 87+	mulu.w d2, d4
 88+	nbcd -(a2)
 89+	neg.l d7
 90+	negx.b d5
 91+	nop
 92+	not.b d3
 93+	or.w d5, d7
 94+	ori.b #7, d5
 95+	ori #5, ccr
 96+	ori #2700, sr
 97+	pea (24, a3)
 98+	reset
 99+	rol.l #7, d0
100+	rol.w d5, d0
101+	ror.w d1, d3
102+	roxl.l #7, d0
103+	roxl.w d5, d0
104+	roxr.w d1, d3
105+	rte
106+	rtr
107+	rts
108+	sbcd d0, d1
109+	sbcd -(a2), -(a3)
110+	slt d5
111+	stop #3
112+	sub.b #42, d1
113+	sub.w d3, d4
114+	sub.l d5, (a0)+
115+	subq.w #5, d0
116+	subx d6, d7
117+	subx -(a4), -(a5)
118+	swap d6
119+	tas (a3)
120+	trap #7
121+	trapv
122+	tst.w (a4)+
123+	unlk a6
124+
+29, -0
 1@@ -0,0 +1,29 @@
 2+#include <stdio.h>
 3+#include "gen_arm.h"
 4+
 5+typedef int32_t (*fib_fun)(int32_t);
 6+
 7+int main(int arc, char **argv)
 8+{
 9+	code_info code;
10+	init_code_info(&code);
11+	uint32_t *fib = code.cur;
12+	subi(&code, r0, r0, 2, SET_COND);
13+	movi_cc(&code, r0, 1, NO_COND, CC_LT);
14+	bx_cc(&code, lr, CC_LT);
15+	pushm(&code, LR | R4);
16+	mov(&code, r4, r0, NO_COND);
17+	bl(&code, fib);
18+	mov(&code, r1, r0, NO_COND);
19+	addi(&code, r0, r4, 1, NO_COND);
20+	mov(&code, r4, r1, NO_COND);
21+	bl(&code, fib);
22+	add(&code, r0, r4, r0, NO_COND);
23+	popm(&code, LR | R4);
24+	bx(&code, lr);
25+
26+	fib_fun fibc = (fib_fun)fib;
27+	printf("fib(10): %d\n", fibc(10));
28+
29+	return 0;
30+}
+101, -0
  1@@ -0,0 +1,101 @@
  2+/*
  3+ Copyright 2017 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include <stdio.h>
  8+#include "vdp.h"
  9+
 10+int headless = 1;
 11+
 12+uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
 13+{
 14+	return 0;
 15+}
 16+
 17+uint16_t read_dma_value(uint32_t address)
 18+{
 19+	return 0;
 20+}
 21+
 22+uint32_t *render_get_video_buffer(uint8_t which, int *pitch)
 23+{
 24+	*pitch = 0;
 25+	return NULL;
 26+}
 27+
 28+void render_video_buffer_updated(uint8_t which, int width)
 29+{
 30+}
 31+
 32+void warning(char *format, ...)
 33+{
 34+}
 35+
 36+
 37+int main(int argc, char **argv)
 38+{
 39+	vdp_context context;
 40+	int ret = 0;
 41+	init_vdp_context(&context, 0);
 42+	vdp_control_port_write(&context, 0x8000 | BIT_PAL_SEL);
 43+	vdp_control_port_write(&context, 0x8100 | BIT_DISP_EN | BIT_VINT_EN | BIT_MODE_5);
 44+	puts("Testing H32 Mode");
 45+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 46+	{
 47+		vdp_run_context(&context, context.cycles + 1);
 48+	}
 49+	vdp_int_ack(&context);
 50+	uint32_t vint_cycle = vdp_next_vint(&context);
 51+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 52+	{
 53+		vdp_run_context(&context, context.cycles + 1);
 54+		uint32_t vint_cycle2 = vdp_next_vint(&context);
 55+		if (vint_cycle2 != vint_cycle) {
 56+			printf("VINT Cycle changed from %d to %d @ line %d, slot %d\n", vint_cycle, vint_cycle2, context.vcounter, context.hslot);;
 57+			ret = 1;
 58+			vint_cycle = vint_cycle2;
 59+		}
 60+	}
 61+	vdp_int_ack(&context);
 62+	puts("Testing H40 Mode");
 63+	vdp_control_port_write(&context, 0x8C81);
 64+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 65+	{
 66+		vdp_run_context(&context, context.cycles + 1);
 67+	}
 68+	vdp_int_ack(&context);
 69+	vint_cycle = vdp_next_vint(&context);
 70+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 71+	{
 72+		vdp_run_context(&context, context.cycles + 1);
 73+		uint32_t vint_cycle2 = vdp_next_vint(&context);
 74+		if (vint_cycle2 != vint_cycle) {
 75+			printf("VINT Cycle changed from %d to %d @ line %d, slot %d\n", vint_cycle, vint_cycle2, context.vcounter, context.hslot);;
 76+			ret = 1;
 77+			vint_cycle = vint_cycle2;
 78+		}
 79+	}
 80+	vdp_int_ack(&context);
 81+	puts("Testing Mode 4");
 82+	vdp_control_port_write(&context, 0x8C00);
 83+	vdp_control_port_write(&context, 0x8100 | BIT_DISP_EN | BIT_VINT_EN);
 84+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 85+	{
 86+		vdp_run_context(&context, context.cycles + 1);
 87+	}
 88+	context.flags2 &= ~FLAG2_VINT_PENDING;
 89+	vint_cycle = vdp_next_vint(&context);
 90+	while (!(context.flags2 & FLAG2_VINT_PENDING))
 91+	{
 92+		vdp_run_context(&context, context.cycles + 1);
 93+		uint32_t vint_cycle2 = vdp_next_vint(&context);
 94+		if (vint_cycle2 != vint_cycle) {
 95+			printf("VINT Cycle changed from %d to %d @ line %d, slot %d\n", vint_cycle, vint_cycle2, context.vcounter, context.hslot);;
 96+			ret = 1;
 97+			vint_cycle = vint_cycle2;
 98+		}
 99+	}
100+	printf("Result: %s\n", ret ? "failure" : "success");
101+	return ret;
102+}
+48, -0
 1@@ -0,0 +1,48 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include "gen_x86.h"
 8+#include "m68k_core.h"
 9+#include <stdio.h>
10+#include <stddef.h>
11+
12+int main(int argc, char ** argv)
13+{
14+	uint8_t foo[512];
15+	uint8_t *cur = foo, *end;
16+	cur = mov_rr(cur, RAX, RBX, SZ_B);
17+	cur = mov_rr(cur, RCX, RDX, SZ_B);
18+	cur = mov_rr(cur, R8, R9, SZ_B);
19+	cur = mov_rr(cur, R8, RAX, SZ_B);
20+	cur = mov_rr(cur, RAX, RBX, SZ_W);
21+	cur = mov_rr(cur, R11, R12, SZ_W);
22+	cur = mov_rr(cur, RAX, RBX, SZ_D);
23+	cur = mov_rr(cur, RAX, RBX, SZ_Q);
24+	cur = mov_ir(cur, 5, RAX, SZ_D);
25+	cur = mov_ir(cur, 3, R8, SZ_D);
26+	cur = mov_ir(cur, 4, RSP, SZ_B);
27+	cur = add_rr(cur, RAX, RBX, SZ_D);
28+	cur = add_ir(cur, 5, RAX, SZ_B);
29+	cur = add_ir(cur, 5, RBX, SZ_B);
30+	cur = add_ir(cur, 5, RBP, SZ_B);
31+	cur = pushf(cur);
32+	cur = popf(cur);
33+	cur = setcc_r(cur, CC_S, RBX);
34+	cur = setcc_r(cur, CC_Z, RDX);
35+	cur = setcc_r(cur, CC_O, BH);
36+	cur = setcc_r(cur, CC_C, DH);
37+	cur = setcc_rind(cur, CC_C, RSI);
38+	cur = mov_rrdisp8(cur, RCX, RSI, offsetof(m68k_context, dregs) + 4 * sizeof(uint32_t), SZ_D);
39+	cur = mov_rdisp8r(cur, RSI, offsetof(m68k_context, dregs) + 5 * sizeof(uint32_t), RCX, SZ_D);
40+	cur = mov_rrind(cur, DH, RSI, SZ_B);
41+	cur = jcc(cur, CC_NZ, -2);
42+	cur = jcc(cur, CC_Z, 0);
43+	cur = jcc(cur, CC_LE, 0x7CA);
44+	for (end = cur, cur = foo; cur != end; cur++) {
45+		printf(" %X", *cur);
46+	}
47+	puts("");
48+	return 0;
49+}
+88, -0
 1@@ -0,0 +1,88 @@
 2+Name	Sizes	Src Modes														Dst Modes
 3+add		bwl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
 4+add		bwl		d																(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 5+adda	wl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	a
 6+addi	bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 7+addq	bwl		#(1-8)															d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
 8+addx	bwl		d																d
 9+addx	bwl		-(a)															-(a)
10+and		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
11+and		bwl		d																(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
12+andi	bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
13+asl		bwl		d;#(1-8)														d
14+asr		bwl		d;#(1-8)														d
15+lsl		bwl		d;#(1-8)														d
16+lsr		bwl		d;#(1-8)														d
17+sub		bwl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
18+sub		bwl		d																(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
19+suba	wl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	a
20+subi	bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
21+subq	bwl		#(1-8)															d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
22+subx	bwl		d																d
23+subx	bwl		-(a)															-(a)
24+bchg	b		d;#(0-255)														(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
25+bchg	l		d;#(0-255)														d
26+bset	b		d;#(0-255)														(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
27+bset	l		d;#(0-255)														d
28+bclr	b		d;#(0-255)														(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
29+bclr	l		d;#(0-255)														d
30+btst	b		d;#(0-255)														(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
31+btst	l		d;#(0-255)														d
32+rol		bwl		d;#(1-8)														d
33+ror		bwl		d;#(1-8)														d
34+abcd	b		d																d
35+abcd	b		-(a)															-(a)
36+sbcd	b		d																d
37+sbcd	b		-(a)															-(a)
38+muls	w		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
39+mulu	w		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
40+move	bwl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
41+movea	wl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	a
42+moveq	l		#(-128-127)														d
43+roxl	bwl		d;#(1-8)														d
44+roxr	bwl		d;#(1-8)														d
45+divs	w		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
46+divu	w		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
47+chk		w		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
48+cmp		bwl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
49+cmpa	wl		d;a;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	a
50+cmpi	bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
51+cmpm	bwl		(a)+															(a)+
52+eor		bwl		d																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
53+eori	bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
54+exg		l		d																d;a
55+exg		l		a																a
56+link	w		a																#n
57+or		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l;#n;(n,pc);(n,pc,x)	d
58+or		bwl		d																(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
59+ori		bwl		#n																d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
60+clr		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
61+ext		wl		d
62+neg		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
63+negx	bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
64+not		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
65+pea		l		(a);(n,a);(n,a,x);(n).w;(n).l;(n,pc);(n,pc,x)
66+rol		w		(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
67+ror		w		(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
68+roxl	w		(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
69+roxr	w		(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
70+st		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
71+sf		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
72+shi		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
73+sls		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
74+scc		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
75+scs		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
76+sne		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
77+seq		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
78+svc		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
79+svs		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
80+spl		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
81+smi		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
82+sge		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
83+slt		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
84+sgt		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
85+sle		b		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
86+swap	w		d
87+tst		bwl		d;(a);(a)+;-(a);(n,a);(n,a,x);(n).w;(n).l
88+lea		l		(a);(n,a);(n,a,x);(n).w;(n).l;(n,pc);(n,pc,x)					a
89+
+81, -0
 1@@ -0,0 +1,81 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm. 
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include "gst.h"
 8+#include <string.h>
 9+#include <stdlib.h>
10+
11+uint8_t busreq;
12+uint8_t reset;
13+
14+void latch_mode(vdp_context * context)
15+{
16+}
17+void ym_data_write(ym2612_context * context, uint8_t value)
18+{
19+	if (context->selected_reg >= YM_REG_END) {
20+		return;
21+	}
22+	if (context->selected_part) {
23+		if (context->selected_reg < YM_PART2_START) {
24+			return;
25+		}
26+		context->part2_regs[context->selected_reg - YM_PART2_START] = value;
27+	} else {
28+		if (context->selected_reg < YM_PART1_START) {
29+			return;
30+		}
31+		context->part1_regs[context->selected_reg - YM_PART1_START] = value;
32+	}
33+}
34+
35+void ym_address_write_part1(ym2612_context * context, uint8_t address)
36+{
37+	//printf("address_write_part1: %X\n", address);
38+	context->selected_reg = address;
39+	context->selected_part = 0;
40+}
41+
42+void ym_address_write_part2(ym2612_context * context, uint8_t address)
43+{
44+	//printf("address_write_part2: %X\n", address);
45+	context->selected_reg = address;
46+	context->selected_part = 1;
47+}
48+
49+uint16_t ram[64*1024];
50+uint8_t zram[8*1024];
51+
52+
53+int main(int argc, char ** argv)
54+{
55+	vdp_context vdp;
56+	ym2612_context ym;
57+	psg_context psg;
58+	m68k_context m68k;
59+	z80_context z80;
60+	genesis_context gen;
61+	if (argc < 3) {
62+		fputs("Usage: testgst infile outfile\n", stderr);
63+		return 1;
64+	}
65+	memset(&gen, 0, sizeof(gen));
66+	memset(&m68k, 0, sizeof(m68k));
67+	memset(&z80, 0, sizeof(z80));
68+	memset(&ym, 0, sizeof(ym));
69+	memset(&vdp, 0, sizeof(vdp));
70+	memset(&psg, 0, sizeof(psg));
71+	m68k.mem_pointers[1] = ram;
72+	z80.mem_pointers[0] = zram;
73+	vdp.vdpmem = malloc(VRAM_SIZE);
74+	gen.vdp = &vdp;
75+	gen.ym = &ym;
76+	gen.psg = &psg;
77+	gen.m68k = &m68k;
78+	gen.z80 = &z80;
79+	uint32_t pc = load_gst(&gen, argv[1]);
80+	save_gst(&gen, argv[2], pc);
81+	return 0;
82+}
+26, -0
 1@@ -0,0 +1,26 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm. 
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include "tern.h"
 8+#include <stdio.h>
 9+#include <stddef.h>
10+
11+int main(int argc, char ** argv)
12+{
13+	tern_node * tree = tern_insert_ptr(NULL, "foo", "bar");
14+	tree = tern_insert_ptr(tree, "foobar", "baz");
15+	tree = tern_insert_ptr(tree, "goobar", "qux");
16+	tree = tern_insert_int(tree, "foobarbaz", 42);
17+	tree = tern_insert_int(tree, "goobarbaz", 21);
18+	printf("foo: %s\n", (char *)tern_find_ptr(tree, "foo"));
19+	printf("foobar: %s\n", (char *)tern_find_ptr(tree, "foobar"));
20+	printf("goobar: %s\n", (char *)tern_find_ptr(tree, "goobar"));
21+	printf("foob: %s\n", (char *)tern_find_ptr(tree, "foob"));
22+	printf("foobarbaz: %d\n", (int)tern_find_int(tree, "foobarbaz", 0));
23+	printf("goobarbaz: %d\n", (int)tern_find_int(tree, "goobarbaz", 0));
24+	printf("foobarb: %d\n", (int)tern_find_int(tree, "foobarb", 0));
25+	return 0;
26+}
27+
+45, -0
 1@@ -0,0 +1,45 @@
 2+0.5.0 TODO List
 3+----------------
 4+Fix DIVU/DIVS timing
 5+Implement SSG-EG Mode
 6+Implement CSM Mode
 7+Provide an option to save SRAM/save states relative to ROM
 8+SMS region handling
 9+Update README
10+	- New controller mapping stuff
11+	- Overscan
12+	- Full screen toggle
13+	- Aspect ratio control
14+	- Soft Reset
15+Update Changelog
16+SMS Pause NMI
17+
18+0.5.0 Nice to Haves
19+-------------------
20+Basic GG support
21+Horizontal border emulation
22+Integrate Jaguar emulation into main executable
23+Realtec mapper support
24+64-bit Windows Build
25+
26+Future Releases (no particular order)
27+---------------
28+MegaWIFI
29+32X
30+Sega CD
31+Full SMS/GG VDP emulation
32+Improve internal CPU debugger
33+Allow "debug windows" so VDP debug output can be viewed simultaneously with normal output
34+YM2413 emulation
35+Laser Active
36+Finish Jaguar emulation
37+Multitap
38+Light Guns
39+XE-1 AP
40+Cheat Codes
41+Controller Mapping UI
42+SVP emulation
43+Rewind
44+Netplay
45+Rewrite CPUs with dynarec DSL
46+ARM support
+84, -0
 1@@ -0,0 +1,84 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include "68kinst.h"
 8+#include "m68k_core.h"
 9+#include "mem.h"
10+#include <stdio.h>
11+#include <stdlib.h>
12+#include <string.h>
13+
14+int headless = 1;
15+void render_errorbox(char * title, char * buf)
16+{
17+}
18+
19+void render_infobox(char * title, char * buf)
20+{
21+}
22+
23+m68k_context * sync_components(m68k_context * context, uint32_t address)
24+{
25+	if (context->current_cycle > 0x80000000) {
26+		context->current_cycle -= 0x80000000;
27+	}
28+	if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
29+		context->target_cycle = context->current_cycle;
30+	}
31+	return context;
32+}
33+
34+m68k_context *reset_handler(m68k_context *context)
35+{
36+	m68k_print_regs(context);
37+	exit(0);
38+	//unreachable
39+	return context;
40+}
41+
42+int main(int argc, char ** argv)
43+{
44+	long filesize;
45+	unsigned short *filebuf;
46+	char disbuf[1024];
47+	unsigned short * cur;
48+	m68k_options opts;
49+	FILE * f = fopen(argv[1], "rb");
50+	fseek(f, 0, SEEK_END);
51+	filesize = ftell(f);
52+	fseek(f, 0, SEEK_SET);
53+	filebuf = malloc(0x400000);
54+	memset(filebuf, 0, 0x400000);
55+	fread(filebuf, 2, filesize/2 > 0x200000 ? 0x200000 : filesize/2, f);
56+	fclose(f);
57+	for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
58+	{
59+		*cur = (*cur >> 8) | (*cur << 8);
60+	}
61+	memmap_chunk memmap[2];
62+	memset(memmap, 0, sizeof(memmap_chunk)*2);
63+	memmap[0].end = 0x400000;
64+	memmap[0].mask = 0xFFFFFF;
65+	memmap[0].flags = MMAP_READ;
66+	memmap[0].buffer = filebuf;
67+
68+	memmap[1].start = 0xE00000;
69+	memmap[1].end = 0x1000000;
70+	memmap[1].mask = 0xFFFF;
71+	memmap[1].flags = MMAP_READ | MMAP_WRITE | MMAP_CODE;
72+	memmap[1].buffer = malloc(64 * 1024);
73+	memset(memmap[1].buffer, 0, 64 * 1024);
74+	init_m68k_opts(&opts, memmap, 2, 1);
75+	m68k_context * context = init_68k_context(&opts, reset_handler);
76+	context->mem_pointers[0] = memmap[0].buffer;
77+	context->mem_pointers[1] = memmap[1].buffer;
78+	context->target_cycle = context->sync_cycle = 0x80000000;
79+	uint32_t address;
80+	address = filebuf[2] << 16 | filebuf[3];
81+	translate_m68k_stream(address, context);
82+	m68k_reset(context);
83+	return 0;
84+}
85+
A util.c
+748, -0
  1@@ -0,0 +1,748 @@
  2+#include <string.h>
  3+#include <stdlib.h>
  4+#include <stdio.h>
  5+#include <ctype.h>
  6+#include <stdint.h>
  7+#include <stdarg.h>
  8+
  9+#include <sys/types.h>
 10+#include <sys/stat.h>
 11+#include <unistd.h>
 12+#include <errno.h>
 13+
 14+#define info_puts(msg) fputs(msg, stdout);
 15+#define warning_puts(msg) fputs(msg, stderr);
 16+#define fatal_puts(msg) fputs(msg, stderr);
 17+
 18+#define info_printf(msg, args) vprintf(msg, args)
 19+#define warning_printf(msg, args) vfprintf(stderr, msg, args)
 20+#define fatal_printf(msg, args) vfprintf(stderr, msg, args)
 21+#include "blastem.h" //for headless global
 22+#include "render.h" //for render_errorbox
 23+#include "util.h"
 24+
 25+char * alloc_concat(char const * first, char const * second)
 26+{
 27+	int flen = strlen(first);
 28+	int slen = strlen(second);
 29+	char * ret = malloc(flen + slen + 1);
 30+	memcpy(ret, first, flen);
 31+	memcpy(ret+flen, second, slen+1);
 32+	return ret;
 33+}
 34+
 35+char * alloc_concat_m(int num_parts, char const ** parts)
 36+{
 37+	int total = 0;
 38+	for (int i = 0; i < num_parts; i++) {
 39+		total += strlen(parts[i]);
 40+	}
 41+	char * ret = malloc(total + 1);
 42+	*ret = 0;
 43+	for (int i = 0; i < num_parts; i++) {
 44+		strcat(ret, parts[i]);
 45+	}
 46+	return ret;
 47+}
 48+
 49+typedef struct {
 50+	uint32_t start;
 51+	uint32_t end;
 52+	char *value;
 53+} var_pos;
 54+
 55+char *replace_vars(char *base, tern_node *vars, uint8_t allow_env)
 56+{
 57+	uint32_t num_vars = 0;
 58+	for (char *cur = base; *cur; ++cur)
 59+	{
 60+		//TODO: Support escaping $ and allow brace syntax
 61+		if (*cur == '$') {
 62+			num_vars++;
 63+		}
 64+	}
 65+	var_pos *positions = calloc(num_vars, sizeof(var_pos));
 66+	num_vars = 0;
 67+	uint8_t in_var = 0;
 68+	uint32_t max_var_len = 0;
 69+	for (char *cur = base; *cur; ++cur)
 70+	{
 71+		if (in_var) {
 72+			if (!(*cur == '_' || isalnum(*cur))) {
 73+				positions[num_vars].end = cur-base;
 74+				if (positions[num_vars].end - positions[num_vars].start > max_var_len) {
 75+					max_var_len = positions[num_vars].end - positions[num_vars].start;
 76+				}
 77+				num_vars++;
 78+				in_var = 0;
 79+			}
 80+		} else if (*cur == '$') {
 81+			positions[num_vars].start = cur-base+1;
 82+			in_var = 1;
 83+		}
 84+	}
 85+	if (in_var) {
 86+		positions[num_vars].end = strlen(base);
 87+		if (positions[num_vars].end - positions[num_vars].start > max_var_len) {
 88+			max_var_len = positions[num_vars].end - positions[num_vars].start;
 89+		}
 90+		num_vars++;
 91+	}
 92+	char *varname = malloc(max_var_len+1);
 93+	uint32_t total_len = 0;
 94+	uint32_t cur = 0;
 95+	for (uint32_t i = 0; i < num_vars; i++)
 96+	{
 97+		total_len += (positions[i].start - 1) - cur;
 98+		cur = positions[i].start;
 99+		memcpy(varname, base + positions[i].start, positions[i].end-positions[i].start);
100+		varname[positions[i].end-positions[i].start] = 0;
101+		positions[i].value = tern_find_ptr(vars, varname);
102+		if (!positions[i].value && allow_env) {
103+			positions[i].value = getenv(varname);
104+		}
105+		if (positions[i].value) {
106+			total_len += strlen(positions[i].value);
107+		}
108+	}
109+	total_len += strlen(base+cur);
110+	free(varname);
111+	char *output = malloc(total_len+1);
112+	cur = 0;
113+	char *curout = output;
114+	for (uint32_t i = 0; i < num_vars; i++)
115+	{
116+		if (positions[i].start-1 > cur) {
117+			memcpy(curout, base + cur, (positions[i].start-1) - cur);
118+			curout += (positions[i].start-1) - cur;
119+		}
120+		if (positions[i].value) {
121+			strcpy(curout, positions[i].value);
122+			curout += strlen(curout);
123+		}
124+		cur = positions[i].end;
125+	};
126+	if (base[cur]) {
127+		strcpy(curout, base+cur);
128+	} else {
129+		*curout = 0;
130+	}
131+	free(positions);
132+	return output;
133+}
134+
135+void byteswap_rom(int filesize, uint16_t *cart)
136+{
137+	for(uint16_t *cur = cart; cur - cart < filesize/2; ++cur)
138+	{
139+		*cur = (*cur >> 8) | (*cur << 8);
140+	}
141+}
142+
143+
144+long file_size(FILE * f)
145+{
146+	fseek(f, 0, SEEK_END);
147+	long fsize = ftell(f);
148+	fseek(f, 0, SEEK_SET);
149+	return fsize;
150+}
151+
152+char * strip_ws(char * text)
153+{
154+	while (*text && (!isprint(*text) || isblank(*text)))
155+	{
156+		text++;
157+	}
158+	char * ret = text;
159+	text = ret + strlen(ret) - 1;
160+	while (text > ret && (!isprint(*text) || isblank(*text)))
161+	{
162+		*text = 0;
163+		text--;
164+	}
165+	return ret;
166+}
167+
168+char * split_keyval(char * text)
169+{
170+	while (*text && !isblank(*text))
171+	{
172+		text++;
173+	}
174+	if (!*text) {
175+		return text;
176+	}
177+	*text = 0;
178+	return text+1;
179+}
180+
181+uint8_t startswith(const char *haystack, const char *prefix)
182+{
183+	return !strncmp(haystack, prefix, strlen(prefix));
184+}
185+
186+void bin_to_hex(uint8_t *output, uint8_t *input, uint64_t size)
187+{
188+	while (size)
189+	{
190+		uint8_t digit = *input >> 4;
191+		digit += digit > 9 ? 'a' - 0xa : '0';
192+		*(output++) = digit;
193+		digit = *(input++) & 0xF;
194+		digit += digit > 9 ? 'a' - 0xa : '0';
195+		*(output++) = digit;
196+		size--;
197+	}
198+	*(output++) = 0;
199+}
200+
201+char *utf16be_to_utf8(uint8_t *buf, uint32_t max_size)
202+{
203+	uint8_t *cur = buf;
204+	uint32_t converted_size = 0;
205+	for (uint32_t i = 0; i < max_size; i++, cur+=2)
206+	{
207+		uint16_t code = *cur << 16 | cur[1];
208+		if (!code) {
209+			break;
210+		}
211+		if (code < 0x80) {
212+			converted_size++;
213+		} else if (code < 0x800) {
214+			converted_size += 2;
215+		} else {
216+			//TODO: Deal with surrogate pairs
217+			converted_size += 3;
218+		}
219+	}
220+	char *out = malloc(converted_size + 1);
221+	char *cur_out = out;
222+	cur = buf;
223+	for (uint32_t i = 0; i < max_size; i++, cur+=2)
224+	{
225+		uint16_t code = *cur << 16 | cur[1];
226+		if (!code) {
227+			break;
228+		}
229+		if (code < 0x80) {
230+			*(cur_out++) = code;
231+		} else if (code < 0x800) {
232+			*(cur_out++) = 0xC0 | code >> 6;
233+			*(cur_out++) = 0x80 | (code & 0x3F);
234+		} else {
235+			//TODO: Deal with surrogate pairs
236+			*(cur_out++) = 0xF0 | code >> 12;
237+			*(cur_out++) = 0x80 | (code >> 6 & 0x3F);
238+			*(cur_out++) = 0x80 | (code & 0x3F);
239+		}
240+	}
241+	*cur_out = 0;
242+	return out;
243+}
244+
245+int utf8_codepoint(const char **text)
246+{
247+	uint8_t initial = **text;
248+	(*text)++;
249+	if (initial < 0x80) {
250+		return initial;
251+	}
252+	int base = 0;
253+	uint8_t extended_bytes = 0;
254+	if ((initial & 0xE0) == 0xC0) {
255+		base = 0x80;
256+		initial &= 0x1F;
257+		extended_bytes = 1;
258+	} else if ((initial & 0xF0) == 0xE0) {
259+		base = 0x800;
260+		initial &= 0xF;
261+		extended_bytes = 2;
262+	} else if ((initial & 0xF8) == 0xF0) {
263+		base = 0x10000;
264+		initial &= 0x7;
265+		extended_bytes = 3;
266+	}
267+	int value = initial;
268+	for (uint8_t i = 0; i < extended_bytes; i++)
269+	{
270+		if ((**text & 0xC0) != 0x80) {
271+			return -1;
272+		}
273+		value = value << 6;
274+		value |= (**text) & 0x3F;
275+		(*text)++;
276+	}
277+	return value + base;
278+}
279+
280+char is_path_sep(char c)
281+{
282+	return c == '/';
283+}
284+
285+char is_absolute_path(char *path)
286+{
287+	return is_path_sep(path[0]);
288+}
289+
290+char * basename_no_extension(const char *path)
291+{
292+	const char *lastdot = NULL;
293+	const char *lastslash = NULL;
294+	const char *cur;
295+	for (cur = path; *cur; cur++)
296+	{
297+		if (*cur == '.') {
298+			lastdot = cur;
299+		} else if (is_path_sep(*cur)) {
300+			lastslash = cur + 1;
301+		}
302+	}
303+	if (!lastdot) {
304+		lastdot = cur;
305+	}
306+	if (!lastslash) {
307+		lastslash = path;
308+	}
309+	char *barename = malloc(lastdot-lastslash+1);
310+	memcpy(barename, lastslash, lastdot-lastslash);
311+	barename[lastdot-lastslash] = 0;
312+	
313+	return barename;
314+}
315+
316+char *path_extension(char const *path)
317+{
318+	char const *lastdot = NULL;
319+	char const *lastslash = NULL;
320+	char const *cur;
321+	for (cur = path; *cur; cur++)
322+	{
323+		if (*cur == '.') {
324+			lastdot = cur;
325+		} else if (is_path_sep(*cur)) {
326+			lastslash = cur + 1;
327+		}
328+	}
329+	if (!lastdot || (lastslash && lastslash > lastdot)) {
330+		//no extension
331+		return NULL;
332+	}
333+	return strdup(lastdot+1);
334+}
335+
336+uint8_t path_matches_extensions(char *path, char **ext_list, uint32_t num_exts)
337+{
338+	char *ext = path_extension(path);
339+	if (!ext) {
340+		return 0;
341+	}
342+	uint32_t extidx;
343+	for (extidx = 0; extidx < num_exts; extidx++)
344+	{
345+		if (!strcasecmp(ext, ext_list[extidx])) {
346+			free(ext);
347+			return 1;
348+		}
349+	}
350+	free(ext);
351+	return 0;
352+}
353+
354+char * path_dirname(const char *path)
355+{
356+	const char *lastslash = NULL;
357+	const char *cur;
358+	for (cur = path; *cur; cur++)
359+	{
360+		if (is_path_sep(*cur)) {
361+			lastslash = cur;
362+		}
363+	}
364+	if (!lastslash) {
365+		return NULL;
366+	}
367+	char *dir = malloc(lastslash-path+1);
368+	memcpy(dir, path, lastslash-path);
369+	dir[lastslash-path] = 0;
370+	
371+	return dir;
372+}
373+
374+uint32_t nearest_pow2(uint32_t val)
375+{
376+	uint32_t ret = 1;
377+	while (ret < val)
378+	{
379+		ret = ret << 1;
380+	}
381+	return ret;
382+}
383+
384+static char * exe_str;
385+
386+void set_exe_str(char * str)
387+{
388+	exe_str = str;
389+}
390+
391+void fatal_error(char *format, ...)
392+{
393+	va_list args;
394+	va_start(args, format);
395+	if (!headless) {
396+		//take a guess at the final size
397+		int32_t size = strlen(format) * 2;
398+		char *buf = malloc(size);
399+		int32_t actual = vsnprintf(buf, size, format, args);
400+		if (actual >= size || actual < 0) {
401+			if (actual < 0) {
402+				//seems on windows, vsnprintf is returning -1 when the buffer is too small
403+				//since we don't know the proper size, a generous multiplier will hopefully suffice
404+				actual = size * 4;
405+			} else {
406+				actual++;
407+			}
408+			free(buf);
409+			buf = malloc(actual);
410+			va_end(args);
411+			va_start(args, format);
412+			vsnprintf(buf, actual, format, args);
413+		}
414+		fatal_puts(buf);
415+		render_errorbox("Fatal Error", buf);
416+		free(buf);
417+	} else {
418+		fatal_printf(format, args);
419+	}
420+	va_end(args);
421+	exit(1);
422+}
423+
424+void warning(char *format, ...)
425+{
426+	va_list args;
427+	va_start(args, format);
428+	if (headless || (isatty(STDERR_FILENO) && isatty(STDIN_FILENO))) {
429+		warning_printf(format, args);
430+	} else {
431+		int32_t size = strlen(format) * 2;
432+		char *buf = malloc(size);
433+		int32_t actual = vsnprintf(buf, size, format, args);
434+		if (actual >= size || actual < 0) {
435+			if (actual < 0) {
436+				//seems on windows, vsnprintf is returning -1 when the buffer is too small
437+				//since we don't know the proper size, a generous multiplier will hopefully suffice
438+				actual = size * 4;
439+			} else {
440+				actual++;
441+			}
442+			free(buf);
443+			buf = malloc(actual);
444+			va_end(args);
445+			va_start(args, format);
446+			vsnprintf(buf, actual, format, args);
447+		}
448+		warning_puts(buf);
449+		render_infobox("BlastEm Info", buf);
450+		free(buf);
451+	}
452+	va_end(args);
453+}
454+
455+static uint8_t output_enabled = 1;
456+void info_message(char *format, ...)
457+{
458+	va_list args;
459+	va_start(args, format);
460+	if (headless || (isatty(STDOUT_FILENO) && isatty(STDIN_FILENO))) {
461+		if (output_enabled) {
462+			info_printf(format, args);
463+		}
464+	} else {
465+		int32_t size = strlen(format) * 2;
466+		char *buf = malloc(size);
467+		int32_t actual = vsnprintf(buf, size, format, args);
468+		if (actual >= size || actual < 0) {
469+			if (actual < 0) {
470+				//seems on windows, vsnprintf is returning -1 when the buffer is too small
471+				//since we don't know the proper size, a generous multiplier will hopefully suffice
472+				actual = size * 4;
473+			} else {
474+				actual++;
475+			}
476+			free(buf);
477+			buf = malloc(actual);
478+			va_end(args);
479+			va_start(args, format);
480+			vsnprintf(buf, actual, format, args);
481+		}
482+		if (output_enabled) {
483+			info_puts(buf);
484+		}
485+		render_infobox("BlastEm Info", buf);
486+		free(buf);
487+	}
488+	va_end(args);
489+}
490+
491+void debug_message(char *format, ...)
492+{
493+	va_list args;
494+	va_start(args, format);
495+	if (output_enabled) {
496+		info_printf(format, args);
497+	}
498+}
499+
500+void disable_stdout_messages(void)
501+{
502+	output_enabled = 0;
503+}
504+
505+char * get_home_dir()
506+{
507+	return getenv("HOME");
508+}
509+
510+char * readlink_alloc(char * path)
511+{
512+	char * linktext = NULL;
513+	ssize_t linksize = 512;
514+	ssize_t cursize = 0;
515+	do {
516+		if (linksize > cursize) {
517+			cursize = linksize;
518+			if (linktext) {
519+				free(linktext);
520+			}
521+		}
522+		linktext = malloc(cursize);
523+		linksize = readlink(path, linktext, cursize-1);
524+		if (linksize == -1) {
525+			perror("readlink");
526+			free(linktext);
527+			return NULL;
528+		}
529+	} while ((linksize+1) > cursize);
530+	linktext[linksize] = 0;
531+	return linktext;
532+}
533+
534+char * get_exe_dir()
535+{
536+	static char * exe_dir;
537+	if (!exe_dir) {
538+		char * cur;
539+		char * linktext = readlink_alloc("/proc/self/exe");
540+		if (!linktext) {
541+			goto fallback;
542+		}
543+		int linksize = strlen(linktext);
544+		for(cur = linktext + linksize - 1; cur != linktext; cur--)
545+		{
546+			if (is_path_sep(*cur)) {
547+				*cur = 0;
548+				break;
549+			}
550+		}
551+		if (cur == linktext) {
552+			free(linktext);
553+fallback:
554+			if (!exe_str) {
555+				fputs("/proc/self/exe is not available and set_exe_str was not called!", stderr);
556+			}
557+			int pathsize = strlen(exe_str);
558+			for(cur = exe_str + pathsize - 1; cur != exe_str; cur--)
559+			{
560+				if (is_path_sep(*cur)) {
561+					exe_dir = malloc(cur-exe_str+1);
562+					memcpy(exe_dir, exe_str, cur-exe_str);
563+					exe_dir[cur-exe_str] = 0;
564+					break;
565+				}
566+			}
567+		} else {
568+			exe_dir = linktext;
569+		}
570+	}
571+	return exe_dir;
572+}
573+#include <dirent.h>
574+
575+dir_entry *get_dir_list(char *path, size_t *numret)
576+{
577+	DIR *d = opendir(path);
578+	if (!d) {
579+		if (numret) {
580+			*numret = 0;
581+		}
582+		return NULL;
583+	}
584+	size_t storage = 64;
585+	dir_entry *ret = malloc(sizeof(dir_entry) * storage);
586+	size_t pos = 0;
587+	struct dirent* entry;
588+	while (entry = readdir(d))
589+	{
590+		if (entry->d_type != DT_REG && entry->d_type != DT_LNK && entry->d_type != DT_DIR) {
591+			continue;
592+		}
593+		if (pos == storage) {
594+			storage = storage * 2;
595+			ret = realloc(ret, sizeof(dir_entry) * storage);
596+		}
597+		ret[pos].name = strdup(entry->d_name);
598+		ret[pos++].is_dir = entry->d_type == DT_DIR;
599+	}
600+	if (numret) {
601+		*numret = pos;
602+	}
603+	closedir(d);
604+	return ret;
605+}
606+
607+time_t get_modification_time(char *path)
608+{
609+	struct stat st;
610+	if (stat(path, &st)) {
611+		return 0;
612+	}
613+#ifdef __APPLE__
614+    return st.st_mtimespec.tv_sec;
615+#else
616+	//Android's Bionic doesn't support the new style so we'll use the old one instead
617+	return st.st_mtime;
618+#endif
619+}
620+
621+int ensure_dir_exists(const char *path)
622+{
623+	struct stat st;
624+	if (stat(path, &st)) {
625+		if (errno == ENOENT) {
626+			char *parent = strdup(path);
627+			char *sep = strrchr(parent, '/');
628+			if (sep && sep != parent) {
629+				*sep = 0;
630+				if (!ensure_dir_exists(parent)) {
631+					free(parent);
632+					return 0;
633+				}
634+				free(parent);
635+			}
636+			return mkdir(path, 0777) == 0;
637+		} else {
638+			char buf[80];
639+			strerror_r(errno, buf, sizeof(buf));
640+			warning("stat failed with error: %s", buf);
641+			return 0;
642+		}
643+	}
644+	return S_ISDIR(st.st_mode);
645+}
646+
647+
648+void free_dir_list(dir_entry *list, size_t numentries)
649+{
650+	for (size_t i = 0; i < numentries; i++)
651+	{
652+		free(list[i].name);
653+	}
654+	free(list);
655+}
656+
657+static int sort_dir_alpha(const void *a, const void *b)
658+{
659+	const dir_entry *da, *db;
660+	da = a;
661+	db = b;
662+	if (da->is_dir != db->is_dir) {
663+		return db->is_dir - da->is_dir;
664+	}
665+	return strcasecmp(((dir_entry *)a)->name, ((dir_entry *)b)->name);
666+}
667+
668+void sort_dir_list(dir_entry *list, size_t num_entries)
669+{
670+	qsort(list, num_entries, sizeof(dir_entry), sort_dir_alpha);
671+}
672+
673+char *read_bundled_file(char *name, uint32_t *sizeret)
674+{
675+#ifdef DATA_PATH
676+	char *data_dir = DATA_PATH;
677+#else
678+	char *data_dir = get_exe_dir();
679+	if (!data_dir) {
680+		if (sizeret) {
681+			*sizeret = -1;
682+		}
683+		return NULL;
684+	}
685+	char const *pieces[] = {data_dir, PATH_SEP, name};
686+	char *path = alloc_concat_m(3, pieces);
687+	FILE *f = fopen(path, "rb");
688+	free(path);
689+	if (!f) {
690+		if (sizeret) {
691+			*sizeret = -1;
692+		}
693+		return NULL;
694+	}
695+
696+	long fsize = file_size(f);
697+	if (sizeret) {
698+		*sizeret = fsize;
699+	}
700+	char *ret;
701+	if (fsize) {
702+		//reserve an extra byte in case caller wants
703+		//to null terminate the data
704+		ret = malloc(fsize+1);
705+		if (fread(ret, 1, fsize, f) != fsize) {
706+			free(ret);
707+			ret = NULL;
708+		}
709+	} else {
710+		ret = NULL;
711+	}
712+	fclose(f);
713+	return ret;
714+}
715+
716+
717+
718+#define CONFIG_PREFIX "/.config"
719+#define USERDATA_SUFFIX "/.local/share"
720+
721+char const *get_config_dir()
722+{
723+	static char* confdir;
724+	if (!confdir) {
725+		char const *base = get_home_dir();
726+		if (base) {
727+			confdir = alloc_concat(base, CONFIG_PREFIX PATH_SEP "blastem");
728+		}
729+	}
730+	return confdir;
731+}
732+
733+char const *get_userdata_dir()
734+{
735+	static char* savedir;
736+	if (!savedir) {
737+		char const *base = get_home_dir();
738+		if (base) {
739+			savedir = alloc_concat(base, USERDATA_SUFFIX);
740+		}
741+	}
742+	return savedir;
743+}
744+
745+
746+
747+
748+
749+#endif
A util.h
+88, -0
 1@@ -0,0 +1,88 @@
 2+#ifndef UTIL_H_
 3+#define UTIL_H_
 4+
 5+#include <stdio.h>
 6+#include <time.h>
 7+#include "tern.h"
 8+
 9+typedef struct {
10+	char    *name;
11+	uint8_t is_dir;
12+} dir_entry;
13+
14+#define PATH_SEP "/"
15+
16+//Utility functions
17+
18+//Allocates a new string containing the concatenation of first and second
19+char * alloc_concat(char const * first, char const * second);
20+//Allocates a new string containing the concatenation of the strings pointed to by parts
21+char * alloc_concat_m(int num_parts, char const ** parts);
22+//Returns a newly allocated string in which all variables in based are replaced with values from vars or the environment
23+char *replace_vars(char *base, tern_node *vars, uint8_t allow_env);
24+//Byteswaps a ROM image in memory
25+void byteswap_rom(int filesize, uint16_t *cart);
26+//Returns the size of a file using fseek and ftell
27+long file_size(FILE * f);
28+//Strips whitespace and non-printable characters from the beginning and end of a string
29+char * strip_ws(char * text);
30+//Inserts a null after the first word, returns a pointer to the second word
31+char * split_keyval(char * text);
32+//Checks if haystack starts with prefix
33+uint8_t startswith(const char *haystack, const char *prefix);
34+//Takes a binary byte buffer and produces a lowercase hex string
35+void bin_to_hex(uint8_t *output, uint8_t *input, uint64_t size);
36+//Takes an (optionally) null-terminated UTF16-BE string and converts a maximum of max_size code-units to UTF-8
37+char *utf16be_to_utf8(uint8_t *buf, uint32_t max_size);
38+//Returns the next Unicode codepoint from a utf-8 string
39+int utf8_codepoint(const char **text);
40+//Determines whether a character is a valid path separator for the current platform
41+char is_path_sep(char c);
42+//Determines whether a path is considered an absolute path on the current platform
43+char is_absolute_path(char *path);
44+//Returns the basename of a path with th extension (if any) stripped
45+char * basename_no_extension(const char *path);
46+//Returns the extension from a path or NULL if there is no extension
47+char *path_extension(char const *path);
48+//Returns true if the given path matches one of the extensions in the list
49+uint8_t path_matches_extensions(char *path, char **ext_list, uint32_t num_exts);
50+//Returns the directory portion of a path or NULL if there is no directory part
51+char *path_dirname(const char *path);
52+//Gets the smallest power of two that is >= a certain value, won't work for values > 0x80000000
53+uint32_t nearest_pow2(uint32_t val);
54+//Should be called by main with the value of argv[0] for use by get_exe_dir
55+void set_exe_str(char * str);
56+//Returns the directory the executable is in
57+char * get_exe_dir();
58+//Returns the user's home directory
59+char * get_home_dir();
60+//Returns an appropriate path for storing config files
61+char const *get_config_dir();
62+//Returns an appropriate path for saving non-config data like savestates
63+char const *get_userdata_dir();
64+//Reads a file bundled with the executable
65+char *read_bundled_file(char *name, uint32_t *sizeret);
66+//Retunrs an array of normal files and directories residing in a directory
67+dir_entry *get_dir_list(char *path, size_t *numret);
68+//Frees a dir list returned by get_dir_list
69+void free_dir_list(dir_entry *list, size_t numentries);
70+//Performs a case-insensitive sort by file name on a dir list
71+void sort_dir_list(dir_entry *list, size_t num_entries);
72+//Gets the modification time of a file
73+time_t get_modification_time(char *path);
74+//Recusrively creates a directory if it does not exist
75+int ensure_dir_exists(const char *path);
76+//Returns the contents of a symlink in a newly allocated string
77+char * readlink_alloc(char * path);
78+//Prints an error message to stderr and to a message box if not in headless mode and then exits
79+void fatal_error(char *format, ...);
80+//Prints an information message to stdout and to a message box if not in headless mode and not attached to a console
81+void info_message(char *format, ...);
82+//Prints an information message to stderr and to a message box if not in headless mode and not attached to a console
83+void warning(char *format, ...);
84+//Prints a debug message to stdout
85+void debug_message(char *format, ...);
86+//Disables output of info and debug messages to stdout
87+void disable_stdout_messages(void);
88+
89+#endif //UTIL_H_
A vdp.c
+4159, -0
   1@@ -0,0 +1,4159 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "vdp.h"
   8+#include "blastem.h"
   9+#include <stdlib.h>
  10+#include <string.h>
  11+#include "render.h"
  12+#include "util.h"
  13+
  14+#define NTSC_INACTIVE_START 224
  15+#define PAL_INACTIVE_START 240
  16+#define MODE4_INACTIVE_START 192
  17+#define BUF_BIT_PRIORITY 0x40
  18+#define MAP_BIT_PRIORITY 0x8000
  19+#define MAP_BIT_H_FLIP 0x800
  20+#define MAP_BIT_V_FLIP 0x1000
  21+
  22+#define SCROLL_BUFFER_MASK (SCROLL_BUFFER_SIZE-1)
  23+#define SCROLL_BUFFER_DRAW (SCROLL_BUFFER_SIZE/2)
  24+
  25+#define MCLKS_SLOT_H40  16
  26+#define MCLKS_SLOT_H32  20
  27+#define VINT_SLOT_H40  0 //21 slots before HSYNC, 16 during, 10 after
  28+#define VINT_SLOT_H32  0  //old value was 23, but recent tests suggest the actual value is close to the H40 one
  29+#define VINT_SLOT_MODE4 4
  30+#define HSYNC_SLOT_H40  230
  31+#define HSYNC_END_H40  (HSYNC_SLOT_H40+17)
  32+#define HBLANK_START_H40 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results
  33+#define HBLANK_END_H40  0 //should be 5.5 according to Nemesis, but 0 seems to fit better with my test ROM results
  34+#define HBLANK_START_H32 233 //should be 147 according to Nemesis which is very different from my test ROM result
  35+#define HBLANK_END_H32 0 //should be 5 according to Nemesis, but 0 seems to fit better with my test ROM results
  36+#define LINE_CHANGE_H40 165
  37+#define LINE_CHANGE_H32 133
  38+#define LINE_CHANGE_MODE4 249
  39+#define VBLANK_START_H40 (LINE_CHANGE_H40+2)
  40+#define VBLANK_START_H32 (LINE_CHANGE_H32+2)
  41+#define FIFO_LATENCY    3
  42+
  43+#define BORDER_TOP_V24     27
  44+#define BORDER_TOP_V28     11
  45+#define BORDER_TOP_V24_PAL 54
  46+#define BORDER_TOP_V28_PAL 38
  47+#define BORDER_TOP_V30_PAL 30
  48+
  49+#define BORDER_BOT_V24     24
  50+#define BORDER_BOT_V28     8
  51+#define BORDER_BOT_V24_PAL 48
  52+#define BORDER_BOT_V28_PAL 32
  53+#define BORDER_BOT_V30_PAL 24
  54+
  55+#define INVALID_LINE (PAL_INACTIVE_START+BORDER_TOP_V30_PAL+BORDER_BOT_V30_PAL)
  56+
  57+enum {
  58+	INACTIVE = 0,
  59+	PREPARING, //used for line 0x1FF
  60+	ACTIVE
  61+};
  62+
  63+static int32_t color_map[1 << 12];
  64+static uint16_t mode4_address_map[0x4000];
  65+static uint32_t planar_to_chunky[256];
  66+static uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255};
  67+
  68+static uint8_t debug_base[][3] = {
  69+	{127, 127, 127}, //BG
  70+	{0, 0, 127},     //A
  71+	{127, 0, 0},     //Window
  72+	{0, 127, 0},     //B
  73+	{127, 0, 127}    //Sprites
  74+};
  75+
  76+static void update_video_params(vdp_context *context)
  77+{
  78+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
  79+		if (context->regs[REG_MODE_2] & BIT_PAL) {
  80+			if (context->flags2 & FLAG2_REGION_PAL) {
  81+				context->inactive_start = PAL_INACTIVE_START;
  82+				context->border_top = BORDER_TOP_V30_PAL;
  83+				context->border_bot = BORDER_BOT_V30_PAL;
  84+			} else {
  85+				//the behavior here is rather weird and needs more investigation
  86+				context->inactive_start = 0xF0;
  87+				context->border_top = 1;
  88+				context->border_bot = 3;
  89+			}
  90+		} else {
  91+			context->inactive_start = NTSC_INACTIVE_START;
  92+			if (context->flags2 & FLAG2_REGION_PAL) {
  93+				context->border_top = BORDER_TOP_V28_PAL;
  94+				context->border_bot = BORDER_BOT_V28_PAL;
  95+			} else {
  96+				context->border_top = BORDER_TOP_V28;
  97+				context->border_bot = BORDER_TOP_V28;
  98+			}
  99+		}
 100+		if (context->regs[REG_MODE_4] & BIT_H40) {
 101+			context->max_sprites_frame = MAX_SPRITES_FRAME;
 102+			context->max_sprites_line = MAX_SPRITES_LINE;
 103+		} else {
 104+			context->max_sprites_frame = MAX_SPRITES_FRAME_H32;
 105+			context->max_sprites_line = MAX_SPRITES_LINE_H32;
 106+		}
 107+		if (context->state == INACTIVE) {
 108+			//Undo forced INACTIVE state due to neither Mode 4 nor Mode 5 being active
 109+			if (context->vcounter < context->inactive_start) {
 110+				context->state = ACTIVE;
 111+			} else if (context->vcounter == 0x1FF) {
 112+				context->state = PREPARING;
 113+			}
 114+		}
 115+	} else {
 116+		context->inactive_start = MODE4_INACTIVE_START;
 117+		if (context->flags2 & FLAG2_REGION_PAL) {
 118+			context->border_top = BORDER_TOP_V24_PAL;
 119+			context->border_bot = BORDER_BOT_V24_PAL;
 120+		} else {
 121+			context->border_top = BORDER_TOP_V24;
 122+			context->border_bot = BORDER_BOT_V24;
 123+		}
 124+		if (!(context->regs[REG_MODE_1] & BIT_MODE_4)){
 125+			context->state = INACTIVE;
 126+		} else if (context->state == INACTIVE) {
 127+			//Undo forced INACTIVE state due to neither Mode 4 nor Mode 5 being active
 128+			if (context->vcounter < context->inactive_start) {
 129+				context->state = ACTIVE;
 130+			}
 131+			else if (context->vcounter == 0x1FF) {
 132+				context->state = PREPARING;
 133+			}
 134+		}
 135+	}
 136+}
 137+
 138+static uint8_t color_map_init_done;
 139+
 140+vdp_context *init_vdp_context(uint8_t region_pal)
 141+{
 142+	vdp_context *context = calloc(1, sizeof(vdp_context) + VRAM_SIZE);
 143+	if (headless) {
 144+		context->output = malloc(LINEBUF_SIZE * sizeof(uint32_t));
 145+		context->output_pitch = 0;
 146+	} else {
 147+		context->cur_buffer = VIDEO_BUFFER_ODD;
 148+		context->fb = render_get_video_buffer(VIDEO_BUFFER_ODD, &context->output_pitch);
 149+	}
 150+	context->sprite_draws = MAX_DRAWS;
 151+	context->fifo_write = 0;
 152+	context->fifo_read = -1;
 153+	context->regs[REG_HINT] = context->hint_counter = 0xFF;
 154+
 155+	if (!color_map_init_done) {
 156+		uint8_t b,g,r;
 157+		for (uint16_t color = 0; color < (1 << 12); color++) {
 158+			if (color & FBUF_SHADOW) {
 159+				b = levels[(color >> 9) & 0x7];
 160+				g = levels[(color >> 5) & 0x7];
 161+				r = levels[(color >> 1) & 0x7];
 162+			} else if(color & FBUF_HILIGHT) {
 163+				b = levels[((color >> 9) & 0x7) + 7];
 164+				g = levels[((color >> 5) & 0x7) + 7];
 165+				r = levels[((color >> 1) & 0x7) + 7];
 166+			} else if(color & FBUF_MODE4) {
 167+				b = levels[(color >> 4 & 0xC) | (color >> 6 & 0x2)];
 168+				g = levels[(color >> 2 & 0x8) | (color >> 1 & 0x4) | (color >> 4 & 0x2)];
 169+				r = levels[(color << 1 & 0xC) | (color >> 1 & 0x2)];
 170+			} else {
 171+				b = levels[(color >> 8) & 0xE];
 172+				g = levels[(color >> 4) & 0xE];
 173+				r = levels[color & 0xE];
 174+			}
 175+			color_map[color] = render_map_color(r, g, b);
 176+		}
 177+		for (uint16_t mode4_addr = 0; mode4_addr < 0x4000; mode4_addr++)
 178+		{
 179+			uint16_t mode5_addr = mode4_addr & 0x3DFD;
 180+			mode5_addr |= mode4_addr << 8 & 0x200;
 181+			mode5_addr |= mode4_addr >> 8 & 2;
 182+			mode4_address_map[mode4_addr] = mode5_addr;
 183+		}
 184+		for (uint32_t planar = 0; planar < 256; planar++)
 185+		{
 186+			uint32_t chunky = 0;
 187+			for (int bit = 7; bit >= 0; bit--)
 188+			{
 189+				chunky = chunky << 4;
 190+				chunky |= planar >> bit & 1;
 191+			}
 192+			planar_to_chunky[planar] = chunky;
 193+		}
 194+		color_map_init_done = 1;
 195+	}
 196+	for (uint8_t color = 0; color < (1 << (3 + 1 + 1 + 1)); color++)
 197+	{
 198+		uint8_t src = color & DBG_SRC_MASK;
 199+		if (src > DBG_SRC_S) {
 200+			context->debugcolors[color] = 0;
 201+		} else {
 202+			uint8_t r,g,b;
 203+			b = debug_base[src][0];
 204+			g = debug_base[src][1];
 205+			r = debug_base[src][2];
 206+			if (color & DBG_PRIORITY)
 207+			{
 208+				if (b) {
 209+					b += 48;
 210+				}
 211+				if (g) {
 212+					g += 48;
 213+				}
 214+				if (r) {
 215+					r += 48;
 216+				}
 217+			}
 218+			if (color & DBG_SHADOW) {
 219+				b /= 2;
 220+				g /= 2;
 221+				r /=2 ;
 222+			}
 223+			if (color & DBG_HILIGHT) {
 224+				if (b) {
 225+					b += 72;
 226+				}
 227+				if (g) {
 228+					g += 72;
 229+				}
 230+				if (r) {
 231+					r += 72;
 232+				}
 233+			}
 234+			context->debugcolors[color] = render_map_color(r, g, b);
 235+		}
 236+	}
 237+	if (region_pal) {
 238+		context->flags2 |= FLAG2_REGION_PAL;
 239+	}
 240+	update_video_params(context);
 241+	if (!headless) {
 242+		context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * context->border_top);
 243+	}
 244+	return context;
 245+}
 246+
 247+void vdp_free(vdp_context *context)
 248+{
 249+	free(context);
 250+}
 251+
 252+static int is_refresh(vdp_context * context, uint32_t slot)
 253+{
 254+	if (context->regs[REG_MODE_4] & BIT_H40) {
 255+		return slot == 250 || slot == 26 || slot == 59 || slot == 90 || slot == 122 || slot == 154;
 256+	} else {
 257+		//TODO: Figure out which slots are refresh when display is off in 32-cell mode
 258+		//These numbers are guesses based on H40 numbers
 259+		return slot == 243 || slot == 19 || slot == 51 || slot == 83 || slot == 115;
 260+		//The numbers below are the refresh slots during active display
 261+		//return (slot == 29 || slot == 61 || slot == 93 || slot == 125);
 262+	}
 263+}
 264+
 265+static void increment_address(vdp_context *context)
 266+{
 267+	context->address += context->regs[REG_AUTOINC];
 268+	if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
 269+		context->address++;
 270+	}
 271+}
 272+
 273+static void render_sprite_cells(vdp_context * context)
 274+{
 275+	sprite_draw * d = context->sprite_draw_list + context->cur_slot;
 276+	context->serial_address = d->address;
 277+	if (context->cur_slot >= context->sprite_draws) {
 278+
 279+		uint16_t dir;
 280+		int16_t x;
 281+		if (d->h_flip) {
 282+			x = d->x_pos + 7;
 283+			dir = -1;
 284+		} else {
 285+			x = d->x_pos;
 286+			dir = 1;
 287+		}
 288+		//printf("Draw Slot %d of %d, Rendering sprite cell from %X to x: %d\n", context->cur_slot, context->sprite_draws, d->address, x);
 289+		context->cur_slot--;
 290+		for (uint16_t address = d->address; address != ((d->address+4) & 0xFFFF); address++) {
 291+			if (x >= 0 && x < 320) {
 292+				if (!(context->linebuf[x] & 0xF)) {
 293+					context->linebuf[x] = (context->vdpmem[address] >> 4) | d->pal_priority;
 294+				} else if (context->vdpmem[address] >> 4) {
 295+					context->flags2 |= FLAG2_SPRITE_COLLIDE;
 296+				}
 297+			}
 298+			x += dir;
 299+			if (x >= 0 && x < 320) {
 300+				if (!(context->linebuf[x] & 0xF)) {
 301+					context->linebuf[x] = (context->vdpmem[address] & 0xF)  | d->pal_priority;
 302+				} else if (context->vdpmem[address] & 0xF) {
 303+					context->flags2 |= FLAG2_SPRITE_COLLIDE;
 304+				}
 305+			}
 306+			x += dir;
 307+		}
 308+	} else {
 309+		context->cur_slot--;
 310+	}
 311+}
 312+
 313+static void fetch_sprite_cells_mode4(vdp_context * context)
 314+{
 315+	if (context->sprite_index >= context->sprite_draws) {
 316+		sprite_draw * d = context->sprite_draw_list + context->sprite_index;
 317+		uint32_t address = mode4_address_map[d->address & 0x3FFF];
 318+		context->fetch_tmp[0] = context->vdpmem[address];
 319+		context->fetch_tmp[1] = context->vdpmem[address + 1];
 320+	}
 321+}
 322+
 323+static void render_sprite_cells_mode4(vdp_context * context)
 324+{
 325+	if (context->sprite_index >= context->sprite_draws) {
 326+		sprite_draw * d = context->sprite_draw_list + context->sprite_index;
 327+		uint32_t pixels = planar_to_chunky[context->fetch_tmp[0]] << 1;
 328+		pixels |= planar_to_chunky[context->fetch_tmp[1]];
 329+		uint32_t address = mode4_address_map[(d->address + 2) & 0x3FFF];
 330+		pixels |= planar_to_chunky[context->vdpmem[address]] << 3;
 331+		pixels |= planar_to_chunky[context->vdpmem[address + 1]] << 2;
 332+		int x = d->x_pos & 0xFF;
 333+		for (int i = 28; i >= 0; i -= 4, x++)
 334+		{
 335+			if (context->linebuf[x] && (pixels >> i & 0xF)) {
 336+				if (
 337+					((context->regs[REG_MODE_1] & BIT_SPRITE_8PX) && x > 8)
 338+					|| ((!(context->regs[REG_MODE_1] & BIT_SPRITE_8PX)) && x < 256)
 339+				) {
 340+					context->flags2 |= FLAG2_SPRITE_COLLIDE;
 341+				}
 342+			} else {
 343+				context->linebuf[x] = pixels >> i & 0xF;
 344+			}
 345+		}
 346+		context->sprite_index--;
 347+	}
 348+}
 349+
 350+static uint32_t mode5_sat_address(vdp_context *context)
 351+{
 352+	uint32_t addr = context->regs[REG_SAT] << 9;
 353+	if (!(context->regs[REG_MODE_2] & BIT_128K_VRAM)) {
 354+		addr &= 0xFFFF;
 355+	}
 356+	if (context->regs[REG_MODE_4] & BIT_H40) {
 357+		addr &= 0x1FC00;
 358+	}
 359+	return addr;
 360+}
 361+
 362+void vdp_print_sprite_table(vdp_context * context)
 363+{
 364+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 365+		uint16_t sat_address = mode5_sat_address(context);
 366+		uint16_t current_index = 0;
 367+		uint8_t count = 0;
 368+		do {
 369+			uint16_t address = current_index * 8 + sat_address;
 370+			uint16_t cache_address = current_index * 4;
 371+			uint8_t height = ((context->sat_cache[cache_address+2] & 0x3) + 1) * 8;
 372+			uint8_t width = (((context->sat_cache[cache_address+2]  >> 2) & 0x3) + 1) * 8;
 373+			int16_t y = ((context->sat_cache[cache_address] & 0x3) << 8 | context->sat_cache[cache_address+1]) & 0x1FF;
 374+			int16_t x = ((context->vdpmem[address+ 6] & 0x3) << 8 | context->vdpmem[address + 7]) & 0x1FF;
 375+			uint16_t link = context->sat_cache[cache_address+3] & 0x7F;
 376+			uint8_t pal = context->vdpmem[address + 4] >> 5 & 0x3;
 377+			uint8_t pri = context->vdpmem[address + 4] >> 7;
 378+			uint16_t pattern = ((context->vdpmem[address + 4] << 8 | context->vdpmem[address + 5]) & 0x7FF) << 5;
 379+			printf("Sprite %d: X=%d(%d), Y=%d(%d), Width=%u, Height=%u, Link=%u, Pal=%u, Pri=%u, Pat=%X\n", current_index, x, x-128, y, y-128, width, height, link, pal, pri, pattern);
 380+			current_index = link;
 381+			count++;
 382+		} while (current_index != 0 && count < 80);
 383+	} else {
 384+		uint16_t sat_address = (context->regs[REG_SAT] & 0x7E) << 7;
 385+		for (int i = 0; i < 64; i++)
 386+		{
 387+			uint8_t y = context->vdpmem[mode4_address_map[sat_address + (i ^ 1)]];
 388+			if (y == 0xD0) {
 389+				break;
 390+			}
 391+			uint8_t x = context->vdpmem[mode4_address_map[sat_address + 0x80 + i*2 + 1]];
 392+			uint16_t tile_address = context->vdpmem[mode4_address_map[sat_address + 0x80 + i*2]] * 32
 393+				+ (context->regs[REG_STILE_BASE] << 11 & 0x2000);
 394+			if (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) {
 395+				tile_address &= ~32;
 396+			}
 397+			printf("Sprite %d: X=%d, Y=%d, Pat=%X\n", i, x, y, tile_address);
 398+		}
 399+	}
 400+}
 401+
 402+#define VRAM_READ 0 //0000
 403+#define VRAM_WRITE 1 //0001
 404+//2 would trigger register write 0010
 405+#define CRAM_WRITE 3 //0011
 406+#define VSRAM_READ 4 //0100
 407+#define VSRAM_WRITE 5//0101
 408+//6 would trigger regsiter write 0110
 409+//7 is a mystery //0111
 410+#define CRAM_READ 8  //1000
 411+//9 is also a mystery //1001
 412+//A would trigger register write 1010
 413+//B is a mystery 1011
 414+#define VRAM_READ8 0xC //1100
 415+//D is a mystery 1101
 416+//E would trigger register write 1110
 417+//F is a mystery 1111
 418+
 419+//Possible theory on how bits work
 420+//CD0 = Read/Write flag
 421+//CD2,(CD1|CD3) = RAM type
 422+//  00 = VRAM
 423+//  01 = CRAM
 424+//  10 = VSRAM
 425+//  11 = VRAM8
 426+//Would result in
 427+//  7 = VRAM8 write
 428+//  9 = CRAM write alias
 429+//  B = CRAM write alias
 430+//  D = VRAM8 write alias
 431+//  F = VRAM8 write alais
 432+
 433+#define DMA_START 0x20
 434+
 435+static const char * cd_name(uint8_t cd)
 436+{
 437+	switch (cd & 0xF)
 438+	{
 439+	case VRAM_READ:
 440+		return "VRAM read";
 441+	case VRAM_WRITE:
 442+		return "VRAM write";
 443+	case CRAM_WRITE:
 444+		return "CRAM write";
 445+	case VSRAM_READ:
 446+		return "VSRAM read";
 447+	case VSRAM_WRITE:
 448+		return "VSRAM write";
 449+	case VRAM_READ8:
 450+		return "VRAM read (undocumented 8-bit mode)";
 451+	default:
 452+		return "invalid";
 453+	}
 454+}
 455+
 456+void vdp_print_reg_explain(vdp_context * context)
 457+{
 458+	char * hscroll[] = {"full", "7-line", "cell", "line"};
 459+	printf("**Mode Group**\n"
 460+	       "00: %.2X | H-ints %s, Pal Select %d, HVC latch %s, Display gen %s\n"
 461+	       "01: %.2X | Display %s, V-ints %s, Height: %d, Mode %d, %dK VRAM\n"
 462+	       "0B: %.2X | E-ints %s, V-Scroll: %s, H-Scroll: %s\n"
 463+	       "0C: %.2X | Width: %d, Shadow/Highlight: %s\n",
 464+	       context->regs[REG_MODE_1], context->regs[REG_MODE_1] & BIT_HINT_EN ? "enabled" : "disabled", (context->regs[REG_MODE_1] & BIT_PAL_SEL) != 0,
 465+	           context->regs[REG_MODE_1] & BIT_HVC_LATCH ? "enabled" : "disabled", context->regs[REG_MODE_1] & BIT_DISP_DIS ? "disabled" : "enabled",
 466+	       context->regs[REG_MODE_2], context->regs[REG_MODE_2] & BIT_DISP_EN ? "enabled" : "disabled", context->regs[REG_MODE_2] & BIT_VINT_EN ? "enabled" : "disabled",
 467+	           context->regs[REG_MODE_2] & BIT_PAL ? 30 : 28, context->regs[REG_MODE_2] & BIT_MODE_5 ? 5 : 4, context->regs[REG_MODE_1] & BIT_128K_VRAM ? 128 : 64, 
 468+	       context->regs[REG_MODE_3], context->regs[REG_MODE_3] & BIT_EINT_EN ? "enabled" : "disabled", context->regs[REG_MODE_3] & BIT_VSCROLL ? "2 cell" : "full",
 469+	           hscroll[context->regs[REG_MODE_3] & 0x3],
 470+	       context->regs[REG_MODE_4], context->regs[REG_MODE_4] & BIT_H40 ? 40 : 32, context->regs[REG_MODE_4] & BIT_HILIGHT ? "enabled" : "disabled");
 471+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 472+		printf("\n**Table Group**\n"
 473+			   "02: %.2X | Scroll A Name Table:    $%.4X\n"
 474+			   "03: %.2X | Window Name Table:      $%.4X\n"
 475+			   "04: %.2X | Scroll B Name Table:    $%.4X\n"
 476+			   "05: %.2X | Sprite Attribute Table: $%.4X\n"
 477+			   "0D: %.2X | HScroll Data Table:     $%.4X\n",
 478+			   context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0x38) << 10,
 479+			   context->regs[REG_WINDOW], (context->regs[REG_WINDOW] & (context->regs[REG_MODE_4] & BIT_H40 ? 0x3C : 0x3E)) << 10,
 480+			   context->regs[REG_SCROLL_B], (context->regs[REG_SCROLL_B] & 0x7) << 13,
 481+			   context->regs[REG_SAT], mode5_sat_address(context),
 482+			   context->regs[REG_HSCROLL], (context->regs[REG_HSCROLL] & 0x3F) << 10);
 483+	} else {
 484+		printf("\n**Table Group**\n"
 485+			   "02: %.2X | Background Name Table:  $%.4X\n"
 486+			   "05: %.2X | Sprite Attribute Table: $%.4X\n"
 487+			   "06: %.2X | Sprite Tile Base:       $%.4X\n"
 488+			   "08: %.2X | Background X Scroll:    %d\n"
 489+			   "09: %.2X | Background Y Scroll:    %d\n",
 490+			   context->regs[REG_SCROLL_A], (context->regs[REG_SCROLL_A] & 0xE) << 10,
 491+			   context->regs[REG_SAT], (context->regs[REG_SAT] & 0x7E) << 7,
 492+			   context->regs[REG_STILE_BASE], (context->regs[REG_STILE_BASE] & 2) << 11,
 493+			   context->regs[REG_X_SCROLL], context->regs[REG_X_SCROLL],
 494+			   context->regs[REG_Y_SCROLL], context->regs[REG_Y_SCROLL]);
 495+			   
 496+	}
 497+	char * sizes[] = {"32", "64", "invalid", "128"};
 498+	printf("\n**Misc Group**\n"
 499+	       "07: %.2X | Backdrop Color: $%X\n"
 500+	       "0A: %.2X | H-Int Counter: %u\n"
 501+	       "0F: %.2X | Auto-increment: $%X\n"
 502+	       "10: %.2X | Scroll A/B Size: %sx%s\n",
 503+	       context->regs[REG_BG_COLOR], context->regs[REG_BG_COLOR],
 504+	       context->regs[REG_HINT], context->regs[REG_HINT],
 505+	       context->regs[REG_AUTOINC], context->regs[REG_AUTOINC],
 506+	       context->regs[REG_SCROLL], sizes[context->regs[REG_SCROLL] & 0x3], sizes[context->regs[REG_SCROLL] >> 4 & 0x3]);
 507+	char * src_types[] = {"68K", "68K", "Copy", "Fill"};
 508+	printf("\n**DMA Group**\n"
 509+	       "13: %.2X |\n"
 510+		   "14: %.2X | DMA Length: $%.4X words\n"
 511+		   "15: %.2X |\n"
 512+		   "16: %.2X |\n"
 513+		   "17: %.2X | DMA Source Address: $%.6X, Type: %s\n",
 514+		   context->regs[REG_DMALEN_L],
 515+		   context->regs[REG_DMALEN_H], context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L],
 516+		   context->regs[REG_DMASRC_L],
 517+		   context->regs[REG_DMASRC_M],
 518+		   context->regs[REG_DMASRC_H],
 519+		       context->regs[REG_DMASRC_H] << 17 | context->regs[REG_DMASRC_M] << 9 | context->regs[REG_DMASRC_L] << 1,
 520+			   src_types[context->regs[REG_DMASRC_H] >> 6 & 3]);
 521+	uint8_t old_flags = context->flags;
 522+	uint8_t old_flags2 = context->flags2;
 523+	printf("\n**Internal Group**\n"
 524+	       "Address: %X\n"
 525+	       "CD:      %X - %s\n"
 526+	       "Pending: %s\n"
 527+		   "VCounter: %d\n"
 528+		   "HCounter: %d\n"
 529+		   "VINT Pending: %s\n"
 530+		   "HINT Pending: %s\n"
 531+		   "Status: %X\n",
 532+	       context->address, context->cd, cd_name(context->cd), 
 533+		   (context->flags & FLAG_PENDING) ? "word" : (context->flags2 & FLAG2_BYTE_PENDING) ? "byte" : "none",
 534+		   context->vcounter, context->hslot*2, (context->flags2 & FLAG2_VINT_PENDING) ? "true" : "false",
 535+		   (context->flags2 & FLAG2_HINT_PENDING) ? "true" : "false", vdp_control_port_read(context));
 536+	//restore flags as calling vdp_control_port_read can change them
 537+	context->flags = old_flags;
 538+	context->flags2 = old_flags2;
 539+}
 540+
 541+static uint8_t is_active(vdp_context *context)
 542+{
 543+	return context->state != INACTIVE && (context->regs[REG_MODE_2] & BIT_DISP_EN) != 0;
 544+}
 545+
 546+static void scan_sprite_table(uint32_t line, vdp_context * context)
 547+{
 548+	if (context->sprite_index && ((uint8_t)context->slot_counter) < context->max_sprites_line) {
 549+		line += 1;
 550+		uint16_t ymask, ymin;
 551+		uint8_t height_mult;
 552+		if (context->double_res) {
 553+			line *= 2;
 554+			if (context->flags2 & FLAG2_EVEN_FIELD) {
 555+				line++;
 556+			}
 557+			ymask = 0x3FF;
 558+			ymin = 256;
 559+			height_mult = 16;
 560+		} else {
 561+			ymask = 0x1FF;
 562+			ymin = 128;
 563+			height_mult = 8;
 564+		}
 565+		context->sprite_index &= 0x7F;
 566+		//TODO: Implement squirelly behavior documented by Kabuto
 567+		if (context->sprite_index >= context->max_sprites_frame) {
 568+			context->sprite_index = 0;
 569+			return;
 570+		}
 571+		uint16_t address = context->sprite_index * 4;
 572+		line += ymin;
 573+		line &= ymask;
 574+		uint16_t y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask;
 575+		uint8_t height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult;
 576+		//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
 577+		if (y <= line && line < (y + height)) {
 578+			//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
 579+			context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2];
 580+			context->sprite_info_list[context->slot_counter++].index = context->sprite_index;
 581+		}
 582+		context->sprite_index = context->sat_cache[address+3] & 0x7F;
 583+		if (context->sprite_index && ((uint8_t)context->slot_counter) < context->max_sprites_line)
 584+		{
 585+			//TODO: Implement squirelly behavior documented by Kabuto
 586+			if (context->sprite_index >= context->max_sprites_frame) {
 587+				context->sprite_index = 0;
 588+				return;
 589+			}
 590+			address = context->sprite_index * 4;
 591+			y = ((context->sat_cache[address] & 0x3) << 8 | context->sat_cache[address+1]) & ymask;
 592+			height = ((context->sat_cache[address+2] & 0x3) + 1) * height_mult;
 593+			//printf("Sprite %d | y: %d, height: %d\n", context->sprite_index, y, height);
 594+			if (y <= line && line < (y + height)) {
 595+				//printf("Sprite %d at y: %d with height %d is on line %d\n", context->sprite_index, y, height, line);
 596+				context->sprite_info_list[context->slot_counter].size = context->sat_cache[address+2];
 597+				context->sprite_info_list[context->slot_counter++].index = context->sprite_index;
 598+			}
 599+			context->sprite_index = context->sat_cache[address+3] & 0x7F;
 600+		}
 601+	}
 602+	//TODO: Seems like the overflow flag should be set here if we run out of sprite info slots without hitting the end of the list
 603+}
 604+
 605+static void scan_sprite_table_mode4(vdp_context * context)
 606+{
 607+	if (context->sprite_index < MAX_SPRITES_FRAME_H32) {
 608+		uint32_t line = context->vcounter;
 609+		line &= 0xFF;
 610+		
 611+		uint32_t sat_address = mode4_address_map[(context->regs[REG_SAT] << 7 & 0x3F00) + context->sprite_index];
 612+		uint32_t y = context->vdpmem[sat_address+1];
 613+		uint32_t size = (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) ? 16 : 8;
 614+		
 615+		if (y == 0xd0) {
 616+			context->sprite_index = MAX_SPRITES_FRAME_H32;
 617+			return;
 618+		} else {
 619+			if (y <= line && line < (y + size)) {
 620+				if (!context->slot_counter) {
 621+					context->sprite_index = MAX_SPRITES_FRAME_H32;
 622+					context->flags |= FLAG_DOT_OFLOW;
 623+					return;
 624+				}
 625+				context->sprite_info_list[--(context->slot_counter)].size = size;
 626+				context->sprite_info_list[context->slot_counter].index = context->sprite_index;
 627+				context->sprite_info_list[context->slot_counter].y = y;
 628+			}
 629+			context->sprite_index++;
 630+		}
 631+		
 632+		if (context->sprite_index < MAX_SPRITES_FRAME_H32) {
 633+			y = context->vdpmem[sat_address];
 634+			if (y == 0xd0) {
 635+				context->sprite_index = MAX_SPRITES_FRAME_H32;
 636+				return;
 637+			} else {
 638+				if (y <= line && line < (y + size)) {
 639+					if (!context->slot_counter) {
 640+						context->sprite_index = MAX_SPRITES_FRAME_H32;
 641+						context->flags |= FLAG_DOT_OFLOW;
 642+						return;
 643+					}
 644+					context->sprite_info_list[--(context->slot_counter)].size = size;
 645+					context->sprite_info_list[context->slot_counter].index = context->sprite_index;
 646+					context->sprite_info_list[context->slot_counter].y = y;
 647+				}
 648+				context->sprite_index++;
 649+			}
 650+		}
 651+		
 652+	}
 653+}
 654+
 655+static void read_sprite_x(uint32_t line, vdp_context * context)
 656+{
 657+	if (context->cur_slot == context->max_sprites_line) {
 658+		context->cur_slot = 0;
 659+	}
 660+	if (context->cur_slot < context->slot_counter) {
 661+		if (context->sprite_draws) {
 662+			line += 1;
 663+			//in tiles
 664+			uint8_t width = ((context->sprite_info_list[context->cur_slot].size >> 2) & 0x3) + 1;
 665+			//in pixels
 666+			uint8_t height = ((context->sprite_info_list[context->cur_slot].size & 0x3) + 1) * 8;
 667+			if (context->double_res) {
 668+				line *= 2;
 669+				if (context->flags2 & FLAG2_EVEN_FIELD) {
 670+					line++;
 671+				}
 672+				height *= 2;
 673+			}
 674+			uint16_t ymask, ymin;
 675+			if (context->double_res) {
 676+				ymask = 0x3FF;
 677+				ymin = 256;
 678+			} else {
 679+				ymask = 0x1FF;
 680+				ymin = 128;
 681+			}
 682+			uint16_t att_addr = mode5_sat_address(context) + context->sprite_info_list[context->cur_slot].index * 8 + 4;
 683+			uint16_t tileinfo = (context->vdpmem[att_addr] << 8) | context->vdpmem[att_addr+1];
 684+			uint8_t pal_priority = (tileinfo >> 9) & 0x70;
 685+			uint8_t row;
 686+			uint16_t cache_addr = context->sprite_info_list[context->cur_slot].index * 4;
 687+			line = (line + ymin) & ymask;
 688+			int16_t y = ((context->sat_cache[cache_addr] << 8 | context->sat_cache[cache_addr+1]) & ymask)/* - ymin*/;
 689+			if (tileinfo & MAP_BIT_V_FLIP) {
 690+				row = (y + height - 1) - line;
 691+			} else {
 692+				row = line-y;
 693+			}
 694+			row &= ymask >> 4;
 695+			uint16_t address;
 696+			if (context->double_res) {
 697+				address = ((tileinfo & 0x3FF) << 6) + row * 4;
 698+			} else {
 699+				address = ((tileinfo & 0x7FF) << 5) + row * 4;
 700+			}
 701+			int16_t x = ((context->vdpmem[att_addr+ 2] & 0x3) << 8 | context->vdpmem[att_addr + 3]) & 0x1FF;
 702+			if (x) {
 703+				context->flags |= FLAG_CAN_MASK;
 704+			} else if(context->flags & (FLAG_CAN_MASK | FLAG_DOT_OFLOW)) {
 705+				context->flags |= FLAG_MASKED;
 706+			}
 707+
 708+			context->flags &= ~FLAG_DOT_OFLOW;
 709+			int16_t i;
 710+			if (context->flags & FLAG_MASKED) {
 711+				for (i=0; i < width && context->sprite_draws; i++) {
 712+					--context->sprite_draws;
 713+					context->sprite_draw_list[context->sprite_draws].x_pos = -128;
 714+					context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
 715+				}
 716+			} else {
 717+				x -= 128;
 718+				int16_t base_x = x;
 719+				int16_t dir;
 720+				if (tileinfo & MAP_BIT_H_FLIP) {
 721+					x += (width-1) * 8;
 722+					dir = -8;
 723+				} else {
 724+					dir = 8;
 725+				}
 726+				//printf("Sprite %d | x: %d, y: %d, width: %d, height: %d, pal_priority: %X, row: %d, tile addr: %X\n", context->sprite_info_list[context->cur_slot].index, x, context->sprite_info_list[context->cur_slot].y, width, height, pal_priority, row, address);
 727+				for (i=0; i < width && context->sprite_draws; i++, x += dir) {
 728+					--context->sprite_draws;
 729+					context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
 730+					context->sprite_draw_list[context->sprite_draws].x_pos = x;
 731+					context->sprite_draw_list[context->sprite_draws].pal_priority = pal_priority;
 732+					context->sprite_draw_list[context->sprite_draws].h_flip = (tileinfo & MAP_BIT_H_FLIP) ? 1 : 0;
 733+				}
 734+			}
 735+			//Used to be i < width
 736+			//TODO: Confirm this is the right condition on hardware
 737+			if (!context->sprite_draws) {
 738+				context->flags |= FLAG_DOT_OFLOW;
 739+			}
 740+		} else {
 741+			context->flags |= FLAG_DOT_OFLOW;
 742+		}
 743+	}
 744+	context->cur_slot++;
 745+}
 746+
 747+static void read_sprite_x_mode4(vdp_context * context)
 748+{
 749+	if (context->cur_slot >= context->slot_counter) {
 750+		uint32_t address = (context->regs[REG_SAT] << 7 & 0x3F00) + 0x80 + context->sprite_info_list[context->cur_slot].index * 2;
 751+		address = mode4_address_map[address];
 752+		--context->sprite_draws;
 753+		uint32_t tile_address = context->vdpmem[address] * 32 + (context->regs[REG_STILE_BASE] << 11 & 0x2000);
 754+		if (context->regs[REG_MODE_2] & BIT_SPRITE_SZ) {
 755+			tile_address &= ~32;
 756+		}
 757+		tile_address += (context->vcounter - context->sprite_info_list[context->cur_slot].y)* 4;
 758+		context->sprite_draw_list[context->sprite_draws].x_pos = context->vdpmem[address + 1];
 759+		context->sprite_draw_list[context->sprite_draws].address = tile_address;
 760+		context->cur_slot--;
 761+	}
 762+}
 763+
 764+#define CRAM_BITS 0xEEE
 765+#define VSRAM_BITS 0x7FF
 766+#define VSRAM_DIRTY_BITS 0xF800
 767+
 768+//rough estimate of slot number at which border display starts
 769+#define BG_START_SLOT 6
 770+
 771+static void update_color_map(vdp_context *context, uint16_t index, uint16_t value)
 772+{
 773+	context->colors[index] = color_map[value & CRAM_BITS];
 774+	context->colors[index + SHADOW_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_SHADOW];
 775+	context->colors[index + HIGHLIGHT_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT];
 776+	context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4];
 777+}
 778+
 779+void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value)
 780+{
 781+	context->cram[addr] = value;
 782+	update_color_map(context, addr, value);
 783+}
 784+
 785+static void write_cram(vdp_context * context, uint16_t address, uint16_t value)
 786+{
 787+	uint16_t addr;
 788+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 789+		addr = (address/2) & (CRAM_SIZE-1);
 790+	} else {
 791+		addr = address & 0x1F;
 792+		value = (value << 1 & 0xE) | (value << 2 & 0xE0) | (value & 0xE00);
 793+	}
 794+	write_cram_internal(context, addr, value);
 795+	
 796+	if (context->hslot >= BG_START_SLOT && (
 797+		context->vcounter < context->inactive_start + context->border_bot 
 798+		|| context->vcounter > 0x200 - context->border_top
 799+	)) {
 800+		uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2;
 801+		if (context->hslot < bg_end_slot) {
 802+			uint32_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->colors[addr] : context->colors[addr + MODE4_OFFSET];
 803+			context->output[(context->hslot - BG_START_SLOT)*2 + 1] = color;
 804+		}
 805+	}
 806+}
 807+
 808+static void vdp_advance_dma(vdp_context * context)
 809+{
 810+	context->regs[REG_DMASRC_L] += 1;
 811+	if (!context->regs[REG_DMASRC_L]) {
 812+		context->regs[REG_DMASRC_M] += 1;
 813+	}
 814+	context->address += context->regs[REG_AUTOINC];
 815+	uint16_t dma_len = ((context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L]) - 1;
 816+	context->regs[REG_DMALEN_H] = dma_len >> 8;
 817+	context->regs[REG_DMALEN_L] = dma_len;
 818+	if (!dma_len) {
 819+		context->flags &= ~FLAG_DMA_RUN;
 820+		context->cd &= 0xF;
 821+	}
 822+}
 823+
 824+static void vdp_check_update_sat(vdp_context *context, uint32_t address, uint16_t value)
 825+{
 826+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 827+		if (!(address & 4)) {
 828+			uint32_t sat_address = mode5_sat_address(context);
 829+			if(address >= sat_address && address < (sat_address + SAT_CACHE_SIZE*2)) {
 830+				uint16_t cache_address = address - sat_address;
 831+				cache_address = (cache_address & 3) | (cache_address >> 1 & 0x1FC);
 832+				context->sat_cache[cache_address] = value >> 8;
 833+				context->sat_cache[cache_address^1] = value;
 834+			}
 835+		}
 836+	}
 837+}
 838+
 839+void vdp_check_update_sat_byte(vdp_context *context, uint32_t address, uint8_t value)
 840+{
 841+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 842+		if (!(address & 4)) {
 843+			uint32_t sat_address = mode5_sat_address(context);
 844+			if(address >= sat_address && address < (sat_address + SAT_CACHE_SIZE*2)) {
 845+				uint16_t cache_address = address - sat_address;
 846+				cache_address = (cache_address & 3) | (cache_address >> 1 & 0x1FC);
 847+				context->sat_cache[cache_address] = value;
 848+			}
 849+		}
 850+	}
 851+}
 852+
 853+static void write_vram_word(vdp_context *context, uint32_t address, uint16_t value)
 854+{
 855+	address = (address & 0x3FC) | (address >> 1 & 0xFC01) | (address >> 9 & 0x2);
 856+	address ^= 1;
 857+	//TODO: Support an option to actually have 128KB of VRAM
 858+	context->vdpmem[address] = value;
 859+}
 860+
 861+static void write_vram_byte(vdp_context *context, uint32_t address, uint8_t value)
 862+{
 863+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
 864+		address &= 0xFFFF;
 865+	} else {
 866+		address = mode4_address_map[address & 0x3FFF];
 867+	}
 868+	context->vdpmem[address] = value;
 869+}
 870+
 871+#define DMA_FILL 0x80
 872+#define DMA_COPY 0xC0
 873+#define DMA_TYPE_MASK 0xC0
 874+static void external_slot(vdp_context * context)
 875+{
 876+	if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL && context->fifo_read < 0) {
 877+		context->fifo_read = (context->fifo_write-1) & (FIFO_SIZE-1);
 878+		fifo_entry * cur = context->fifo + context->fifo_read;
 879+		cur->cycle = context->cycles;
 880+		cur->address = context->address;
 881+		cur->partial = 1;
 882+		vdp_advance_dma(context);
 883+	}
 884+	fifo_entry * start = context->fifo + context->fifo_read;
 885+	if (context->fifo_read >= 0 && start->cycle <= context->cycles) {
 886+		switch (start->cd & 0xF)
 887+		{
 888+		case VRAM_WRITE:
 889+			if ((context->regs[REG_MODE_2] & (BIT_128K_VRAM|BIT_MODE_5)) == (BIT_128K_VRAM|BIT_MODE_5)) {
 890+				vdp_check_update_sat(context, start->address, start->value);
 891+				write_vram_word(context, start->address, start->value);
 892+			} else {
 893+				uint8_t byte = start->partial == 1 ? start->value >> 8 : start->value;
 894+				vdp_check_update_sat_byte(context, start->address ^ 1, byte);
 895+				write_vram_byte(context, start->address ^ 1, byte);
 896+				if (!start->partial) {
 897+					start->address = start->address ^ 1;
 898+					start->partial = 1;
 899+					//skip auto-increment and removal of entry from fifo
 900+					return;
 901+				}
 902+			}
 903+			break;
 904+		case CRAM_WRITE: {
 905+			//printf("CRAM Write | %X to %X\n", start->value, (start->address/2) & (CRAM_SIZE-1));
 906+			if (start->partial == 3) {
 907+				uint16_t val;
 908+				if ((start->address & 1) && (context->regs[REG_MODE_2] & BIT_MODE_5)) {
 909+					val = (context->cram[start->address >> 1 & (CRAM_SIZE-1)] & 0xFF) | start->value << 8;
 910+				} else {
 911+					uint16_t address = (context->regs[REG_MODE_2] & BIT_MODE_5) ? start->address >> 1 & (CRAM_SIZE-1) : start->address & 0x1F;
 912+					val = (context->cram[address] & 0xFF00) | start->value;
 913+				}
 914+				write_cram(context, start->address, val);
 915+			} else {
 916+				write_cram(context, start->address, start->partial ? context->fifo[context->fifo_write].value : start->value);
 917+			}
 918+			break;
 919+		}
 920+		case VSRAM_WRITE:
 921+			if (((start->address/2) & 63) < VSRAM_SIZE) {
 922+				//printf("VSRAM Write: %X to %X @ frame: %d, vcounter: %d, hslot: %d, cycle: %d\n", start->value, start->address, context->frame, context->vcounter, context->hslot, context->cycles);
 923+				if (start->partial == 3) {
 924+					if (start->address & 1) {
 925+						context->vsram[(start->address/2) & 63] &= 0xFF;
 926+						context->vsram[(start->address/2) & 63] |= start->value << 8;
 927+					} else {
 928+						context->vsram[(start->address/2) & 63] &= 0xFF00;
 929+						context->vsram[(start->address/2) & 63] |= start->value;
 930+					}
 931+				} else {
 932+					context->vsram[(start->address/2) & 63] = start->partial ? context->fifo[context->fifo_write].value : start->value;
 933+				}
 934+			}
 935+
 936+			break;
 937+		}
 938+		context->fifo_read = (context->fifo_read+1) & (FIFO_SIZE-1);
 939+		if (context->fifo_read == context->fifo_write) {
 940+			if ((context->cd & 0x20) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
 941+				context->flags |= FLAG_DMA_RUN;
 942+			}
 943+			context->fifo_read = -1;
 944+		}
 945+	} else if ((context->flags & FLAG_DMA_RUN) && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY) {
 946+		if (context->flags & FLAG_READ_FETCHED) {
 947+			write_vram_byte(context, context->address ^ 1, context->prefetch);
 948+			
 949+			//Update DMA state
 950+			vdp_advance_dma(context);
 951+			
 952+			context->flags &= ~FLAG_READ_FETCHED;
 953+		} else {
 954+			context->prefetch = context->vdpmem[(context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L] ^ 1];
 955+			
 956+			context->flags |= FLAG_READ_FETCHED;
 957+		}
 958+	} else if (!(context->cd & 1) && !(context->flags & (FLAG_READ_FETCHED|FLAG_PENDING))) {
 959+		switch(context->cd & 0xF)
 960+		{
 961+		case VRAM_READ:
 962+			if (context->flags2 & FLAG2_READ_PENDING) {
 963+				context->prefetch |= context->vdpmem[context->address | 1];
 964+				context->flags |= FLAG_READ_FETCHED;
 965+				context->flags2 &= ~FLAG2_READ_PENDING;
 966+				//Should this happen after the prefetch or after the read?
 967+				increment_address(context);
 968+			} else {
 969+				//TODO: 128K VRAM Mode
 970+				context->prefetch = context->vdpmem[context->address & 0xFFFE] << 8;
 971+				context->flags2 |= FLAG2_READ_PENDING;
 972+			}
 973+			break;
 974+		case VRAM_READ8: {
 975+			uint32_t address = context->address ^ 1;
 976+			if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
 977+				address = mode4_address_map[address & 0x3FFF];
 978+			}
 979+			context->prefetch = context->vdpmem[address];
 980+			context->prefetch |= context->fifo[context->fifo_write].value & 0xFF00;
 981+			context->flags |= FLAG_READ_FETCHED;
 982+			//Should this happen after the prefetch or after the read?
 983+			increment_address(context);
 984+			break;
 985+		}
 986+		case CRAM_READ:
 987+			context->prefetch = context->cram[(context->address/2) & (CRAM_SIZE-1)] & CRAM_BITS;
 988+			context->prefetch |= context->fifo[context->fifo_write].value & ~CRAM_BITS;
 989+			context->flags |= FLAG_READ_FETCHED;
 990+			//Should this happen after the prefetch or after the read?
 991+			increment_address(context);
 992+			break;
 993+		case VSRAM_READ: {
 994+			uint16_t address = (context->address /2) & 63;
 995+			if (address >= VSRAM_SIZE) {
 996+				address = 0;
 997+			}
 998+			context->prefetch = context->vsram[address] & VSRAM_BITS;
 999+			context->prefetch |= context->fifo[context->fifo_write].value & VSRAM_DIRTY_BITS;
1000+			context->flags |= FLAG_READ_FETCHED;
1001+			//Should this happen after the prefetch or after the read?
1002+			increment_address(context);
1003+			break;
1004+		}
1005+		}
1006+	}
1007+}
1008+
1009+static void run_dma_src(vdp_context * context, int32_t slot)
1010+{
1011+	//TODO: Figure out what happens if CD bit 4 is not set in DMA copy mode
1012+	//TODO: Figure out what happens when CD:0-3 is not set to a write mode in DMA operations
1013+	if (context->fifo_write == context->fifo_read) {
1014+		return;
1015+	}
1016+	fifo_entry * cur = NULL;
1017+	if (!(context->regs[REG_DMASRC_H] & 0x80))
1018+	{
1019+		//68K -> VDP
1020+		if (slot == -1 || !is_refresh(context, slot-1)) {
1021+			cur = context->fifo + context->fifo_write;
1022+			cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
1023+			cur->address = context->address;
1024+			cur->value = read_dma_value((context->regs[REG_DMASRC_H] << 16) | (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
1025+			cur->cd = context->cd;
1026+			cur->partial = 0;
1027+			if (context->fifo_read < 0) {
1028+				context->fifo_read = context->fifo_write;
1029+			}
1030+			context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
1031+			vdp_advance_dma(context);
1032+		}
1033+	}
1034+}
1035+
1036+#define WINDOW_RIGHT 0x80
1037+#define WINDOW_DOWN  0x80
1038+
1039+static void read_map_scroll(uint16_t column, uint16_t vsram_off, uint32_t line, uint16_t address, uint16_t hscroll_val, vdp_context * context)
1040+{
1041+	uint16_t window_line_shift, v_offset_mask, vscroll_shift;
1042+	if (context->double_res) {
1043+		line *= 2;
1044+		if (context->flags2 & FLAG2_EVEN_FIELD) {
1045+			line++;
1046+		}
1047+		window_line_shift = 4;
1048+		v_offset_mask = 0xF;
1049+		vscroll_shift = 4;
1050+	} else {
1051+		window_line_shift = 3;
1052+		v_offset_mask = 0x7;
1053+		vscroll_shift = 3;
1054+	}
1055+	//TODO: Further research on vscroll latch behavior and the "first column bug"
1056+	if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
1057+		if (!column) {
1058+			if (context->regs[REG_MODE_4] & BIT_H40) {
1059+				//Based on observed behavior documented by Eke-Eke, I'm guessing the VDP
1060+				//ends up fetching the last value on the VSRAM bus in the H40 case
1061+				//getting the last latched value should be close enough for now
1062+				if (!vsram_off) {
1063+					context->vscroll_latch[0] = context->vscroll_latch[1];
1064+				}
1065+			} else {
1066+				//supposedly it's always forced to 0 in the H32 case
1067+				context->vscroll_latch[0] = context->vscroll_latch[1] = 0;
1068+			}
1069+		} else if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
1070+			context->vscroll_latch[vsram_off] = context->vsram[column - 2 + vsram_off];
1071+		}
1072+	}
1073+	if (!vsram_off) {
1074+		uint16_t left_col, right_col;
1075+		if (context->regs[REG_WINDOW_H] & WINDOW_RIGHT) {
1076+			left_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2 + 2;
1077+			right_col = 42;
1078+		} else {
1079+			left_col = 0;
1080+			right_col = (context->regs[REG_WINDOW_H] & 0x1F) * 2;
1081+			if (right_col) {
1082+				right_col += 2;
1083+			}
1084+		}
1085+		uint16_t top_line, bottom_line;
1086+		if (context->regs[REG_WINDOW_V] & WINDOW_DOWN) {
1087+			top_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1088+			bottom_line = context->double_res ? 481 : 241;
1089+		} else {
1090+			top_line = 0;
1091+			bottom_line = (context->regs[REG_WINDOW_V] & 0x1F) << window_line_shift;
1092+		}
1093+		if ((column >= left_col && column < right_col) || (line >= top_line && line < bottom_line)) {
1094+			uint16_t address = context->regs[REG_WINDOW] << 10;
1095+			uint16_t line_offset, offset, mask;
1096+			if (context->regs[REG_MODE_4] & BIT_H40) {
1097+				address &= 0xF000;
1098+				line_offset = (((line) >> vscroll_shift) * 64 * 2) & 0xFFF;
1099+				mask = 0x7F;
1100+
1101+			} else {
1102+				address &= 0xF800;
1103+				line_offset = (((line) >> vscroll_shift) * 32 * 2) & 0xFFF;
1104+				mask = 0x3F;
1105+			}
1106+			if (context->double_res) {
1107+				mask <<= 1;
1108+				mask |= 1;
1109+			}
1110+			offset = address + line_offset + (((column - 2) * 2) & mask);
1111+			context->col_1 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1112+			//printf("Window | top: %d, bot: %d, left: %d, right: %d, base: %X, line: %X offset: %X, tile: %X, reg: %X\n", top_line, bottom_line, left_col, right_col, address, line_offset, offset, ((context->col_1 & 0x3FF) << 5), context->regs[REG_WINDOW]);
1113+			offset = address + line_offset + (((column - 1) * 2) & mask);
1114+			context->col_2 = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1115+			context->v_offset = (line) & v_offset_mask;
1116+			context->flags |= FLAG_WINDOW;
1117+			return;
1118+		}
1119+		context->flags &= ~FLAG_WINDOW;
1120+	}
1121+	//TODO: Verify behavior for 0x20 case
1122+	uint16_t vscroll = 0xFF | (context->regs[REG_SCROLL] & 0x30) << 4;
1123+	if (context->double_res) {
1124+		vscroll <<= 1;
1125+		vscroll |= 1;
1126+	}
1127+	vscroll &= context->vscroll_latch[vsram_off] + line;
1128+	context->v_offset = vscroll & v_offset_mask;
1129+	//printf("%s | line %d, vsram: %d, vscroll: %d, v_offset: %d\n",(vsram_off ? "B" : "A"), line, context->vsram[context->regs[REG_MODE_3] & 0x4 ? column : 0], vscroll, context->v_offset);
1130+	vscroll >>= vscroll_shift;
1131+	uint16_t hscroll_mask;
1132+	uint16_t v_mul;
1133+	switch(context->regs[REG_SCROLL] & 0x3)
1134+	{
1135+	case 0:
1136+		hscroll_mask = 0x1F;
1137+		v_mul = 64;
1138+		break;
1139+	case 0x1:
1140+		hscroll_mask = 0x3F;
1141+		v_mul = 128;
1142+		break;
1143+	case 0x2:
1144+		//TODO: Verify this behavior
1145+		hscroll_mask = 0x1F;
1146+		v_mul = 0;
1147+		break;
1148+	case 0x3:
1149+		hscroll_mask = 0x7F;
1150+		v_mul = 256;
1151+		break;
1152+	}
1153+	uint16_t hscroll, offset;
1154+	for (int i = 0; i < 2; i++) {
1155+		hscroll = (column - 2 + i - ((hscroll_val/8) & 0xFFFE)) & hscroll_mask;
1156+		offset = address + ((vscroll * v_mul + hscroll*2) & 0x1FFF);
1157+		//printf("%s | line: %d, col: %d, x: %d, hs_mask %X, scr reg: %X, tbl addr: %X\n", (vsram_off ? "B" : "A"), line, (column-2+i), hscroll, hscroll_mask, context->regs[REG_SCROLL], offset);
1158+		uint16_t col_val = (context->vdpmem[offset] << 8) | context->vdpmem[offset+1];
1159+		if (i) {
1160+			context->col_2 = col_val;
1161+		} else {
1162+			context->col_1 = col_val;
1163+		}
1164+	}
1165+}
1166+
1167+static void read_map_scroll_a(uint16_t column, uint32_t line, vdp_context * context)
1168+{
1169+	read_map_scroll(column, 0, line, (context->regs[REG_SCROLL_A] & 0x38) << 10, context->hscroll_a, context);
1170+}
1171+
1172+static void read_map_scroll_b(uint16_t column, uint32_t line, vdp_context * context)
1173+{
1174+	read_map_scroll(column, 1, line, (context->regs[REG_SCROLL_B] & 0x7) << 13, context->hscroll_b, context);
1175+}
1176+
1177+static void read_map_mode4(uint16_t column, uint32_t line, vdp_context * context)
1178+{
1179+	uint32_t address = (context->regs[REG_SCROLL_A] & 0xE) << 10;
1180+	//add row
1181+	uint32_t vscroll = line;
1182+	if (column < 24 || !(context->regs[REG_MODE_1] & BIT_VSCRL_LOCK)) {
1183+		vscroll += context->regs[REG_Y_SCROLL];
1184+	}
1185+	if (vscroll > 223) {
1186+		vscroll -= 224;
1187+	}
1188+	address += (vscroll >> 3) * 2 * 32;
1189+	//add column
1190+	address += ((column - (context->hscroll_a >> 3)) & 31) * 2;
1191+	//adjust for weird VRAM mapping in Mode 4
1192+	address = mode4_address_map[address];
1193+	context->col_1 = (context->vdpmem[address] << 8) | context->vdpmem[address+1];
1194+}
1195+
1196+static void render_map(uint16_t col, uint8_t * tmp_buf, uint8_t offset, vdp_context * context)
1197+{
1198+	uint16_t address;
1199+	uint16_t vflip_base;
1200+	if (context->double_res) {
1201+		address = ((col & 0x3FF) << 6);
1202+		vflip_base = 60;
1203+	} else {
1204+		address = ((col & 0x7FF) << 5);
1205+		vflip_base = 28;
1206+	}
1207+	if (col & MAP_BIT_V_FLIP) {
1208+		address +=  vflip_base - 4 * context->v_offset;
1209+	} else {
1210+		address += 4 * context->v_offset;
1211+	}
1212+	uint8_t pal_priority = (col >> 9) & 0x70;
1213+	uint32_t bits = *((uint32_t *)(&context->vdpmem[address]));
1214+	if (col & MAP_BIT_H_FLIP) {
1215+		uint32_t shift = 28;
1216+		for (int i = 0; i < 4; i++)
1217+		{
1218+			uint8_t right = pal_priority | ((bits >> shift) & 0xF);
1219+			shift -= 4;
1220+			tmp_buf[offset++] = pal_priority | ((bits >> shift) & 0xF);
1221+			shift -= 4;
1222+			offset &= SCROLL_BUFFER_MASK;
1223+			tmp_buf[offset++] = right;
1224+			offset &= SCROLL_BUFFER_MASK;
1225+		}
1226+	} else {
1227+		for (int i = 0; i < 4; i++)
1228+		{
1229+			uint8_t right = pal_priority | (bits & 0xF);
1230+			bits >>= 4;
1231+			tmp_buf[offset++] = pal_priority | (bits & 0xF);
1232+			offset &= SCROLL_BUFFER_MASK;
1233+			bits >>= 4;
1234+			tmp_buf[offset++] = right;
1235+			offset &= SCROLL_BUFFER_MASK;
1236+		}
1237+	}
1238+}
1239+
1240+static void render_map_1(vdp_context * context)
1241+{
1242+	render_map(context->col_1, context->tmp_buf_a, context->buf_a_off, context);
1243+}
1244+
1245+static void render_map_2(vdp_context * context)
1246+{
1247+	render_map(context->col_2, context->tmp_buf_a, context->buf_a_off+8, context);
1248+}
1249+
1250+static void render_map_3(vdp_context * context)
1251+{
1252+	render_map(context->col_1, context->tmp_buf_b, context->buf_b_off, context);
1253+}
1254+
1255+static void fetch_map_mode4(uint16_t col, uint32_t line, vdp_context *context)
1256+{
1257+	//calculate pixel row to fetch
1258+	uint32_t vscroll = line;
1259+	if (col < 24 || !(context->regs[REG_MODE_1] & BIT_VSCRL_LOCK)) {
1260+		vscroll += context->regs[REG_Y_SCROLL];
1261+	}
1262+	if (vscroll > 223) {
1263+		vscroll -= 224;
1264+	}
1265+	vscroll &= 7;
1266+	if (context->col_1 & 0x400) {
1267+		vscroll = 7 - vscroll;
1268+	}
1269+	
1270+	uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4];
1271+	context->fetch_tmp[0] = context->vdpmem[address];
1272+	context->fetch_tmp[1] = context->vdpmem[address+1];
1273+}
1274+
1275+static uint8_t composite_normal(vdp_context *context, uint8_t *debug_dst, uint8_t sprite, uint8_t plane_a, uint8_t plane_b, uint8_t bg_index)
1276+{
1277+	uint8_t pixel = bg_index;
1278+	uint8_t src = DBG_SRC_BG;
1279+	if (plane_b & 0xF) {
1280+		pixel = plane_b;
1281+		src = DBG_SRC_B;
1282+	}
1283+	if (plane_a & 0xF && (plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1284+		pixel = plane_a;
1285+		src = DBG_SRC_A;
1286+	}
1287+	if (sprite & 0xF && (sprite & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1288+		pixel = sprite;
1289+		src = DBG_SRC_S;
1290+	}
1291+	*debug_dst = src;
1292+	return pixel;
1293+}
1294+typedef struct {
1295+	uint8_t index, intensity;
1296+} sh_pixel;
1297+
1298+static sh_pixel composite_highlight(vdp_context *context, uint8_t *debug_dst, uint8_t sprite, uint8_t plane_a, uint8_t plane_b, uint8_t bg_index)
1299+{
1300+	uint8_t pixel = bg_index;
1301+	uint8_t src = DBG_SRC_BG;
1302+	uint8_t intensity = 0;
1303+	if (plane_b & 0xF) {
1304+		pixel = plane_b;
1305+		src = DBG_SRC_B;
1306+	}
1307+	intensity = plane_b & BUF_BIT_PRIORITY;
1308+	if (plane_a & 0xF && (plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1309+		pixel = plane_a;
1310+		src = DBG_SRC_A;
1311+	}
1312+	intensity |= plane_a & BUF_BIT_PRIORITY;
1313+	if (sprite & 0xF && (sprite & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1314+		if ((sprite & 0x3F) == 0x3E) {
1315+			intensity += BUF_BIT_PRIORITY;
1316+		} else if ((sprite & 0x3F) == 0x3F) {
1317+			intensity = 0;
1318+		} else {
1319+			pixel = sprite;
1320+			src = DBG_SRC_S;
1321+			if ((pixel & 0xF) == 0xE) {
1322+				intensity = BUF_BIT_PRIORITY;
1323+			} else {
1324+				intensity |= pixel & BUF_BIT_PRIORITY;
1325+			}
1326+		}
1327+	}
1328+	*debug_dst = src;
1329+	return (sh_pixel){.index = pixel, .intensity = intensity};
1330+}
1331+
1332+static void render_normal(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
1333+{
1334+	int start = 0;
1335+	if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1336+		uint32_t bgcolor = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1337+		for (int i = 0; i < 8; ++i)
1338+		{
1339+			*(dst++) = bgcolor;
1340+			*(debug_dst++) = DBG_SRC_BG;
1341+		}
1342+		start = 8;
1343+	}
1344+	uint8_t *sprite_buf = context->linebuf + col * 8 + start;
1345+	for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1346+	{
1347+		uint8_t sprite, plane_a, plane_b;
1348+		plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1349+		plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1350+		sprite = *sprite_buf;
1351+		uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]);
1352+		debug_dst++;
1353+		*(dst++) = context->colors[pixel & 0x3F];
1354+	}
1355+}
1356+
1357+static void render_highlight(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
1358+{
1359+	int start = 0;
1360+	if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1361+		uint32_t bgcolor = context->colors[SHADOW_OFFSET + (context->regs[REG_BG_COLOR] & 0x3F)];
1362+		for (int i = 0; i < 8; ++i)
1363+		{
1364+			*(dst++) = bgcolor;
1365+			*(debug_dst++) = DBG_SRC_BG | DBG_SHADOW;
1366+		}
1367+		start = 8;
1368+	}
1369+	uint8_t *sprite_buf = context->linebuf + col * 8 + start;
1370+	for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1371+	{
1372+		uint8_t sprite, plane_a, plane_b;
1373+		plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1374+		plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1375+		sprite = *sprite_buf;
1376+		sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]);
1377+		uint32_t *colors;
1378+		if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1379+			colors = context->colors + HIGHLIGHT_OFFSET;
1380+		} else if (pixel.intensity) {
1381+			colors = context->colors;
1382+		} else {
1383+			colors = context->colors + SHADOW_OFFSET;
1384+		}
1385+		debug_dst++;
1386+		*(dst++) = colors[pixel.index & 0x3F];
1387+	}
1388+}
1389+
1390+static void render_testreg(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1391+{
1392+	if (output_disabled) {
1393+		switch (test_layer)
1394+		{
1395+		case 0:
1396+			for (int i = 0; i < 16; i++)
1397+			{
1398+				*(dst++) = 0x3F; //TODO: confirm this on hardware
1399+				*(debug_dst++) = DBG_SRC_BG;
1400+			}
1401+			break;
1402+		case 1: {
1403+			uint8_t *sprite_buf = context->linebuf + col * 8;
1404+			for (int i = 0; i < 16; i++)
1405+			{
1406+				*(dst++) = context->colors[*(sprite_buf++) & 0x3F];
1407+				*(debug_dst++) = DBG_SRC_S;
1408+			}
1409+			break;
1410+		}
1411+		case 2:
1412+			for (int i = 0; i < 16; i++)
1413+			{
1414+				*(dst++) = context->colors[context->tmp_buf_a[(plane_a_off++) & SCROLL_BUFFER_MASK] & 0x3F];
1415+				*(debug_dst++) = DBG_SRC_A;
1416+			}
1417+			break;
1418+		case 3:
1419+			for (int i = 0; i < 16; i++)
1420+			{
1421+				*(dst++) = context->colors[context->tmp_buf_b[(plane_b_off++) & SCROLL_BUFFER_MASK] & 0x3F];
1422+				*(debug_dst++) = DBG_SRC_B;
1423+			}
1424+			break;
1425+		}
1426+	} else {
1427+		int start = 0;
1428+		uint8_t *sprite_buf = context->linebuf + col * 8;
1429+		if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1430+			//TODO: Confirm how test register interacts with column 0 blanking
1431+			uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1432+			uint8_t src = DBG_SRC_BG;
1433+			for (int i = 0; i < 8; ++i)
1434+			{
1435+				switch (test_layer)
1436+				{
1437+				case 1:
1438+					pixel &= sprite_buf[i];
1439+					if (pixel) {
1440+						src = DBG_SRC_S;
1441+					}
1442+					break;
1443+				case 2:
1444+					pixel &= context->tmp_buf_a[(plane_a_off + i) & SCROLL_BUFFER_MASK];
1445+					if (pixel) {
1446+						src = DBG_SRC_A;
1447+					}
1448+					break;
1449+				case 3:
1450+					pixel &= context->tmp_buf_b[(plane_b_off + i) & SCROLL_BUFFER_MASK];
1451+					if (pixel) {
1452+						src = DBG_SRC_B;
1453+					}
1454+					break;
1455+				}
1456+				
1457+				*(dst++) = context->colors[pixel & 0x3F];
1458+				*(debug_dst++) = src;
1459+			}
1460+			plane_a_off += 8;
1461+			plane_b_off += 8;
1462+			sprite_buf += 8;
1463+			start = 8;
1464+		}
1465+		for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1466+		{
1467+			uint8_t sprite, plane_a, plane_b;
1468+			plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1469+			plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1470+			sprite = *sprite_buf;
1471+			uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, 0x3F);
1472+			switch (test_layer)
1473+			{
1474+			case 1:
1475+				pixel &= sprite;
1476+				if (pixel) {
1477+					*debug_dst = DBG_SRC_S;
1478+				}
1479+				break;
1480+			case 2:
1481+				pixel &= plane_a;
1482+				if (pixel) {
1483+					*debug_dst = DBG_SRC_A;
1484+				}
1485+				break;
1486+			case 3:
1487+				pixel &= plane_b;
1488+				if (pixel) {
1489+					*debug_dst = DBG_SRC_B;
1490+				}
1491+				break;
1492+			}
1493+			debug_dst++;
1494+			*(dst++) = context->colors[pixel & 0x3F];
1495+		}
1496+	}
1497+}
1498+
1499+static void render_testreg_highlight(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1500+{
1501+	int start = 0;
1502+	uint8_t *sprite_buf = context->linebuf + col * 8;
1503+	if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1504+		//TODO: Confirm how test register interacts with column 0 blanking
1505+		uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1506+		uint8_t src = DBG_SRC_BG | DBG_SHADOW;
1507+		for (int i = 0; i < 8; ++i)
1508+		{
1509+			switch (test_layer)
1510+			{
1511+			case 1:
1512+				pixel &= sprite_buf[i];
1513+				if (pixel) {
1514+					src = DBG_SRC_S | DBG_SHADOW;
1515+				}
1516+				break;
1517+			case 2:
1518+				pixel &= context->tmp_buf_a[(plane_a_off + i) & SCROLL_BUFFER_MASK];
1519+				if (pixel) {
1520+					src = DBG_SRC_A | DBG_SHADOW;
1521+				}
1522+				break;
1523+			case 3:
1524+				pixel &= context->tmp_buf_b[(plane_b_off + i) & SCROLL_BUFFER_MASK];
1525+				if (pixel) {
1526+					src = DBG_SRC_B | DBG_SHADOW;
1527+				}
1528+				break;
1529+			}
1530+			
1531+			*(dst++) = context->colors[SHADOW_OFFSET + (pixel & 0x3F)];
1532+			*(debug_dst++) = src;
1533+		}
1534+		plane_a_off += 8;
1535+		plane_b_off += 8;
1536+		sprite_buf += 8;
1537+		start = 8;
1538+	}
1539+	for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1540+	{
1541+		uint8_t sprite, plane_a, plane_b;
1542+		plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1543+		plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1544+		sprite = *sprite_buf;
1545+		sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, 0x3F);
1546+		uint32_t *colors;
1547+		if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1548+			colors = context->colors + HIGHLIGHT_OFFSET;
1549+		} else if (pixel.intensity) {
1550+			colors = context->colors;
1551+		} else {
1552+			colors = context->colors + SHADOW_OFFSET;
1553+		}
1554+		if (output_disabled) {
1555+			pixel.index = 0x3F;
1556+		}
1557+		switch (test_layer)
1558+		{
1559+		case 1:
1560+			pixel.index &= sprite;
1561+			if (pixel.index) {
1562+				*debug_dst = DBG_SRC_S;
1563+			}
1564+			break;
1565+		case 2:
1566+			pixel.index &= plane_a;
1567+			if (pixel.index) {
1568+				*debug_dst = DBG_SRC_A;
1569+			}
1570+			break;
1571+		case 3:
1572+			pixel.index &= plane_b;
1573+			if (pixel.index) {
1574+				*debug_dst = DBG_SRC_B;
1575+			}
1576+			break;
1577+		}
1578+		debug_dst++;
1579+		*(dst++) = colors[pixel.index & 0x3F];
1580+	}
1581+}
1582+
1583+static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
1584+{
1585+	uint32_t *dst;
1586+	uint8_t *debug_dst;
1587+	uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
1588+	uint8_t test_layer = context->test_port >> 7 & 3;
1589+	if (context->state == PREPARING && !test_layer) {
1590+		if (col) {
1591+			col -= 2;
1592+			dst = context->output + BORDER_LEFT + col * 8;
1593+		} else {
1594+			dst = context->output;
1595+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1596+			for (int i = 0; i < BORDER_LEFT; i++, dst++)
1597+			{
1598+				*dst = bg_color;
1599+			}
1600+			context->done_output = dst;
1601+			return;
1602+		}
1603+		uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1604+		for (int i = 0; i < 16; i++)
1605+		{
1606+			*(dst++) = color;
1607+		}
1608+		context->done_output = dst;
1609+		return;
1610+	}
1611+	line &= 0xFF;
1612+	render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context);
1613+	uint8_t *sprite_buf;
1614+	uint8_t sprite, plane_a, plane_b;
1615+	int plane_a_off, plane_b_off;
1616+	if (col)
1617+	{
1618+		col-=2;
1619+		dst = context->output + BORDER_LEFT + col * 8;
1620+		debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8;
1621+		
1622+		
1623+		uint8_t a_src, src;
1624+		if (context->flags & FLAG_WINDOW) {
1625+			plane_a_off = context->buf_a_off;
1626+			a_src = DBG_SRC_W;
1627+		} else {
1628+			plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF);
1629+			a_src = DBG_SRC_A;
1630+		}
1631+		plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
1632+		//printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
1633+
1634+		if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
1635+			if (output_disabled || test_layer) {
1636+				render_testreg_highlight(context, col, dst, debug_dst, plane_a_off, plane_b_off, output_disabled, test_layer);
1637+			} else {
1638+				render_highlight(context, col, dst, debug_dst, plane_a_off, plane_b_off);
1639+			}
1640+		} else {
1641+			if (output_disabled || test_layer) {
1642+				render_testreg(context, col, dst, debug_dst, plane_a_off, plane_b_off, output_disabled, test_layer);
1643+			} else {
1644+				render_normal(context, col, dst, debug_dst, plane_a_off, plane_b_off);
1645+			}
1646+		}
1647+		dst += 16;
1648+	} else {
1649+		dst = context->output;
1650+		debug_dst = context->layer_debug_buf;
1651+		uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1652+		if (output_disabled) {
1653+			pixel = 0x3F;
1654+		}
1655+		uint32_t bg_color = context->colors[pixel];
1656+		if (test_layer) {
1657+			switch(test_layer)
1658+			{
1659+			case 1:
1660+				bg_color = context->colors[0];
1661+				for (int i = 0; i < BORDER_LEFT; i++, dst++, debug_dst++)
1662+				{
1663+					*dst = bg_color;
1664+					*debug_dst = DBG_SRC_BG;
1665+					
1666+				}
1667+				break;
1668+			case 2: {
1669+				//plane A
1670+				//TODO: Deal with Window layer
1671+				int i;
1672+				i = 0;
1673+				uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT);
1674+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
1675+				for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
1676+				{
1677+					*dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK]];
1678+					*debug_dst = DBG_SRC_A;
1679+				}
1680+				break;
1681+			}
1682+			case 3: {
1683+				//plane B
1684+				int i;
1685+				i = 0;
1686+				uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT);
1687+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
1688+				for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
1689+				{
1690+					*dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK]];
1691+					*debug_dst = DBG_SRC_B;
1692+				}
1693+				break;
1694+			}
1695+			}
1696+		} else {
1697+			for (int i = 0; i < BORDER_LEFT; i++, dst++, debug_dst++)
1698+			{
1699+				*dst = bg_color;
1700+				*debug_dst = DBG_SRC_BG;
1701+			}
1702+		}
1703+	}
1704+	context->done_output = dst;
1705+	context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1706+	context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1707+}
1708+
1709+static void render_map_mode4(uint32_t line, int32_t col, vdp_context * context)
1710+{
1711+	uint32_t vscroll = line;
1712+	if (col < 24 || !(context->regs[REG_MODE_1] & BIT_VSCRL_LOCK)) {
1713+		vscroll += context->regs[REG_Y_SCROLL];
1714+	}
1715+	if (vscroll > 223) {
1716+		vscroll -= 224;
1717+	}
1718+	vscroll &= 7;
1719+	if (context->col_1 & 0x400) {
1720+		//vflip
1721+		vscroll = 7 - vscroll;
1722+	}
1723+	
1724+	uint32_t pixels = planar_to_chunky[context->fetch_tmp[0]] << 1;
1725+	pixels |=  planar_to_chunky[context->fetch_tmp[1]];
1726+	
1727+	uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4 + 2];
1728+	pixels |= planar_to_chunky[context->vdpmem[address]] << 3;
1729+	pixels |= planar_to_chunky[context->vdpmem[address+1]] << 2;
1730+	
1731+	int i, i_inc, i_limit;
1732+	if (context->col_1 & 0x200) {
1733+		//hflip
1734+		i = 0;
1735+		i_inc = 4;
1736+		i_limit = 32;
1737+	} else {
1738+		i = 28;
1739+		i_inc = -4;
1740+		i_limit = -4;
1741+	}
1742+	uint8_t pal_priority = (context->col_1 >> 7 & 0x10) | (context->col_1 >> 6 & 0x40);
1743+	for (uint8_t *dst = context->tmp_buf_a + context->buf_a_off; i != i_limit; i += i_inc, dst++)
1744+	{
1745+		*dst = (pixels >> i & 0xF) | pal_priority;
1746+	}
1747+	context->buf_a_off = (context->buf_a_off + 8) & 15;
1748+	
1749+	uint8_t bgcolor = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET;
1750+	uint32_t *dst = context->output + col * 8 + BORDER_LEFT;
1751+	uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT;
1752+	if (context->state == PREPARING) {
1753+		for (int i = 0; i < 16; i++)
1754+		{
1755+			*(dst++) = context->colors[bgcolor];
1756+		}
1757+		context->done_output = dst;
1758+		return;
1759+	}
1760+	
1761+	if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1762+		uint8_t *sprite_src = context->linebuf + col * 8;
1763+		if (context->regs[REG_MODE_1] & BIT_SPRITE_8PX) {
1764+			sprite_src += 8;
1765+		}
1766+		for (int i = 0; i < 8; i++, sprite_src++)
1767+		{
1768+			uint8_t *bg_src = context->tmp_buf_a + ((8 + i + col * 8 - (context->hscroll_a & 0x7)) & 15);
1769+			if ((*bg_src & 0x4F) > 0x40 || !*sprite_src) {
1770+				//background plane has priority and is opaque or sprite layer is transparent
1771+				*(dst++) = context->colors[(*bg_src & 0x1F) + MODE4_OFFSET];
1772+				*(debug_dst++) = DBG_SRC_A;
1773+			} else {
1774+				//sprite layer is opaque and not covered by high priority BG pixels
1775+				*(dst++) = context->colors[*sprite_src | 0x10 + MODE4_OFFSET];
1776+				*(debug_dst++) = DBG_SRC_S;
1777+			}
1778+		}
1779+	} else {
1780+		for (int i = 0; i < 8; i++)
1781+		{
1782+			*(dst++) = context->colors[bgcolor];
1783+			*(debug_dst++) = DBG_SRC_BG;
1784+		}
1785+	}
1786+	context->done_output = dst;
1787+}
1788+
1789+static uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19};
1790+
1791+static void vdp_advance_line(vdp_context *context)
1792+{
1793+#ifdef TIMING_DEBUG
1794+	static uint32_t last_line = 0xFFFFFFFF;
1795+	if (last_line != 0xFFFFFFFF) {
1796+		uint32_t diff = context->cycles - last_line;
1797+		if (diff != MCLKS_LINE) {
1798+			printf("Line %d took %d cycles\n", context->vcounter, diff);
1799+		}
1800+	}
1801+	last_line = context->cycles;
1802+#endif
1803+	uint16_t jump_start, jump_end;
1804+	uint8_t is_mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
1805+	if (is_mode_5) {
1806+		if (context->flags2 & FLAG2_REGION_PAL) {
1807+			if (context->regs[REG_MODE_2] & BIT_PAL) {
1808+				jump_start = 0x10B;
1809+				jump_end = 0x1D2;
1810+			} else {
1811+				jump_start = 0x103;
1812+				jump_end = 0x1CA;
1813+			}
1814+		} else if (context->regs[REG_MODE_2] & BIT_PAL) {
1815+			jump_start = 0x100;
1816+			jump_end = 0x1FA;
1817+		} else {
1818+			jump_start = 0xEB;
1819+			jump_end = 0x1E5;
1820+		}
1821+	} else {
1822+		jump_start = 0xDB;
1823+		jump_end = 0x1D5;
1824+	}
1825+
1826+	if (context->enabled_debuggers & (1 << VDP_DEBUG_CRAM | 1 << VDP_DEBUG_COMPOSITE)) {
1827+		uint32_t line = context->vcounter;
1828+		if (line >= jump_end) {
1829+			line -= jump_end - jump_start;
1830+		}
1831+		uint32_t total_lines = (context->flags2 & FLAG2_REGION_PAL) ? 313 : 262;
1832+		
1833+		if (total_lines - line <= context->border_top) {
1834+			line -= total_lines - context->border_top;
1835+		} else {
1836+			line += context->border_top;
1837+		}
1838+		if (context->enabled_debuggers & (1 << VDP_DEBUG_CRAM)) {
1839+			uint32_t *fb = context->debug_fbs[VDP_DEBUG_CRAM] + context->debug_fb_pitch[VDP_DEBUG_CRAM] * line / sizeof(uint32_t);
1840+			for (int i = 0; i < 64; i++)
1841+			{
1842+				for (int x = 0; x < 8; x++)
1843+				{
1844+					*(fb++) = context->colors[i];
1845+				}
1846+			}
1847+		}
1848+		if (
1849+			context->enabled_debuggers & (1 << VDP_DEBUG_COMPOSITE)
1850+			&& line < (context->inactive_start + context->border_bot + context->border_top)
1851+		) {
1852+			uint32_t *fb = context->debug_fbs[VDP_DEBUG_COMPOSITE] + context->debug_fb_pitch[VDP_DEBUG_COMPOSITE] * line / sizeof(uint32_t);
1853+			for (int i = 0; i < LINEBUF_SIZE; i++)
1854+			{
1855+				*(fb++) = context->debugcolors[context->layer_debug_buf[i]];
1856+			}
1857+		}
1858+	}
1859+	
1860+	context->vcounter++;
1861+	if (context->vcounter == jump_start) {
1862+		context->vcounter = jump_end;
1863+	} else {
1864+		context->vcounter &= 0x1FF;
1865+	}
1866+	if (context->state == PREPARING) {
1867+		context->state = ACTIVE;
1868+	}
1869+	if (context->vcounter == 0x1FF) {
1870+		context->flags2 &= ~FLAG2_PAUSE;
1871+	}
1872+
1873+	if (context->state != ACTIVE) {
1874+		context->hint_counter = context->regs[REG_HINT];
1875+	} else if (context->hint_counter) {
1876+		context->hint_counter--;
1877+	} else {
1878+		context->flags2 |= FLAG2_HINT_PENDING;
1879+		context->pending_hint_start = context->cycles;
1880+		context->hint_counter = context->regs[REG_HINT];
1881+	}
1882+}
1883+
1884+static void vdp_update_per_frame_debug(vdp_context *context)
1885+{
1886+	if (context->enabled_debuggers & (1 << VDP_DEBUG_PLANE)) {
1887+		uint32_t pitch;
1888+		uint32_t *fb = render_get_video_buffer(context->debug_fb_indices[VDP_DEBUG_PLANE], &pitch);
1889+		uint16_t hscroll_mask;
1890+		uint16_t v_mul;
1891+		uint16_t vscroll_mask = 0x1F | (context->regs[REG_SCROLL] & 0x30) << 1;
1892+		switch(context->regs[REG_SCROLL] & 0x3)
1893+		{
1894+		case 0:
1895+			hscroll_mask = 0x1F;
1896+			v_mul = 64;
1897+			break;
1898+		case 0x1:
1899+			hscroll_mask = 0x3F;
1900+			v_mul = 128;
1901+			break;
1902+		case 0x2:
1903+			//TODO: Verify this behavior
1904+			hscroll_mask = 0x1F;
1905+			v_mul = 0;
1906+			break;
1907+		case 0x3:
1908+			hscroll_mask = 0x7F;
1909+			v_mul = 256;
1910+			break;
1911+		}
1912+		uint16_t table_address;
1913+		switch(context->debug_modes[VDP_DEBUG_PLANE] % 3)
1914+		{
1915+		case 0:
1916+			table_address = context->regs[REG_SCROLL_A] << 10 & 0xE000;
1917+			break;
1918+		case 1:
1919+			table_address = context->regs[REG_SCROLL_B] << 13 & 0xE000;
1920+			break;
1921+		case 2:
1922+			table_address = context->regs[REG_WINDOW] << 10;
1923+			if (context->regs[REG_MODE_4] & BIT_H40) {
1924+				table_address &= 0xF000;
1925+				v_mul = 128;
1926+				hscroll_mask = 0x3F;
1927+			} else {
1928+				table_address &= 0xF800;
1929+				v_mul = 64;
1930+				hscroll_mask = 0x1F;
1931+			}
1932+			vscroll_mask = 0x1F;
1933+			break;
1934+		}
1935+		uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR & 0x3F]];
1936+		for (uint16_t row = 0; row < 128; row++)
1937+		{
1938+			uint16_t row_address = table_address + (row & vscroll_mask) * v_mul;
1939+			for (uint16_t col = 0; col < 128; col++)
1940+			{
1941+				uint16_t address = row_address + (col & hscroll_mask) * 2;
1942+				//pccv hnnn nnnn nnnn
1943+				//
1944+				uint16_t entry = context->vdpmem[address] << 8 | context->vdpmem[address + 1];
1945+				uint8_t pal = entry >> 9 & 0x30;
1946+				
1947+				uint32_t *dst = fb + (row * pitch * 8 / sizeof(uint32_t)) + col * 8;
1948+				address = (entry & 0x7FF) * 32;
1949+				int y_diff = 4;
1950+				if (entry & 0x1000) {
1951+					y_diff = -4;
1952+					address += 7 * 4;
1953+				}
1954+				int x_diff = 1;
1955+				if (entry & 0x800) {
1956+					x_diff = -1;
1957+					address += 3;
1958+				}
1959+				for (int y = 0; y < 8; y++)
1960+				{
1961+					uint16_t trow_address = address;
1962+					uint32_t *row_dst = dst;
1963+					for (int x = 0; x < 4; x++)
1964+					{
1965+						uint8_t byte = context->vdpmem[trow_address];
1966+						trow_address += x_diff;
1967+						uint8_t left, right;
1968+						if (x_diff > 0) {
1969+							left = byte >> 4;
1970+							right = byte & 0xF;
1971+						} else {
1972+							left = byte & 0xF;
1973+							right = byte >> 4;
1974+						}
1975+						*(row_dst++) = left ? context->colors[left|pal] : bg_color;
1976+						*(row_dst++) = right ? context->colors[right|pal] : bg_color;
1977+					}
1978+					address += y_diff;
1979+					dst += pitch / sizeof(uint32_t);
1980+				}
1981+			}
1982+		}
1983+		render_video_buffer_updated(context->debug_fb_indices[VDP_DEBUG_PLANE], 1024);
1984+	}
1985+	
1986+	if (context->enabled_debuggers & (1 << VDP_DEBUG_VRAM)) {
1987+		uint32_t pitch;
1988+		uint32_t *fb = render_get_video_buffer(context->debug_fb_indices[VDP_DEBUG_VRAM], &pitch);
1989+		
1990+		uint8_t pal = (context->debug_modes[VDP_DEBUG_VRAM] % 4) << 4;
1991+		for (int y = 0; y < 512; y++)
1992+		{
1993+			uint32_t *line = fb + y * pitch / sizeof(uint32_t);
1994+			int row = y >> 4;
1995+			int yoff = y >> 1 & 7;
1996+			for (int col = 0; col < 64; col++)
1997+			{
1998+				uint16_t address = (row * 64 + col) * 32 + yoff * 4;
1999+				for (int x = 0; x < 4; x++)
2000+				{
2001+					uint8_t byte = context->vdpmem[address++];
2002+					uint8_t left = byte >> 4 | pal;
2003+					uint8_t right = byte & 0xF | pal;
2004+					*(line++) = context->colors[left];
2005+					*(line++) = context->colors[left];
2006+					*(line++) = context->colors[right];
2007+					*(line++) = context->colors[right];
2008+				}
2009+			}
2010+		}
2011+		
2012+		render_video_buffer_updated(context->debug_fb_indices[VDP_DEBUG_VRAM], 1024);
2013+	}
2014+	
2015+	if (context->enabled_debuggers & (1 << VDP_DEBUG_CRAM)) {
2016+		uint32_t starting_line = 512 - 32*4;
2017+		uint32_t *line = context->debug_fbs[VDP_DEBUG_CRAM] 
2018+			+ context->debug_fb_pitch[VDP_DEBUG_CRAM]  * starting_line / sizeof(uint32_t);
2019+		for (int pal = 0; pal < 4; pal ++)
2020+		{
2021+			uint32_t *cur;
2022+			for (int y = 0; y < 31; y++)
2023+			{
2024+				cur = line;
2025+				for (int offset = 0; offset < 16; offset++)
2026+				{
2027+					for (int x = 0; x < 31; x++)
2028+					{
2029+						*(cur++) = context->colors[pal * 16 + offset];
2030+					}
2031+					*(cur++) = 0xFF000000;
2032+				}
2033+				line += context->debug_fb_pitch[VDP_DEBUG_CRAM] / sizeof(uint32_t);
2034+			}
2035+			cur = line;
2036+			for (int x = 0; x < 512; x++)
2037+			{
2038+				*(cur++) = 0xFF000000;
2039+			}
2040+			line += context->debug_fb_pitch[VDP_DEBUG_CRAM] / sizeof(uint32_t);
2041+		}
2042+		render_video_buffer_updated(context->debug_fb_indices[VDP_DEBUG_CRAM], 512);
2043+		context->debug_fbs[VDP_DEBUG_CRAM] = render_get_video_buffer(context->debug_fb_indices[VDP_DEBUG_CRAM], &context->debug_fb_pitch[VDP_DEBUG_CRAM]);
2044+	}
2045+	if (context->enabled_debuggers & (1 << VDP_DEBUG_COMPOSITE)) {
2046+		render_video_buffer_updated(context->debug_fb_indices[VDP_DEBUG_COMPOSITE], LINEBUF_SIZE);
2047+		context->debug_fbs[VDP_DEBUG_COMPOSITE] = render_get_video_buffer(context->debug_fb_indices[VDP_DEBUG_COMPOSITE], &context->debug_fb_pitch[VDP_DEBUG_COMPOSITE]);
2048+	}		
2049+}
2050+
2051+void vdp_force_update_framebuffer(vdp_context *context)
2052+{
2053+	uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) 
2054+			? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL 
2055+			: 224 + BORDER_TOP_V28 + BORDER_BOT_V28;
2056+			
2057+	uint16_t to_fill = lines_max - context->output_lines;
2058+	memset(
2059+		((char *)context->fb) + context->output_pitch * context->output_lines,
2060+		0,
2061+		to_fill * context->output_pitch
2062+	);
2063+	render_video_buffer_updated(context->cur_buffer, context->h40_lines > context->output_lines / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2064+	context->fb = render_get_video_buffer(context->cur_buffer, &context->output_pitch);
2065+	vdp_update_per_frame_debug(context);
2066+}
2067+
2068+static void advance_output_line(vdp_context *context)
2069+{
2070+	if (headless) {
2071+		if (context->vcounter == context->inactive_start) {
2072+			context->frame++;
2073+		}
2074+		context->vcounter &= 0x1FF;
2075+	} else {
2076+		uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) 
2077+			? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL 
2078+			: 224 + BORDER_TOP_V28 + BORDER_BOT_V28;
2079+
2080+		if (context->output_lines == lines_max) {
2081+			render_video_buffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2082+			context->cur_buffer = context->flags2 & FLAG2_EVEN_FIELD ? VIDEO_BUFFER_EVEN : VIDEO_BUFFER_ODD;
2083+			context->fb = render_get_video_buffer(context->cur_buffer, &context->output_pitch);
2084+			vdp_update_per_frame_debug(context);
2085+			context->h40_lines = 0;
2086+			context->frame++;
2087+			context->output_lines = 0;
2088+		}
2089+		uint32_t output_line = context->vcounter;
2090+		if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) {
2091+			//vcounter increment occurs much later in Mode 4
2092+			output_line++;
2093+		} 
2094+		if (output_line < context->inactive_start + context->border_bot && context->output_lines > 0) {
2095+			output_line = context->output_lines++;//context->border_top + context->vcounter;
2096+		} else if (output_line >= 0x200 - context->border_top) {
2097+			if (output_line == 0x200 - context->border_top) {
2098+				//We're at the top of the display, force context->output_lines to be zero to avoid
2099+				//potential screen rolling if the mode is changed at an inopportune time
2100+				context->output_lines = 0;
2101+			}
2102+			output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top);
2103+		} else {
2104+			output_line = INVALID_LINE;
2105+		}
2106+		context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line);
2107+		context->done_output = context->output;
2108+#ifdef DEBUG_FB_FILL
2109+		for (int i = 0; i < LINEBUF_SIZE; i++)
2110+		{
2111+			context->output[i] = 0xFFFF00FF;
2112+		}
2113+#endif	
2114+		if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) {
2115+			context->h40_lines++;
2116+		}
2117+	}
2118+}
2119+
2120+void vdp_release_framebuffer(vdp_context *context)
2121+{
2122+	render_video_buffer_updated(context->cur_buffer, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER));
2123+	context->output = context->fb = NULL;
2124+}
2125+
2126+void vdp_reacquire_framebuffer(vdp_context *context)
2127+{
2128+	context->fb = render_get_video_buffer(context->cur_buffer, &context->output_pitch);
2129+	uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) 
2130+			? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL
2131+			: 224 + BORDER_TOP_V28 + BORDER_BOT_V28;
2132+	if (context->output_lines <= lines_max && context->output_lines > 0) {
2133+		context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1));
2134+	} else {
2135+		context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * INVALID_LINE);
2136+	}
2137+}
2138+
2139+static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col)
2140+{
2141+	uint8_t base = col >> 9 & 0x30;
2142+	for (int i = 0; i < 4; i++, address++)
2143+	{
2144+		uint8_t byte = context->vdpmem[address & 0xFFFF];
2145+		buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte >> 4;
2146+		buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte & 0xF;
2147+	}
2148+}
2149+
2150+static void draw_right_border(vdp_context *context)
2151+{
2152+	uint32_t *dst = context->output + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256);
2153+	uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
2154+	if ((context->test_port & TEST_BIT_DISABLE) != 0) {
2155+		pixel = 0x3F;
2156+	}
2157+	uint32_t bg_color = context->colors[pixel];
2158+	uint8_t test_layer = context->test_port >> 7 & 3;
2159+	if (test_layer) {
2160+		switch(test_layer)
2161+			{
2162+			case 1:
2163+				bg_color = context->colors[0];
2164+				for (int i = 0; i < BORDER_RIGHT; i++, dst++)
2165+				{
2166+					*dst = bg_color;
2167+				}
2168+				break;
2169+			case 2: {
2170+				//plane A
2171+				//TODO: Deal with Window layer
2172+				int i;
2173+				i = 0;
2174+				uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF);
2175+				//uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 
2176+				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
2177+				{
2178+					*dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
2179+				}
2180+				break;
2181+			}
2182+			case 3: {
2183+				//plane B
2184+				int i;
2185+				i = 0;
2186+				uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF);
2187+				//uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 
2188+				for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
2189+				{
2190+					*dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
2191+				}
2192+				break;
2193+			}
2194+			}
2195+	} else {
2196+		for (int i = 0; i < BORDER_RIGHT; i++, dst++)
2197+		{
2198+			*dst = bg_color;
2199+		}
2200+	}
2201+	context->done_output = dst;
2202+	context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2203+	context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2204+}
2205+
2206+#define CHECK_ONLY if (context->cycles >= target_cycles) { return; }
2207+#define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
2208+
2209+#define COLUMN_RENDER_BLOCK(column, startcyc) \
2210+	case startcyc:\
2211+		read_map_scroll_a(column, context->vcounter, context);\
2212+		CHECK_LIMIT\
2213+	case ((startcyc+1)&0xFF):\
2214+		external_slot(context);\
2215+		CHECK_LIMIT\
2216+	case ((startcyc+2)&0xFF):\
2217+		render_map_1(context);\
2218+		CHECK_LIMIT\
2219+	case ((startcyc+3)&0xFF):\
2220+		render_map_2(context);\
2221+		CHECK_LIMIT\
2222+	case ((startcyc+4)&0xFF):\
2223+		read_map_scroll_b(column, context->vcounter, context);\
2224+		CHECK_LIMIT\
2225+	case ((startcyc+5)&0xFF):\
2226+		read_sprite_x(context->vcounter, context);\
2227+		CHECK_LIMIT\
2228+	case ((startcyc+6)&0xFF):\
2229+		render_map_3(context);\
2230+		CHECK_LIMIT\
2231+	case ((startcyc+7)&0xFF):\
2232+		render_map_output(context->vcounter, column, context);\
2233+		CHECK_LIMIT
2234+
2235+#define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \
2236+	case startcyc:\
2237+		read_map_scroll_a(column, context->vcounter, context);\
2238+		CHECK_LIMIT\
2239+	case (startcyc+1):\
2240+		/* refresh, no don't run dma src */\
2241+		context->hslot++;\
2242+		context->cycles += slot_cycles;\
2243+		CHECK_ONLY\
2244+	case (startcyc+2):\
2245+		render_map_1(context);\
2246+		CHECK_LIMIT\
2247+	case (startcyc+3):\
2248+		render_map_2(context);\
2249+		CHECK_LIMIT\
2250+	case (startcyc+4):\
2251+		read_map_scroll_b(column, context->vcounter, context);\
2252+		CHECK_LIMIT\
2253+	case (startcyc+5):\
2254+		read_sprite_x(context->vcounter, context);\
2255+		CHECK_LIMIT\
2256+	case (startcyc+6):\
2257+		render_map_3(context);\
2258+		CHECK_LIMIT\
2259+	case (startcyc+7):\
2260+		render_map_output(context->vcounter, column, context);\
2261+		CHECK_LIMIT
2262+		
2263+#define COLUMN_RENDER_BLOCK_MODE4(column, startcyc) \
2264+	case startcyc:\
2265+		read_map_mode4(column, context->vcounter, context);\
2266+		CHECK_LIMIT\
2267+	case ((startcyc+1)&0xFF):\
2268+		if (column & 3) {\
2269+			scan_sprite_table_mode4(context);\
2270+		} else {\
2271+			external_slot(context);\
2272+		}\
2273+		CHECK_LIMIT\
2274+	case ((startcyc+2)&0xFF):\
2275+		fetch_map_mode4(column, context->vcounter, context);\
2276+		CHECK_LIMIT\
2277+	case ((startcyc+3)&0xFF):\
2278+		render_map_mode4(context->vcounter, column, context);\
2279+		CHECK_LIMIT
2280+		
2281+#define CHECK_LIMIT_HSYNC(slot) \
2282+	if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2283+	if (slot >= HSYNC_SLOT_H40 && slot < HSYNC_END_H40) {\
2284+		context->cycles += h40_hsync_cycles[slot - HSYNC_SLOT_H40];\
2285+	} else {\
2286+		context->cycles += slot_cycles;\
2287+	}\
2288+	if (slot == 182) {\
2289+		context->hslot = 229;\
2290+	} else {\
2291+		context->hslot++;\
2292+	}\
2293+	CHECK_ONLY
2294+
2295+#define SPRITE_RENDER_H40(slot) \
2296+	case slot:\
2297+		if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\
2298+			advance_output_line(context);\
2299+		}\
2300+		if (slot == 168 || slot == 247 || slot == 248) {\
2301+			render_border_garbage(\
2302+				context,\
2303+				context->sprite_draw_list[context->cur_slot].address,\
2304+				context->tmp_buf_b,\
2305+				context->buf_b_off + (slot == 247 ? 0 : 8),\
2306+				slot == 247 ? context->col_1 : context->col_2\
2307+			);\
2308+			if (slot == 248) {\
2309+				context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
2310+				context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
2311+			}\
2312+		} else if (slot == 243) {\
2313+			render_border_garbage(\
2314+				context,\
2315+				context->sprite_draw_list[context->cur_slot].address,\
2316+				context->tmp_buf_a,\
2317+				context->buf_a_off,\
2318+				context->col_1\
2319+			);\
2320+		} else if (slot == 169) {\
2321+			draw_right_border(context);\
2322+		}\
2323+		render_sprite_cells( context);\
2324+		scan_sprite_table(context->vcounter, context);\
2325+		CHECK_LIMIT_HSYNC(slot)
2326+
2327+//Note that the line advancement check will fail if BG_START_SLOT is > 6
2328+//as we're bumping up against the hcounter jump
2329+#define SPRITE_RENDER_H32(slot) \
2330+	case slot:\
2331+		if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2332+			advance_output_line(context);\
2333+		}\
2334+		if (slot == 136 || slot == 247 || slot == 248) {\
2335+			render_border_garbage(\
2336+				context,\
2337+				context->sprite_draw_list[context->cur_slot].address,\
2338+				context->tmp_buf_b,\
2339+				context->buf_b_off + (slot == 247 ? 0 : 8),\
2340+				slot == 247 ? context->col_1 : context->col_2\
2341+			);\
2342+			if (slot == 248) {\
2343+				context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
2344+				context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
2345+			}\
2346+		} else if (slot == 137) {\
2347+			draw_right_border(context);\
2348+		}\
2349+		render_sprite_cells( context);\
2350+		scan_sprite_table(context->vcounter, context);\
2351+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2352+		if (slot == 147) {\
2353+			context->hslot = 233;\
2354+		} else {\
2355+			context->hslot++;\
2356+		}\
2357+		context->cycles += slot_cycles;\
2358+		CHECK_ONLY
2359+		
2360+#define MODE4_CHECK_SLOT_LINE(slot) \
2361+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2362+		if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2363+			advance_output_line(context);\
2364+		}\
2365+		if ((slot) == 147) {\
2366+			context->hslot = 233;\
2367+		} else {\
2368+			context->hslot++;\
2369+		}\
2370+		context->cycles += slot_cycles;\
2371+		if ((slot+1) == LINE_CHANGE_MODE4) {\
2372+			vdp_advance_line(context);\
2373+			if (context->vcounter == 192) {\
2374+				return;\
2375+			}\
2376+		}\
2377+		CHECK_ONLY
2378+
2379+#define CALC_SLOT(slot, increment) ((slot+increment) > 147 && (slot+increment) < 233 ? (slot+increment-148+233): (slot+increment))
2380+		
2381+#define SPRITE_RENDER_H32_MODE4(slot) \
2382+	case slot:\
2383+		read_sprite_x_mode4(context);\
2384+		MODE4_CHECK_SLOT_LINE(slot)\
2385+	case CALC_SLOT(slot, 1):\
2386+		read_sprite_x_mode4(context);\
2387+		MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot,1))\
2388+	case CALC_SLOT(slot, 2):\
2389+		fetch_sprite_cells_mode4(context);\
2390+		MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 2))\
2391+	case CALC_SLOT(slot, 3):\
2392+		if ((slot + 3) == 140) {\
2393+			uint32_t *dst = context->output + BORDER_LEFT + 256 + 8;\
2394+			uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];\
2395+			for (int i = 0; i < BORDER_RIGHT-8; i++, dst++)\
2396+			{\
2397+				*dst = bgcolor;\
2398+			}\
2399+			context->done_output = dst;\
2400+		}\
2401+		render_sprite_cells_mode4(context);\
2402+		MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 3))\
2403+	case CALC_SLOT(slot, 4):\
2404+		fetch_sprite_cells_mode4(context);\
2405+		MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 4))\
2406+	case CALC_SLOT(slot, 5):\
2407+		render_sprite_cells_mode4(context);\
2408+		MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5))
2409+
2410+static void vdp_h40(vdp_context * context, uint32_t target_cycles)
2411+{
2412+	uint16_t address;
2413+	uint32_t mask;
2414+	uint32_t const slot_cycles = MCLKS_SLOT_H40;
2415+	switch(context->hslot)
2416+	{
2417+	for (;;)
2418+	{
2419+	case 165:
2420+		if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
2421+			//TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
2422+			//See note in vdp_h32 for why this was originally moved out of read_map_scroll
2423+			//Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232
2424+			//pretty consistently
2425+			context->vscroll_latch[0] = context->vsram[0];
2426+			context->vscroll_latch[1] = context->vsram[1];
2427+		}
2428+		if (context->state == PREPARING) {
2429+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2430+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2431+			if (dst >= context->done_output) {
2432+				*dst = bg_color;
2433+			}
2434+			dst++;
2435+			if (dst >= context->done_output) {
2436+				*dst = bg_color;
2437+			}
2438+			external_slot(context);
2439+		} else {
2440+			render_sprite_cells(context);
2441+		}
2442+		CHECK_LIMIT
2443+	case 166:
2444+		if (context->state == PREPARING) {
2445+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2446+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2447+			if (dst >= context->done_output) {
2448+				*dst = bg_color;
2449+			}
2450+			dst++;
2451+			if (dst >= context->done_output) {
2452+				*dst = bg_color;
2453+			}
2454+			external_slot(context);
2455+		} else {
2456+			render_sprite_cells(context);
2457+		}
2458+		if (context->vcounter == context->inactive_start) {
2459+			context->hslot++;
2460+			context->cycles += slot_cycles;
2461+			return;
2462+		}
2463+		CHECK_LIMIT
2464+	//sprite attribute table scan starts
2465+	case 167:
2466+		if (context->state == PREPARING) {
2467+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2468+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2469+			for (int i = 0; i < LINEBUF_SIZE - 2 * (context->hslot - BG_START_SLOT); i++, dst++)
2470+			{
2471+				if (dst >= context->done_output) {
2472+					*dst = bg_color;
2473+				}
2474+			}
2475+		}
2476+		context->sprite_index = 0x80;
2477+		context->slot_counter = 0;
2478+		render_border_garbage(
2479+			context,
2480+			context->sprite_draw_list[context->cur_slot].address,
2481+			context->tmp_buf_b, context->buf_b_off,
2482+			context->col_1
2483+		);
2484+		render_sprite_cells(context);
2485+		scan_sprite_table(context->vcounter, context);
2486+		CHECK_LIMIT
2487+	SPRITE_RENDER_H40(168)
2488+	SPRITE_RENDER_H40(169)
2489+	SPRITE_RENDER_H40(170)
2490+	SPRITE_RENDER_H40(171)
2491+	SPRITE_RENDER_H40(172)
2492+	SPRITE_RENDER_H40(173)
2493+	SPRITE_RENDER_H40(174)
2494+	SPRITE_RENDER_H40(175)
2495+	SPRITE_RENDER_H40(176)
2496+	SPRITE_RENDER_H40(177)//End of border?
2497+	SPRITE_RENDER_H40(178)
2498+	SPRITE_RENDER_H40(179)
2499+	SPRITE_RENDER_H40(180)
2500+	SPRITE_RENDER_H40(181)
2501+	SPRITE_RENDER_H40(182)
2502+	SPRITE_RENDER_H40(229)
2503+	//!HSYNC asserted
2504+	SPRITE_RENDER_H40(230)
2505+	SPRITE_RENDER_H40(231)
2506+	case 232:
2507+		external_slot(context);
2508+		CHECK_LIMIT_HSYNC(232)
2509+	SPRITE_RENDER_H40(233)
2510+	SPRITE_RENDER_H40(234)
2511+	SPRITE_RENDER_H40(235)
2512+	SPRITE_RENDER_H40(236)
2513+	SPRITE_RENDER_H40(237)
2514+	SPRITE_RENDER_H40(238)
2515+	SPRITE_RENDER_H40(239)
2516+	SPRITE_RENDER_H40(240)
2517+	SPRITE_RENDER_H40(241)
2518+	SPRITE_RENDER_H40(242)
2519+	SPRITE_RENDER_H40(243) //provides "garbage" for border when plane A selected
2520+	case 244:
2521+		address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
2522+		mask = 0;
2523+		if (context->regs[REG_MODE_3] & 0x2) {
2524+			mask |= 0xF8;
2525+		}
2526+		if (context->regs[REG_MODE_3] & 0x1) {
2527+			mask |= 0x7;
2528+		}
2529+		render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
2530+		address += (context->vcounter & mask) * 4;
2531+		context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
2532+		context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
2533+		//printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
2534+		if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); }
2535+		context->hslot++;
2536+		context->cycles += h40_hsync_cycles[14];
2537+		CHECK_ONLY //provides "garbage" for border when plane A selected
2538+	//!HSYNC high
2539+	SPRITE_RENDER_H40(245)
2540+	SPRITE_RENDER_H40(246)
2541+	SPRITE_RENDER_H40(247) //provides "garbage" for border when plane B selected
2542+	SPRITE_RENDER_H40(248) //provides "garbage" for border when plane B selected
2543+	case 249:
2544+		read_map_scroll_a(0, context->vcounter, context);
2545+		CHECK_LIMIT
2546+	SPRITE_RENDER_H40(250)
2547+	case 251:
2548+		render_map_1(context);
2549+		scan_sprite_table(context->vcounter, context);//Just a guess
2550+		CHECK_LIMIT
2551+	case 252:
2552+		render_map_2(context);
2553+		scan_sprite_table(context->vcounter, context);//Just a guess
2554+		CHECK_LIMIT
2555+	case 253:
2556+		read_map_scroll_b(0, context->vcounter, context);
2557+		CHECK_LIMIT
2558+	SPRITE_RENDER_H40(254)
2559+	case 255:
2560+		render_map_3(context);
2561+		scan_sprite_table(context->vcounter, context);//Just a guess
2562+		CHECK_LIMIT
2563+	case 0:
2564+		render_map_output(context->vcounter, 0, context);
2565+		scan_sprite_table(context->vcounter, context);//Just a guess
2566+		//seems like the sprite table scan fills a shift register
2567+		//values are FIFO, but unused slots precede used slots
2568+		//so we set cur_slot to slot_counter and let it wrap around to
2569+		//the beginning of the list
2570+		context->cur_slot = context->slot_counter;
2571+		context->sprite_draws = MAX_DRAWS;
2572+		context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
2573+		CHECK_LIMIT
2574+	COLUMN_RENDER_BLOCK(2, 1)
2575+	COLUMN_RENDER_BLOCK(4, 9)
2576+	COLUMN_RENDER_BLOCK(6, 17)
2577+	COLUMN_RENDER_BLOCK_REFRESH(8, 25)
2578+	COLUMN_RENDER_BLOCK(10, 33)
2579+	COLUMN_RENDER_BLOCK(12, 41)
2580+	COLUMN_RENDER_BLOCK(14, 49)
2581+	COLUMN_RENDER_BLOCK_REFRESH(16, 57)
2582+	COLUMN_RENDER_BLOCK(18, 65)
2583+	COLUMN_RENDER_BLOCK(20, 73)
2584+	COLUMN_RENDER_BLOCK(22, 81)
2585+	COLUMN_RENDER_BLOCK_REFRESH(24, 89)
2586+	COLUMN_RENDER_BLOCK(26, 97)
2587+	COLUMN_RENDER_BLOCK(28, 105)
2588+	COLUMN_RENDER_BLOCK(30, 113)
2589+	COLUMN_RENDER_BLOCK_REFRESH(32, 121)
2590+	COLUMN_RENDER_BLOCK(34, 129)
2591+	COLUMN_RENDER_BLOCK(36, 137)
2592+	COLUMN_RENDER_BLOCK(38, 145)
2593+	COLUMN_RENDER_BLOCK_REFRESH(40, 153)
2594+	case 161:
2595+		external_slot(context);
2596+		CHECK_LIMIT
2597+	case 162:
2598+		external_slot(context);
2599+		CHECK_LIMIT
2600+	//sprite render to line buffer starts
2601+	case 163:
2602+		context->cur_slot = MAX_DRAWS-1;
2603+		memset(context->linebuf, 0, LINEBUF_SIZE);
2604+		render_border_garbage(
2605+			context,
2606+			context->sprite_draw_list[context->cur_slot].address,
2607+			context->tmp_buf_a, context->buf_a_off,
2608+			context->col_1
2609+		);
2610+		render_sprite_cells(context);
2611+		CHECK_LIMIT
2612+	case 164:
2613+		render_border_garbage(
2614+			context,
2615+			context->sprite_draw_list[context->cur_slot].address,
2616+			context->tmp_buf_a, context->buf_a_off + 8,
2617+			context->col_2
2618+		);
2619+		render_sprite_cells(context);
2620+		if (context->flags & FLAG_DMA_RUN) {
2621+			run_dma_src(context, -1);
2622+		}
2623+		context->hslot++;
2624+		context->cycles += slot_cycles;
2625+		vdp_advance_line(context);
2626+		CHECK_ONLY
2627+	}
2628+	default:
2629+		context->hslot++;
2630+		context->cycles += slot_cycles;
2631+		return;
2632+	}
2633+}
2634+
2635+static void vdp_h32(vdp_context * context, uint32_t target_cycles)
2636+{
2637+	uint16_t address;
2638+	uint32_t mask;
2639+	uint32_t const slot_cycles = MCLKS_SLOT_H32;
2640+	switch(context->hslot)
2641+	{
2642+	for (;;)
2643+	{
2644+	case 133:
2645+		if (context->state == PREPARING) {
2646+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2647+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2648+			if (dst >= context->done_output) {
2649+				*dst = bg_color;
2650+			}
2651+			dst++;
2652+			if (dst >= context->done_output) {
2653+				*dst = bg_color;
2654+			}
2655+			external_slot(context);
2656+		} else {
2657+			render_sprite_cells(context);
2658+		}
2659+		CHECK_LIMIT
2660+	case 134:
2661+		if (context->state == PREPARING) {
2662+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2663+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2664+			if (dst >= context->done_output) {
2665+				*dst = bg_color;
2666+			}
2667+			dst++;
2668+			if (dst >= context->done_output) {
2669+				*dst = bg_color;
2670+			}
2671+			external_slot(context);
2672+		} else {
2673+			render_sprite_cells(context);
2674+		}
2675+		if (context->vcounter == context->inactive_start) {
2676+			context->hslot++;
2677+			context->cycles += slot_cycles;
2678+			return;
2679+		}
2680+		CHECK_LIMIT
2681+	//sprite attribute table scan starts
2682+	case 135:
2683+		if (context->state == PREPARING) {
2684+			uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2685+			uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2686+			for (int i = 0; i < (256+HORIZ_BORDER) - 2 * (context->hslot - BG_START_SLOT); i++)
2687+			{
2688+				if (dst >= context->done_output) {
2689+					*(dst++) = bg_color;
2690+				}
2691+			}
2692+		}
2693+		context->sprite_index = 0x80;
2694+		context->slot_counter = 0;
2695+		render_border_garbage(
2696+			context,
2697+			context->sprite_draw_list[context->cur_slot].address,
2698+			context->tmp_buf_b, context->buf_b_off,
2699+			context->col_1
2700+		);
2701+		render_sprite_cells(context);
2702+		scan_sprite_table(context->vcounter, context);
2703+		CHECK_LIMIT
2704+	SPRITE_RENDER_H32(136)
2705+	SPRITE_RENDER_H32(137)
2706+	SPRITE_RENDER_H32(138)
2707+	SPRITE_RENDER_H32(139)
2708+	SPRITE_RENDER_H32(140)
2709+	SPRITE_RENDER_H32(141)
2710+	SPRITE_RENDER_H32(142)
2711+	SPRITE_RENDER_H32(143)
2712+	SPRITE_RENDER_H32(144)
2713+	case 145:
2714+		external_slot(context);
2715+		CHECK_LIMIT
2716+	SPRITE_RENDER_H32(146)
2717+	SPRITE_RENDER_H32(147)
2718+	SPRITE_RENDER_H32(233)
2719+	SPRITE_RENDER_H32(234)
2720+	SPRITE_RENDER_H32(235)
2721+	//HSYNC start
2722+	SPRITE_RENDER_H32(236)
2723+	SPRITE_RENDER_H32(237)
2724+	SPRITE_RENDER_H32(238)
2725+	SPRITE_RENDER_H32(239)
2726+	SPRITE_RENDER_H32(240)
2727+	SPRITE_RENDER_H32(241)
2728+	SPRITE_RENDER_H32(242)
2729+	case 243:
2730+		if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
2731+			//TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
2732+			//Top Gear 2 has a very efficient HINT routine that can occassionally hit this slot with a VSRAM write
2733+			//Since CRAM-updatnig HINT routines seem to indicate that my HINT latency is perhaps slightly too high
2734+			//the most reasonable explanation is that vscroll is latched before this slot, but tests are needed
2735+			//to confirm that one way or another
2736+			context->vscroll_latch[0] = context->vsram[0];
2737+			context->vscroll_latch[1] = context->vsram[1];
2738+		}
2739+		external_slot(context);
2740+		//provides "garbage" for border when plane A selected
2741+		render_border_garbage(
2742+				context,
2743+				context->sprite_draw_list[context->cur_slot].address,
2744+				context->tmp_buf_a,
2745+				context->buf_a_off,
2746+				context->col_1
2747+			);
2748+		CHECK_LIMIT
2749+	case 244:
2750+		address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
2751+		mask = 0;
2752+		if (context->regs[REG_MODE_3] & 0x2) {
2753+			mask |= 0xF8;
2754+		}
2755+		if (context->regs[REG_MODE_3] & 0x1) {
2756+			mask |= 0x7;
2757+		}
2758+		render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
2759+		address += (context->vcounter & mask) * 4;
2760+		context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
2761+		context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
2762+		//printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
2763+		CHECK_LIMIT //provides "garbage" for border when plane A selected
2764+	SPRITE_RENDER_H32(245)
2765+	SPRITE_RENDER_H32(246)
2766+	SPRITE_RENDER_H32(247) //provides "garbage" for border when plane B selected
2767+	SPRITE_RENDER_H32(248) //provides "garbage" for border when plane B selected
2768+	//!HSYNC high
2769+	case 249:
2770+		read_map_scroll_a(0, context->vcounter, context);
2771+		CHECK_LIMIT
2772+	SPRITE_RENDER_H32(250)
2773+	case 251:
2774+		render_map_1(context);
2775+		scan_sprite_table(context->vcounter, context);//Just a guess
2776+		CHECK_LIMIT
2777+	case 252:
2778+		render_map_2(context);
2779+		scan_sprite_table(context->vcounter, context);//Just a guess
2780+		CHECK_LIMIT
2781+	case 253:
2782+		read_map_scroll_b(0, context->vcounter, context);
2783+		CHECK_LIMIT
2784+	case 254:
2785+		render_sprite_cells(context);
2786+		scan_sprite_table(context->vcounter, context);
2787+		CHECK_LIMIT
2788+	case 255:
2789+		render_map_3(context);
2790+		scan_sprite_table(context->vcounter, context);//Just a guess
2791+		CHECK_LIMIT
2792+	case 0:
2793+		render_map_output(context->vcounter, 0, context);
2794+		scan_sprite_table(context->vcounter, context);//Just a guess
2795+		//reverse context slot counter so it counts the number of sprite slots
2796+		//filled rather than the number of available slots
2797+		//context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
2798+		context->cur_slot = context->slot_counter;
2799+		context->sprite_draws = MAX_DRAWS_H32;
2800+		context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
2801+		CHECK_LIMIT
2802+	COLUMN_RENDER_BLOCK(2, 1)
2803+	COLUMN_RENDER_BLOCK(4, 9)
2804+	COLUMN_RENDER_BLOCK(6, 17)
2805+	COLUMN_RENDER_BLOCK_REFRESH(8, 25)
2806+	COLUMN_RENDER_BLOCK(10, 33)
2807+	COLUMN_RENDER_BLOCK(12, 41)
2808+	COLUMN_RENDER_BLOCK(14, 49)
2809+	COLUMN_RENDER_BLOCK_REFRESH(16, 57)
2810+	COLUMN_RENDER_BLOCK(18, 65)
2811+	COLUMN_RENDER_BLOCK(20, 73)
2812+	COLUMN_RENDER_BLOCK(22, 81)
2813+	COLUMN_RENDER_BLOCK_REFRESH(24, 89)
2814+	COLUMN_RENDER_BLOCK(26, 97)
2815+	COLUMN_RENDER_BLOCK(28, 105)
2816+	COLUMN_RENDER_BLOCK(30, 113)
2817+	COLUMN_RENDER_BLOCK_REFRESH(32, 121)
2818+	case 129:
2819+		external_slot(context);
2820+		CHECK_LIMIT
2821+	case 130: {
2822+		external_slot(context);
2823+		CHECK_LIMIT
2824+	}
2825+	//sprite render to line buffer starts
2826+	case 131:
2827+		context->cur_slot = MAX_DRAWS_H32-1;
2828+		memset(context->linebuf, 0, LINEBUF_SIZE);
2829+		render_border_garbage(
2830+			context,
2831+			context->sprite_draw_list[context->cur_slot].address,
2832+			context->tmp_buf_a, context->buf_a_off,
2833+			context->col_1
2834+		);
2835+		render_sprite_cells(context);
2836+		CHECK_LIMIT
2837+	case 132:
2838+		render_border_garbage(
2839+			context,
2840+			context->sprite_draw_list[context->cur_slot].address,
2841+			context->tmp_buf_a, context->buf_a_off + 8,
2842+			context->col_2
2843+		);
2844+		render_sprite_cells(context);
2845+		if (context->flags & FLAG_DMA_RUN) {
2846+			run_dma_src(context, -1);
2847+		}
2848+		context->hslot++;
2849+		context->cycles += slot_cycles;
2850+		vdp_advance_line(context);
2851+		CHECK_ONLY
2852+	}
2853+	default:
2854+		context->hslot++;
2855+		context->cycles += MCLKS_SLOT_H32;
2856+	}
2857+}
2858+
2859+static void vdp_h32_mode4(vdp_context * context, uint32_t target_cycles)
2860+{
2861+	uint16_t address;
2862+	uint32_t mask;
2863+	uint32_t const slot_cycles = MCLKS_SLOT_H32;
2864+	switch(context->hslot)
2865+	{
2866+	for (;;)
2867+	{
2868+	//sprite rendering starts
2869+	SPRITE_RENDER_H32_MODE4(137)
2870+	SPRITE_RENDER_H32_MODE4(143)
2871+	case 234:
2872+		external_slot(context);
2873+		CHECK_LIMIT
2874+	case 235:
2875+		external_slot(context);
2876+		CHECK_LIMIT
2877+	//!HSYNC low
2878+	case 236:
2879+		external_slot(context);
2880+		CHECK_LIMIT
2881+	case 237:
2882+		external_slot(context);
2883+		CHECK_LIMIT
2884+	case 238:
2885+		external_slot(context);
2886+		CHECK_LIMIT
2887+	SPRITE_RENDER_H32_MODE4(239)
2888+	SPRITE_RENDER_H32_MODE4(245)
2889+	case 251:
2890+		external_slot(context);
2891+		CHECK_LIMIT
2892+	case 252:
2893+		external_slot(context);
2894+		if (context->regs[REG_MODE_1] & BIT_HSCRL_LOCK && context->vcounter < 16) {
2895+			context->hscroll_a = 0;
2896+		} else {
2897+			context->hscroll_a = context->regs[REG_X_SCROLL];
2898+		}
2899+		CHECK_LIMIT
2900+	case 253:
2901+		context->sprite_index = 0;
2902+		context->slot_counter = MAX_DRAWS_H32_MODE4;
2903+		scan_sprite_table_mode4(context);
2904+		CHECK_LIMIT
2905+	case 254:
2906+		scan_sprite_table_mode4(context);
2907+		CHECK_LIMIT
2908+	case 255:
2909+		scan_sprite_table_mode4(context);
2910+		CHECK_LIMIT
2911+	case 0: {
2912+		scan_sprite_table_mode4(context);
2913+		uint32_t *dst = context->output;;
2914+		uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2915+		for (int i = 0; i < BORDER_LEFT-8; i++, dst++)
2916+		{
2917+			*dst = bgcolor;
2918+		}
2919+		context->done_output = dst;
2920+		CHECK_LIMIT
2921+	}
2922+	case 1:
2923+		scan_sprite_table_mode4(context);
2924+		CHECK_LIMIT
2925+	case 2:
2926+		scan_sprite_table_mode4(context);
2927+		CHECK_LIMIT
2928+	case 3:
2929+		scan_sprite_table_mode4(context);
2930+		CHECK_LIMIT
2931+	case 4: {
2932+		scan_sprite_table_mode4(context);
2933+		context->buf_a_off = 8;
2934+		memset(context->tmp_buf_a, 0, 8);
2935+		uint32_t *dst = context->output + BORDER_LEFT - 8;
2936+		uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2937+		for (int i = 0; i < 8; i++, dst++)
2938+		{
2939+			*dst = bgcolor;
2940+		}
2941+		context->done_output = dst;
2942+		CHECK_LIMIT
2943+	}
2944+	COLUMN_RENDER_BLOCK_MODE4(0, 5)
2945+	COLUMN_RENDER_BLOCK_MODE4(1, 9)
2946+	COLUMN_RENDER_BLOCK_MODE4(2, 13)
2947+	COLUMN_RENDER_BLOCK_MODE4(3, 17)
2948+	COLUMN_RENDER_BLOCK_MODE4(4, 21)
2949+	COLUMN_RENDER_BLOCK_MODE4(5, 25)
2950+	COLUMN_RENDER_BLOCK_MODE4(6, 29)
2951+	COLUMN_RENDER_BLOCK_MODE4(7, 33)
2952+	COLUMN_RENDER_BLOCK_MODE4(8, 37)
2953+	COLUMN_RENDER_BLOCK_MODE4(9, 41)
2954+	COLUMN_RENDER_BLOCK_MODE4(10, 45)
2955+	COLUMN_RENDER_BLOCK_MODE4(11, 49)
2956+	COLUMN_RENDER_BLOCK_MODE4(12, 53)
2957+	COLUMN_RENDER_BLOCK_MODE4(13, 57)
2958+	COLUMN_RENDER_BLOCK_MODE4(14, 61)
2959+	COLUMN_RENDER_BLOCK_MODE4(15, 65)
2960+	COLUMN_RENDER_BLOCK_MODE4(16, 69)
2961+	COLUMN_RENDER_BLOCK_MODE4(17, 73)
2962+	COLUMN_RENDER_BLOCK_MODE4(18, 77)
2963+	COLUMN_RENDER_BLOCK_MODE4(19, 81)
2964+	COLUMN_RENDER_BLOCK_MODE4(20, 85)
2965+	COLUMN_RENDER_BLOCK_MODE4(21, 89)
2966+	COLUMN_RENDER_BLOCK_MODE4(22, 93)
2967+	COLUMN_RENDER_BLOCK_MODE4(23, 97)
2968+	COLUMN_RENDER_BLOCK_MODE4(24, 101)
2969+	COLUMN_RENDER_BLOCK_MODE4(25, 105)
2970+	COLUMN_RENDER_BLOCK_MODE4(26, 109)
2971+	COLUMN_RENDER_BLOCK_MODE4(27, 113)
2972+	COLUMN_RENDER_BLOCK_MODE4(28, 117)
2973+	COLUMN_RENDER_BLOCK_MODE4(29, 121)
2974+	COLUMN_RENDER_BLOCK_MODE4(30, 125)
2975+	COLUMN_RENDER_BLOCK_MODE4(31, 129)
2976+	case 133:
2977+		external_slot(context);
2978+		CHECK_LIMIT
2979+	case 134:
2980+		external_slot(context);
2981+		CHECK_LIMIT
2982+	case 135:
2983+		external_slot(context);
2984+		CHECK_LIMIT
2985+	case 136: {
2986+		external_slot(context);
2987+		//set things up for sprite rendering in the next slot
2988+		memset(context->linebuf, 0, LINEBUF_SIZE);
2989+		context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1;
2990+		context->sprite_draws = MAX_DRAWS_H32_MODE4;
2991+		uint32_t *dst = context->output + BORDER_LEFT + 256;
2992+		uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2993+		for (int i = 0; i < 8; i++, dst++)
2994+		{
2995+			*dst = bgcolor;
2996+		}
2997+		context->done_output = dst;
2998+		CHECK_LIMIT
2999+	}}
3000+	default:
3001+		context->hslot++;
3002+		context->cycles += MCLKS_SLOT_H32;
3003+	}
3004+}
3005+
3006+static void inactive_test_output(vdp_context *context, uint8_t is_h40, uint8_t test_layer)
3007+{
3008+	uint8_t max_slot = is_h40 ? 169 : 136;
3009+	if (context->hslot > max_slot) {
3010+		return;
3011+	}
3012+	uint32_t *dst = context->output + (context->hslot >> 3) * SCROLL_BUFFER_DRAW;
3013+	int32_t len;
3014+	uint32_t src_off;
3015+	if (context->hslot) {
3016+		dst -= SCROLL_BUFFER_DRAW - BORDER_LEFT;
3017+		src_off = 0;
3018+		len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW;
3019+	} else {
3020+		src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT;
3021+		len = BORDER_LEFT;
3022+	}
3023+	uint8_t *src;
3024+	if (test_layer == 2) {
3025+		//plane A
3026+		src_off += context->buf_a_off + context->hscroll_a;
3027+		src = context->tmp_buf_a;
3028+	} else if (test_layer == 3){
3029+		//plane B
3030+		src_off += context->buf_b_off + context->hscroll_b;
3031+		src = context->tmp_buf_b;
3032+	} else {
3033+		//sprite layer
3034+		for (; len >=0; len--, dst++, src_off++)
3035+		{
3036+			*dst = context->colors[0];
3037+		}
3038+	}
3039+	for (; len >=0; len--, dst++, src_off++)
3040+	{
3041+		*dst = context->colors[src[src_off & SCROLL_BUFFER_MASK] & 0x3F];
3042+	}
3043+	context->done_output = dst;
3044+	context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3045+	context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3046+}
3047+
3048+static void check_switch_inactive(vdp_context *context, uint8_t is_h40)
3049+{
3050+	//technically the second hcounter check should be different for H40, but this is probably close enough for now
3051+	if (context->state == ACTIVE && context->vcounter == context->inactive_start && (context->hslot >= (is_h40 ? 167 : 135) || context->hslot < 133)) {
3052+		context->state = INACTIVE;
3053+	}
3054+}
3055+
3056+static void vdp_inactive(vdp_context *context, uint32_t target_cycles, uint8_t is_h40, uint8_t mode_5)
3057+{
3058+	uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest, latch_slot;
3059+	uint8_t index_reset_value, max_draws, max_sprites;
3060+	uint16_t vint_line, active_line;
3061+	uint32_t bg_color;
3062+	
3063+	if (mode_5) {
3064+		if (is_h40) {
3065+			latch_slot = 165;
3066+			buf_clear_slot = 163;
3067+			index_reset_slot = 167;
3068+			bg_end_slot = BG_START_SLOT + LINEBUF_SIZE/2;
3069+			max_draws = MAX_DRAWS-1;
3070+			max_sprites = MAX_SPRITES_LINE;
3071+			index_reset_value = 0x80;
3072+			vint_slot = VINT_SLOT_H40;
3073+			line_change = LINE_CHANGE_H40;
3074+			jump_start = 182;
3075+			jump_dest = 229;
3076+		} else {
3077+			bg_end_slot = BG_START_SLOT + (256+HORIZ_BORDER)/2;
3078+			max_draws = MAX_DRAWS_H32-1;
3079+			max_sprites = MAX_SPRITES_LINE_H32;
3080+			buf_clear_slot = 128;
3081+			index_reset_slot = 132;
3082+			index_reset_value = 0x80;
3083+			vint_slot = VINT_SLOT_H32;
3084+			line_change = LINE_CHANGE_H32;
3085+			jump_start = 147;
3086+			jump_dest = 233;
3087+			latch_slot = 243;
3088+		}
3089+		vint_line = context->inactive_start;
3090+		active_line = 0x1FF;
3091+		if (context->regs[REG_MODE_3] & BIT_VSCROLL) {
3092+			latch_slot = 220;
3093+		}
3094+	} else {
3095+		latch_slot = 220;
3096+		bg_end_slot = BG_START_SLOT + (256+HORIZ_BORDER)/2;
3097+		max_draws = MAX_DRAWS_H32_MODE4;
3098+		max_sprites = 8;
3099+		buf_clear_slot = 136;
3100+		index_reset_slot = 253;
3101+		index_reset_value = 0;
3102+		vint_line = context->inactive_start + 1;
3103+		vint_slot = VINT_SLOT_MODE4;
3104+		line_change = LINE_CHANGE_MODE4;
3105+		bg_color = render_map_color(0, 0, 0);
3106+		jump_start = 147;
3107+		jump_dest = 233;
3108+		if (context->regs[REG_MODE_1] & BIT_MODE_4) {
3109+			active_line = 0x1FF;
3110+		} else {
3111+			//never active unless either mode 4 or mode 5 is turned on
3112+			active_line = 0x200;
3113+		}
3114+	}
3115+	uint32_t *dst;
3116+	uint8_t *debug_dst;
3117+	if (
3118+		(
3119+			context->vcounter < context->inactive_start + context->border_bot 
3120+			|| context->vcounter >= 0x200 - context->border_top
3121+		) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot
3122+	) {
3123+		dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3124+		debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3125+	} else {
3126+		dst = NULL;
3127+	}
3128+		
3129+	if (
3130+		!dst && context->vcounter == context->inactive_start + context->border_bot
3131+		&& context->hslot >= line_change  && context->hslot < bg_end_slot
3132+	) {
3133+		dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3134+		debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3135+	}
3136+		
3137+	uint8_t test_layer = context->test_port >> 7 & 3;
3138+	if (test_layer) {
3139+		dst = NULL;
3140+	}
3141+	
3142+	while(context->cycles < target_cycles)
3143+	{
3144+		check_switch_inactive(context, is_h40);
3145+		if (context->hslot == BG_START_SLOT && !test_layer && (
3146+			context->vcounter < context->inactive_start + context->border_bot 
3147+			|| context->vcounter >= 0x200 - context->border_top
3148+		)) {
3149+			dst = context->output + (context->hslot - BG_START_SLOT) * 2;
3150+			debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3151+		} else if (context->hslot == bg_end_slot) {
3152+			advance_output_line(context);
3153+			dst = NULL;
3154+		}
3155+		//this will need some tweaking to properly interact with 128K mode, 
3156+		//but this should be good enough for now
3157+		context->serial_address += 1024;
3158+		if (test_layer) {
3159+			switch (context->hslot & 7)
3160+			{
3161+			case 3:
3162+				render_border_garbage(context, context->serial_address, context->tmp_buf_a, context->buf_a_off, context->col_1);
3163+				break;
3164+			case 4:
3165+				render_border_garbage(context, context->serial_address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
3166+				break;
3167+			case 7:
3168+				render_border_garbage(context, context->serial_address, context->tmp_buf_b, context->buf_b_off, context->col_1);
3169+				break;
3170+			case 0:
3171+				render_border_garbage(context, context->serial_address, context->tmp_buf_b, context->buf_b_off+8, context->col_2);
3172+				inactive_test_output(context, is_h40, test_layer);
3173+				break;
3174+			}
3175+		}
3176+		
3177+		if (context->hslot == buf_clear_slot) {
3178+			if (mode_5) {
3179+				context->cur_slot = max_draws;
3180+			} else {
3181+				context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1;
3182+				context->sprite_draws = MAX_DRAWS_H32_MODE4;
3183+			}
3184+			memset(context->linebuf, 0, LINEBUF_SIZE);
3185+		} else if (context->hslot == index_reset_slot) {
3186+			context->sprite_index = index_reset_value;
3187+			context->slot_counter = mode_5 ? 0 : max_sprites;
3188+		} else if (context->hslot == latch_slot) {
3189+			//it seems unlikely to me that vscroll actually gets latched when the display is off
3190+			//but it's the only straightforward way to reconcile what I'm seeing between Skitchin 
3191+			//(which seems to expect vscroll to be latched early) and the intro of Gunstar Heroes
3192+			//(which disables the display and ends up with garbage if vscroll is latched during that period)
3193+			//without it. Some more tests are definitely needed
3194+			context->vscroll_latch[0] = context->vsram[0];
3195+			context->vscroll_latch[1] = context->vsram[1];
3196+		} else if (context->vcounter == vint_line && context->hslot == vint_slot) {
3197+			context->flags2 |= FLAG2_VINT_PENDING;
3198+			context->pending_vint_start = context->cycles;
3199+		} else if (context->vcounter == context->inactive_start && context->hslot == 1 && (context->regs[REG_MODE_4] & BIT_INTERLACE)) {
3200+			context->flags2 ^= FLAG2_EVEN_FIELD;
3201+		}
3202+		
3203+		if (dst) {
3204+			if (mode_5) {
3205+				bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
3206+			} else if (context->regs[REG_MODE_1] & BIT_MODE_4) {
3207+				bg_color = context->colors[MODE4_OFFSET + 0x10 + (context->regs[REG_BG_COLOR] & 0xF)];
3208+			}
3209+			if (dst >= context->done_output) {
3210+				*(dst++) = bg_color;
3211+				*(debug_dst++) = DBG_SRC_BG;
3212+			} else {
3213+				dst++;
3214+				debug_dst++;
3215+			}
3216+			if (dst >= context->done_output) {
3217+				*(dst++) = bg_color;
3218+				*(debug_dst++) = DBG_SRC_BG;
3219+				context->done_output = dst;
3220+			} else {
3221+				dst++;
3222+				debug_dst++;
3223+			}
3224+			if (context->hslot == (bg_end_slot-1)) {
3225+				*(dst++) = bg_color;
3226+				*(debug_dst++) = DBG_SRC_BG;
3227+				context->done_output = dst;
3228+			}
3229+		}
3230+		
3231+		if (!is_refresh(context, context->hslot)) {
3232+			external_slot(context);
3233+			if (context->flags & FLAG_DMA_RUN && !is_refresh(context, context->hslot)) {
3234+				run_dma_src(context, context->hslot);
3235+			}
3236+		}
3237+		
3238+		if (is_h40) {
3239+			if (context->hslot >= HSYNC_SLOT_H40 && context->hslot < HSYNC_END_H40) {
3240+				context->cycles += h40_hsync_cycles[context->hslot - HSYNC_SLOT_H40];
3241+			} else {
3242+				context->cycles += MCLKS_SLOT_H40;
3243+			}
3244+		} else {
3245+			context->cycles += MCLKS_SLOT_H32;
3246+		}
3247+		if (context->hslot == jump_start) {
3248+			context->hslot = jump_dest;
3249+		} else {
3250+			context->hslot++;
3251+		}
3252+		if (context->hslot == line_change) {
3253+			vdp_advance_line(context);
3254+			if (context->vcounter == active_line) {
3255+				context->state = PREPARING;
3256+				return;
3257+			}
3258+		}
3259+	}
3260+}
3261+
3262+void vdp_run_context_full(vdp_context * context, uint32_t target_cycles)
3263+{
3264+	uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
3265+	uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
3266+	while(context->cycles < target_cycles)
3267+	{
3268+		check_switch_inactive(context, is_h40);
3269+		
3270+		if (is_active(context)) {
3271+			if (mode_5) {
3272+				if (is_h40) {
3273+					vdp_h40(context, target_cycles);
3274+				} else {
3275+					vdp_h32(context, target_cycles);
3276+				}
3277+			} else {
3278+				vdp_h32_mode4(context, target_cycles);
3279+			}
3280+		} else {
3281+			vdp_inactive(context, target_cycles, is_h40, mode_5);
3282+		}
3283+	}
3284+}
3285+
3286+void vdp_run_context(vdp_context *context, uint32_t target_cycles)
3287+{
3288+	//TODO: Deal with H40 hsync shenanigans
3289+	uint32_t slot_cyc = context->regs[REG_MODE_4] & BIT_H40 ? 15 : 19;
3290+	if (target_cycles < slot_cyc) {
3291+		//avoid overflow
3292+		return;
3293+	}
3294+	vdp_run_context_full(context, target_cycles - slot_cyc);
3295+}
3296+
3297+uint32_t vdp_run_to_vblank(vdp_context * context)
3298+{
3299+	uint32_t old_frame = context->frame;
3300+	while (context->frame == old_frame) {
3301+		vdp_run_context_full(context, context->cycles + MCLKS_LINE);
3302+	}
3303+	return context->cycles;
3304+}
3305+
3306+void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles)
3307+{
3308+	for(;;) {
3309+		uint32_t dmalen = (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L];
3310+		if (!dmalen) {
3311+			dmalen = 0x10000;
3312+		}
3313+		uint32_t min_dma_complete = dmalen * (context->regs[REG_MODE_4] & BIT_H40 ? 16 : 20);
3314+		if (
3315+			(context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_COPY 
3316+			|| (((context->cd & 0xF) == VRAM_WRITE) && !(context->regs[REG_MODE_2] & BIT_128K_VRAM))) {
3317+			//DMA copies take twice as long to complete since they require a read and a write
3318+			//DMA Fills and transfers to VRAM also take twice as long as it requires 2 writes for a single word
3319+			//unless 128KB mode is enabled
3320+			min_dma_complete *= 2;
3321+		}
3322+		min_dma_complete += context->cycles;
3323+		if (target_cycles < min_dma_complete) {
3324+			vdp_run_context_full(context, target_cycles);
3325+			return;
3326+		} else {
3327+			vdp_run_context_full(context, min_dma_complete);
3328+			if (!(context->flags & FLAG_DMA_RUN)) {
3329+				return;
3330+			}
3331+		}
3332+	}
3333+}
3334+
3335+static uint16_t get_ext_vcounter(vdp_context *context)
3336+{
3337+	uint16_t line= context->vcounter;
3338+	if (context->regs[REG_MODE_4] & BIT_INTERLACE) {
3339+		if (context->double_res) {
3340+			line <<= 1;
3341+		} else {
3342+			line &= 0x1FE;
3343+		}
3344+		if (line & 0x100) {
3345+			line |= 1;
3346+		}
3347+	}
3348+	return line << 8;
3349+}
3350+
3351+void vdp_latch_hv(vdp_context *context)
3352+{
3353+	context->hv_latch = context->hslot | get_ext_vcounter(context);
3354+}
3355+
3356+uint16_t vdp_hv_counter_read(vdp_context * context)
3357+{
3358+	if ((context->regs[REG_MODE_2] & BIT_MODE_5) && (context->regs[REG_MODE_1] & BIT_HVC_LATCH)) {
3359+		return context->hv_latch;
3360+	}
3361+	uint16_t hv;
3362+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3363+		hv = context->hslot;
3364+	} else {
3365+		hv = context->hv_latch & 0xFF;
3366+	}
3367+	hv |= get_ext_vcounter(context);
3368+	
3369+	return hv;
3370+}
3371+
3372+int vdp_control_port_write(vdp_context * context, uint16_t value)
3373+{
3374+	//printf("control port write: %X at %d\n", value, context->cycles);
3375+	if (context->flags & FLAG_DMA_RUN) {
3376+		return -1;
3377+	}
3378+	if (context->flags & FLAG_PENDING) {
3379+		context->address = (context->address & 0x3FFF) | (value << 14 & 0x1C000);
3380+		//It seems like the DMA enable bit doesn't so much enable DMA so much 
3381+		//as it enables changing CD5 from control port writes
3382+		uint8_t preserve = (context->regs[REG_MODE_2] & BIT_DMA_ENABLE) ? 0x3 : 0x23;
3383+		context->cd = (context->cd & preserve) | ((value >> 2) & ~preserve & 0xFF);
3384+		context->flags &= ~FLAG_PENDING;
3385+		//Should these be taken care of here or after the first write?
3386+		context->flags &= ~FLAG_READ_FETCHED;
3387+		context->flags2 &= ~FLAG2_READ_PENDING;
3388+		//printf("New Address: %X, New CD: %X\n", context->address, context->cd);
3389+		if (context->cd & 0x20) {
3390+			//
3391+			if((context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) {
3392+				//DMA copy or 68K -> VDP, transfer starts immediately
3393+				//printf("DMA start (length: %X) at cycle %d, frame: %d, vcounter: %d, hslot: %d\n", (context->regs[REG_DMALEN_H] << 8) | context->regs[REG_DMALEN_L], context->cycles, context->frame, context->vcounter, context->hslot);
3394+				if (!(context->regs[REG_DMASRC_H] & 0x80)) {
3395+					//printf("DMA Address: %X, New CD: %X, Source: %X, Length: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_H] << 17) | (context->regs[REG_DMASRC_M] << 9) | (context->regs[REG_DMASRC_L] << 1), context->regs[REG_DMALEN_H] << 8 | context->regs[REG_DMALEN_L]);
3396+					//68K -> VDP DMA takes a few slots to actually start reading even though it acquires the bus immediately
3397+					//logic analyzer captures made it seem like the proper value is 4 slots, but that seems to cause trouble with the Nemesis' FIFO Wait State test
3398+					//only captures are from a direct color DMA demo which will generally start DMA at a very specific point in display so other values are plausible
3399+					//sticking with 3 slots for now until I can do some more captures
3400+					vdp_run_context_full(context, context->cycles + 12 * ((context->regs[REG_MODE_2] & BIT_MODE_5) && (context->regs[REG_MODE_4] & BIT_H40) ? 4 : 5));
3401+					context->flags |= FLAG_DMA_RUN;
3402+					return 1;
3403+				} else {
3404+					context->flags |= FLAG_DMA_RUN;
3405+					//printf("DMA Copy Address: %X, New CD: %X, Source: %X\n", context->address, context->cd, (context->regs[REG_DMASRC_M] << 8) | context->regs[REG_DMASRC_L]);
3406+				}
3407+			} else {
3408+				//printf("DMA Fill Address: %X, New CD: %X\n", context->address, context->cd);
3409+			}
3410+		}
3411+	} else {
3412+		uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5;
3413+		context->address = (context->address &0xC000) | (value & 0x3FFF);
3414+		context->cd = (context->cd & 0x3C) | (value >> 14);
3415+		if ((value & 0xC000) == 0x8000) {
3416+			//Register write
3417+			uint8_t reg = (value >> 8) & 0x1F;
3418+			if (reg < (mode_5 ? VDP_REGS : 0xB)) {
3419+				//printf("register %d set to %X\n", reg, value & 0xFF);
3420+				if (reg == REG_MODE_1 && (value & BIT_HVC_LATCH) && !(context->regs[reg] & BIT_HVC_LATCH)) {
3421+					vdp_latch_hv(context);
3422+				}
3423+				if (reg == REG_BG_COLOR) {
3424+					value &= 0x3F;
3425+				}
3426+				/*if (reg == REG_MODE_4 && ((value ^ context->regs[reg]) & BIT_H40)) {
3427+					printf("Mode changed from H%d to H%d @ %d, frame: %d\n", context->regs[reg] & BIT_H40 ? 40 : 32, value & BIT_H40 ? 40 : 32, context->cycles, context->frame);
3428+				}*/
3429+				context->regs[reg] = value;
3430+				if (reg == REG_MODE_4) {
3431+					context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES);
3432+					if (!context->double_res) {
3433+						context->flags2 &= ~FLAG2_EVEN_FIELD;
3434+					}
3435+				}
3436+				if (reg == REG_MODE_1 || reg == REG_MODE_2 || reg == REG_MODE_4) {
3437+					update_video_params(context);
3438+				}
3439+			}
3440+		} else if (mode_5) {
3441+			context->flags |= FLAG_PENDING;
3442+			//Should these be taken care of here or after the second write?
3443+			//context->flags &= ~FLAG_READ_FETCHED;
3444+			//context->flags2 &= ~FLAG2_READ_PENDING;
3445+		} else {
3446+			context->flags &= ~FLAG_READ_FETCHED;
3447+			context->flags2 &= ~FLAG2_READ_PENDING;
3448+		}
3449+	}
3450+	return 0;
3451+}
3452+
3453+void vdp_control_port_write_pbc(vdp_context *context, uint8_t value)
3454+{
3455+	if (context->flags2 & FLAG2_BYTE_PENDING) {
3456+		uint16_t full_val = value << 8 | context->pending_byte;
3457+		context->flags2 &= ~FLAG2_BYTE_PENDING;
3458+		//TODO: Deal with fact that Vbus->VDP DMA doesn't do anything in PBC mode
3459+		vdp_control_port_write(context, full_val);
3460+		if (context->cd == VRAM_READ) {
3461+			context->cd = VRAM_READ8;
3462+		}
3463+	} else {
3464+		context->pending_byte = value;
3465+		context->flags2 |= FLAG2_BYTE_PENDING;
3466+	}
3467+}
3468+
3469+int vdp_data_port_write(vdp_context * context, uint16_t value)
3470+{
3471+	//printf("data port write: %X at %d\n", value, context->cycles);
3472+	if (context->flags & FLAG_DMA_RUN && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) != DMA_FILL) {
3473+		return -1;
3474+	}
3475+	if (context->flags & FLAG_PENDING) {
3476+		context->flags &= ~FLAG_PENDING;
3477+		//Should these be cleared here?
3478+		context->flags &= ~FLAG_READ_FETCHED;
3479+		context->flags2 &= ~FLAG2_READ_PENDING;
3480+	}
3481+	/*if (context->fifo_cur == context->fifo_end) {
3482+		printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
3483+	}*/
3484+	if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
3485+		context->flags &= ~FLAG_DMA_RUN;
3486+	}
3487+	while (context->fifo_write == context->fifo_read) {
3488+		vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
3489+	}
3490+	fifo_entry * cur = context->fifo + context->fifo_write;
3491+	cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
3492+	cur->address = context->address;
3493+	cur->value = value;
3494+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3495+		cur->cd = context->cd;
3496+	} else {
3497+		cur->cd = (context->cd & 2) | 1;
3498+	}
3499+	cur->partial = 0;
3500+	if (context->fifo_read < 0) {
3501+		context->fifo_read = context->fifo_write;
3502+	}
3503+	context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
3504+	increment_address(context);
3505+	return 0;
3506+}
3507+
3508+void vdp_data_port_write_pbc(vdp_context * context, uint8_t value)
3509+{
3510+	if (context->flags & FLAG_PENDING) {
3511+		context->flags &= ~FLAG_PENDING;
3512+		//Should these be cleared here?
3513+		context->flags &= ~FLAG_READ_FETCHED;
3514+		context->flags2 &= ~FLAG2_READ_PENDING;
3515+	}
3516+	context->flags2 &= ~FLAG2_BYTE_PENDING;
3517+	/*if (context->fifo_cur == context->fifo_end) {
3518+		printf("FIFO full, waiting for space before next write at cycle %X\n", context->cycles);
3519+	}*/
3520+	if (context->cd & 0x20 && (context->regs[REG_DMASRC_H] & DMA_TYPE_MASK) == DMA_FILL) {
3521+		context->flags &= ~FLAG_DMA_RUN;
3522+	}
3523+	while (context->fifo_write == context->fifo_read) {
3524+		vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
3525+	}
3526+	fifo_entry * cur = context->fifo + context->fifo_write;
3527+	cur->cycle = context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20)*FIFO_LATENCY;
3528+	cur->address = context->address;
3529+	cur->value = value;
3530+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3531+		cur->cd = context->cd;
3532+	} else {
3533+		cur->cd = (context->cd & 2) | 1;
3534+	}
3535+	cur->partial = 3;
3536+	if (context->fifo_read < 0) {
3537+		context->fifo_read = context->fifo_write;
3538+	}
3539+	context->fifo_write = (context->fifo_write + 1) & (FIFO_SIZE-1);
3540+	increment_address(context);
3541+}
3542+
3543+void vdp_test_port_write(vdp_context * context, uint16_t value)
3544+{
3545+	context->test_port = value;
3546+}
3547+
3548+uint16_t vdp_control_port_read(vdp_context * context)
3549+{
3550+	context->flags &= ~FLAG_PENDING;
3551+	context->flags2 &= ~FLAG2_BYTE_PENDING;
3552+	//Bits 15-10 are not fixed like Charles MacDonald's doc suggests, but instead open bus values that reflect 68K prefetch
3553+	uint16_t value = context->system->get_open_bus_value(context->system) & 0xFC00;
3554+	if (context->fifo_read < 0) {
3555+		value |= 0x200;
3556+	}
3557+	if (context->fifo_read == context->fifo_write) {
3558+		value |= 0x100;
3559+	}
3560+	if (context->flags2 & FLAG2_VINT_PENDING) {
3561+		value |= 0x80;
3562+	}
3563+	if (context->flags & FLAG_DOT_OFLOW) {
3564+		value |= 0x40;
3565+		context->flags &= ~FLAG_DOT_OFLOW;
3566+	}
3567+	if (context->flags2 & FLAG2_SPRITE_COLLIDE) {
3568+		value |= 0x20;
3569+		context->flags2 &= ~FLAG2_SPRITE_COLLIDE;
3570+	}
3571+	if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) {
3572+		value |= 0x10;
3573+	}
3574+	uint32_t slot = context->hslot;
3575+	if (!is_active(context)) {
3576+		value |= 0x8;
3577+	}
3578+	if (context->regs[REG_MODE_4] & BIT_H40) {
3579+		if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) {
3580+			value |= 0x4;
3581+		}
3582+	} else {
3583+		if (slot < HBLANK_END_H32 || slot > HBLANK_START_H32) {
3584+			value |= 0x4;
3585+		}
3586+	}
3587+	if (context->cd & 0x20) {
3588+		value |= 0x2;
3589+	}
3590+	if (context->flags2 & FLAG2_REGION_PAL) {
3591+		value |= 0x1;
3592+	}
3593+	//printf("status read at cycle %d returned %X\n", context->cycles, value);
3594+	return value;
3595+}
3596+
3597+uint16_t vdp_data_port_read(vdp_context * context)
3598+{
3599+	if (context->flags & FLAG_PENDING) {
3600+		context->flags &= ~FLAG_PENDING;
3601+		//Should these be cleared here?
3602+		context->flags &= ~FLAG_READ_FETCHED;
3603+		context->flags2 &= ~FLAG2_READ_PENDING;
3604+	}
3605+	if (context->cd & 1) {
3606+		warning("Read from VDP data port while writes are configured, CPU is now frozen. VDP Address: %X, CD: %X\n", context->address, context->cd);
3607+	}
3608+	while (!(context->flags & FLAG_READ_FETCHED)) {
3609+		vdp_run_context_full(context, context->cycles + ((context->regs[REG_MODE_4] & BIT_H40) ? 16 : 20));
3610+	}
3611+	context->flags &= ~FLAG_READ_FETCHED;
3612+	return context->prefetch;
3613+}
3614+
3615+uint8_t vdp_data_port_read_pbc(vdp_context * context)
3616+{
3617+	context->flags &= ~(FLAG_PENDING | FLAG_READ_FETCHED);
3618+	context->flags2 &= ~FLAG2_BYTE_PENDING;
3619+		
3620+	context->cd = VRAM_READ8;
3621+	return context->prefetch;
3622+}
3623+
3624+uint16_t vdp_test_port_read(vdp_context * context)
3625+{
3626+	//TODO: Find out what actually gets returned here
3627+	return context->test_port;
3628+}
3629+
3630+void vdp_adjust_cycles(vdp_context * context, uint32_t deduction)
3631+{
3632+	context->cycles -= deduction;
3633+	if (context->pending_vint_start >= deduction) {
3634+		context->pending_vint_start -= deduction;
3635+	} else {
3636+		context->pending_vint_start = 0;
3637+	}
3638+	if (context->pending_hint_start >= deduction) {
3639+		context->pending_hint_start -= deduction;
3640+	} else {
3641+		context->pending_hint_start = 0;
3642+	}
3643+	if (context->fifo_read >= 0) {
3644+		int32_t idx = context->fifo_read;
3645+		do {
3646+			if (context->fifo[idx].cycle >= deduction) {
3647+				context->fifo[idx].cycle -= deduction;
3648+			} else {
3649+				context->fifo[idx].cycle = 0;
3650+			}
3651+			idx = (idx+1) & (FIFO_SIZE-1);
3652+		} while(idx != context->fifo_write);
3653+	}
3654+}
3655+
3656+static uint32_t vdp_cycles_hslot_wrap_h40(vdp_context * context)
3657+{
3658+	if (context->hslot < 183) {
3659+		return MCLKS_LINE - context->hslot * MCLKS_SLOT_H40;
3660+	} else if (context->hslot < HSYNC_END_H40) {
3661+		uint32_t before_hsync = context->hslot < HSYNC_SLOT_H40 ? (HSYNC_SLOT_H40 - context->hslot) * MCLKS_SLOT_H40 : 0;
3662+		uint32_t hsync = 0;
3663+		for (int i = context->hslot <= HSYNC_SLOT_H40 ? 0 : context->hslot - HSYNC_SLOT_H40; i < sizeof(h40_hsync_cycles)/sizeof(uint32_t); i++)
3664+		{
3665+			hsync += h40_hsync_cycles[i];
3666+		}
3667+		uint32_t after_hsync = (256- HSYNC_END_H40) * MCLKS_SLOT_H40;
3668+		return before_hsync + hsync + after_hsync;
3669+	} else {
3670+		return (256-context->hslot) * MCLKS_SLOT_H40;
3671+	}
3672+}
3673+
3674+static uint32_t vdp_cycles_next_line(vdp_context * context)
3675+{
3676+	if (context->regs[REG_MODE_4] & BIT_H40) {
3677+		//TODO: Handle "illegal" Mode 4/H40 combo
3678+		if (context->hslot < LINE_CHANGE_H40) {
3679+			return (LINE_CHANGE_H40 - context->hslot) * MCLKS_SLOT_H40;
3680+		} else {
3681+			return vdp_cycles_hslot_wrap_h40(context) + LINE_CHANGE_H40 * MCLKS_SLOT_H40;
3682+		}
3683+	} else {
3684+		if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3685+			if (context->hslot < LINE_CHANGE_H32) {
3686+				return (LINE_CHANGE_H32 - context->hslot) * MCLKS_SLOT_H32;
3687+			} else if (context->hslot < 148) {
3688+				return MCLKS_LINE - (context->hslot - LINE_CHANGE_H32) * MCLKS_SLOT_H32;
3689+			} else {
3690+				return (256-context->hslot + LINE_CHANGE_H32) * MCLKS_SLOT_H32;
3691+			}
3692+		} else {
3693+			if (context->hslot < 148) {
3694+				return (148 - context->hslot + LINE_CHANGE_MODE4 - 233) * MCLKS_SLOT_H32;
3695+			} else if (context->hslot < LINE_CHANGE_MODE4) {
3696+				return (LINE_CHANGE_MODE4 - context->hslot) * MCLKS_SLOT_H32;
3697+			} else {
3698+				return MCLKS_LINE - (context->hslot - LINE_CHANGE_MODE4) * MCLKS_SLOT_H32;
3699+			}
3700+		}
3701+	}
3702+}
3703+
3704+static void get_jump_params(vdp_context *context, uint32_t *jump_start, uint32_t *jump_dst)
3705+{
3706+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3707+		if (context->flags2 & FLAG2_REGION_PAL) {
3708+			if (context->regs[REG_MODE_2] & BIT_PAL) {
3709+				*jump_start = 0x10B;
3710+				*jump_dst = 0x1D2;
3711+			} else {
3712+				*jump_start = 0x103;
3713+				*jump_dst = 0x1CA;
3714+			}
3715+		} else {
3716+			if (context->regs[REG_MODE_2] & BIT_PAL) {
3717+				*jump_start = 0x100;
3718+				*jump_dst = 0x1FA;
3719+			} else {
3720+				*jump_start = 0xEB;
3721+				*jump_dst = 0x1E5;
3722+			}
3723+		}
3724+	} else {
3725+		*jump_start = 0xDB;
3726+		*jump_dst = 0x1D5;
3727+	}
3728+}
3729+
3730+static uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target)
3731+{
3732+	uint32_t jump_start, jump_dst;
3733+	get_jump_params(context, &jump_start, &jump_dst);
3734+	uint32_t lines;
3735+	if (context->vcounter < target) {
3736+		if (target < jump_start || context->vcounter > jump_start) {
3737+			lines = target - context->vcounter;
3738+		} else {
3739+			lines = jump_start - context->vcounter + target - jump_dst;
3740+		}
3741+	} else {
3742+		if (context->vcounter < jump_start) {
3743+			lines = jump_start - context->vcounter + 512 - jump_dst;
3744+		} else {
3745+			lines = 512 - context->vcounter;
3746+		}
3747+		if (target < jump_start) {
3748+			lines += target;
3749+		} else {
3750+			lines += jump_start + target - jump_dst;
3751+		}
3752+	}
3753+	return MCLKS_LINE * (lines - 1) + vdp_cycles_next_line(context);
3754+}
3755+
3756+uint32_t vdp_cycles_to_frame_end(vdp_context * context)
3757+{
3758+	return context->cycles + vdp_cycles_to_line(context, context->inactive_start);
3759+}
3760+
3761+uint32_t vdp_next_hint(vdp_context * context)
3762+{
3763+	if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) {
3764+		return 0xFFFFFFFF;
3765+	}
3766+	if (context->flags2 & FLAG2_HINT_PENDING) {
3767+		return context->pending_hint_start;
3768+	}
3769+	uint32_t hint_line;
3770+	if (context->state != ACTIVE) {
3771+		hint_line = context->regs[REG_HINT];
3772+		if (hint_line > context->inactive_start) {
3773+			return 0xFFFFFFFF;
3774+		}
3775+	} else {
3776+		hint_line = context->vcounter + context->hint_counter + 1;
3777+		if (context->vcounter < context->inactive_start) {
3778+			if (hint_line > context->inactive_start) {
3779+				hint_line = context->regs[REG_HINT];
3780+				if (hint_line > context->inactive_start) {
3781+					return 0xFFFFFFFF;
3782+				}
3783+				if (hint_line >= context->vcounter) {
3784+					//Next interrupt is for a line in the next frame that
3785+					//is higher than the line we're on now so just passing
3786+					//that line number to vdp_cycles_to_line will yield the wrong
3787+					//result
3788+					return context->cycles + vdp_cycles_to_line(context,  0) + hint_line * MCLKS_LINE;
3789+				}
3790+			}
3791+		} else {
3792+			uint32_t jump_start, jump_dst;
3793+			get_jump_params(context, &jump_start, &jump_dst);
3794+			if (hint_line >= jump_start && context->vcounter < jump_dst) {
3795+				hint_line = (hint_line + jump_dst - jump_start) & 0x1FF;
3796+			}
3797+			if (hint_line < context->vcounter && hint_line > context->inactive_start) {
3798+				return 0xFFFFFFFF;
3799+			}
3800+		}
3801+	}
3802+	return context->cycles + vdp_cycles_to_line(context, hint_line);
3803+}
3804+
3805+static uint32_t vdp_next_vint_real(vdp_context * context)
3806+{
3807+	if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) {
3808+		return 0xFFFFFFFF;
3809+	}
3810+	if (context->flags2 & FLAG2_VINT_PENDING) {
3811+		return context->pending_vint_start;
3812+	}
3813+
3814+
3815+	return vdp_next_vint_z80(context);
3816+}
3817+
3818+uint32_t vdp_next_vint(vdp_context *context)
3819+{
3820+	uint32_t ret = vdp_next_vint_real(context);
3821+#ifdef TIMING_DEBUG
3822+	static uint32_t last = 0xFFFFFFFF;
3823+	if (last != ret) {
3824+		printf("vdp_next_vint is %d at frame %d, line %d, hslot %d\n", ret, context->frame, context->vcounter, context->hslot);
3825+	}
3826+	last = ret;
3827+#endif
3828+	return ret;
3829+}
3830+
3831+uint32_t vdp_next_vint_z80(vdp_context * context)
3832+{
3833+	uint16_t vint_line = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->inactive_start : context->inactive_start + 1;
3834+	if (context->vcounter == vint_line) {
3835+		if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3836+			if (context->regs[REG_MODE_4] & BIT_H40) {
3837+				if (context->hslot >= LINE_CHANGE_H40 || context->hslot <= VINT_SLOT_H40) {
3838+					uint32_t cycles = context->cycles;
3839+					if (context->hslot >= LINE_CHANGE_H40) {
3840+						if (context->hslot < 183) {
3841+							cycles += (183 - context->hslot) * MCLKS_SLOT_H40;
3842+						}
3843+						
3844+						if (context->hslot < HSYNC_SLOT_H40) {
3845+							cycles += (HSYNC_SLOT_H40 - (context->hslot >= 229 ? context->hslot : 229)) * MCLKS_SLOT_H40;
3846+						}
3847+						for (int slot = context->hslot <= HSYNC_SLOT_H40 ? HSYNC_SLOT_H40 : context->hslot; slot < HSYNC_END_H40; slot++ )
3848+						{
3849+							cycles += h40_hsync_cycles[slot - HSYNC_SLOT_H40];
3850+						}
3851+						cycles += (256 - (context->hslot > HSYNC_END_H40 ? context->hslot : HSYNC_END_H40)) * MCLKS_SLOT_H40;
3852+					}
3853+					
3854+					cycles += (VINT_SLOT_H40 - (context->hslot >= LINE_CHANGE_H40 ? 0 : context->hslot)) * MCLKS_SLOT_H40;
3855+					return cycles;
3856+				}
3857+			} else {
3858+				if (context->hslot >= LINE_CHANGE_H32 || context->hslot <= VINT_SLOT_H32) {
3859+					if (context->hslot <= VINT_SLOT_H32) {
3860+						return context->cycles + (VINT_SLOT_H32 - context->hslot) * MCLKS_SLOT_H32;
3861+					} else if (context->hslot < 233) {
3862+						return context->cycles + (VINT_SLOT_H32 + 256 - 233 + 148 - context->hslot) * MCLKS_SLOT_H32;
3863+					} else {
3864+						return context->cycles + (VINT_SLOT_H32 + 256 - context->hslot) * MCLKS_SLOT_H32;
3865+					}
3866+				}
3867+			}
3868+		} else {
3869+			if (context->hslot >= LINE_CHANGE_MODE4) {
3870+				return context->cycles + (VINT_SLOT_MODE4 + 256 - context->hslot) * MCLKS_SLOT_H32;
3871+			}
3872+			if (context->hslot <= VINT_SLOT_MODE4) {
3873+				return context->cycles + (VINT_SLOT_MODE4 - context->hslot) * MCLKS_SLOT_H32;
3874+			}
3875+		}
3876+	}
3877+	int32_t cycles_to_vint = vdp_cycles_to_line(context, vint_line);
3878+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3879+		if (context->regs[REG_MODE_4] & BIT_H40) {
3880+			cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 - VINT_SLOT_H40) * MCLKS_SLOT_H40;
3881+		} else {
3882+			cycles_to_vint += (VINT_SLOT_H32 + 256 - 233 + 148 - LINE_CHANGE_H32) * MCLKS_SLOT_H32;
3883+		}
3884+	} else {
3885+		cycles_to_vint += (256 - LINE_CHANGE_MODE4 + VINT_SLOT_MODE4) * MCLKS_SLOT_H32;
3886+	}
3887+	return context->cycles + cycles_to_vint;
3888+}
3889+
3890+uint32_t vdp_next_nmi(vdp_context *context)
3891+{
3892+	if (!(context->flags2 & FLAG2_PAUSE)) {
3893+		return 0xFFFFFFFF;
3894+	}
3895+	return context->cycles + vdp_cycles_to_line(context, 0x1FF);
3896+}
3897+
3898+void vdp_pbc_pause(vdp_context *context)
3899+{
3900+	context->flags2 |= FLAG2_PAUSE;
3901+}
3902+
3903+void vdp_int_ack(vdp_context * context)
3904+{
3905+	//CPU interrupt acknowledge is only used in Mode 5
3906+	if (context->regs[REG_MODE_2] & BIT_MODE_5) {
3907+		//Apparently the VDP interrupt controller is not very smart
3908+		//Instead of paying attention to what interrupt is being acknowledged it just 
3909+		//clears the pending flag for whatever interrupt it is currently asserted
3910+		//which may be different from the interrupt it was asserting when the 68k
3911+		//started the interrupt process. The window for this is narrow and depends
3912+		//on the latency between the int enable register write and the interrupt being
3913+		//asserted, but Fatal Rewind depends on this due to some buggy code
3914+		if ((context->flags2 & FLAG2_VINT_PENDING) && (context->regs[REG_MODE_2] & BIT_VINT_EN)) {
3915+			context->flags2 &= ~FLAG2_VINT_PENDING;
3916+		} else if((context->flags2 & FLAG2_HINT_PENDING) && (context->regs[REG_MODE_1] & BIT_HINT_EN)) {
3917+			context->flags2 &= ~FLAG2_HINT_PENDING;
3918+		}
3919+	}
3920+}
3921+
3922+void vdp_serialize(vdp_context *context, serialize_buffer *buf)
3923+{
3924+	save_int8(buf, VRAM_SIZE / 1024);//VRAM size in KB, needed for future proofing
3925+	save_buffer8(buf, context->vdpmem, VRAM_SIZE);
3926+	save_buffer16(buf, context->cram, CRAM_SIZE);
3927+	save_buffer16(buf, context->vsram, VSRAM_SIZE);
3928+	save_buffer8(buf, context->sat_cache, SAT_CACHE_SIZE);
3929+	for (int i = 0; i <= REG_DMASRC_H; i++)
3930+	{
3931+		save_int8(buf, context->regs[i]);
3932+	}
3933+	save_int32(buf, context->address);
3934+	save_int32(buf, context->serial_address);
3935+	save_int8(buf, context->cd);
3936+	uint8_t fifo_size;
3937+	if (context->fifo_read < 0) {
3938+		fifo_size = 0;
3939+	} else if (context->fifo_write > context->fifo_read) {
3940+		fifo_size = context->fifo_write - context->fifo_read;
3941+	} else {
3942+		fifo_size = context->fifo_write + FIFO_SIZE - context->fifo_read;
3943+	}
3944+	save_int8(buf, fifo_size);
3945+	for (int i = 0, cur = context->fifo_read; i < fifo_size; i++)
3946+	{
3947+		fifo_entry *entry = context->fifo + cur;
3948+		cur = (cur + 1) & (FIFO_SIZE - 1);
3949+		save_int32(buf, entry->cycle);
3950+		save_int32(buf, entry->address);
3951+		save_int16(buf, entry->value);
3952+		save_int8(buf, entry->cd);
3953+		save_int8(buf, entry->partial);
3954+	}
3955+	//FIXME: Flag bits should be rearranged for maximum correspondence to status reg
3956+	save_int16(buf, context->flags2 << 8 | context->flags);
3957+	save_int32(buf, context->frame);
3958+	save_int16(buf, context->vcounter);
3959+	save_int8(buf, context->hslot);
3960+	save_int16(buf, context->hv_latch);
3961+	save_int8(buf, context->state);
3962+	save_int16(buf, context->hscroll_a);
3963+	save_int16(buf, context->hscroll_b);
3964+	save_int16(buf, context->vscroll_latch[0]);
3965+	save_int16(buf, context->vscroll_latch[1]);
3966+	save_int16(buf, context->col_1);
3967+	save_int16(buf, context->col_2);
3968+	save_int16(buf, context->test_port);
3969+	save_buffer8(buf, context->tmp_buf_a, SCROLL_BUFFER_SIZE);
3970+	save_buffer8(buf, context->tmp_buf_b, SCROLL_BUFFER_SIZE);
3971+	save_int8(buf, context->buf_a_off);
3972+	save_int8(buf, context->buf_b_off);
3973+	//FIXME: Sprite rendering state is currently a mess
3974+	save_int8(buf, context->sprite_index);
3975+	save_int8(buf, context->sprite_draws);
3976+	save_int8(buf, context->slot_counter);
3977+	save_int8(buf, context->cur_slot);
3978+	for (int i = 0; i < MAX_DRAWS; i++)
3979+	{
3980+		sprite_draw *draw = context->sprite_draw_list + i;
3981+		save_int16(buf, draw->address);
3982+		save_int16(buf, draw->x_pos);
3983+		save_int8(buf, draw->pal_priority);
3984+		save_int8(buf, draw->h_flip);
3985+	}
3986+	for (int i = 0; i < MAX_SPRITES_LINE; i++)
3987+	{
3988+		sprite_info *info = context->sprite_info_list + i;
3989+		save_int8(buf, info->size);
3990+		save_int8(buf, info->index);
3991+		save_int16(buf, info->y);
3992+	}
3993+	save_buffer8(buf, context->linebuf, LINEBUF_SIZE);
3994+	
3995+	save_int32(buf, context->cycles);
3996+	save_int32(buf, context->pending_vint_start);
3997+	save_int32(buf, context->pending_hint_start);
3998+}
3999+
4000+void vdp_deserialize(deserialize_buffer *buf, void *vcontext)
4001+{
4002+	vdp_context *context = vcontext;
4003+	uint8_t vramk = load_int8(buf);
4004+	load_buffer8(buf, context->vdpmem, (vramk * 1024) <= VRAM_SIZE ? vramk * 1024 : VRAM_SIZE);
4005+	if ((vramk * 1024) > VRAM_SIZE) {
4006+		buf->cur_pos += (vramk * 1024) - VRAM_SIZE;
4007+	}
4008+	load_buffer16(buf, context->cram, CRAM_SIZE);
4009+	for (int i = 0; i < CRAM_SIZE; i++)
4010+	{
4011+		update_color_map(context, i, context->cram[i]);
4012+	}
4013+	load_buffer16(buf, context->vsram, VSRAM_SIZE);
4014+	load_buffer8(buf, context->sat_cache, SAT_CACHE_SIZE);
4015+	for (int i = 0; i <= REG_DMASRC_H; i++)
4016+	{
4017+		context->regs[i] = load_int8(buf);
4018+	}
4019+	context->address = load_int32(buf);
4020+	context->serial_address = load_int32(buf);
4021+	context->cd = load_int8(buf);
4022+	uint8_t fifo_size = load_int8(buf);
4023+	if (fifo_size > FIFO_SIZE) {
4024+		fatal_error("Invalid fifo size %d", fifo_size);
4025+	}
4026+	if (fifo_size) {
4027+		context->fifo_read = 0;
4028+		context->fifo_write = fifo_size & (FIFO_SIZE - 1);
4029+		for (int i = 0; i < fifo_size; i++)
4030+		{
4031+			fifo_entry *entry = context->fifo + i;
4032+			entry->cycle = load_int32(buf);
4033+			entry->address = load_int32(buf);
4034+			entry->value = load_int16(buf);
4035+			entry->cd = load_int8(buf);
4036+			entry->partial = load_int8(buf);
4037+		}
4038+	} else {
4039+		context->fifo_read = -1;
4040+		context->fifo_write = 0;
4041+	}
4042+	uint16_t flags = load_int16(buf);
4043+	context->flags2 = flags >> 8;
4044+	context->flags = flags;
4045+	context->frame = load_int32(buf);
4046+	context->vcounter = load_int16(buf);
4047+	context->hslot = load_int8(buf);
4048+	context->hv_latch = load_int16(buf);
4049+	context->state = load_int8(buf);
4050+	context->hscroll_a = load_int16(buf);
4051+	context->hscroll_b = load_int16(buf);
4052+	context->vscroll_latch[0] = load_int16(buf);
4053+	context->vscroll_latch[1] = load_int16(buf);
4054+	context->col_1 = load_int16(buf);
4055+	context->col_2 = load_int16(buf);
4056+	context->test_port = load_int16(buf);
4057+	load_buffer8(buf, context->tmp_buf_a, SCROLL_BUFFER_SIZE);
4058+	load_buffer8(buf, context->tmp_buf_b, SCROLL_BUFFER_SIZE);
4059+	context->buf_a_off = load_int8(buf) & SCROLL_BUFFER_MASK;
4060+	context->buf_b_off = load_int8(buf) & SCROLL_BUFFER_MASK;
4061+	context->sprite_index = load_int8(buf);
4062+	context->sprite_draws = load_int8(buf);
4063+	context->slot_counter = load_int8(buf);
4064+	context->cur_slot = load_int8(buf);
4065+	for (int i = 0; i < MAX_DRAWS; i++)
4066+	{
4067+		sprite_draw *draw = context->sprite_draw_list + i;
4068+		draw->address = load_int16(buf);
4069+		draw->x_pos = load_int16(buf);
4070+		draw->pal_priority = load_int8(buf);
4071+		draw->h_flip = load_int8(buf);
4072+	}
4073+	for (int i = 0; i < MAX_SPRITES_LINE; i++)
4074+	{
4075+		sprite_info *info = context->sprite_info_list + i;
4076+		info->size = load_int8(buf);
4077+		info->index = load_int8(buf);
4078+		info->y = load_int16(buf);
4079+	}
4080+	load_buffer8(buf, context->linebuf, LINEBUF_SIZE);
4081+	
4082+	context->cycles = load_int32(buf);
4083+	context->pending_vint_start = load_int32(buf);
4084+	context->pending_hint_start = load_int32(buf);
4085+	update_video_params(context);
4086+}
4087+
4088+static vdp_context *current_vdp;
4089+static void vdp_debug_window_close(uint8_t which)
4090+{
4091+	//TODO: remove need for current_vdp global, and find the VDP via current_system instead
4092+	for (int i = 0; i < VDP_NUM_DEBUG_TYPES; i++)
4093+	{
4094+		if (current_vdp->enabled_debuggers & (1 << i) && which == current_vdp->debug_fb_indices[i]) {
4095+			vdp_toggle_debug_view(current_vdp, i);
4096+			break;
4097+		}
4098+	}
4099+}
4100+
4101+void vdp_toggle_debug_view(vdp_context *context, uint8_t debug_type)
4102+{
4103+	if (context->enabled_debuggers & 1 << debug_type) {
4104+		render_destroy_window(context->debug_fb_indices[debug_type]);
4105+		context->enabled_debuggers &= ~(1 << debug_type);
4106+	} else {
4107+		uint32_t width,height;
4108+		uint8_t fetch_immediately = 0;
4109+		char *caption;
4110+		switch(debug_type)
4111+		{
4112+		case VDP_DEBUG_PLANE:
4113+			caption = "BlastEm - VDP Plane Debugger";
4114+			width = height = 1024;
4115+			break;
4116+		case VDP_DEBUG_VRAM:
4117+			caption = "BlastEm - VDP VRAM Debugger";
4118+			width = 1024;
4119+			height = 512;
4120+			break;
4121+		case VDP_DEBUG_CRAM:
4122+			caption = "BlastEm - VDP CRAM Debugger";
4123+			width = 512;
4124+			height = 512;
4125+			fetch_immediately = 1;
4126+			break;
4127+		case VDP_DEBUG_COMPOSITE:
4128+			caption = "BlastEm - VDP Plane Composition Debugger";
4129+			width = LINEBUF_SIZE;
4130+			height = context->inactive_start + context->border_top + context->border_bot;
4131+			fetch_immediately = 1;
4132+			break;
4133+		default:
4134+			return;
4135+		}
4136+		current_vdp = context;
4137+		context->debug_fb_indices[debug_type] = render_create_window(caption, width, height, vdp_debug_window_close);
4138+		if (context->debug_fb_indices[debug_type]) {
4139+			context->enabled_debuggers |= 1 << debug_type;
4140+		}
4141+		if (fetch_immediately) {
4142+			context->debug_fbs[debug_type] = render_get_video_buffer(context->debug_fb_indices[debug_type], &context->debug_fb_pitch[debug_type]);
4143+		}
4144+	}
4145+}
4146+
4147+void vdp_inc_debug_mode(vdp_context *context)
4148+{
4149+	uint8_t active = render_get_active_video_buffer();
4150+	if (active < VIDEO_BUFFER_USER_START) {
4151+		return;
4152+	}
4153+	for (int i = 0; i < VDP_NUM_DEBUG_TYPES; i++)
4154+	{
4155+		if (context->enabled_debuggers & (1 << i) && context->debug_fb_indices[i] == active) {
4156+			context->debug_modes[i]++;
4157+			return;
4158+		}
4159+	}
4160+}
A vdp.h
+280, -0
  1@@ -0,0 +1,280 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef VDP_H_
  8+#define VDP_H_
  9+
 10+#include <stdint.h>
 11+#include <stdio.h>
 12+#include "system.h"
 13+#include "serialize.h"
 14+
 15+#define VDP_REGS 24
 16+#define CRAM_SIZE 64
 17+#define SHADOW_OFFSET CRAM_SIZE
 18+#define HIGHLIGHT_OFFSET (SHADOW_OFFSET+CRAM_SIZE)
 19+#define MODE4_OFFSET (HIGHLIGHT_OFFSET+CRAM_SIZE)
 20+#define VSRAM_SIZE 40
 21+#define VRAM_SIZE (64*1024)
 22+#define BORDER_LEFT 13
 23+#define BORDER_RIGHT 14
 24+#define HORIZ_BORDER (BORDER_LEFT+BORDER_RIGHT)
 25+#define LINEBUF_SIZE (320+HORIZ_BORDER) //H40 + full border
 26+#define SCROLL_BUFFER_SIZE 32
 27+#define BORDER_BOTTOM 13 //TODO: Replace with actual value
 28+#define MAX_DRAWS 40
 29+#define MAX_DRAWS_H32 32
 30+#define MAX_DRAWS_H32_MODE4 8
 31+#define MAX_SPRITES_LINE 20
 32+#define MAX_SPRITES_LINE_H32 16
 33+#define MAX_SPRITES_FRAME 80
 34+#define MAX_SPRITES_FRAME_H32 64
 35+#define SAT_CACHE_SIZE (MAX_SPRITES_FRAME * 4)
 36+
 37+#define FBUF_SHADOW 0x0001
 38+#define FBUF_HILIGHT 0x0010
 39+#define FBUF_MODE4 0x0100
 40+#define DBG_SHADOW 0x10
 41+#define DBG_HILIGHT 0x20
 42+#define DBG_PRIORITY 0x8
 43+#define DBG_SRC_MASK 0x7
 44+#define DBG_SRC_A 0x1
 45+#define DBG_SRC_W 0x2
 46+#define DBG_SRC_B 0x3
 47+#define DBG_SRC_S 0x4
 48+#define DBG_SRC_BG 0x0
 49+
 50+#define MCLKS_LINE 3420
 51+
 52+#define FLAG_DOT_OFLOW     0x01
 53+#define FLAG_CAN_MASK      0x02
 54+#define FLAG_MASKED        0x04
 55+#define FLAG_WINDOW        0x08
 56+#define FLAG_PENDING       0x10
 57+#define FLAG_READ_FETCHED  0x20
 58+#define FLAG_DMA_RUN       0x40
 59+#define FLAG_DMA_PROG      0x80
 60+
 61+#define FLAG2_VINT_PENDING   0x01
 62+#define FLAG2_HINT_PENDING   0x02
 63+#define FLAG2_READ_PENDING   0x04
 64+#define FLAG2_SPRITE_COLLIDE 0x08
 65+#define FLAG2_REGION_PAL     0x10
 66+#define FLAG2_EVEN_FIELD     0x20
 67+#define FLAG2_BYTE_PENDING   0x40
 68+#define FLAG2_PAUSE          0x80
 69+
 70+#define DISPLAY_ENABLE 0x40
 71+
 72+enum {
 73+	REG_MODE_1=0,
 74+	REG_MODE_2,
 75+	REG_SCROLL_A,
 76+	REG_WINDOW,
 77+	REG_SCROLL_B,
 78+	REG_SAT,
 79+	REG_STILE_BASE,
 80+	REG_BG_COLOR,
 81+	REG_X_SCROLL,
 82+	REG_Y_SCROLL,
 83+	REG_HINT,
 84+	REG_MODE_3,
 85+	REG_MODE_4,
 86+	REG_HSCROLL,
 87+	REG_BGTILE_BASE,
 88+	REG_AUTOINC,
 89+	REG_SCROLL,
 90+	REG_WINDOW_H,
 91+	REG_WINDOW_V,
 92+	REG_DMALEN_L,
 93+	REG_DMALEN_H,
 94+	REG_DMASRC_L,
 95+	REG_DMASRC_M,
 96+	REG_DMASRC_H
 97+};
 98+
 99+//Mode reg 1
100+#define BIT_VSCRL_LOCK 0x80
101+#define BIT_HSCRL_LOCK 0x40
102+#define BIT_COL0_MASK  0x20
103+#define BIT_HINT_EN    0x10
104+#define BIT_SPRITE_8PX 0x08
105+#define BIT_PAL_SEL    0x04
106+#define BIT_MODE_4     BIT_PAL_SEL
107+#define BIT_HVC_LATCH  0x02
108+#define BIT_DISP_DIS   0x01
109+
110+//Mode reg 2
111+#define BIT_128K_VRAM  0x80
112+#define BIT_DISP_EN    0x40
113+#define BIT_VINT_EN    0x20
114+#define BIT_DMA_ENABLE 0x10
115+#define BIT_PAL        0x08
116+#define BIT_MODE_5     0x04
117+#define BIT_SPRITE_SZ  0x02
118+
119+//Mode reg 3
120+#define BIT_EINT_EN    0x10
121+#define BIT_VSCROLL    0x04
122+
123+//Mode reg 4
124+#define BIT_H40        0x01
125+#define BIT_HILIGHT    0x8
126+#define BIT_DOUBLE_RES 0x4
127+#define BIT_INTERLACE  0x2
128+
129+//Test register
130+#define TEST_BIT_DISABLE 0x40
131+
132+typedef struct {
133+	uint16_t address;
134+	int16_t x_pos;
135+	uint8_t pal_priority;
136+	uint8_t h_flip;
137+} sprite_draw;
138+
139+typedef struct {
140+	uint8_t size;
141+	uint8_t index;
142+	int16_t y;
143+} sprite_info;
144+
145+#define FIFO_SIZE 4
146+
147+typedef struct {
148+	uint32_t cycle;
149+	uint32_t address;
150+	uint16_t value;
151+	uint8_t  cd;
152+	uint8_t  partial;
153+} fifo_entry;
154+
155+enum {
156+	VDP_DEBUG_PLANE,
157+	VDP_DEBUG_VRAM,
158+	VDP_DEBUG_CRAM,
159+	VDP_DEBUG_COMPOSITE,
160+	VDP_NUM_DEBUG_TYPES
161+};
162+
163+typedef struct {
164+	system_header  *system;
165+	//pointer to current line in framebuffer
166+	uint32_t       *output;
167+	uint32_t       *done_output;
168+	//pointer to current framebuffer
169+	uint32_t       *fb;
170+	uint32_t       *debug_fbs[VDP_NUM_DEBUG_TYPES];
171+	uint32_t       output_pitch;
172+	uint32_t       debug_fb_pitch[VDP_NUM_DEBUG_TYPES];
173+	fifo_entry     fifo[FIFO_SIZE];
174+	int32_t        fifo_write;
175+	int32_t        fifo_read;
176+	uint32_t       address;
177+	uint32_t       serial_address;
178+	uint32_t       colors[CRAM_SIZE*4];
179+	uint32_t       debugcolors[1 << (3 + 1 + 1 + 1)];//3 bits for source, 1 bit for priority, 1 bit for shadow, 1 bit for hilight
180+	uint16_t       cram[CRAM_SIZE];
181+	uint32_t       frame;
182+	uint8_t        cd;
183+	uint8_t	       flags;
184+	uint8_t        regs[VDP_REGS];
185+	//cycle count in MCLKs
186+	uint32_t       cycles;
187+	uint32_t       pending_vint_start;
188+	uint32_t       pending_hint_start;
189+	uint16_t       vsram[VSRAM_SIZE];
190+	uint16_t       vscroll_latch[2];
191+	uint16_t       vcounter;
192+	uint16_t       inactive_start;
193+	uint16_t       border_top;
194+	uint16_t       border_bot;
195+	uint16_t       hscroll_a;
196+	uint16_t       hscroll_b;
197+	uint16_t       h40_lines;
198+	uint16_t       output_lines;
199+	sprite_draw    sprite_draw_list[MAX_DRAWS];
200+	sprite_info    sprite_info_list[MAX_SPRITES_LINE];
201+	uint8_t        sat_cache[SAT_CACHE_SIZE];
202+	uint16_t       col_1;
203+	uint16_t       col_2;
204+	uint16_t       hv_latch;
205+	uint16_t       prefetch;
206+	uint16_t       test_port;
207+	//stores 2-bit palette + 4-bit palette index + priority for current sprite line
208+	uint8_t        linebuf[LINEBUF_SIZE];
209+	uint8_t        layer_debug_buf[LINEBUF_SIZE];
210+	uint8_t        hslot; //hcounter/2
211+	uint8_t	       sprite_index;
212+	uint8_t        sprite_draws;
213+	int8_t         slot_counter;
214+	int8_t         cur_slot;
215+	uint8_t        max_sprites_frame;
216+	uint8_t        max_sprites_line;
217+	uint8_t        fetch_tmp[2];
218+	uint8_t        v_offset;
219+	uint8_t        hint_counter;
220+	uint8_t        flags2;
221+	uint8_t        double_res;
222+	uint8_t        buf_a_off;
223+	uint8_t        buf_b_off;
224+	uint8_t        pending_byte;
225+	uint8_t        state;
226+	uint8_t        cur_buffer;
227+	uint8_t        tmp_buf_a[SCROLL_BUFFER_SIZE];
228+	uint8_t        tmp_buf_b[SCROLL_BUFFER_SIZE];
229+	uint8_t        enabled_debuggers;
230+	uint8_t        debug_fb_indices[VDP_NUM_DEBUG_TYPES];
231+	uint8_t        debug_modes[VDP_NUM_DEBUG_TYPES];
232+	uint8_t        vdpmem[];
233+} vdp_context;
234+
235+
236+
237+vdp_context *init_vdp_context(uint8_t region_pal);
238+void vdp_free(vdp_context *context);
239+void vdp_run_context_full(vdp_context * context, uint32_t target_cycles);
240+void vdp_run_context(vdp_context * context, uint32_t target_cycles);
241+//runs from current cycle count to VBLANK for the current mode, returns ending cycle count
242+uint32_t vdp_run_to_vblank(vdp_context * context);
243+//runs until the target cycle is reached or the current DMA operation has completed, whicever comes first
244+void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles);
245+uint8_t vdp_load_gst(vdp_context * context, FILE * state_file);
246+uint8_t vdp_save_gst(vdp_context * context, FILE * outfile);
247+int vdp_control_port_write(vdp_context * context, uint16_t value);
248+void vdp_control_port_write_pbc(vdp_context * context, uint8_t value);
249+int vdp_data_port_write(vdp_context * context, uint16_t value);
250+void vdp_data_port_write_pbc(vdp_context * context, uint8_t value);
251+void vdp_test_port_write(vdp_context * context, uint16_t value);
252+uint16_t vdp_control_port_read(vdp_context * context);
253+uint16_t vdp_data_port_read(vdp_context * context);
254+uint8_t vdp_data_port_read_pbc(vdp_context * context);
255+void vdp_latch_hv(vdp_context *context);
256+uint16_t vdp_hv_counter_read(vdp_context * context);
257+uint16_t vdp_test_port_read(vdp_context * context);
258+void vdp_adjust_cycles(vdp_context * context, uint32_t deduction);
259+uint32_t vdp_next_hint(vdp_context * context);
260+uint32_t vdp_next_vint(vdp_context * context);
261+uint32_t vdp_next_vint_z80(vdp_context * context);
262+uint32_t vdp_next_nmi(vdp_context *context);
263+void vdp_int_ack(vdp_context * context);
264+void vdp_print_sprite_table(vdp_context * context);
265+void vdp_print_reg_explain(vdp_context * context);
266+void latch_mode(vdp_context * context);
267+uint32_t vdp_cycles_to_frame_end(vdp_context * context);
268+void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value);
269+void vdp_check_update_sat_byte(vdp_context *context, uint32_t address, uint8_t value);
270+void vdp_pbc_pause(vdp_context *context);
271+void vdp_release_framebuffer(vdp_context *context);
272+void vdp_reacquire_framebuffer(vdp_context *context);
273+void vdp_serialize(vdp_context *context, serialize_buffer *buf);
274+void vdp_deserialize(deserialize_buffer *buf, void *vcontext);
275+void vdp_force_update_framebuffer(vdp_context *context);
276+void vdp_toggle_debug_view(vdp_context *context, uint8_t debug_type);
277+void vdp_inc_debug_mode(vdp_context *context);
278+//to be implemented by the host system
279+uint16_t read_dma_value(uint32_t address);
280+
281+#endif //VDP_H_
A vgm.h
+74, -0
 1@@ -0,0 +1,74 @@
 2+#ifndef VGM_H_
 3+#define VGM_H_
 4+
 5+#pragma pack(push, 1)
 6+typedef struct {
 7+	char     ident[4];
 8+	uint32_t eof_offset;
 9+	uint32_t version;
10+	uint32_t sn76489_clk;
11+	uint32_t ym2413_clk;
12+	uint32_t gd3_offset;
13+	uint32_t num_samples;
14+	uint32_t loop_offset;
15+	uint32_t loop_samples;
16+	uint32_t rate;
17+	uint16_t sn76489_fb;
18+	uint8_t  sn76489_shift;
19+	uint8_t  sn76489_flags;
20+	uint32_t ym2612_clk;
21+	uint32_t ym2151_clk;
22+	uint32_t data_offset;
23+	uint32_t sega_pcm_clk;
24+	uint32_t sega_pcm_reg;
25+} vgm_header;
26+
27+enum {
28+	CMD_PSG_STEREO = 0x4F,
29+	CMD_PSG,
30+	CMD_YM2413,
31+	CMD_YM2612_0,
32+	CMD_YM2612_1,
33+	CMD_YM2151,
34+	CMD_YM2203,
35+	CMD_YM2608_0,
36+	CMD_YM2608_1,
37+	CMD_YM2610_0,
38+	CMD_YM2610_1,
39+	CMD_YM3812,
40+	CMD_YM3526,
41+	CMD_Y8950,
42+	CMD_YMZ280B,
43+	CMD_YMF262_0,
44+	CMD_YMF262_1,
45+	CMD_WAIT = 0x61,
46+	CMD_WAIT_60,
47+	CMD_WAIT_50,
48+	CMD_END = 0x66,
49+	CMD_DATA,
50+	CMD_PCM_WRITE,
51+	CMD_WAIT_SHORT = 0x70,
52+	CMD_YM2612_DAC = 0x80,
53+	CMD_DAC_STREAM_SETUP = 0x90,
54+	CMD_DAC_STREAM_DATA,
55+	CMD_DAC_STREAM_FREQ,
56+	CMD_DAC_STREAM_START,
57+	CMD_DAC_STREAM_STOP,
58+	CMD_DAC_STREAM_STARTFAST,
59+	CMD_DATA_SEEK = 0xE0
60+};
61+
62+enum {
63+	DATA_YM2612_PCM = 0
64+};
65+
66+#pragma pack(pop)
67+
68+typedef struct {
69+	struct data_block *next;
70+	uint8_t           *data;
71+	uint32_t          size;
72+	uint8_t           type;
73+} data_block;
74+
75+#endif //VGM_H_
+248, -0
  1@@ -0,0 +1,248 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "render.h"
  8+#include "ym2612.h"
  9+#include "psg.h"
 10+#include "config.h"
 11+#include "util.h"
 12+#include <stdint.h>
 13+#include <stdio.h>
 14+#include <stdlib.h>
 15+#include <string.h>
 16+#include "vgm.h"
 17+
 18+#define MCLKS_NTSC 53693175
 19+#define MCLKS_PAL  53203395
 20+
 21+#define MCLKS_PER_68K 7
 22+#define MCLKS_PER_YM  MCLKS_PER_68K
 23+#define MCLKS_PER_Z80 15
 24+#define MCLKS_PER_PSG (MCLKS_PER_Z80*16)
 25+
 26+void handle_keydown(int keycode)
 27+{
 28+}
 29+
 30+void handle_keyup(int keycode)
 31+{
 32+}
 33+
 34+void handle_joydown(int joystick, int button)
 35+{
 36+}
 37+
 38+void handle_joyup(int joystick, int button)
 39+{
 40+}
 41+
 42+void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
 43+{
 44+}
 45+
 46+void handle_joy_axis(int joystick, int axis, int16_t value)
 47+{
 48+}
 49+
 50+void handle_joy_added(int joystick)
 51+{
 52+}
 53+
 54+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay)
 55+{
 56+}
 57+
 58+void handle_mousedown(int mouse, int button)
 59+{
 60+}
 61+
 62+void handle_mouseup(int mouse, int button)
 63+{
 64+}
 65+
 66+int headless = 0;
 67+
 68+#define CYCLE_LIMIT MCLKS_NTSC/60
 69+#define MAX_SOUND_CYCLES 100000
 70+tern_node * config;
 71+
 72+void vgm_wait(ym2612_context * y_context, psg_context * p_context, uint32_t * current_cycle, uint32_t cycles)
 73+{
 74+	while (cycles > MAX_SOUND_CYCLES)
 75+	{
 76+		vgm_wait(y_context, p_context, current_cycle, MAX_SOUND_CYCLES);
 77+		cycles -= MAX_SOUND_CYCLES;
 78+	}
 79+	*current_cycle += cycles;
 80+	psg_run(p_context, *current_cycle);
 81+	ym_run(y_context, *current_cycle);
 82+
 83+	if (*current_cycle > CYCLE_LIMIT) {
 84+		*current_cycle -= CYCLE_LIMIT;
 85+		p_context->cycles -= CYCLE_LIMIT;
 86+		y_context->current_cycle -= CYCLE_LIMIT;
 87+		process_events();
 88+	}
 89+}
 90+
 91+int main(int argc, char ** argv)
 92+{
 93+	set_exe_str(argv[0]);
 94+	data_block *blocks = NULL;
 95+	data_block *seek_block = NULL;
 96+	uint32_t seek_offset;
 97+	uint32_t block_offset;
 98+
 99+	uint32_t fps = 60;
100+	config = load_config(argv[0]);
101+	render_init(320, 240, "vgm play", 0);
102+
103+	uint32_t opts = 0;
104+	if (argc >= 3 && !strcmp(argv[2], "-y")) {
105+		opts |= YM_OPT_WAVE_LOG;
106+	}
107+	
108+	char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval;
109+	uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390;
110+
111+	ym2612_context y_context;
112+	ym_init(&y_context, MCLKS_NTSC, MCLKS_PER_YM, opts);
113+
114+	psg_context p_context;
115+	psg_init(&p_context, MCLKS_NTSC, MCLKS_PER_PSG);
116+
117+	FILE * f = fopen(argv[1], "rb");
118+	vgm_header header;
119+	fread(&header, sizeof(header), 1, f);
120+	if (header.version < 0x150 || !header.data_offset) {
121+		header.data_offset = 0xC;
122+	}
123+	fseek(f, header.data_offset + 0x34, SEEK_SET);
124+	uint32_t data_size = header.eof_offset + 4 - (header.data_offset + 0x34);
125+	uint8_t * data = malloc(data_size);
126+	fread(data, 1, data_size, f);
127+	fclose(f);
128+
129+	uint32_t mclks_sample = MCLKS_NTSC / 44100;
130+	uint32_t loop_count = 2;
131+
132+	uint8_t * end = data + data_size;
133+	uint8_t * cur = data;
134+	uint32_t current_cycle = 0;
135+	while (cur < end) {
136+		uint8_t cmd = *(cur++);
137+		switch(cmd)
138+		{
139+		case CMD_PSG_STEREO:
140+			//ignore for now
141+			cur++;
142+			break;
143+		case CMD_PSG:
144+			psg_write(&p_context, *(cur++));
145+			break;
146+		case CMD_YM2612_0:
147+			ym_address_write_part1(&y_context, *(cur++));
148+			ym_data_write(&y_context, *(cur++));
149+			break;
150+		case CMD_YM2612_1:
151+			ym_address_write_part2(&y_context, *(cur++));
152+			ym_data_write(&y_context, *(cur++));
153+			break;
154+		case CMD_WAIT: {
155+			uint32_t wait_time = *(cur++);
156+			wait_time |= *(cur++) << 8;
157+			wait_time *= mclks_sample;
158+			vgm_wait(&y_context, &p_context, &current_cycle, wait_time);
159+			break;
160+		}
161+		case CMD_WAIT_60:
162+			vgm_wait(&y_context, &p_context, &current_cycle, 735 * mclks_sample);
163+			break;
164+		case CMD_WAIT_50:
165+			vgm_wait(&y_context, &p_context, &current_cycle, 882 * mclks_sample);
166+			break;
167+		case CMD_END:
168+			if (header.loop_offset && --loop_count) {
169+				cur = data + header.loop_offset + 0x1C - (header.data_offset + 0x34);
170+			} else {
171+				//TODO: fade out
172+				return 0;
173+			}
174+			break;
175+		case CMD_DATA: {
176+			cur++; //skip compat command
177+			uint8_t data_type = *(cur++);
178+			uint32_t data_size = *(cur++);
179+			data_size |= *(cur++) << 8;
180+			data_size |= *(cur++) << 16;
181+			data_size |= *(cur++) << 24;
182+			if (data_type == DATA_YM2612_PCM) {
183+				data_block ** curblock = &blocks;
184+				while(*curblock)
185+				{
186+					curblock = &((*curblock)->next);
187+				}
188+				*curblock = malloc(sizeof(data_block));
189+				(*curblock)->size = data_size;
190+				(*curblock)->type = data_type;
191+				(*curblock)->data = cur;
192+				(*curblock)->next = NULL;
193+			} else {
194+				fprintf(stderr, "Skipping data block with unrecognized type %X\n", data_type);
195+			}
196+			cur += data_size;
197+			break;
198+		}
199+		case CMD_DATA_SEEK: {
200+			uint32_t new_offset = *(cur++);
201+			new_offset |= *(cur++) << 8;
202+			new_offset |= *(cur++) << 16;
203+			new_offset |= *(cur++) << 24;
204+			if (!seek_block || new_offset < seek_offset) {
205+				seek_block = blocks;
206+				seek_offset = 0;
207+				block_offset = 0;
208+			}
209+			while (seek_block && (seek_offset - block_offset + seek_block->size) < new_offset)
210+			{
211+				seek_offset += seek_block->size - block_offset;
212+				seek_block = seek_block->next;
213+				block_offset = 0;
214+			}
215+			block_offset += new_offset-seek_offset;
216+			seek_offset = new_offset;
217+			break;
218+		}
219+
220+		default:
221+			if (cmd >= CMD_WAIT_SHORT && cmd < (CMD_WAIT_SHORT + 0x10)) {
222+				uint32_t wait_time = (cmd & 0xF) + 1;
223+				wait_time *= mclks_sample;
224+				vgm_wait(&y_context, &p_context, &current_cycle, wait_time);
225+			} else if (cmd >= CMD_YM2612_DAC && cmd < CMD_DAC_STREAM_SETUP) {
226+				if (seek_block) {
227+					ym_address_write_part1(&y_context, 0x2A);
228+					ym_data_write(&y_context, seek_block->data[block_offset++]);
229+					seek_offset++;
230+					if (block_offset > seek_block->size) {
231+						seek_block = seek_block->next;
232+						block_offset = 0;
233+					}
234+				} else {
235+					fputs("Encountered DAC write command but data seek pointer is invalid!\n", stderr);
236+				}
237+				uint32_t wait_time = (cmd & 0xF);
238+				if (wait_time)
239+				{
240+					wait_time *= mclks_sample;
241+					vgm_wait(&y_context, &p_context, &current_cycle, wait_time);
242+				}
243+			} else {
244+				fatal_error("unimplemented command: %X at offset %X\n", cmd, (unsigned int)(cur - data - 1));
245+			}
246+		}
247+	}
248+	return 0;
249+}
+274, -0
  1@@ -0,0 +1,274 @@
  2+/*
  3+ Copyright 2015 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "ym2612.h"
  8+#include "vgm.h"
  9+#include <stdint.h>
 10+#include <stdio.h>
 11+#include <stdlib.h>
 12+#include <string.h>
 13+
 14+#define OUT_CHANNELS 10
 15+#define DAC_CHANNEL 5
 16+#define PSG_BASE 6
 17+#define SAMPLE_THRESHOLD 100
 18+
 19+uint32_t total_delay;
 20+void accum_wait(uint32_t *delays, uint32_t samples)
 21+{
 22+	total_delay += samples;
 23+	for (int i = 0; i < OUT_CHANNELS; i++)
 24+	{
 25+		delays[i] += samples;
 26+	}
 27+}
 28+
 29+void write_wait(uint8_t **out_buffer, uint32_t *delay)
 30+{
 31+	while (*delay >= 65535)
 32+	{
 33+		*((*out_buffer)++) = CMD_WAIT;
 34+		*((*out_buffer)++) = 0xFF;
 35+		*((*out_buffer)++) = 0xFF;
 36+		*delay -= 65535;
 37+	}
 38+	if (*delay) {
 39+		if (*delay == 735) {
 40+			*((*out_buffer)++) = CMD_WAIT_60;
 41+		} else if (*delay > 735 && *delay <= 751) {
 42+			*((*out_buffer)++) = CMD_WAIT_60;
 43+			*((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 736;
 44+		} else if (*delay == 882) {
 45+			*((*out_buffer)++) = CMD_WAIT_50;
 46+		} else if (*delay > 882 && *delay <= 898) {
 47+			*((*out_buffer)++) = CMD_WAIT_50;
 48+			*((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 882;
 49+		} else if (*delay <= 16) {
 50+			*((*out_buffer)++) = CMD_WAIT_SHORT + *delay - 1;
 51+		} else {
 52+			*((*out_buffer)++) = CMD_WAIT;
 53+			*((*out_buffer)++) = *delay;
 54+			*((*out_buffer)++) = *delay >> 8;
 55+		}
 56+		*delay = 0;
 57+	}
 58+}
 59+
 60+int main(int argc, char ** argv)
 61+{
 62+	data_block *blocks = NULL;
 63+	data_block *seek_block = NULL;
 64+	uint32_t seek_offset;
 65+	uint32_t block_offset;
 66+
 67+
 68+	FILE * f = fopen(argv[1], "rb");
 69+	vgm_header header;
 70+	size_t bytes = fread(&header, 1, sizeof(header), f);
 71+	if (bytes != sizeof(header)) {
 72+		fputs("Error reading file\n", stderr);
 73+		exit(1);
 74+	}
 75+	if (header.version < 0x150 || !header.data_offset) {
 76+		header.data_offset = 0xC;
 77+	}
 78+	fseek(f, header.data_offset + 0x34, SEEK_SET);
 79+	uint32_t data_size = header.eof_offset + 4 - (header.data_offset + 0x34);
 80+	uint8_t * data = malloc(data_size);
 81+	data_size = fread(data, 1, data_size, f);
 82+	fclose(f);
 83+	uint8_t *buffers[OUT_CHANNELS];
 84+	uint8_t *out_pos[OUT_CHANNELS];
 85+	uint8_t has_real_data[OUT_CHANNELS];
 86+	uint32_t delay[OUT_CHANNELS];
 87+
 88+	buffers[0] = malloc(data_size * OUT_CHANNELS);
 89+	out_pos[0] = buffers[0];
 90+	has_real_data[0] = 0;
 91+	delay[0] = 0;
 92+	for (int i = 1; i < OUT_CHANNELS; i++)
 93+	{
 94+		buffers[i] = buffers[i-1] + data_size;
 95+		out_pos[i] = buffers[i];
 96+		has_real_data[i] = 0;
 97+		delay[i] = 0;
 98+	}
 99+
100+	uint8_t * end = data + data_size;
101+	uint8_t * cur = data;
102+	uint32_t current_cycle = 0;
103+	uint8_t psg_latch = 0;
104+	uint8_t param,reg;
105+	uint8_t channel;
106+	uint32_t sample_count = 0;
107+	uint8_t last_cmd;
108+	while (cur < end) {
109+		uint8_t cmd = *(cur++);
110+		switch(cmd)
111+		{
112+		case CMD_PSG_STEREO:
113+			//ignore for now
114+			cur++;
115+			break;
116+		case CMD_PSG:
117+			param = *(cur++);
118+			if (param & 0x80) {
119+				psg_latch = param;
120+				channel = param >> 5 & 3;
121+			} else {
122+				channel = psg_latch >> 5 & 3;
123+			}
124+			write_wait(out_pos + PSG_BASE+channel, delay + PSG_BASE+channel);
125+			*(out_pos[PSG_BASE+channel]++) = cmd;
126+			*(out_pos[PSG_BASE+channel]++) = param;
127+			has_real_data[PSG_BASE+channel] = 1;
128+			break;
129+		case CMD_YM2612_0:
130+			reg = *(cur++);
131+			param = *(cur++);
132+			if (reg < REG_KEY_ONOFF) {
133+				for (int i = 0; i < 6; i++)
134+				{
135+					write_wait(out_pos + i, delay + i);
136+					*(out_pos[i]++) = cmd;
137+					*(out_pos[i]++) = reg;
138+					*(out_pos[i]++) = param;
139+				}
140+				break;
141+			} else if(reg == REG_DAC || reg == REG_DAC_ENABLE) {
142+				if (reg == REG_DAC) {
143+					sample_count++;
144+				}
145+				channel = DAC_CHANNEL;
146+			} else if(reg == REG_KEY_ONOFF) {
147+				channel = param & 7;
148+				if (channel > 2) {
149+					channel--;
150+				}
151+				if (param & 0xF0) {
152+					has_real_data[channel] = 1;
153+				}
154+			} else if (reg >= REG_FNUM_LOW_CH3 && reg < REG_ALG_FEEDBACK) {
155+				channel = 2;
156+			} else {
157+				channel = 255;
158+			}
159+		case CMD_YM2612_1:
160+			if (cmd == CMD_YM2612_1) {
161+				reg = *(cur++);
162+				param = *(cur++);
163+				channel = 255;
164+			}
165+			if (channel >= PSG_BASE) {
166+				if (reg >= REG_DETUNE_MULT && reg < REG_FNUM_LOW) {
167+					channel = (cmd == CMD_YM2612_0 ? 0 : 3) + (reg & 0xC >> 2);
168+				} else if ((reg >= REG_FNUM_LOW && reg < REG_FNUM_LOW_CH3) || (reg >= REG_ALG_FEEDBACK && reg < 0xC0)) {
169+					channel = (cmd == CMD_YM2612_0 ? 0 : 3) + (reg & 0x3);
170+				} else {
171+					fprintf(stderr, "WARNING: Skipping nrecognized write to register %X on part %d\n", reg, (cmd == CMD_YM2612_0 ? 1 : 2));
172+				}
173+			}
174+			if (channel < PSG_BASE) {
175+				write_wait(out_pos + channel, delay + channel);
176+				*(out_pos[channel]++) = cmd;
177+				*(out_pos[channel]++) = reg;
178+				*(out_pos[channel]++) = param;
179+			}
180+			break;
181+		case CMD_WAIT: {
182+			uint32_t wait_time = *(cur++);
183+			wait_time |= *(cur++) << 8;
184+			accum_wait(delay, wait_time);
185+			break;
186+		}
187+		case CMD_WAIT_60:
188+			accum_wait(delay, 735);
189+			break;
190+		case CMD_WAIT_50:
191+			accum_wait(delay, 882);
192+			break;
193+		case CMD_END:
194+			for (int i = 0; i < OUT_CHANNELS; i++)
195+			{
196+				write_wait(out_pos + i, delay + i);
197+				*(out_pos[i]++) = cmd;
198+			}
199+			cur = end;
200+			break;
201+		case CMD_DATA: {
202+			uint8_t * start = cur - 1;
203+			cur++; //skip compat command
204+			uint8_t data_type = *(cur++);
205+			uint32_t data_size = *(cur++);
206+			data_size |= *(cur++) << 8;
207+			data_size |= *(cur++) << 16;
208+			data_size |= *(cur++) << 24;
209+			if (cur + data_size > end) {
210+				data_size = end - cur;
211+			}
212+			cur += data_size;
213+			if (data_type == DATA_YM2612_PCM) {
214+				write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL);
215+				memcpy(out_pos[DAC_CHANNEL], start, cur-start);
216+				out_pos[DAC_CHANNEL] += cur-start;
217+			} else {
218+				fprintf(stderr, "WARNING: Skipping data block with unrecognized type %X\n", data_type);
219+			}
220+			break;
221+		}
222+		case CMD_DATA_SEEK: {
223+			write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL);
224+			memcpy(out_pos[DAC_CHANNEL], cur-1, 5);
225+			out_pos[DAC_CHANNEL] += 5;
226+			cur += 4;
227+			break;
228+		}
229+
230+		default:
231+			if (cmd >= CMD_WAIT_SHORT && cmd < (CMD_WAIT_SHORT + 0x10)) {
232+				accum_wait(delay, (cmd & 0xF) + 1);
233+			} else if (cmd >= CMD_YM2612_DAC && cmd < CMD_DAC_STREAM_SETUP) {
234+				write_wait(out_pos + DAC_CHANNEL, delay + DAC_CHANNEL);
235+				*(out_pos[DAC_CHANNEL]++) = cmd;
236+				for (int i = 0; i < OUT_CHANNELS; i++)
237+				{
238+					if (i != DAC_CHANNEL)
239+					{
240+						delay[i] += cmd & 0xF;
241+					}
242+				}
243+				sample_count++;
244+			} else {
245+				fprintf(stderr, "unimplemented command: %X at offset %X, last valid command was %X\n", cmd, (unsigned int)(cur - data - 1), last_cmd);
246+				exit(1);
247+			}
248+		}
249+		last_cmd = cmd;
250+	}
251+	if (sample_count > SAMPLE_THRESHOLD) {
252+		has_real_data[DAC_CHANNEL] = 1;
253+	}
254+	for (int i = 0; i < OUT_CHANNELS; i++)
255+	{
256+		if (has_real_data[i]) {
257+			char fname[11];
258+			sprintf(fname, i < PSG_BASE ? "ym_%d.vgm" : "psg_%d.vgm", i < PSG_BASE ? i : i - PSG_BASE);
259+			f = fopen(fname, "wb");
260+			if (!f) {
261+				fprintf(stderr, "Failed to open %s for writing\n", fname);
262+				exit(1);
263+			}
264+			data_size = out_pos[i] - buffers[i];
265+			header.eof_offset = (header.data_offset + 0x34) + data_size - 4;
266+			header.gd3_offset = 0;
267+			fwrite(&header, 1, sizeof(header), f);
268+			fseek(f, header.data_offset + 0x34, SEEK_SET);
269+			fwrite(buffers[i], 1, data_size, f);
270+			fclose(f);
271+		}
272+	}
273+	printf("total_delay: %d\n", total_delay);
274+	return 0;
275+}
+100, -0
  1@@ -0,0 +1,100 @@
  2+#include <stdio.h>
  3+#include "vos_program_module.h"
  4+
  5+int main(int argc, char ** argv)
  6+{
  7+	vos_program_module header;
  8+	FILE * f = fopen(argv[1], "rb");
  9+	vos_read_header(f, &header);
 10+	vos_read_alloc_module_map(f, &header);
 11+	vos_read_alloc_external_vars(f, &header);
 12+
 13+	printf("Version: %d\n", header.version);
 14+	printf("Binder Version: %s\n", header.binder_version.str);
 15+	printf("Binder Options: %s\n", header.binder_options.str);
 16+	printf("System name: %s\n", header.system_name.str);
 17+	printf("User name: %s\n", header.user_name.str);
 18+	printf("Date bound: %d\n", header.date_bound);
 19+	printf("Code addresss: 0x%X, Static address: 0x%X\n",
 20+	       header.main_entry_link.code_address, header.main_entry_link.static_address);
 21+	printf("User boundary: 0x%X\n", header.user_boundary);
 22+	printf("Num modules: %d\n", header.n_modules);
 23+	printf("Num extern vars: %d\n", header.n_external_vars);
 24+	printf("Num link names: %d\n", header.n_link_names);
 25+	printf("Num unsapped links: %d\n", header.n_unsnapped_links);
 26+	printf("Num VM pages: %d\n", header.n_vm_pages);
 27+	printf("Num header pages: %d\n", header.n_header_pages);
 28+	for (int i = 0; i < 3; i++) {
 29+		for (int j = 0; j < 4; j++) {
 30+			printf("Info %d:%d\n\tAddress: 0x%X\n\tLength: 0x%X\n",
 31+			       i, j, header.info[i][j].address, header.info[i][j].len);
 32+		}
 33+	}
 34+	printf("Module map address: 0x%X\n", header.module_map_address);
 35+	printf("Module map length: 0x%X\n", header.module_map_len);
 36+	printf("External vars map address: 0x%X\n", header.external_vars_map_address);
 37+	printf("External vars map length: 0x%X\n", header.external_vars_map_len);
 38+	printf("Link names map address: 0x%X\n", header.link_names_map_address);
 39+	printf("Link names map length: 0x%X\n", header.link_names_map_len);
 40+	printf("Header address: 0x%X\n", header.header_address);
 41+	printf("Header length: 0x%X\n", header.header_len);
 42+	//printf("Access Info: 0x%X\n", header.header_address);
 43+	printf("Flags: 0x%X\n", header.flags);
 44+	printf("Num tasks: %d\n", header.n_tasks);
 45+	printf("Stack Size: 0x%X\n", header.stack_len);
 46+	printf("Num entries: %d\n", header.n_entries);
 47+	printf("Entry map address: 0x%X\n", header.entry_map_address);
 48+	printf("Entry map length: 0x%X\n", header.entry_map_len);
 49+	printf("Pop Version: %d\n", header.pop_version);
 50+	printf("Processor: %d\n", header.processor);
 51+	printf("Processor family: %d\n", header.processor_family);
 52+	printf("Release name: %s\n", header.release_name.str);
 53+	printf("Relocation info:\n\tMap Addres: 0x%X\n\tMap Length: 0x%X\n\tNum Relocations: %d\n",
 54+	       header.relocation_info.map_address, header.relocation_info.map_len,
 55+		   header.relocation_info.n_relocations);
 56+	printf("High water mark: 0x%X\n", header.high_water_mark);
 57+	printf("Copyright notice: %s\n", header.program_name.str);
 58+	printf("String pool address: 0x%X\n", header.string_pool_address);
 59+	printf("String pool length: 0x%X\n", header.string_pool_len);
 60+	printf("Object dir map address: 0x%X\n", header.obj_dir_map_address);
 61+	printf("Object dir map length: 0x%X\n", header.obj_dir_map_len);
 62+	puts("Global offset table addresses:");
 63+	for (int i = 0; i < 3; i++) {
 64+		printf("\t%d: 0x%X\n", i, header.global_offset_table_address[i]);
 65+	}
 66+	for (int i = 0; i < 3; i++) {
 67+		printf("Block map info %d\n\tAddress: 0x%X\n\tLength: 0x%X\n",
 68+			   i, header.block_map_info[i].address, header.block_map_info[i].len);
 69+	}
 70+	printf("Secton map file address: 0x%X\n", header.section_map_file_address);
 71+	printf("Secton map address: 0x%X\n", header.section_map_address);
 72+	printf("Secton map length: 0x%X\n", header.section_map_len);
 73+	printf("Num sections: %d\n", header.n_sections);
 74+	printf("Max heap size: 0x%X\n", header.max_heap_size);
 75+	printf("Max program size: 0x%X\n", header.max_program_size);
 76+	printf("Max stack size: 0x%X\n", header.max_stack_size);
 77+	printf("Stack fence size: 0x%X\n", header.stack_fence_size);
 78+
 79+	puts("\nModules");
 80+	for (int i = 0; i < header.n_modules; i++) {
 81+		printf("\t%s:\n\t\tCode Address: 0x%X, Length: 0x%X\n",
 82+			   header.module_map_entries[i].name.str,
 83+			   header.module_map_entries[i].code_address,
 84+			   header.module_map_entries[i].code_length);
 85+		printf("\t\tFoo Address: 0x%X, Length: 0x%X\n",
 86+		       header.module_map_entries[i].foo_address,
 87+			   header.module_map_entries[i].foo_length);
 88+		printf("\t\tBar Address: 0x%X, Length: 0x%X\n",
 89+		       header.module_map_entries[i].bar_address,
 90+			   header.module_map_entries[i].bar_length);
 91+	}
 92+
 93+	puts("\nExtrnal Vars");
 94+	for (int i = 0; i < header.n_external_vars; i++) {
 95+		printf("\t%s: 0x%X\n",
 96+		       header.external_vars[i].name.str, header.external_vars[i].address);
 97+	}
 98+
 99+	vos_header_cleanup(&header);
100+	return 0;
101+}
+208, -0
  1@@ -0,0 +1,208 @@
  2+#include <stdio.h>
  3+#include <stdlib.h>
  4+#include <stddef.h>
  5+#include <string.h>
  6+#include "vos_program_module.h"
  7+
  8+static uint16_t big16(uint8_t ** src)
  9+{
 10+	uint16_t ret = *((*src)++) << 8;
 11+	ret |= *((*src)++);
 12+	return ret;
 13+}
 14+
 15+static uint32_t big32(uint8_t ** src)
 16+{
 17+	uint32_t ret = *((*src)++) << 24;
 18+	ret |= *((*src)++) << 16;
 19+	ret |= *((*src)++) << 8;
 20+	ret |= *((*src)++);
 21+	return ret;
 22+}
 23+
 24+static void string_(uint8_t ** src, uint16_t *len, char * str, uint32_t storage)
 25+{
 26+	*len = big16(src);
 27+	memcpy(str, *src, storage);
 28+	*src += storage;
 29+	if (*len >= storage)
 30+	{
 31+		*len = storage;
 32+	} else {
 33+		str[*len] = 0;
 34+	}
 35+	if (storage & 1)
 36+	{
 37+		(*src)++;
 38+	}
 39+}
 40+
 41+#define string(src, field) string_(src, &(field).len, (field).str, sizeof((field).str))
 42+
 43+
 44+int vos_read_header(FILE * f, vos_program_module *out)
 45+{
 46+	uint8_t buffer[4096];
 47+	if (fread(buffer, 1, sizeof(buffer), f) != sizeof(buffer))
 48+	{
 49+		return 0;
 50+	}
 51+	uint8_t *cur = buffer;
 52+	out->version = big16(&cur);
 53+	string(&cur, out->binder_version);
 54+	string(&cur, out->binder_options);
 55+	string(&cur, out->system_name);
 56+	string(&cur, out->user_name);
 57+	out->date_bound = big32(&cur);
 58+	out->main_entry_link.code_address = big32(&cur);
 59+	out->main_entry_link.static_address = big32(&cur);
 60+	out->user_boundary = big32(&cur);
 61+	out->n_modules = big16(&cur);
 62+	out->n_external_vars = big16(&cur);
 63+	out->n_link_names = big16(&cur);
 64+	out->n_unsnapped_links = big16(&cur);
 65+	out->n_vm_pages = big16(&cur);
 66+	out->n_header_pages = big16(&cur);
 67+	for (int i = 0; i < 3; i++)
 68+	{
 69+		for (int j = 0; j < 4; j++)
 70+		{
 71+			out->info[i][j].address = big32(&cur);
 72+			out->info[i][j].len = big32(&cur);
 73+		}
 74+	}
 75+	out->module_map_address = big32(&cur);
 76+	out->module_map_len = big32(&cur);
 77+	out->external_vars_map_address = big32(&cur);
 78+	out->external_vars_map_len = big32(&cur);
 79+	out->link_names_map_address = big32(&cur);
 80+	out->link_names_map_len = big32(&cur);
 81+	out->link_map_address = big32(&cur);
 82+	out->link_map_len = big32(&cur);
 83+	out->header_address = big32(&cur);
 84+	out->header_len = big32(&cur);
 85+	memcpy(out->access_info, cur, sizeof(out->access_info));
 86+	cur += sizeof(out->access_info);
 87+	out->flags = big32(&cur);
 88+	out->n_tasks = big16(&cur);
 89+	for (int i = 0; i < 3; i++)
 90+	{
 91+		out->task_static_len[i] = big32(&cur);
 92+	}
 93+	out->stack_len = big32(&cur);
 94+	out->n_entries = big16(&cur);
 95+	out->entry_map_address = big32(&cur);
 96+	out->entry_map_len = big32(&cur);
 97+	out->pop_version = big16(&cur);
 98+	out->processor = big16(&cur);
 99+	string(&cur, out->release_name);
100+	out->relocation_info.map_address = big32(&cur);
101+	out->relocation_info.map_len = big32(&cur);
102+	out->relocation_info.n_relocations = big32(&cur);
103+	out->high_water_mark = big32(&cur);
104+	string(&cur, out->copyright_notice);
105+	for (int i = 0; i < 14; i++)
106+	{
107+		out->module_origins[i] = big32(&cur);
108+	}
109+	out->processor_family = big16(&cur);
110+	string(&cur, out->program_name);
111+	out->string_pool_address = big32(&cur);
112+	out->string_pool_len = big32(&cur);
113+	out->obj_dir_map_address = big32(&cur);
114+	out->obj_dir_map_len = big32(&cur);
115+	for (int i = 0; i < 3; i++)
116+	{
117+		out->global_offset_table_address[i] = big32(&cur);
118+	}
119+	for (int i = 0; i < 3; i++)
120+	{
121+		out->block_map_info[i].address = big32(&cur);
122+		out->block_map_info[i].len = big32(&cur);
123+	}
124+	out->section_map_file_address = big32(&cur);
125+	out->section_map_address = big32(&cur);
126+	out->section_map_len = big32(&cur);
127+	out->n_sections = big16(&cur);
128+	out->max_heap_size = big32(&cur);
129+	out->max_program_size = big32(&cur);
130+	out->max_stack_size = big32(&cur);
131+	out->stack_fence_size = big32(&cur);
132+
133+	out->module_map_entries = NULL;
134+	out->external_vars = NULL;
135+	return 1;
136+}
137+
138+#define MODULE_MAP_ENTRY_SIZE 74
139+
140+int vos_read_alloc_module_map(FILE * f, vos_program_module *header)
141+{
142+	if (header->module_map_len != header->n_modules * MODULE_MAP_ENTRY_SIZE)
143+	{
144+		return 0;
145+	}
146+	uint8_t * buf = malloc(header->module_map_len);
147+	fseek(f, header->module_map_address + 0x1000 - header->user_boundary, SEEK_SET);
148+	if (fread(buf, 1, header->module_map_len, f) != header->module_map_len)
149+	{
150+		free(buf);
151+		return 0;
152+	}
153+	uint8_t * cur = buf;
154+	header->module_map_entries = malloc(sizeof(vos_module_map_entry) * header->n_modules);
155+	for (int i = 0; i < header->n_modules; i++)
156+	{
157+		string(&cur, header->module_map_entries[i].name);
158+		for (int j = 0; j < 5; j++)
159+		{
160+			header->module_map_entries[i].unknown[j] = big16(&cur);
161+		}
162+		header->module_map_entries[i].code_address = big32(&cur);
163+		header->module_map_entries[i].code_length = big32(&cur);
164+		header->module_map_entries[i].foo_address = big32(&cur);
165+		header->module_map_entries[i].foo_length = big32(&cur);
166+		header->module_map_entries[i].bar_address = big32(&cur);
167+		header->module_map_entries[i].bar_length = big32(&cur);
168+		for (int j = 0; j < 3; j++)
169+		{
170+			header->module_map_entries[i].unknown2[j] = big16(&cur);
171+		}
172+	}
173+	return 1;
174+}
175+
176+#define EXTERNAL_VAR_ENTRY_SIZE 44
177+
178+int vos_read_alloc_external_vars(FILE * f, vos_program_module *header)
179+{
180+	if (header->external_vars_map_len != header->n_external_vars * EXTERNAL_VAR_ENTRY_SIZE)
181+	{
182+		return 0;
183+	}
184+	uint8_t * buf = malloc(header->external_vars_map_len);
185+	fseek(f, header->external_vars_map_address + 0x1000 - header->user_boundary, SEEK_SET);
186+	if (fread(buf, 1, header->external_vars_map_len, f) != header->external_vars_map_len)
187+	{
188+		free(buf);
189+		return 0;
190+	}
191+	uint8_t * cur = buf;
192+	header->external_vars = malloc(sizeof(vos_external_var_entry) * header->n_external_vars);
193+	for (int i = 0; i < header->n_external_vars; i++)
194+	{
195+		string(&cur, header->external_vars[i].name);
196+		header->external_vars[i].address = big32(&cur);
197+		for (int j = 0; j < 3; j++)
198+		{
199+			header->external_vars[i].unknown[j] = big16(&cur);
200+		}
201+	}
202+	return 1;
203+}
204+
205+void vos_header_cleanup(vos_program_module *header)
206+{
207+	free(header->module_map_entries);
208+	free(header->external_vars);
209+}
+134, -0
  1@@ -0,0 +1,134 @@
  2+#ifndef VOS_PROGRAM_MODULE_H_
  3+#define VOS_PROGRAM_MODULE_H_
  4+
  5+#include <stdint.h>
  6+
  7+typedef struct
  8+{
  9+	struct {
 10+		uint16_t len;
 11+		char     str[32];
 12+	} name;
 13+	uint16_t unknown[5];
 14+	uint32_t code_address;
 15+	uint32_t code_length;
 16+	uint32_t foo_address;
 17+	uint32_t foo_length;
 18+	uint32_t bar_address;
 19+	uint32_t bar_length;
 20+	uint16_t unknown2[3];
 21+} vos_module_map_entry;
 22+
 23+typedef struct
 24+{
 25+	struct {
 26+		uint16_t len;
 27+		char     str[32];
 28+	} name;
 29+	uint32_t address;
 30+	uint16_t unknown[3];
 31+} vos_external_var_entry;
 32+
 33+typedef struct
 34+{
 35+	uint16_t version;
 36+	struct {
 37+		uint16_t len;
 38+		char     str[32];
 39+	} binder_version;
 40+	struct {
 41+		uint16_t len;
 42+		char     str[32];
 43+	} binder_options;
 44+	struct {
 45+		uint16_t len;
 46+		char     str[32];
 47+	} system_name;
 48+	struct {
 49+		uint16_t len;
 50+		char     str[65];
 51+	} user_name;
 52+	uint32_t date_bound;
 53+	struct {
 54+		uint32_t code_address;
 55+		uint32_t static_address;
 56+	} main_entry_link;
 57+	uint32_t user_boundary;
 58+	uint16_t n_modules;
 59+	uint16_t n_external_vars;
 60+	uint16_t n_link_names;
 61+	uint16_t n_unsnapped_links;
 62+	uint16_t n_vm_pages;
 63+	uint16_t n_header_pages;
 64+	struct {
 65+		uint32_t address;
 66+		uint32_t len;
 67+	} info[3][4];
 68+	uint32_t module_map_address;
 69+	uint32_t module_map_len;
 70+	uint32_t external_vars_map_address;
 71+	uint32_t external_vars_map_len;
 72+	uint32_t link_names_map_address;
 73+	uint32_t link_names_map_len;
 74+	uint32_t link_map_address;
 75+	uint32_t link_map_len;
 76+	uint32_t header_address;
 77+	uint32_t header_len;
 78+	uint8_t  access_info[2048];
 79+	uint32_t flags;
 80+	uint16_t n_tasks;
 81+	uint32_t task_static_len[3];
 82+	uint32_t stack_len;
 83+	uint16_t n_entries;
 84+	uint32_t entry_map_address;
 85+	uint32_t entry_map_len;
 86+	uint16_t pop_version;
 87+	uint16_t processor;
 88+	struct {
 89+		uint16_t len;
 90+		char     str[32];
 91+	} release_name;
 92+	struct {
 93+		uint32_t map_address;
 94+		uint32_t map_len;
 95+		uint32_t n_relocations;
 96+	} relocation_info;
 97+	uint32_t high_water_mark;
 98+	struct {
 99+		uint16_t len;
100+		char     str[256];
101+	} copyright_notice;
102+	uint32_t module_origins[14];
103+	uint16_t processor_family;
104+	struct {
105+		uint16_t len;
106+		char     str[32];
107+	} program_name;
108+	uint32_t string_pool_address;
109+	uint32_t string_pool_len;
110+	uint32_t obj_dir_map_address;
111+	uint32_t obj_dir_map_len;
112+	uint32_t global_offset_table_address[3];
113+	struct {
114+		uint32_t address;
115+		uint32_t len;
116+	} block_map_info[3];
117+	uint32_t section_map_file_address;
118+	uint32_t section_map_address;
119+	uint32_t section_map_len;
120+	uint16_t n_sections;
121+	uint32_t max_heap_size;
122+	uint32_t max_program_size;
123+	uint32_t max_stack_size;
124+	uint32_t stack_fence_size;
125+
126+	vos_module_map_entry   *module_map_entries;
127+	vos_external_var_entry *external_vars;
128+} vos_program_module;
129+
130+int vos_read_header(FILE * f, vos_program_module *out);
131+int vos_read_alloc_module_map(FILE * f, vos_program_module *header);
132+int vos_read_alloc_external_vars(FILE * f, vos_program_module *header);
133+void vos_header_cleanup(vos_program_module *header);
134+
135+#endif //VOS_PROGRAM_MODULE_H_
A wave.c
+46, -0
 1@@ -0,0 +1,46 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm.
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#include "wave.h"
 8+#include <stddef.h>
 9+#include <string.h>
10+
11+int wave_init(FILE * f, uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels)
12+{
13+	wave_header header;
14+	memcpy(header.chunk.id, "RIFF", 4);
15+	memcpy(header.chunk.format, "WAVE", 4);
16+	header.chunk.size = 0; //This will be filled in later
17+	memcpy(header.format_header.id, "fmt ", 4);
18+	header.format_header.size = sizeof(wave_header) - (sizeof(header.chunk) + sizeof(header.data_header) + sizeof(header.format_header));
19+	header.audio_format = 1;
20+	header.num_channels = num_channels;
21+	header.sample_rate = sample_rate;
22+	header.byte_rate = sample_rate * num_channels * (bits_per_sample/8);
23+	header.block_align = num_channels * (bits_per_sample/8);
24+	header.bits_per_sample = bits_per_sample;
25+	memcpy(header.data_header.id, "data", 4);
26+	header.data_header.size = 0;//This will be filled in later;
27+	return fwrite(&header, 1, sizeof(header), f) == sizeof(header);
28+}
29+
30+int wave_finalize(FILE * f)
31+{
32+	uint32_t size = ftell(f);
33+	fseek(f, offsetof(wave_header, chunk.size), SEEK_SET);
34+	size -= 8;
35+	if (fwrite(&size, sizeof(size), 1, f) != 1) {
36+		fclose(f);
37+		return 0;
38+	}
39+	fseek(f, offsetof(wave_header, data_header.size), SEEK_SET);
40+	size -= 36;
41+	if (fwrite(&size, sizeof(size), 1, f) != 1) {
42+		fclose(f);
43+		return 0;
44+	}
45+	fclose(f);
46+	return 1;
47+}
A wave.h
+43, -0
 1@@ -0,0 +1,43 @@
 2+/*
 3+ Copyright 2013 Michael Pavone
 4+ This file is part of BlastEm. 
 5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 6+*/
 7+#ifndef WAVE_H_
 8+#define WAVE_H_
 9+
10+#include <stdint.h>
11+#include <stdio.h>
12+
13+#pragma pack(push, 1)
14+
15+typedef struct {
16+	char     id[4];
17+	uint32_t size;
18+	char     format[4];
19+} riff_chunk;
20+
21+typedef struct {
22+	char     id[4];
23+	uint32_t size;
24+} riff_sub_chunk;
25+
26+typedef struct {
27+	riff_chunk     chunk;
28+	riff_sub_chunk format_header;
29+	uint16_t       audio_format;
30+	uint16_t       num_channels;
31+	uint32_t       sample_rate;
32+	uint32_t       byte_rate;
33+	uint16_t       block_align;
34+	uint16_t       bits_per_sample;
35+	riff_sub_chunk data_header;
36+} wave_header;
37+
38+#pragma pack(pop)
39+
40+int wave_init(FILE * f, uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels);
41+int wave_finalize(FILE * f);
42+
43+#endif //WAVE_H_
44+
+426, -0
  1@@ -0,0 +1,426 @@
  2+#include <stdlib.h>
  3+#include <stddef.h>
  4+#include <string.h>
  5+#include "romdb.h"
  6+#include "genesis.h"
  7+#include "tern.h"
  8+#include "xband.h"
  9+#include "util.h"
 10+
 11+#define BIT_ROM_HI 4
 12+
 13+enum {
 14+	PATCH0_LOW,
 15+	PATCH0_MID,
 16+	PATCH0_HI,
 17+	PATCH1_LOW=4,
 18+	PATCH1_MID,
 19+	PATCH1_HI,
 20+	PATCH2_LOW=8,
 21+	PATCH2_MID,
 22+	PATCH2_HI,
 23+	PATCH3_LOW=12,
 24+	PATCH3_MID,
 25+	PATCH3_HI,
 26+	PATCH4_LOW=16,
 27+	PATCH4_MID,
 28+	PATCH4_HI,
 29+	PATCH5_LOW=20,
 30+	PATCH5_MID,
 31+	PATCH5_HI,
 32+	PATCH6_LOW=24,
 33+	PATCH6_MID,
 34+	PATCH6_HI,
 35+	PATCH7_LOW=28,
 36+	PATCH7_MID,
 37+	PATCH7_HI,
 38+	PATCH8_LOW=32,
 39+	PATCH8_MID,
 40+	PATCH8_HI,
 41+	PATCH9_LOW=36,
 42+	PATCH9_MID,
 43+	PATCH9_HI,
 44+	PATCH10_LOW=40,
 45+	PATCH10_MID,
 46+	PATCH10_HI,
 47+	RANGE0_START_LOW=44,
 48+	RANGE0_START_MID,
 49+	RANGE0_START_HI,
 50+	RANGE1_START=48,
 51+	RANGE1_START_MID,
 52+	RANGE1_START_HI,
 53+	MAGIC_LOW=56,
 54+	MAGIC_MID,
 55+	MAGIC_HI,
 56+	RANGE0_END_LOW=64,
 57+	RANGE0_END_MID,
 58+	RANGE0_END_HI,
 59+	RANGE1_END_LOW=68,
 60+	RANGE1_END_MID,
 61+	RANGE1_END_HI,
 62+	RANGE0_DEST_LOW=80,
 63+	RANGE0_DEST_HI,
 64+	RANGE0_MASK,
 65+	RANGE1_DEST_LOW=84,
 66+	RANGE1_DEST_HI,
 67+	RANGE1_MASK,
 68+	
 69+	MORE_MYSTERY=219,
 70+	UNKNOWN_REG=221,
 71+	UNKNOWN_REG2,
 72+	UNKNOWN_REG3,
 73+	
 74+};
 75+
 76+//#define DO_DEBUG_PRINT
 77+#ifdef DO_DEBUG_PRINT
 78+#define dprintf printf
 79+#define dputs puts
 80+#else
 81+#define dprintf
 82+#define dputs
 83+#endif
 84+
 85+uint8_t xband_detect(uint8_t *rom, uint32_t rom_size)
 86+{
 87+	if (rom_size < 0x200) {
 88+		return 0;
 89+	} 
 90+	
 91+	//product ID is all NULL
 92+	for (int i = GAME_ID_OFF; i <= (GAME_ID_OFF + GAME_ID_LEN); i++)
 93+	{
 94+		if (rom[i]) {
 95+			return 0;
 96+		}
 97+	}
 98+	
 99+	if (!memcmp(rom+8, "DAVE", 4)) {
100+		//XBAND test roms
101+		return 1;
102+	}
103+	
104+	//Internal ROM is 512KB, accept larger ones for overdumps and custom firmware
105+	if (rom_size < (512*1024)) {
106+		return 0;
107+	}
108+	
109+	//ROM has no standard header, but does have a jump at $100
110+	if (rom[0x100] != 0x4E || rom[0x101] != 0xF9) {
111+		return 0;
112+	}
113+	
114+	
115+	return 1;
116+}
117+
118+static xband *get_xband(genesis_context *gen)
119+{
120+	if (!gen->extra) {
121+		gen->extra = gen->m68k->options->gen.memmap[0].buffer;
122+		gen->m68k->mem_pointers[2] = (uint16_t *)gen->save_storage;
123+	}
124+	return gen->extra;
125+}
126+
127+static void update_control(genesis_context *gen, uint8_t value)
128+{
129+	xband *x = gen->extra;
130+	if ((x->control ^ value) & BIT_ROM_HI) {
131+		if (value & BIT_ROM_HI) {
132+			gen->m68k->mem_pointers[0] = (uint16_t *)gen->save_storage;
133+			gen->m68k->mem_pointers[1] = NULL;
134+			gen->m68k->mem_pointers[2] = gen->cart;
135+			gen->m68k->mem_pointers[3] = x->cart_space - 0x100000;
136+		} else {
137+			gen->m68k->mem_pointers[0] = x->cart_space;
138+			gen->m68k->mem_pointers[1] = x->cart_space;
139+			gen->m68k->mem_pointers[2] = (uint16_t *)gen->save_storage;
140+			gen->m68k->mem_pointers[3] = NULL;
141+		}
142+		m68k_invalidate_code_range(gen->m68k, 0, 0x3BC000);
143+	}
144+	x->control = value;
145+}
146+
147+static void *xband_write_b(uint32_t address, void *context, uint8_t value)
148+{
149+	m68k_context *m68k = context;
150+	genesis_context *gen = m68k->system;
151+	xband *x = get_xband(gen);
152+	if (address == 0x181) {
153+		x->kill = value;
154+		dprintf("Write to \"soft\" kill register %X\n", value);
155+	} else if (address == 0x183) {
156+		update_control(gen, value);
157+		dprintf("Write to \"soft\" control register %X\n", value);
158+	} else if ((x->control & BIT_ROM_HI && address < 0x200000) || (address >= 0x200000 && !(x->control & BIT_ROM_HI))) {
159+		gen->save_storage[(address & 0xFFFF) ^ 1] = value;
160+		m68k_handle_code_write(address, m68k);
161+		//TODO: handle code at mirror addresses
162+	} else {
163+		printf("Unhandled write to cartridge area %X: %X\n", address, value);
164+	}
165+	return context;
166+}
167+
168+static void *xband_write_hi_b(uint32_t address, void *context, uint8_t value)
169+{
170+	return xband_write_b(address | 0x200000, context, value);
171+}
172+
173+static void *xband_write_w(uint32_t address, void *context, uint16_t value)
174+{
175+	m68k_context *m68k = context;
176+	genesis_context *gen = m68k->system;
177+	xband *x = get_xband(gen);
178+	if (address == 0x180 || address == 0x182) {
179+		return xband_write_b(address | 1, context, value);
180+	} else if ((x->control & BIT_ROM_HI && address < 0x200000) || (address >= 0x200000 && !(x->control & BIT_ROM_HI))) {
181+		gen->save_storage[address & 0xFFFE] = value;
182+		gen->save_storage[(address & 0xFFFE) | 1] = value >> 8;
183+		m68k_handle_code_write(address, m68k);
184+		//TODO: handle code at mirror addresses
185+		return context;
186+	}
187+	printf("Unhandled write to %X: %X\n", address, value);
188+	return context;
189+}
190+
191+static void *xband_write_hi_w(uint32_t address, void *context, uint16_t value)
192+{
193+	return xband_write_w(address | 0x200000, context, value);
194+}
195+
196+static uint16_t xband_read_w(uint32_t address, void *context)
197+{
198+	m68k_context *m68k = context;
199+	genesis_context *gen = m68k->system;
200+	xband *x = get_xband(gen);
201+	//TODO: actually do something intelligent here
202+	return x->cart_space[address >> 1];
203+}
204+
205+static uint16_t xband_read_hi_w(uint32_t address, void *context)
206+{
207+	return xband_read_w(address | 0x200000, context);
208+}
209+
210+static uint8_t xband_read_b(uint32_t address, void *context)
211+{
212+	uint16_t val = xband_read_w(address, context);
213+	return address & 1 ? val : val >> 8;
214+}
215+
216+static uint8_t xband_read_hi_b(uint32_t address, void *context)
217+{
218+	return xband_read_b(address | 0x200000, context);
219+}
220+
221+static void *xband_reg_write_b(uint32_t address, void *context, uint8_t value)
222+{
223+	m68k_context *m68k = context;
224+	genesis_context *gen = m68k->system;
225+	if (!(address & 1)) {
226+		printf("Ignoring write to even address %X: %X\n", address, value);
227+		return context;
228+	}
229+	xband *x = get_xband(gen);
230+	if (address < 0x3BFE00) {
231+		uint32_t offset = (address - 0x3BC001) / 2;
232+		if (offset < XBAND_REGS) {
233+			switch (offset)
234+			{
235+			case MORE_MYSTERY:
236+			case UNKNOWN_REG:
237+				dprintf("Write to mysterious reg: %X: %X\n", address, value);
238+				value = value & 0x7F;
239+				break;
240+			case UNKNOWN_REG3:
241+				dprintf("Write to mysterious reg: %X: %X\n", address, value);
242+				value = value & 0xFE;
243+				break;
244+			}
245+			x->regs[offset] = value;
246+			dprintf("Write to register %X(%d): %X\n", address, offset, value);
247+		} else {
248+			printf("Unhandled register write %X: %X\n", address, value);
249+		}
250+	} else {
251+		if (address == 0x3BFE01) {
252+			x->kill = value;
253+			dprintf("Write to kill register %X\n", value);
254+		} else if (address == 0x3BFE03) {
255+			update_control(gen, value);
256+			dprintf("Write to control register %X\n", value);
257+		} else {
258+			printf("Unhandled register write %X: %X\n", address, value);
259+		}
260+	}
261+	return context;
262+}
263+
264+static void *xband_reg_write_w(uint32_t address, void *context, uint16_t value)
265+{
266+	return xband_reg_write_b(address | 1, context, value);
267+}
268+
269+static uint8_t xband_reg_read_b(uint32_t address, void *context)
270+{
271+	m68k_context *m68k = context;
272+	genesis_context *gen = m68k->system;
273+	if (!(address & 1)) {
274+		printf("Read from even address %X\n", address);
275+		return gen->header.get_open_bus_value(&gen->header) >> 8;
276+	}
277+	xband *x = get_xband(gen);
278+	if (address < 0x3BFE00) {
279+		uint32_t offset = (address - 0x3BC001) / 2;
280+		if (offset < XBAND_REGS) {
281+			dprintf("Regsister read: %X\n", address);
282+			return x->regs[offset];
283+		} else {
284+			printf("Unhandled register read from address %X\n", address);
285+			return 0x5D;
286+		}
287+	} else {
288+		if (address == 0x3BFE01) {
289+			return x->kill;
290+		} else if (address == 0x3BFE03) {
291+			return x->control;
292+		} else {
293+			printf("Unhandled register read from address %X\n", address);
294+			return 0x5D;
295+		}
296+	}
297+}
298+
299+static uint16_t xband_reg_read_w(uint32_t address, void *context)
300+{
301+	m68k_context *m68k = context;
302+	genesis_context *gen = m68k->system;
303+	uint16_t value = xband_reg_read_b(address | 1, context);
304+	value |= gen->header.get_open_bus_value(&gen->header) & 0xFF00;
305+	return value;
306+}
307+
308+void xband_serialize(genesis_context *gen, serialize_buffer *buf)
309+{
310+	xband *x = get_xband(gen);
311+	save_int8(buf, x->kill);
312+	save_int8(buf, x->control);
313+	save_buffer8(buf, x->regs, XBAND_REGS);
314+}
315+
316+void xband_deserialize(deserialize_buffer *buf, genesis_context *gen)
317+{
318+	xband *x = get_xband(gen);
319+	x->kill = load_int8(buf);
320+	update_control(gen, load_int8(buf));
321+	for (int i = 0; i < XBAND_REGS; i++)
322+	{
323+		xband_write_b(0x3BC001 + i*2, gen->m68k, load_int8(buf));
324+	}
325+}
326+
327+rom_info xband_configure_rom(tern_node *rom_db, void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks)
328+{
329+	rom_info info;
330+	if (lock_on && lock_on_size) {
331+		rom_info lock_on_info = configure_rom(rom_db, lock_on, lock_on_size, NULL, 0, base_map, base_chunks);
332+		info.name = alloc_concat("XBAND - ", lock_on_info.name);
333+		info.regions = lock_on_info.regions;
334+		free_rom_info(&lock_on_info);
335+	} else {
336+		info.name = strdup("XBAND");
337+		info.regions = REGION_J|REGION_U|REGION_E;
338+	}
339+	info.save_size = 64*1024;
340+	info.save_buffer = malloc(info.save_size);
341+	info.save_mask = info.save_size-1;
342+	info.save_type = RAM_FLAG_BOTH;
343+	info.port1_override = info.ext_override = info.mouse_mode = NULL;
344+	info.port2_override = strdup("xband keyboard");
345+	info.eeprom_map = NULL;
346+	info.num_eeprom = 0;
347+	info.rom = rom;
348+	info.rom_size = rom_size;
349+	info.is_save_lock_on = 0;
350+	xband *x = calloc(sizeof(xband), 1);
351+	rom_size = nearest_pow2(rom_size);
352+	for (int i = 0; (i + rom_size) <= sizeof(x->cart_space) / 2; i += rom_size)
353+	{
354+		memcpy(x->cart_space + i/2, rom, rom_size);
355+	}
356+	if (lock_on && lock_on_size >= 0x200) {
357+		memcpy(x->cart_space + 0x80, ((uint16_t *)lock_on) + 0x80, 0x100);
358+	}
359+	//observed power on values
360+	memset(x->regs, 0, sizeof(x->regs));
361+	x->regs[0x7C] = 0;
362+	x->regs[0x7D] = 0x80;
363+	x->regs[0xB4] = 0x7F;
364+	x->regs[UNKNOWN_REG2] = 8;
365+	
366+	byteswap_rom(0x400000, x->cart_space);
367+	
368+	info.mapper_type = MAPPER_XBAND;
369+	info.map_chunks = base_chunks + 5;
370+	info.map = calloc(sizeof(memmap_chunk), info.map_chunks);
371+	info.map[0].mask = 0xFFFFFF;
372+	info.map[0].aux_mask = 0xFFFFFF;
373+	info.map[0].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_AUX_BUFF;
374+	info.map[0].start = 0;
375+	info.map[0].end = 0x10000;
376+	info.map[0].ptr_index = 0;
377+	info.map[0].buffer = x->cart_space;
378+	info.map[0].write_16 = xband_write_w;
379+	info.map[0].write_8 = xband_write_b;
380+	info.map[0].read_16 = xband_read_w;
381+	info.map[0].read_8 = xband_read_b;
382+	info.map[1].mask = 0xFFFFFF;
383+	info.map[1].aux_mask = 0xFFFFFF;
384+	info.map[1].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_AUX_BUFF;
385+	info.map[1].start = 0x10000;
386+	info.map[1].end = 0x200000;
387+	info.map[1].ptr_index = 1;
388+	info.map[1].buffer = x->cart_space;
389+	info.map[1].write_16 = xband_write_w;
390+	info.map[1].write_8 = xband_write_b;
391+	info.map[1].read_16 = xband_read_w;
392+	info.map[1].read_8 = xband_read_b;
393+	info.map[2].mask = 0xFFFF;
394+	info.map[2].aux_mask = 0xFFFF;
395+	info.map[2].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX|MMAP_FUNC_NULL;
396+	info.map[2].start = 0x200000;
397+	info.map[2].end = 0x210000;
398+	info.map[2].ptr_index = 2;
399+	info.map[2].buffer = NULL;
400+	info.map[2].write_16 = xband_write_hi_w;
401+	info.map[2].write_8 = xband_write_hi_b;
402+	info.map[2].read_16 = xband_read_hi_w;
403+	info.map[2].read_8 = xband_read_hi_b;
404+	info.map[3].mask = 0xFFFFFF;
405+	info.map[3].aux_mask = 0xFFFFFF;
406+	info.map[3].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX|MMAP_FUNC_NULL;
407+	info.map[3].start = 0x210000;
408+	info.map[3].end = 0x3BC000;
409+	info.map[3].ptr_index = 3;
410+	info.map[3].buffer = NULL;
411+	info.map[3].write_16 = xband_write_w;
412+	info.map[3].write_8 = xband_write_b;
413+	info.map[3].read_16 = xband_read_w;
414+	info.map[3].read_8 = xband_read_b;
415+	info.map[4].mask = 0xFFFFFF;
416+	info.map[4].flags = MMAP_READ|MMAP_CODE|MMAP_PTR_IDX|MMAP_FUNC_NULL;
417+	info.map[4].start = 0x3BC000;
418+	info.map[4].end = 0x3C0000;
419+	info.map[4].ptr_index = 4;
420+	info.map[4].write_16 = xband_reg_write_w;
421+	info.map[4].write_8 = xband_reg_write_b;
422+	info.map[4].read_16 = xband_reg_read_w;
423+	info.map[4].read_8 = xband_reg_read_b;
424+	memcpy(info.map + 5, base_map, base_chunks * sizeof(memmap_chunk));
425+	
426+	return info;
427+}
+20, -0
 1@@ -0,0 +1,20 @@
 2+#ifndef XBAND_H_
 3+#define XBAND_H_
 4+#include <stdint.h>
 5+#include "serialize.h"
 6+
 7+#define XBAND_REGS 0xE0
 8+
 9+typedef struct {
10+	uint16_t cart_space[0x200000];
11+	uint8_t regs[XBAND_REGS];
12+	uint8_t kill;
13+	uint8_t control;
14+} xband;
15+
16+uint8_t xband_detect(uint8_t *rom, uint32_t rom_size);
17+rom_info xband_configure_rom(tern_node *rom_db, void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks);
18+void xband_serialize(genesis_context *gen, serialize_buffer *buf);
19+void xband_deserialize(deserialize_buffer *buf, genesis_context *gen);
20+
21+#endif //XBAND_H_
+1245, -0
   1@@ -0,0 +1,1245 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include <string.h>
   8+#include <math.h>
   9+#include <stdio.h>
  10+#include <stdlib.h>
  11+#include "ym2612.h"
  12+#include "render.h"
  13+#include "wave.h"
  14+#include "blastem.h"
  15+
  16+//#define DO_DEBUG_PRINT
  17+#ifdef DO_DEBUG_PRINT
  18+#define dfprintf fprintf
  19+#define dfopen(var, fname, mode) var=fopen(fname, mode)
  20+#else
  21+#define dfprintf
  22+#define dfopen(var, fname, mode)
  23+#endif
  24+
  25+#define BUSY_CYCLES_ADDRESS 17
  26+#define BUSY_CYCLES_DATA_LOW 83
  27+#define BUSY_CYCLES_DATA_HIGH 47
  28+#define OP_UPDATE_PERIOD 144
  29+
  30+#define BIT_TIMERA_ENABLE 0x1
  31+#define BIT_TIMERB_ENABLE 0x2
  32+#define BIT_TIMERA_OVEREN 0x4
  33+#define BIT_TIMERB_OVEREN 0x8
  34+#define BIT_TIMERA_RESET  0x10
  35+#define BIT_TIMERB_RESET  0x20
  36+
  37+#define BIT_TIMERA_LOAD   0x40
  38+#define BIT_TIMERB_LOAD   0x80
  39+
  40+#define BIT_STATUS_TIMERA 0x1
  41+#define BIT_STATUS_TIMERB 0x2
  42+
  43+static uint32_t ym_calc_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op);
  44+
  45+enum {
  46+	PHASE_ATTACK,
  47+	PHASE_DECAY,
  48+	PHASE_SUSTAIN,
  49+	PHASE_RELEASE
  50+};
  51+
  52+uint8_t did_tbl_init = 0;
  53+//According to Nemesis, real hardware only uses a 256 entry quarter sine table; however,
  54+//memory is cheap so using a half sine table will probably save some cycles
  55+//a full sine table would be nice, but negative numbers don't get along with log2
  56+#define SINE_TABLE_SIZE 512
  57+static uint16_t sine_table[SINE_TABLE_SIZE];
  58+//Similar deal here with the power table for log -> linear conversion
  59+//According to Nemesis, real hardware only uses a 256 entry table for the fractional part
  60+//and uses the whole part as a shift amount.
  61+#define POW_TABLE_SIZE (1 << 13)
  62+static uint16_t pow_table[POW_TABLE_SIZE];
  63+
  64+static uint16_t rate_table_base[] = {
  65+	//main portion
  66+	0,1,0,1,0,1,0,1,
  67+	0,1,0,1,1,1,0,1,
  68+	0,1,1,1,0,1,1,1,
  69+	0,1,1,1,1,1,1,1,
  70+	//top end
  71+	1,1,1,1,1,1,1,1,
  72+	1,1,1,2,1,1,1,2,
  73+	1,2,1,2,1,2,1,2,
  74+	1,2,2,2,1,2,2,2,
  75+};
  76+
  77+static uint16_t rate_table[64*8];
  78+
  79+static uint8_t lfo_timer_values[] = {108, 77, 71, 67, 62, 44, 8, 5};
  80+static uint8_t lfo_pm_base[][8] = {
  81+	{0,   0,   0,   0,   0,   0,   0,   0},
  82+	{0,   0,   0,   0,   4,   4,   4,   4},
  83+	{0,   0,   0,   4,   4,   4,   8,   8},
  84+	{0,   0,   4,   4,   8,   8, 0xc, 0xc},
  85+	{0,   0,   4,   8,   8,   8, 0xc,0x10},
  86+	{0,   0,   8, 0xc,0x10,0x10,0x14,0x18},
  87+	{0,   0,0x10,0x18,0x20,0x20,0x28,0x30},
  88+	{0,   0,0x20,0x30,0x40,0x40,0x50,0x60}
  89+};
  90+static int16_t lfo_pm_table[128 * 32 * 8];
  91+
  92+int16_t ams_shift[] = {8, 1, -1, -2};
  93+
  94+#define MAX_ENVELOPE 0xFFC
  95+#define YM_DIVIDER 2
  96+#define CYCLE_NEVER 0xFFFFFFFF
  97+
  98+static uint16_t round_fixed_point(double value, int dec_bits)
  99+{
 100+	return value * (1 << dec_bits) + 0.5;
 101+}
 102+
 103+static FILE * debug_file = NULL;
 104+static uint32_t first_key_on=0;
 105+
 106+static ym2612_context * log_context = NULL;
 107+
 108+static void ym_finalize_log()
 109+{
 110+	if (!log_context) {
 111+		return;
 112+	}
 113+	for (int i = 0; i < NUM_CHANNELS; i++) {
 114+		if (log_context->channels[i].logfile) {
 115+			wave_finalize(log_context->channels[i].logfile);
 116+		}
 117+	}
 118+	log_context = NULL;
 119+}
 120+
 121+void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock)
 122+{
 123+	render_audio_adjust_clock(context->audio, master_clock, context->clock_inc * NUM_OPERATORS);
 124+}
 125+
 126+#define TIMER_A_MAX 1023
 127+#define TIMER_B_MAX 255
 128+
 129+void ym_reset(ym2612_context *context)
 130+{
 131+	memset(context->part1_regs, 0, sizeof(context->part1_regs));
 132+	memset(context->part2_regs, 0, sizeof(context->part2_regs));
 133+	memset(context->operators, 0, sizeof(context->operators));
 134+	FILE* savedlogs[NUM_CHANNELS];
 135+	for (int i = 0; i < NUM_CHANNELS; i++)
 136+	{
 137+		savedlogs[i] = context->channels[i].logfile;
 138+	}
 139+	memset(context->channels, 0, sizeof(context->channels));
 140+	memset(context->ch3_supp, 0, sizeof(context->ch3_supp));
 141+	context->selected_reg = 0;
 142+	context->csm_keyon = 0;
 143+	context->ch3_mode = 0;
 144+	context->dac_enable = 0;
 145+	context->status = 0;
 146+	context->timer_a_load = 0;
 147+	context->timer_b_load = 0;
 148+	//TODO: Confirm these on hardware
 149+	context->timer_a = TIMER_A_MAX;
 150+	context->timer_b = TIMER_B_MAX;
 151+	
 152+	//TODO: Reset LFO state
 153+	
 154+	//some games seem to expect that the LR flags start out as 1
 155+	for (int i = 0; i < NUM_CHANNELS; i++) {
 156+		context->channels[i].lr = 0xC0;
 157+		context->channels[i].logfile = savedlogs[i];
 158+	}
 159+	context->write_cycle = CYCLE_NEVER;
 160+	for (int i = 0; i < NUM_OPERATORS; i++) {
 161+		context->operators[i].envelope = MAX_ENVELOPE;
 162+		context->operators[i].env_phase = PHASE_RELEASE;
 163+	}
 164+}
 165+
 166+void ym_init(ym2612_context * context, uint32_t master_clock, uint32_t clock_div, uint32_t options)
 167+{
 168+	static uint8_t registered_finalize;
 169+	dfopen(debug_file, "ym_debug.txt", "w");
 170+	memset(context, 0, sizeof(*context));
 171+	context->clock_inc = clock_div * 6;
 172+	context->audio = render_audio_source(master_clock, context->clock_inc * NUM_OPERATORS, 2);
 173+	
 174+	//some games seem to expect that the LR flags start out as 1
 175+	for (int i = 0; i < NUM_CHANNELS; i++) {
 176+		if (options & YM_OPT_WAVE_LOG) {
 177+			char fname[64];
 178+			sprintf(fname, "ym_channel_%d.wav", i);
 179+			FILE * f = context->channels[i].logfile = fopen(fname, "wb");
 180+			if (!f) {
 181+				fprintf(stderr, "Failed to open WAVE log file %s for writing\n", fname);
 182+				continue;
 183+			}
 184+			if (!wave_init(f, master_clock / (context->clock_inc * NUM_OPERATORS), 16, 1)) {
 185+				fclose(f);
 186+				context->channels[i].logfile = NULL;
 187+			}
 188+		}
 189+	}
 190+	if (options & YM_OPT_WAVE_LOG) {
 191+		log_context = context;
 192+		if (!registered_finalize) {
 193+			atexit(ym_finalize_log);
 194+			registered_finalize = 1;
 195+		}
 196+	}
 197+	if (!did_tbl_init) {
 198+		//populate sine table
 199+		for (int32_t i = 0; i < 512; i++) {
 200+			double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 );
 201+
 202+			//table stores 4.8 fixed pointed representation of the base 2 log
 203+			sine_table[i] = round_fixed_point(-log2(sine), 8);
 204+		}
 205+		//populate power table
 206+		for (int32_t i = 0; i < POW_TABLE_SIZE; i++) {
 207+			double linear = pow(2, -((double)((i & 0xFF)+1) / 256.0));
 208+			int32_t tmp = round_fixed_point(linear, 11);
 209+			int32_t shift = (i >> 8) - 2;
 210+			if (shift < 0) {
 211+				tmp <<= 0-shift;
 212+			} else {
 213+				tmp >>= shift;
 214+			}
 215+			pow_table[i] =  tmp;
 216+		}
 217+		//populate envelope generator rate table, from small base table
 218+		for (int rate = 0; rate < 64; rate++) {
 219+			for (int cycle = 0; cycle < 8; cycle++) {
 220+				uint16_t value;
 221+				if (rate < 2) {
 222+					value = 0;
 223+				} else if (rate >= 60) {
 224+					value = 8;
 225+				} else if (rate < 8) {
 226+					value = rate_table_base[((rate & 6) == 6 ? 16 : 0) + cycle];
 227+				} else if (rate < 48) {
 228+					value = rate_table_base[(rate & 0x3) * 8 + cycle];
 229+				} else {
 230+					value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << ((rate - 48) >> 2);
 231+				}
 232+				rate_table[rate * 8 + cycle] = value;
 233+			}
 234+		}
 235+		//populate LFO PM table from small base table
 236+		//seems like there must be a better way to derive this
 237+		for (int freq = 0; freq < 128; freq++) {
 238+			for (int pms = 0; pms < 8; pms++) {
 239+				for (int step = 0; step < 32; step++) {
 240+					int16_t value = 0;
 241+					for (int bit = 0x40, shift = 0; bit > 0; bit >>= 1, shift++) {
 242+						if (freq & bit) {
 243+							value += lfo_pm_base[pms][(step & 0x8) ? 7-step & 7 : step & 7] >> shift;
 244+						}
 245+					}
 246+					if (step & 0x10) {
 247+						value = -value;
 248+					}
 249+					lfo_pm_table[freq * 256 + pms * 32 + step] = value;
 250+				}
 251+			}
 252+		}
 253+	}
 254+	ym_reset(context);
 255+	ym_enable_zero_offset(context, 1);
 256+}
 257+
 258+void ym_free(ym2612_context *context)
 259+{
 260+	render_free_source(context->audio);
 261+	if (context == log_context) {
 262+		ym_finalize_log();
 263+	}
 264+	free(context);
 265+}
 266+
 267+void ym_enable_zero_offset(ym2612_context *context, uint8_t enabled)
 268+{
 269+	if (enabled) {
 270+		context->zero_offset = 0x70;
 271+		context->volume_mult = 79;
 272+		context->volume_div = 120;
 273+	} else {
 274+		context->zero_offset = 0;
 275+		context->volume_mult = 2;
 276+		context->volume_div = 3;
 277+	}
 278+}
 279+#define YM_MOD_SHIFT 1
 280+
 281+#define CSM_MODE 0x80
 282+
 283+#define SSG_ENABLE    8
 284+#define SSG_INVERT    4
 285+#define SSG_ALTERNATE 2
 286+#define SSG_HOLD      1
 287+
 288+#define SSG_CENTER 0x800
 289+
 290+static void start_envelope(ym_operator *op, ym_channel *channel)
 291+{
 292+	//Deal with "infinite" attack rates
 293+	uint8_t rate = op->rates[PHASE_ATTACK];
 294+	if (rate) {
 295+		uint8_t ks = channel->keycode >> op->key_scaling;;
 296+		rate = rate*2 + ks;
 297+	}
 298+	if (rate >= 62) {
 299+		op->env_phase = PHASE_DECAY;
 300+		op->envelope = 0;
 301+	} else {
 302+		op->env_phase = PHASE_ATTACK;
 303+	}
 304+}
 305+
 306+static void keyon(ym_operator *op, ym_channel *channel)
 307+{
 308+	start_envelope(op, channel);
 309+	op->phase_counter = 0;
 310+	op->inverted = op->ssg & SSG_INVERT;
 311+}
 312+
 313+static const uint8_t keyon_bits[] = {0x10, 0x40, 0x20, 0x80};
 314+
 315+static void keyoff(ym_operator *op)
 316+{
 317+	op->env_phase = PHASE_RELEASE;
 318+	if (op->inverted) {
 319+		//Nemesis says the inversion state doesn't change here, but I don't see how that is observable either way
 320+		op->inverted = 0;
 321+		op->envelope = (SSG_CENTER - op->envelope) & MAX_ENVELOPE;
 322+	}
 323+}
 324+
 325+static void csm_keyoff(ym2612_context *context)
 326+{
 327+	context->csm_keyon = 0;
 328+	uint8_t changes = 0xF0 ^ context->channels[2].keyon;
 329+	for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
 330+	{
 331+		if (changes & keyon_bits[bit]) {
 332+			keyoff(context->operators + op);
 333+		}
 334+	}
 335+}
 336+
 337+void ym_run(ym2612_context * context, uint32_t to_cycle)
 338+{
 339+	//printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
 340+	//TODO: Fix channel update order OR remap channels in register write
 341+	for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) {
 342+		//Update timers at beginning of 144 cycle period
 343+		if (!context->current_op) {
 344+			if (context->timer_control & BIT_TIMERA_ENABLE) {
 345+				if (context->timer_a != TIMER_A_MAX) {
 346+					context->timer_a++;
 347+					if (context->csm_keyon) {
 348+						csm_keyoff(context);
 349+					}
 350+				} else {
 351+					if (context->timer_control & BIT_TIMERA_LOAD) {
 352+						context->timer_control &= ~BIT_TIMERA_LOAD;
 353+					} else if (context->timer_control & BIT_TIMERA_OVEREN) {
 354+						context->status |= BIT_STATUS_TIMERA;
 355+					}
 356+					context->timer_a = context->timer_a_load;
 357+					if (!context->csm_keyon && context->ch3_mode == CSM_MODE) {
 358+						context->csm_keyon = 0xF0;
 359+						uint8_t changes = 0xF0 ^ context->channels[2].keyon;;
 360+						for (uint8_t op = 2*4, bit = 0; op < 3*4; op++, bit++)
 361+						{
 362+							if (changes & keyon_bits[bit]) {
 363+								keyon(context->operators + op, context->channels + 2);
 364+							}
 365+						}
 366+					}
 367+				}
 368+			}
 369+			if (!context->sub_timer_b) {
 370+				if (context->timer_control & BIT_TIMERB_ENABLE) {
 371+					if (context->timer_b != TIMER_B_MAX) {
 372+						context->timer_b++;
 373+					} else {
 374+						if (context->timer_control & BIT_TIMERB_LOAD) {
 375+							context->timer_control &= ~BIT_TIMERB_LOAD;
 376+						} else if (context->timer_control & BIT_TIMERB_OVEREN) {
 377+							context->status |= BIT_STATUS_TIMERB;
 378+						}
 379+						context->timer_b = context->timer_b_load;
 380+					}
 381+				}
 382+			}
 383+			context->sub_timer_b += 0x10;
 384+			//Update LFO
 385+			if (context->lfo_enable) {
 386+				if (context->lfo_counter) {
 387+					context->lfo_counter--;
 388+				} else {
 389+					context->lfo_counter = lfo_timer_values[context->lfo_freq];
 390+					context->lfo_am_step += 2;
 391+					context->lfo_am_step &= 0xFE;
 392+					context->lfo_pm_step = context->lfo_am_step / 8;
 393+				}
 394+			}
 395+		}
 396+		//Update Envelope Generator
 397+		if (!(context->current_op % 3)) {
 398+			uint32_t env_cyc = context->env_counter;
 399+			uint32_t op = context->current_env_op;
 400+			ym_operator * operator = context->operators + op;
 401+			ym_channel * channel = context->channels + op/4;
 402+			uint8_t rate;
 403+			if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
 404+				//operator->envelope = operator->sustain_level;
 405+				operator->env_phase = PHASE_SUSTAIN;
 406+			}
 407+			rate = operator->rates[operator->env_phase];
 408+			if (rate) {
 409+				uint8_t ks = channel->keycode >> operator->key_scaling;;
 410+				rate = rate*2 + ks;
 411+				if (rate > 63) {
 412+					rate = 63;
 413+				}
 414+			}
 415+			uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
 416+			if (first_key_on) {
 417+				dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1));
 418+			}
 419+			if (!(env_cyc & ((1 << cycle_shift) - 1))) {
 420+				uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
 421+				uint16_t envelope_inc = rate_table[rate * 8 + update_cycle];
 422+				if (operator->env_phase == PHASE_ATTACK) {
 423+					//this can probably be optimized to a single shift rather than a multiply + shift
 424+					if (first_key_on) {
 425+						dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc);
 426+					}
 427+					uint16_t old_env = operator->envelope;
 428+					operator->envelope += ((~operator->envelope * envelope_inc) >> 4) & 0xFFFFFFFC;
 429+					if (operator->envelope > old_env) {
 430+						//Handle overflow
 431+						operator->envelope = 0;
 432+					}
 433+					if (!operator->envelope) {
 434+						operator->env_phase = PHASE_DECAY;
 435+					}
 436+				} else {
 437+					if (first_key_on) {
 438+						dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc,
 439+							operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release"));
 440+					}
 441+					if (operator->ssg) {
 442+						if (operator->envelope < SSG_CENTER) {
 443+							envelope_inc *= 4;
 444+						} else {
 445+							envelope_inc = 0;
 446+						}
 447+					}
 448+					//envelope value is 10-bits, but it will be used as a 4.8 value
 449+					operator->envelope += envelope_inc << 2;
 450+					//clamp to max attenuation value
 451+					if (
 452+						operator->envelope > MAX_ENVELOPE 
 453+						|| (operator->env_phase == PHASE_RELEASE && operator->envelope >= SSG_CENTER)
 454+					) {
 455+						operator->envelope = MAX_ENVELOPE;
 456+					}
 457+				}
 458+			}
 459+			context->current_env_op++;
 460+			if (context->current_env_op == NUM_OPERATORS) {
 461+				context->current_env_op = 0;
 462+				context->env_counter++;
 463+			}
 464+		}
 465+
 466+		//Update Phase Generator
 467+		uint32_t channel = context->current_op / 4;
 468+		if (channel != 5 || !context->dac_enable) {
 469+			uint32_t op = context->current_op;
 470+			//printf("updating operator %d of channel %d\n", op, channel);
 471+			ym_operator * operator = context->operators + op;
 472+			ym_channel * chan = context->channels + channel;
 473+			uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
 474+			operator->phase_counter += ym_calc_phase_inc(context, operator, context->current_op);
 475+			int16_t mod = 0;
 476+			if (op & 3) {
 477+				if (operator->mod_src[0]) {
 478+					mod = *operator->mod_src[0];
 479+					if (operator->mod_src[1]) {
 480+						mod += *operator->mod_src[1];
 481+					}
 482+					mod >>= YM_MOD_SHIFT;
 483+				}
 484+			} else {
 485+				if (chan->feedback) {
 486+					mod = (chan->op1_old + operator->output) >> (10-chan->feedback);
 487+				}
 488+			}
 489+			uint16_t env = operator->envelope;
 490+			if (operator->ssg) {
 491+				if (env >= SSG_CENTER) {
 492+					if (operator->ssg & SSG_ALTERNATE) {
 493+						if (operator->env_phase != PHASE_RELEASE && (
 494+							!(operator->ssg & SSG_HOLD) || ((operator->ssg ^ operator->inverted) & SSG_INVERT) == 0
 495+						)) {
 496+							operator->inverted ^= SSG_INVERT;
 497+						}
 498+					} else if (!(operator->ssg & SSG_HOLD)) {
 499+						phase = operator->phase_counter = 0;
 500+					}
 501+					if (
 502+						(operator->env_phase == PHASE_DECAY || operator->env_phase == PHASE_SUSTAIN) 
 503+						&& !(operator->ssg & SSG_HOLD)
 504+					) {
 505+						start_envelope(operator, chan);
 506+						env = operator->envelope;
 507+					}
 508+				}
 509+				if (operator->inverted) {
 510+					env = (SSG_CENTER - env) & MAX_ENVELOPE;
 511+				}
 512+			}
 513+			env += operator->total_level;
 514+			if (operator->am) {
 515+				uint16_t base_am = (context->lfo_am_step & 0x80 ? context->lfo_am_step : ~context->lfo_am_step) & 0x7E;
 516+				if (ams_shift[chan->ams] >= 0) {
 517+					env += (base_am >> ams_shift[chan->ams]) & MAX_ENVELOPE;
 518+				} else {
 519+					env += base_am << (-ams_shift[chan->ams]);
 520+				}
 521+			}
 522+			if (env > MAX_ENVELOPE) {
 523+				env = MAX_ENVELOPE;
 524+			}
 525+			if (first_key_on) {
 526+				dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]);
 527+			}
 528+			//if ((channel != 0 && channel != 4) || chan->algorithm != 5) {
 529+				phase += mod;
 530+			//}
 531+
 532+			int16_t output = pow_table[sine_table[phase & 0x1FF] + env];
 533+			if (phase & 0x200) {
 534+				output = -output;
 535+			}
 536+			if (op % 4 == 0) {
 537+				chan->op1_old = operator->output;
 538+			} else if (op % 4 == 2) {
 539+				chan->op2_old = operator->output;
 540+			}
 541+			operator->output = output;
 542+			//Update the channel output if we've updated all operators
 543+			if (op % 4 == 3) {
 544+				if (chan->algorithm < 4) {
 545+					chan->output = operator->output;
 546+				} else if(chan->algorithm == 4) {
 547+					chan->output = operator->output + context->operators[channel * 4 + 2].output;
 548+				} else {
 549+					output = 0;
 550+					for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
 551+						output += context->operators[op].output;
 552+					}
 553+					chan->output = output;
 554+				}
 555+				if (first_key_on) {
 556+					int16_t value = context->channels[channel].output & 0x3FE0;
 557+					if (value & 0x2000) {
 558+						value |= 0xC000;
 559+					}
 560+					dfprintf(debug_file, "channel %d output: %d\n", channel, (value * context->volume_mult) / context->volume_div);
 561+				}
 562+			}
 563+			//puts("operator update done");
 564+		}
 565+		context->current_op++;
 566+		if (context->current_op == NUM_OPERATORS) {
 567+			context->current_op = 0;
 568+			
 569+			int16_t left = 0, right = 0;
 570+			for (int i = 0; i < NUM_CHANNELS; i++) {
 571+				int16_t value = context->channels[i].output;
 572+				if (value > 0x1FE0) {
 573+					value = 0x1FE0;
 574+				} else if (value < -0x1FF0) {
 575+					value = -0x1FF0;
 576+				} else {
 577+					value &= 0x3FE0;
 578+					if (value & 0x2000) {
 579+						value |= 0xC000;
 580+					}
 581+				}
 582+				if (value >= 0) {
 583+					value += context->zero_offset;
 584+				} else {
 585+					value -= context->zero_offset;
 586+				}
 587+				if (context->channels[i].logfile) {
 588+					fwrite(&value, sizeof(value), 1, context->channels[i].logfile);
 589+				}
 590+				if (context->channels[i].lr & 0x80) {
 591+					left += (value * context->volume_mult) / context->volume_div;
 592+				} else if (context->zero_offset) {
 593+					if (value >= 0) {
 594+						left += (context->zero_offset * context->volume_mult) / context->volume_div;
 595+					} else {
 596+						left -= (context->zero_offset * context->volume_mult) / context->volume_div;
 597+					}
 598+				}
 599+				if (context->channels[i].lr & 0x40) {
 600+					right += (value * context->volume_mult) / context->volume_div;
 601+				} else if (context->zero_offset) {
 602+					if (value >= 0) {
 603+						right += (context->zero_offset * context->volume_mult) / context->volume_div;
 604+					} else {
 605+						right -= (context->zero_offset * context->volume_mult) / context->volume_div;
 606+					}
 607+				}
 608+			}
 609+			render_put_stereo_sample(context->audio, left, right);
 610+		}
 611+		
 612+	}
 613+	if (context->current_cycle >= context->write_cycle + (context->busy_cycles * context->clock_inc / 6)) {
 614+		context->status &= 0x7F;
 615+		context->write_cycle = CYCLE_NEVER;
 616+	}
 617+	//printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
 618+}
 619+
 620+void ym_address_write_part1(ym2612_context * context, uint8_t address)
 621+{
 622+	//printf("address_write_part1: %X\n", address);
 623+	context->selected_reg = address;
 624+	context->selected_part = 0;
 625+	context->write_cycle = context->current_cycle;
 626+	context->busy_cycles = BUSY_CYCLES_ADDRESS;
 627+	context->status |= 0x80;
 628+}
 629+
 630+void ym_address_write_part2(ym2612_context * context, uint8_t address)
 631+{
 632+	//printf("address_write_part2: %X\n", address);
 633+	context->selected_reg = address;
 634+	context->selected_part = 1;
 635+	context->write_cycle = context->current_cycle;
 636+	context->busy_cycles = BUSY_CYCLES_ADDRESS;
 637+	context->status |= 0x80;
 638+}
 639+
 640+static uint8_t fnum_to_keycode[] = {
 641+	//F11 = 0
 642+	0,0,0,0,0,0,0,1,
 643+	//F11 = 1
 644+	2,3,3,3,3,3,3,3
 645+};
 646+
 647+//table courtesy of Nemesis
 648+static uint32_t detune_table[][4] = {
 649+	{0, 0, 1, 2},   //0  (0x00)
 650+    {0, 0, 1, 2},   //1  (0x01)
 651+    {0, 0, 1, 2},   //2  (0x02)
 652+    {0, 0, 1, 2},   //3  (0x03)
 653+    {0, 1, 2, 2},   //4  (0x04)
 654+    {0, 1, 2, 3},   //5  (0x05)
 655+    {0, 1, 2, 3},   //6  (0x06)
 656+    {0, 1, 2, 3},   //7  (0x07)
 657+    {0, 1, 2, 4},   //8  (0x08)
 658+    {0, 1, 3, 4},   //9  (0x09)
 659+    {0, 1, 3, 4},   //10 (0x0A)
 660+    {0, 1, 3, 5},   //11 (0x0B)
 661+    {0, 2, 4, 5},   //12 (0x0C)
 662+    {0, 2, 4, 6},   //13 (0x0D)
 663+    {0, 2, 4, 6},   //14 (0x0E)
 664+    {0, 2, 5, 7},   //15 (0x0F)
 665+    {0, 2, 5, 8},   //16 (0x10)
 666+    {0, 3, 6, 8},   //17 (0x11)
 667+    {0, 3, 6, 9},   //18 (0x12)
 668+    {0, 3, 7,10},   //19 (0x13)
 669+    {0, 4, 8,11},   //20 (0x14)
 670+    {0, 4, 8,12},   //21 (0x15)
 671+    {0, 4, 9,13},   //22 (0x16)
 672+    {0, 5,10,14},   //23 (0x17)
 673+    {0, 5,11,16},   //24 (0x18)
 674+    {0, 6,12,17},   //25 (0x19)
 675+    {0, 6,13,19},   //26 (0x1A)
 676+    {0, 7,14,20},   //27 (0x1B)
 677+    {0, 8,16,22},   //28 (0x1C)
 678+    {0, 8,16,22},   //29 (0x1D)
 679+    {0, 8,16,22},   //30 (0x1E)
 680+    {0, 8,16,22}
 681+};  //31 (0x1F)
 682+
 683+static uint32_t ym_calc_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op)
 684+{
 685+	uint32_t chan_num = op / 4;
 686+	//printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op);
 687+	//base frequency
 688+	ym_channel * channel = context->channels + chan_num;
 689+	uint32_t inc, detune;
 690+	if (chan_num == 2 && context->ch3_mode && (op < (2*4 + 3))) {
 691+		//supplemental fnum registers are in a different order than normal slot paramters
 692+		int index = op-2*4;
 693+		if (index < 2) {
 694+			index ^= 1;
 695+		}
 696+		inc = context->ch3_supp[index].fnum;
 697+		if (channel->pms) {
 698+			inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step];
 699+			inc &= 0xFFF;
 700+		}
 701+		if (!context->ch3_supp[index].block) {
 702+			inc >>= 1;
 703+		} else {
 704+			inc <<= (context->ch3_supp[index].block-1);
 705+		}
 706+		//detune
 707+		detune = detune_table[context->ch3_supp[index].keycode][operator->detune & 0x3];
 708+	} else {
 709+		inc = channel->fnum;
 710+		if (channel->pms) {
 711+			inc = inc * 2 + lfo_pm_table[(inc & 0x7F0) * 16 + channel->pms + context->lfo_pm_step];
 712+			inc &= 0xFFF;
 713+		}
 714+		if (!channel->block) {
 715+			inc >>= 1;
 716+		} else {
 717+			inc <<= (channel->block-1);
 718+		}
 719+		//detune
 720+		detune = detune_table[channel->keycode][operator->detune & 0x3];
 721+	}
 722+	if (channel->pms) {
 723+		inc >>= 1;
 724+	}
 725+	if (operator->detune & 0x4) {
 726+		inc -= detune;
 727+		//this can underflow, mask to 17-bit result
 728+		inc &= 0x1FFFF;
 729+	} else {
 730+		inc += detune;
 731+	}
 732+	//multiple
 733+	if (operator->multiple) {
 734+		inc *= operator->multiple;
 735+		inc &= 0xFFFFF;
 736+	} else {
 737+		//0.5
 738+		inc >>= 1;
 739+	}
 740+	//printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple);
 741+	return inc;
 742+}
 743+
 744+void ym_data_write(ym2612_context * context, uint8_t value)
 745+{
 746+	if (context->selected_reg >= YM_REG_END) {
 747+		return;
 748+	}
 749+	if (context->selected_part) {
 750+		if (context->selected_reg < YM_PART2_START) {
 751+			return;
 752+		}
 753+		context->part2_regs[context->selected_reg - YM_PART2_START] = value;
 754+	} else {
 755+		if (context->selected_reg < YM_PART1_START) {
 756+			return;
 757+		}
 758+		context->part1_regs[context->selected_reg - YM_PART1_START] = value;
 759+	}
 760+	dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1);
 761+	if (context->selected_reg < 0x30) {
 762+		//Shared regs
 763+		switch (context->selected_reg)
 764+		{
 765+		//TODO: Test reg
 766+		case REG_LFO:
 767+			/*if ((value & 0x8) && !context->lfo_enable) {
 768+				printf("LFO Enabled, Freq: %d\n", value & 0x7);
 769+			}*/
 770+			context->lfo_enable = value & 0x8;
 771+			if (!context->lfo_enable) {
 772+				context->lfo_am_step = context->lfo_pm_step = 0;
 773+			}
 774+			context->lfo_freq = value & 0x7;
 775+
 776+			break;
 777+		case REG_TIMERA_HIGH:
 778+			context->timer_a_load &= 0x3;
 779+			context->timer_a_load |= value << 2;
 780+			break;
 781+		case REG_TIMERA_LOW:
 782+			context->timer_a_load &= 0xFFFC;
 783+			context->timer_a_load |= value & 0x3;
 784+			break;
 785+		case REG_TIMERB:
 786+			context->timer_b_load = value;
 787+			break;
 788+		case REG_TIME_CTRL: {
 789+			if (value & BIT_TIMERA_ENABLE && !(context->timer_control & BIT_TIMERA_ENABLE)) {
 790+				context->timer_a = TIMER_A_MAX;
 791+				context->timer_control |= BIT_TIMERA_LOAD;
 792+			}
 793+			if (value & BIT_TIMERB_ENABLE && !(context->timer_control & BIT_TIMERB_ENABLE)) {
 794+				context->timer_b = TIMER_B_MAX;
 795+				context->timer_control |= BIT_TIMERB_LOAD;
 796+			}
 797+			context->timer_control &= (BIT_TIMERA_LOAD | BIT_TIMERB_LOAD);
 798+			context->timer_control |= value & 0xF;
 799+			if (value & BIT_TIMERA_RESET) {
 800+				context->status &= ~BIT_STATUS_TIMERA;
 801+			}
 802+			if (value & BIT_TIMERB_RESET) {
 803+				context->status &= ~BIT_STATUS_TIMERB;
 804+			}
 805+			if (context->ch3_mode == CSM_MODE && (value & 0xC0) != CSM_MODE && context->csm_keyon) {
 806+				csm_keyoff(context);
 807+			}
 808+			context->ch3_mode = value & 0xC0;
 809+			break;
 810+		}
 811+		case REG_KEY_ONOFF: {
 812+			uint8_t channel = value & 0x7;
 813+			if (channel != 3 && channel != 7) {
 814+				if (channel > 2) {
 815+					channel--;
 816+				}
 817+				uint8_t changes = channel == 2 
 818+					? (value | context->csm_keyon) ^  (context->channels[channel].keyon | context->csm_keyon)
 819+					: value ^ context->channels[channel].keyon;
 820+				context->channels[channel].keyon = value & 0xF0;
 821+				for (uint8_t op = channel * 4, bit = 0; op < (channel + 1) * 4; op++, bit++) {
 822+					if (changes & keyon_bits[bit]) {
 823+						if (value & keyon_bits[bit]) {
 824+							first_key_on = 1;
 825+							//printf("Key On for operator %d in channel %d\n", op, channel);
 826+							keyon(context->operators + op, context->channels + channel);
 827+						} else {
 828+							//printf("Key Off for operator %d in channel %d\n", op, channel);
 829+							keyoff(context->operators + op);
 830+						}
 831+					}
 832+				}
 833+			}
 834+			break;
 835+		}
 836+		case REG_DAC:
 837+			if (context->dac_enable) {
 838+				context->channels[5].output = (((int16_t)value) - 0x80) << 6;
 839+				//printf("DAC Write %X(%d) @ %d\n", value, context->channels[5].output, context->current_cycle);
 840+			}
 841+			break;
 842+		case REG_DAC_ENABLE:
 843+			//printf("DAC Enable: %X\n", value);
 844+			context->dac_enable = value & 0x80;
 845+			break;
 846+		}
 847+	} else if (context->selected_reg < 0xA0) {
 848+		//part
 849+		uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0;
 850+		//channel in part
 851+		if ((context->selected_reg & 0x3) != 0x3) {
 852+			op += 4 * (context->selected_reg & 0x3) + ((context->selected_reg & 0xC) / 4);
 853+			//printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4);
 854+			ym_operator * operator = context->operators + op;
 855+			switch (context->selected_reg & 0xF0)
 856+			{
 857+			case REG_DETUNE_MULT:
 858+				operator->detune = value >> 4 & 0x7;
 859+				operator->multiple = value & 0xF;
 860+				break;
 861+			case REG_TOTAL_LEVEL:
 862+				operator->total_level = (value & 0x7F) << 5;
 863+				break;
 864+			case REG_ATTACK_KS:
 865+				operator->key_scaling = 3 - (value >> 6);
 866+				operator->rates[PHASE_ATTACK] = value & 0x1F;
 867+				break;
 868+			case REG_DECAY_AM:
 869+				operator->am = value & 0x80;
 870+				operator->rates[PHASE_DECAY] = value & 0x1F;
 871+				break;
 872+			case REG_SUSTAIN_RATE:
 873+				operator->rates[PHASE_SUSTAIN] = value & 0x1F;
 874+				break;
 875+			case REG_S_LVL_R_RATE:
 876+				operator->rates[PHASE_RELEASE] = (value & 0xF) << 1 | 1;
 877+				operator->sustain_level = (value & 0xF0) << 3;
 878+				if (operator->sustain_level == 0x780) {
 879+					operator->sustain_level = MAX_ENVELOPE;
 880+				}
 881+				break;
 882+			case REG_SSG_EG:
 883+				if (!(value & SSG_ENABLE)) {
 884+					value = 0;
 885+				}
 886+				if ((value ^ operator->ssg) & SSG_INVERT) {
 887+					operator->inverted ^= SSG_INVERT;
 888+				}
 889+				operator->ssg = value;
 890+				break;
 891+			}
 892+		}
 893+	} else {
 894+		uint8_t channel = context->selected_reg & 0x3;
 895+		if (channel != 3) {
 896+			if (context->selected_part) {
 897+				channel += 3;
 898+			}
 899+			//printf("write targets channel %d\n", channel);
 900+			switch (context->selected_reg & 0xFC)
 901+			{
 902+			case REG_FNUM_LOW:
 903+				context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7;
 904+				context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value;
 905+				context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7];
 906+				break;
 907+			case REG_BLOCK_FNUM_H:{
 908+				context->channels[channel].block_fnum_latch = value;
 909+				break;
 910+			}
 911+			case REG_FNUM_LOW_CH3:
 912+				if (channel < 3) {
 913+					context->ch3_supp[channel].block = context->ch3_supp[channel].block_fnum_latch >> 3 & 0x7;
 914+					context->ch3_supp[channel].fnum = (context->ch3_supp[channel].block_fnum_latch & 0x7) << 8 | value;
 915+					context->ch3_supp[channel].keycode = context->ch3_supp[channel].block << 2 | fnum_to_keycode[context->ch3_supp[channel].fnum >> 7];
 916+				}
 917+				break;
 918+			case REG_BLOCK_FN_CH3:
 919+				if (channel < 3) {
 920+					context->ch3_supp[channel].block_fnum_latch = value;
 921+				}
 922+				break;
 923+			case REG_ALG_FEEDBACK:
 924+				context->channels[channel].algorithm = value & 0x7;
 925+				switch (context->channels[channel].algorithm)
 926+				{
 927+				case 0:
 928+					//operator 3 modulated by operator 2
 929+					//this uses a special op2 result reg on HW, but that reg will have the most recent
 930+					//result from op2 when op3 starts executing
 931+					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
 932+					context->operators[channel*4+1].mod_src[1] = NULL;
 933+					
 934+					//operator 2 modulated by operator 1
 935+					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
 936+					
 937+					//operator 4 modulated by operator 3
 938+					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
 939+					context->operators[channel*4+3].mod_src[1] = NULL;
 940+					break;
 941+				case 1:
 942+					//operator 3 modulated by operator 1+2
 943+					//op1 starts executing before this, but due to pipeline length the most current result is
 944+					//not available and instead the previous result is used
 945+					context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
 946+					//this uses a special op2 result reg on HW, but that reg will have the most recent
 947+					//result from op2 when op3 starts executing
 948+					context->operators[channel*4+1].mod_src[1] = &context->operators[channel*4+2].output;
 949+					
 950+					//operator 2 unmodulated
 951+					context->operators[channel*4+2].mod_src[0] = NULL;
 952+					
 953+					//operator 4 modulated by operator 3
 954+					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
 955+					context->operators[channel*4+3].mod_src[1] = NULL;
 956+					break;
 957+				case 2:
 958+					//operator 3 modulated by operator 2
 959+					//this uses a special op2 result reg on HW, but that reg will have the most recent
 960+					//result from op2 when op3 starts executing
 961+					context->operators[channel*4+1].mod_src[0] = &context->operators[channel*4+2].output;
 962+					context->operators[channel*4+1].mod_src[1] = NULL;
 963+					
 964+					//operator 2 unmodulated
 965+					context->operators[channel*4+2].mod_src[0] = NULL;
 966+					
 967+					//operator 4 modulated by operator 1+3
 968+					//this uses a special op1 result reg on HW, but that reg will have the most recent
 969+					//result from op1 when op4 starts executing
 970+					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
 971+					context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
 972+					break;
 973+				case 3:
 974+					//operator 3 unmodulated
 975+					context->operators[channel*4+1].mod_src[0] = NULL;
 976+					context->operators[channel*4+1].mod_src[1] = NULL;
 977+					
 978+					//operator 2 modulated by operator 1
 979+					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
 980+					
 981+					//operator 4 modulated by operator 2+3
 982+					//op2 starts executing before this, but due to pipeline length the most current result is
 983+					//not available and instead the previous result is used
 984+					context->operators[channel*4+3].mod_src[0] = &context->channels[channel].op2_old;
 985+					context->operators[channel*4+3].mod_src[1] = &context->operators[channel*4+1].output;
 986+					break;
 987+				case 4:
 988+					//operator 3 unmodulated
 989+					context->operators[channel*4+1].mod_src[0] = NULL;
 990+					context->operators[channel*4+1].mod_src[1] = NULL;
 991+					
 992+					//operator 2 modulated by operator 1
 993+					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
 994+					
 995+					//operator 4 modulated by operator 3
 996+					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+1].output;
 997+					context->operators[channel*4+3].mod_src[1] = NULL;
 998+					break;
 999+				case 5:
1000+					//operator 3 modulated by operator 1
1001+					//op1 starts executing before this, but due to pipeline length the most current result is
1002+					//not available and instead the previous result is used
1003+					context->operators[channel*4+1].mod_src[0] = &context->channels[channel].op1_old;
1004+					context->operators[channel*4+1].mod_src[1] = NULL;
1005+					
1006+					//operator 2 modulated by operator 1
1007+					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1008+					
1009+					//operator 4 modulated by operator 1
1010+					//this uses a special op1 result reg on HW, but that reg will have the most recent
1011+					//result from op1 when op4 starts executing
1012+					context->operators[channel*4+3].mod_src[0] = &context->operators[channel*4+0].output;
1013+					context->operators[channel*4+3].mod_src[1] = NULL;
1014+					break;
1015+				case 6:
1016+					//operator 3 unmodulated
1017+					context->operators[channel*4+1].mod_src[0] = NULL;
1018+					context->operators[channel*4+1].mod_src[1] = NULL;
1019+					
1020+					//operator 2 modulated by operator 1
1021+					context->operators[channel*4+2].mod_src[0] = &context->operators[channel*4+0].output;
1022+					
1023+					//operator 4 unmodulated
1024+					context->operators[channel*4+3].mod_src[0] = NULL;
1025+					context->operators[channel*4+3].mod_src[1] = NULL;
1026+					break;
1027+				case 7:
1028+					//everything is an output so no modulation (except for op 1 feedback)
1029+					context->operators[channel*4+1].mod_src[0] = NULL;
1030+					context->operators[channel*4+1].mod_src[1] = NULL;
1031+					
1032+					context->operators[channel*4+2].mod_src[0] = NULL;
1033+					
1034+					context->operators[channel*4+3].mod_src[0] = NULL;
1035+					context->operators[channel*4+3].mod_src[1] = NULL;
1036+					break;
1037+				}
1038+				context->channels[channel].feedback = value >> 3 & 0x7;
1039+				//printf("Algorithm %d, feedback %d for channel %d\n", value & 0x7, value >> 3 & 0x7, channel);
1040+				break;
1041+			case REG_LR_AMS_PMS:
1042+				context->channels[channel].pms = (value & 0x7) * 32;
1043+				context->channels[channel].ams = value >> 4 & 0x3;
1044+				context->channels[channel].lr = value & 0xC0;
1045+				//printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel);
1046+				break;
1047+			}
1048+		}
1049+	}
1050+
1051+	context->write_cycle = context->current_cycle;
1052+	context->busy_cycles = context->selected_reg < 0xA0 ? BUSY_CYCLES_DATA_LOW : BUSY_CYCLES_DATA_HIGH;
1053+	context->status |= 0x80;
1054+}
1055+
1056+uint8_t ym_read_status(ym2612_context * context)
1057+{
1058+	return context->status;
1059+}
1060+
1061+void ym_print_channel_info(ym2612_context *context, int channel)
1062+{
1063+	ym_channel *chan = context->channels + channel;
1064+	printf("\n***Channel %d***\n"
1065+	       "Algorithm: %d\n"
1066+		   "Feedback:  %d\n"
1067+		   "Pan:       %s\n"
1068+		   "AMS:       %d\n"
1069+		   "PMS:       %d\n",
1070+		   channel+1, chan->algorithm, chan->feedback,
1071+		   chan->lr == 0xC0 ? "LR" : chan->lr == 0x80 ? "L" : chan->lr == 0x40 ? "R" : "",
1072+		   chan->ams, chan->pms);
1073+	if (channel == 2) {
1074+		printf(
1075+		   "Mode:      %X: %s\n",
1076+		   context->ch3_mode, context->ch3_mode ? "special" : "normal");
1077+	}
1078+	for (int operator = channel * 4; operator < channel * 4+4; operator++)
1079+	{
1080+		int dispnum = operator - channel * 4 + 1;
1081+		if (dispnum == 2) {
1082+			dispnum = 3;
1083+		} else if (dispnum == 3) {
1084+			dispnum = 2;
1085+		}
1086+		ym_operator *op = context->operators + operator;
1087+		printf("\nOperator %d:\n"
1088+		       "    Multiple:      %d\n"
1089+			   "    Detune:        %d\n"
1090+			   "    Total Level:   %d\n"
1091+			   "    Attack Rate:   %d\n"
1092+			   "    Key Scaling:   %d\n"
1093+			   "    Decay Rate:    %d\n"
1094+			   "    Sustain Level: %d\n"
1095+			   "    Sustain Rate:  %d\n"
1096+			   "    Release Rate:  %d\n"
1097+			   "    Amplitude Modulation %s\n",
1098+			   dispnum, op->multiple, op->detune, op->total_level,
1099+			   op->rates[PHASE_ATTACK], op->key_scaling, op->rates[PHASE_DECAY],
1100+			   op->sustain_level, op->rates[PHASE_SUSTAIN], op->rates[PHASE_RELEASE],
1101+			   op->am ? "On" : "Off");
1102+	}
1103+}
1104+
1105+void ym_print_timer_info(ym2612_context *context)
1106+{
1107+	printf("***Timer A***\n"
1108+	       "Current Value: %d\n"
1109+		   "Load Value:    %d\n"
1110+		   "Triggered:     %s\n"
1111+		   "Enabled:       %s\n\n",
1112+		   context->timer_a,
1113+		   context->timer_a_load,
1114+		   context->status & BIT_STATUS_TIMERA ? "yes" : "no",
1115+		   context->timer_control & BIT_TIMERA_ENABLE ? "yes" : "no");
1116+	printf("***Timer B***\n"
1117+	       "Current Value: %d\n"
1118+		   "Load Value:    %d\n"
1119+		   "Triggered:     %s\n"
1120+		   "Enabled:       %s\n\n",
1121+		   context->timer_b,
1122+		   context->timer_b_load,
1123+		   context->status & BIT_STATUS_TIMERB ? "yes" : "no",
1124+		   context->timer_control & BIT_TIMERB_ENABLE ? "yes" : "no");
1125+}
1126+
1127+void ym_serialize(ym2612_context *context, serialize_buffer *buf)
1128+{
1129+	save_buffer8(buf, context->part1_regs, YM_PART1_REGS);
1130+	save_buffer8(buf, context->part2_regs, YM_PART2_REGS);
1131+	for (int i = 0; i < NUM_OPERATORS; i++)
1132+	{
1133+		save_int32(buf, context->operators[i].phase_counter);
1134+		save_int16(buf, context->operators[i].envelope);
1135+		save_int16(buf, context->operators[i].output);
1136+		save_int8(buf, context->operators[i].env_phase);
1137+		save_int8(buf, context->operators[i].inverted);
1138+	}
1139+	for (int i = 0; i < NUM_CHANNELS; i++)
1140+	{
1141+		save_int16(buf, context->channels[i].output);
1142+		save_int16(buf, context->channels[i].op1_old);
1143+		//Due to the latching behavior, these need to be saved
1144+		//even though duplicate info is probably in the regs array
1145+		save_int8(buf, context->channels[i].block);
1146+		save_int16(buf, context->channels[i].fnum);
1147+		save_int8(buf, context->channels[i].keyon);
1148+	}
1149+	for (int i = 0; i < 3; i++)
1150+	{
1151+		//Due to the latching behavior, these need to be saved
1152+		//even though duplicate info is probably in the regs array
1153+		save_int8(buf, context->ch3_supp[i].block);
1154+		save_int8(buf, context->ch3_supp[i].fnum);
1155+	}
1156+	save_int8(buf, context->timer_control);
1157+	save_int16(buf, context->timer_a);
1158+	save_int8(buf, context->timer_b);
1159+	save_int8(buf, context->sub_timer_b);
1160+	save_int16(buf, context->env_counter);
1161+	save_int8(buf, context->current_op);
1162+	save_int8(buf, context->current_env_op);
1163+	save_int8(buf, context->lfo_counter);
1164+	save_int8(buf, context->csm_keyon);
1165+	save_int8(buf, context->status);
1166+	save_int8(buf, context->selected_reg);
1167+	save_int8(buf, context->selected_part);
1168+	save_int32(buf, context->current_cycle);
1169+	save_int32(buf, context->write_cycle);
1170+	save_int32(buf, context->busy_cycles);
1171+}
1172+
1173+void ym_deserialize(deserialize_buffer *buf, void *vcontext)
1174+{
1175+	ym2612_context *context = vcontext;
1176+	uint8_t temp_regs[YM_PART1_REGS];
1177+	load_buffer8(buf, temp_regs, YM_PART1_REGS);
1178+	context->selected_part = 0;
1179+	for (int i = 0; i < YM_PART1_REGS; i++)
1180+	{
1181+		uint8_t reg = YM_PART1_START + i;
1182+		if (reg == REG_TIME_CTRL) {
1183+			context->ch3_mode = temp_regs[i] & 0xC0;
1184+		} else if (reg != REG_FNUM_LOW && reg != REG_KEY_ONOFF) {
1185+			context->selected_reg = reg;
1186+			ym_data_write(context, temp_regs[i]);
1187+		}
1188+	}
1189+	load_buffer8(buf, temp_regs, YM_PART2_REGS);
1190+	context->selected_part = 1;
1191+	for (int i = 0; i < YM_PART2_REGS; i++)
1192+	{
1193+		uint8_t reg = YM_PART2_START + i;
1194+		if (reg != REG_FNUM_LOW) {
1195+			context->selected_reg = reg;
1196+			ym_data_write(context, temp_regs[i]);
1197+		}
1198+	}
1199+	for (int i = 0; i < NUM_OPERATORS; i++)
1200+	{
1201+		context->operators[i].phase_counter = load_int32(buf);
1202+		context->operators[i].envelope = load_int16(buf);
1203+		context->operators[i].output = load_int16(buf);
1204+		context->operators[i].env_phase = load_int8(buf);
1205+		if (context->operators[i].env_phase > PHASE_RELEASE) {
1206+			context->operators[i].env_phase = PHASE_RELEASE;
1207+		}
1208+		context->operators[i].inverted = load_int8(buf) != 0 ? SSG_INVERT : 0;
1209+	}
1210+	for (int i = 0; i < NUM_CHANNELS; i++)
1211+	{
1212+		context->channels[i].output = load_int16(buf);
1213+		context->channels[i].op1_old = load_int16(buf);
1214+		context->channels[i].block = load_int8(buf);
1215+		context->channels[i].fnum = load_int16(buf);
1216+		context->channels[i].keycode = context->channels[i].block << 2 | fnum_to_keycode[context->channels[i].fnum >> 7];
1217+		context->channels[i].keyon = load_int8(buf);
1218+	}
1219+	for (int i = 0; i < 3; i++)
1220+	{
1221+		context->ch3_supp[i].block = load_int8(buf);
1222+		context->ch3_supp[i].fnum = load_int8(buf);
1223+		context->ch3_supp[i].keycode = context->ch3_supp[i].block << 2 | fnum_to_keycode[context->ch3_supp[i].fnum >> 7];
1224+	}
1225+	context->timer_control = load_int8(buf);
1226+	context->timer_a = load_int16(buf);
1227+	context->timer_b = load_int8(buf);
1228+	context->sub_timer_b = load_int8(buf);
1229+	context->env_counter = load_int16(buf);
1230+	context->current_op = load_int8(buf);
1231+	if (context->current_op >= NUM_OPERATORS) {
1232+		context->current_op = 0;
1233+	}
1234+	context->current_env_op = load_int8(buf);
1235+	if (context->current_env_op >= NUM_OPERATORS) {
1236+		context->current_env_op = 0;
1237+	}
1238+	context->lfo_counter = load_int8(buf);
1239+	context->csm_keyon = load_int8(buf);
1240+	context->status = load_int8(buf);
1241+	context->selected_reg = load_int8(buf);
1242+	context->selected_part = load_int8(buf);
1243+	context->current_cycle = load_int32(buf);
1244+	context->write_cycle = load_int32(buf);
1245+	context->busy_cycles = load_int32(buf);
1246+}
+149, -0
  1@@ -0,0 +1,149 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef YM2612_H_
  8+#define YM2612_H_
  9+
 10+#include <stdint.h>
 11+#include <stdio.h>
 12+#include "serialize.h"
 13+#include "render.h"
 14+
 15+#define NUM_PART_REGS (0xB7-0x30)
 16+#define NUM_CHANNELS 6
 17+#define NUM_OPERATORS (4*NUM_CHANNELS)
 18+
 19+#define YM_OPT_WAVE_LOG 1
 20+
 21+typedef struct {
 22+	int16_t  *mod_src[2];
 23+	uint32_t phase_counter;
 24+	uint16_t envelope;
 25+	int16_t  output;
 26+	uint16_t total_level;
 27+	uint16_t sustain_level;
 28+	uint8_t  rates[4];
 29+	uint8_t  key_scaling;
 30+	uint8_t  multiple;
 31+	uint8_t  detune;
 32+	uint8_t  am;
 33+	uint8_t  env_phase;
 34+	uint8_t  ssg;
 35+	uint8_t  inverted;
 36+} ym_operator;
 37+
 38+typedef struct {
 39+	FILE *   logfile;
 40+	uint16_t fnum;
 41+	int16_t  output;
 42+	int16_t  op1_old;
 43+	int16_t  op2_old;
 44+	uint8_t  block_fnum_latch;
 45+	uint8_t  block;
 46+	uint8_t  keycode;
 47+	uint8_t  algorithm;
 48+	uint8_t  feedback;
 49+	uint8_t  ams;
 50+	uint8_t  pms;
 51+	uint8_t  lr;
 52+	uint8_t  keyon;
 53+} ym_channel;
 54+
 55+typedef struct {
 56+	uint16_t fnum;
 57+	uint8_t  block;
 58+	uint8_t  block_fnum_latch;
 59+	uint8_t  keycode;
 60+} ym_supp;
 61+
 62+#define YM_PART1_START 0x21
 63+#define YM_PART2_START 0x30
 64+#define YM_REG_END     0xB8
 65+#define YM_PART1_REGS (YM_REG_END-YM_PART1_START)
 66+#define YM_PART2_REGS (YM_REG_END-YM_PART2_START)
 67+
 68+typedef struct {
 69+	audio_source *audio;
 70+    uint32_t    clock_inc;
 71+	uint32_t    current_cycle;
 72+	//TODO: Condense the next two fields into one
 73+	uint32_t    write_cycle;
 74+	uint32_t    busy_cycles;
 75+	int32_t     volume_mult;
 76+	int32_t     volume_div;
 77+	ym_operator operators[NUM_OPERATORS];
 78+	ym_channel  channels[NUM_CHANNELS];
 79+	int16_t     zero_offset;
 80+	uint16_t    timer_a;
 81+	uint16_t    timer_a_load;
 82+	uint16_t    env_counter;
 83+	ym_supp     ch3_supp[3];
 84+	uint8_t     timer_b;
 85+	uint8_t     sub_timer_b;
 86+	uint8_t     timer_b_load;
 87+	uint8_t     ch3_mode;
 88+	uint8_t     current_op;
 89+	uint8_t     current_env_op;
 90+
 91+	uint8_t     timer_control;
 92+	uint8_t     dac_enable;
 93+	uint8_t     lfo_enable;
 94+	uint8_t     lfo_freq;
 95+	uint8_t     lfo_counter;
 96+	uint8_t     lfo_am_step;
 97+	uint8_t     lfo_pm_step;
 98+	uint8_t     csm_keyon;
 99+	uint8_t     status;
100+	uint8_t     selected_reg;
101+	uint8_t     selected_part;
102+	uint8_t     part1_regs[YM_PART1_REGS];
103+	uint8_t     part2_regs[YM_PART2_REGS];
104+} ym2612_context;
105+
106+enum {
107+	REG_LFO          = 0x22,
108+	REG_TIMERA_HIGH  = 0x24,
109+	REG_TIMERA_LOW,
110+	REG_TIMERB,
111+	REG_TIME_CTRL,
112+	REG_KEY_ONOFF,
113+	REG_DAC          = 0x2A,
114+	REG_DAC_ENABLE,
115+
116+	REG_DETUNE_MULT  = 0x30,
117+	REG_TOTAL_LEVEL  = 0x40,
118+	REG_ATTACK_KS    = 0x50,
119+	REG_DECAY_AM     = 0x60,
120+	REG_SUSTAIN_RATE = 0x70,
121+	REG_S_LVL_R_RATE = 0x80,
122+	REG_SSG_EG       = 0x90,
123+
124+	REG_FNUM_LOW     = 0xA0,
125+	REG_BLOCK_FNUM_H = 0xA4,
126+	REG_FNUM_LOW_CH3 = 0xA8,
127+	REG_BLOCK_FN_CH3 = 0xAC,
128+	REG_ALG_FEEDBACK = 0xB0,
129+	REG_LR_AMS_PMS   = 0xB4
130+};
131+
132+void ym_init(ym2612_context * context, uint32_t master_clock, uint32_t clock_div, uint32_t options);
133+void ym_reset(ym2612_context *context);
134+void ym_free(ym2612_context *context);
135+void ym_enable_zero_offset(ym2612_context *context, uint8_t enabled);
136+void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock);
137+void ym_run(ym2612_context * context, uint32_t to_cycle);
138+void ym_address_write_part1(ym2612_context * context, uint8_t address);
139+void ym_address_write_part2(ym2612_context * context, uint8_t address);
140+void ym_data_write(ym2612_context * context, uint8_t value);
141+uint8_t ym_read_status(ym2612_context * context);
142+uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile);
143+uint8_t ym_save_gst(ym2612_context * context, FILE * gstfile);
144+void ym_print_channel_info(ym2612_context *context, int channel);
145+void ym_print_timer_info(ym2612_context *context);
146+void ym_serialize(ym2612_context *context, serialize_buffer *buf);
147+void ym_deserialize(deserialize_buffer *buf, void *vcontext);
148+
149+#endif //YM2612_H_
150+
+2539, -0
   1@@ -0,0 +1,2539 @@
   2+info
   3+	prefix z80_
   4+	opcode_size 8
   5+	extra_tables cb ed dded fded ddcb fdcb dd fd
   6+	body z80_run_op
   7+	sync_cycle z80_sync_cycle
   8+	interrupt z80_interrupt
   9+	include z80_util.c
  10+	header z80.h
  11+	
  12+declare
  13+	void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask);
  14+	z80_context * init_z80_context(z80_options *options);
  15+	void z80_run(z80_context *context, uint32_t target_cycle);
  16+	void z80_assert_reset(z80_context * context, uint32_t cycle);
  17+	void z80_clear_reset(z80_context * context, uint32_t cycle);
  18+	void z80_assert_busreq(z80_context * context, uint32_t cycle);
  19+	void z80_clear_busreq(z80_context * context, uint32_t cycle);
  20+	void z80_assert_nmi(z80_context *context, uint32_t cycle);
  21+	uint8_t z80_get_busack(z80_context * context, uint32_t cycle);
  22+	void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end);
  23+	void z80_adjust_cycles(z80_context * context, uint32_t deduction);
  24+	void z80_serialize(z80_context *context, serialize_buffer *buf);
  25+	void z80_deserialize(deserialize_buffer *buf, void *vcontext);
  26+	void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler);
  27+	void zremove_breakpoint(z80_context * context, uint16_t address);
  28+	void z80_options_free(z80_options *opts);
  29+	void z80_sync_cycle(z80_context *context, uint32_t target_cycle);
  30+
  31+regs
  32+	main 8 b c d e h l f a
  33+	alt 8 b' c' d' e' h' l' f' a'
  34+	i 8
  35+	r 8
  36+	rhigh 8
  37+	iff1 8
  38+	iff2 8
  39+	imode 8
  40+	sp 16
  41+	ix 16
  42+	iy 16
  43+	pc 16
  44+	wz 16
  45+	nflag 8
  46+	last_flag_result 8
  47+	pvflag 8
  48+	chflags 8
  49+	zflag 8
  50+	scratch1 16
  51+	scratch2 16
  52+	busreq 8
  53+	busack 8
  54+	reset 8
  55+	io_map ptrmemmap_chunk
  56+	io_chunks 32
  57+	io_mask 32
  58+	int_cycle 32
  59+	int_end_cycle 32
  60+	int_value 8
  61+	nmi_cycle 32
  62+	system ptrvoid
  63+	fastread ptr8 64
  64+	fastwrite ptr8 64
  65+	mem_pointers ptr8 4
  66+	
  67+flags
  68+	register f
  69+	S 7 sign last_flag_result.7
  70+	Z 6 zero zflag
  71+	Y 5 bit-5 last_flag_result.5
  72+	H 4 half-carry chflags.3
  73+	P 2 parity pvflag
  74+	V 2 overflow pvflag
  75+	X 3 bit-3 last_flag_result.3
  76+	N 1 none nflag
  77+	C 0 carry chflags.7
  78+
  79+	
  80+z80_op_fetch
  81+	cycles 1
  82+	add 1 r r
  83+	mov pc scratch1
  84+	ocall read_8
  85+	add 1 pc pc
  86+	
  87+z80_run_op
  88+	#printf "Z80: %X @ %d\n" pc cycles
  89+	#printf "Z80: %X - A: %X, B: %X, C: %X D: %X, E: %X, H: %X, L: %X, SP: %X, IX: %X, IY: %X @ %d\n" pc a b c d e h l sp ix iy cycles
  90+	z80_op_fetch
  91+	dispatch scratch1
  92+
  93+z80_interrupt
  94+	cmp int_cycle cycles
  95+	if >=U
  96+	
  97+	mov 0 iff1
  98+	mov 0 iff2
  99+	cycles 6
 100+	update_sync
 101+	
 102+	switch imode
 103+	case 0
 104+	dispatch int_value
 105+	
 106+	case 1
 107+	dispatch 0xFF
 108+	
 109+	case 2
 110+	lsl i 8 pc
 111+	or int_value pc pc
 112+	#CD is call
 113+	dispatch 0xCD
 114+	end
 115+	
 116+	else
 117+	
 118+	cmp nmi_cycle cycles
 119+	if >=U
 120+	
 121+	mov 0xFFFFFFFF nmi_cycle
 122+	mov 0 iff1
 123+	local pch 8
 124+	lsr pc 8 pch
 125+	meta high pch
 126+	meta low pc
 127+	z80_push
 128+	mov 0x66 pc
 129+	update_sync
 130+	
 131+	end
 132+	end
 133+	
 134+	
 135+11001011 cb_prefix
 136+	z80_op_fetch
 137+	dispatch scratch1 cb
 138+
 139+11011101 dd_prefix
 140+	z80_op_fetch
 141+	dispatch scratch1 dd
 142+
 143+11101101 ed_prefix
 144+	z80_op_fetch
 145+	dispatch scratch1 ed
 146+
 147+11111101 fd_prefix
 148+	z80_op_fetch
 149+	dispatch scratch1 fd
 150+	
 151+dd 11001011 ddcb_prefix
 152+	z80_calc_index ix
 153+	cycles 2
 154+	mov pc scratch1
 155+	ocall read_8
 156+	add 1 pc pc
 157+	dispatch scratch1 ddcb
 158+	
 159+fd 11001011 fdcb_prefix
 160+	z80_calc_index iy
 161+	cycles 2
 162+	mov pc scratch1
 163+	ocall read_8
 164+	add 1 pc pc
 165+	dispatch scratch1 fdcb
 166+	
 167+z80_check_cond
 168+	arg cond 8
 169+	local invert 8
 170+	switch cond
 171+	case 0
 172+	meta istrue invert
 173+	lnot zflag invert
 174+	
 175+	case 1
 176+	meta istrue zflag
 177+	
 178+	case 2
 179+	meta istrue invert
 180+	not chflags invert
 181+	and 0x80 invert invert
 182+	
 183+	case 3
 184+	meta istrue invert
 185+	and 0x80 chflags invert
 186+	
 187+	case 4
 188+	meta istrue invert
 189+	lnot pvflag invert
 190+	
 191+	case 5
 192+	meta istrue pvflag
 193+	
 194+	case 6
 195+	meta istrue invert
 196+	not last_flag_result invert
 197+	and 0x80 invert invert
 198+	
 199+	case 7
 200+	meta istrue invert
 201+	and 0x80 last_flag_result invert
 202+	
 203+	end
 204+	
 205+z80_fetch_hl
 206+	lsl h 8 scratch1
 207+	or l scratch1 scratch1
 208+	ocall read_8
 209+	
 210+z80_store_hl
 211+	lsl h 8 scratch2
 212+	or l scratch2 scratch2
 213+	ocall write_8
 214+
 215+z80_fetch_immed
 216+	mov pc scratch1
 217+	ocall read_8
 218+	add 1 pc pc
 219+	
 220+z80_fetch_immed16
 221+	mov pc scratch1
 222+	ocall read_8
 223+	mov scratch1 wz
 224+	add 1 pc pc
 225+	mov pc scratch1
 226+	ocall read_8
 227+	add 1 pc pc
 228+	lsl scratch1 8 scratch1
 229+	or scratch1 wz wz
 230+
 231+z80_fetch_immed_reg16
 232+	mov pc scratch1
 233+	ocall read_8
 234+	mov scratch1 low
 235+	add 1 pc pc
 236+	mov pc scratch1
 237+	ocall read_8
 238+	mov scratch1 high
 239+	add 1 pc pc
 240+	
 241+z80_fetch_immed_to_reg16
 242+	mov pc scratch1
 243+	ocall read_8
 244+	mov scratch1 reg
 245+	add 1 pc pc
 246+	mov pc scratch1
 247+	ocall read_8
 248+	add 1 pc pc
 249+	lsl scratch1 8 scratch1
 250+	or scratch1 reg reg
 251+
 252+01RRR110 ld_from_hl
 253+	z80_fetch_hl
 254+	mov scratch1 main.R
 255+
 256+01DDDSSS ld_from_reg
 257+	mov main.S main.D
 258+	
 259+dd 01DDD100 ld_from_ixh
 260+	invalid D 6
 261+	lsr ix 8 main.D
 262+	
 263+dd 01100SSS ld_to_ixh
 264+	invalid S 6
 265+	local tmp 16
 266+	and 0xFF ix ix
 267+	lsl main.S 8 tmp
 268+	or tmp ix ix
 269+	
 270+dd 0110D10S ld_ixb_to_ixb
 271+
 272+dd 01DDD101 ld_from_ixl
 273+	invalid D 6
 274+	mov ix main.D
 275+	
 276+dd 01101SSS ld_to_ixl
 277+	invalid S 6
 278+	and 0xFF00 ix ix
 279+	or main.S ix ix
 280+	
 281+dd 01100101 ld_ixl_to_ixh
 282+	local tmp 16
 283+	lsl ix 8 tmp
 284+	and 0xFF ix ix
 285+	or tmp ix ix
 286+	
 287+dd 01101100 ld_ixh_to_ixl
 288+	local tmp 16
 289+	lsr ix 8 tmp
 290+	and 0xFF00 ix ix
 291+	or tmp ix ix
 292+	
 293+fd 01DDD100 ld_from_iyh
 294+	invalid D 6
 295+	lsr iy 8 main.D
 296+	
 297+fd 01100SSS ld_to_iyh
 298+	invalid S 6
 299+	local tmp 16
 300+	and 0xFF iy iy
 301+	lsl main.S 8 tmp
 302+	or tmp iy iy
 303+	
 304+fd 0110D10S ld_iyb_to_iyb
 305+
 306+fd 01DDD101 ld_from_iyl
 307+	invalid D 6
 308+	mov iy main.D
 309+	
 310+fd 01101SSS ld_to_iyl
 311+	invalid S 6
 312+	and 0xFF00 iy iy
 313+	or main.S iy iy
 314+	
 315+fd 01100101 ld_iyl_to_iyh
 316+	local tmp 16
 317+	lsl iy 8 tmp
 318+	and 0xFF iy iy
 319+	or tmp iy iy
 320+	
 321+fd 01101100 ld_iyh_to_iyl
 322+	local tmp 16
 323+	lsr iy 8 tmp
 324+	and 0xFF00 iy iy
 325+	or tmp iy iy
 326+	
 327+z80_calc_index
 328+	arg index 16
 329+	mov index wz
 330+	z80_fetch_immed
 331+	sext 16 scratch1 scratch1
 332+	add scratch1 wz wz
 333+
 334+z80_fetch_index
 335+	arg index 16
 336+	z80_calc_index index
 337+	mov wz scratch1
 338+	cycles 5
 339+	ocall read_8
 340+	
 341+z80_store_index
 342+	mov wz scratch2
 343+	ocall write_8
 344+	
 345+dd 01RRR110 ld_from_ix
 346+	z80_fetch_index ix
 347+	mov scratch1 main.R
 348+
 349+fd 01RRR110 ld_from_iy
 350+	z80_fetch_index iy
 351+	mov scratch1 main.R
 352+
 353+00RRR110 ld_immed
 354+	z80_fetch_immed
 355+	mov scratch1 main.R
 356+	
 357+dd 00100110 ld_immed_ixh
 358+	z80_fetch_immed
 359+	lsl scratch1 8 scratch1
 360+	and 0xFF ix ix
 361+	or scratch1 ix ix
 362+	
 363+dd 00101110 ld_immed_ixl
 364+	z80_fetch_immed
 365+	and 0xFF00 ix ix
 366+	or scratch1 ix ix
 367+	
 368+fd 00100110 ld_immed_iyh
 369+	z80_fetch_immed
 370+	lsl scratch1 8 scratch1
 371+	and 0xFF iy iy
 372+	or scratch1 iy iy
 373+	
 374+fd 00101110 ld_immed_iyl
 375+	z80_fetch_immed
 376+	and 0xFF00 iy iy
 377+	or scratch1 iy iy
 378+
 379+01110RRR ld_to_hl
 380+	mov main.R scratch1
 381+	z80_store_hl
 382+
 383+dd 01110RRR ld_to_ix
 384+	z80_calc_index ix
 385+	mov wz scratch2
 386+	mov main.R scratch1
 387+	cycles 5
 388+	ocall write_8
 389+
 390+fd 01110RRR ld_to_iy
 391+	z80_calc_index iy
 392+	mov wz scratch2
 393+	mov main.R scratch1
 394+	cycles 5
 395+	ocall write_8
 396+
 397+00110110 ld_to_hl_immed
 398+	z80_fetch_immed
 399+	z80_store_hl
 400+	
 401+dd 00110110 ld_to_ixd_immed
 402+	z80_calc_index ix
 403+	z80_fetch_immed
 404+	cycles 2
 405+	mov wz scratch2
 406+	ocall write_8
 407+	
 408+fd 00110110 ld_to_iyd_immed
 409+	z80_calc_index iy
 410+	z80_fetch_immed
 411+	cycles 2
 412+	mov wz scratch2
 413+	ocall write_8
 414+
 415+00001010 ld_a_from_bc
 416+	lsl b 8 wz
 417+	or c wz wz
 418+	mov wz scratch1
 419+	add 1 wz wz
 420+	ocall read_8
 421+	mov scratch1 a
 422+
 423+00011010 ld_a_from_de
 424+	lsl d 8 wz
 425+	or e wz wz
 426+	mov wz scratch1
 427+	add 1 wz wz
 428+	ocall read_8
 429+	mov scratch1 a
 430+
 431+00111010 ld_a_from_immed
 432+	z80_fetch_immed16
 433+	mov wz scratch1
 434+	add 1 wz wz
 435+	ocall read_8
 436+	mov scratch1 a
 437+	
 438+00000010 ld_a_to_bc
 439+	local tmp 8
 440+	lsl b 8 scratch2
 441+	or c scratch2 scratch2
 442+	mov a scratch1
 443+	add c 1 tmp
 444+	lsl a 8 wz
 445+	or tmp wz wz
 446+	ocall write_8
 447+	
 448+00010010 ld_a_to_de
 449+	local tmp 8
 450+	lsl d 8 scratch2
 451+	or e scratch2 scratch2
 452+	mov a scratch1
 453+	add e 1 tmp
 454+	lsl a 8 wz
 455+	or tmp wz wz
 456+	ocall write_8
 457+
 458+00110010 ld_a_to_immed
 459+	local tmp 16
 460+	z80_fetch_immed16
 461+	mov wz scratch2
 462+	mov a scratch1
 463+	add 1 wz wz
 464+	ocall write_8
 465+	and 0xFF wz wz
 466+	lsl a 8 tmp
 467+	or tmp wz wz
 468+
 469+ed 01000111 ld_i_a
 470+	mov a i
 471+	cycles 1
 472+
 473+ed 01001111 ld_r_a
 474+	mov a r
 475+	and 0x80 a rhigh
 476+	cycles 1
 477+
 478+ed 01011111 ld_a_r
 479+	cycles 1
 480+	and 0x7F r a
 481+	or rhigh a a
 482+	update_flags SZYH0XN0
 483+	mov iff2 pvflag
 484+	
 485+ed 01010111 ld_a_i
 486+	cycles 1
 487+	mov i a
 488+	update_flags SZYH0XN0
 489+	mov iff2 pvflag
 490+
 491+00000001 ld_bc_immed
 492+	meta high b
 493+	meta low c
 494+	z80_fetch_immed_reg16
 495+
 496+00010001 ld_de_immed
 497+	meta high d
 498+	meta low e
 499+	z80_fetch_immed_reg16
 500+
 501+00100001 ld_hl_immed
 502+	meta high h
 503+	meta low l
 504+	z80_fetch_immed_reg16
 505+
 506+00110001 ld_sp_immed
 507+	meta reg sp
 508+	z80_fetch_immed_to_reg16
 509+
 510+dd 00100001 ld_ix_immed
 511+	meta reg ix
 512+	z80_fetch_immed_to_reg16
 513+
 514+fd 00100001 ld_iy_immed
 515+	meta reg iy
 516+	z80_fetch_immed_to_reg16
 517+	
 518+z80_fetch16_from_immed
 519+	z80_fetch_immed16
 520+	mov wz scratch1
 521+	ocall read_8
 522+	mov scratch1 low
 523+	add 1 wz wz
 524+	mov wz scratch1
 525+	ocall read_8
 526+	mov scratch1 high
 527+	add 1 wz wz
 528+
 529+00101010 ld_hl_from_immed
 530+	meta low l
 531+	meta high h
 532+	z80_fetch16_from_immed
 533+
 534+ed 01001011 ld_bc_from_immed
 535+	meta low c
 536+	meta high b
 537+	z80_fetch16_from_immed
 538+
 539+ed 01011011 ld_de_from_immed
 540+	meta low e
 541+	meta high d
 542+	z80_fetch16_from_immed
 543+
 544+ed 01101011 ld_hl_from_immed_slow
 545+	meta low l
 546+	meta high h
 547+	z80_fetch16_from_immed
 548+	
 549+z80_fetch_reg16_from_immed
 550+	z80_fetch_immed16
 551+	mov wz scratch1
 552+	ocall read_8
 553+	mov scratch1 reg
 554+	add 1 wz wz
 555+	mov wz scratch1
 556+	ocall read_8
 557+	lsl scratch1 8 scratch1
 558+	or scratch1 reg reg
 559+	add 1 wz wz
 560+
 561+ed 01111011 ld_sp_from_immed
 562+	meta reg sp
 563+	z80_fetch_reg16_from_immed
 564+
 565+dd 00101010 ld_ix_from_immed
 566+	meta reg ix
 567+	z80_fetch_reg16_from_immed
 568+
 569+fd 00101010 ld_iy_from_immed
 570+	meta reg iy
 571+	z80_fetch_reg16_from_immed
 572+
 573+00100010 ld_hl_to_immed
 574+	z80_fetch_immed16
 575+	mov wz scratch2
 576+	mov l scratch1
 577+	ocall write_8
 578+	add 1 wz wz
 579+	mov wz scratch2
 580+	mov h scratch1
 581+	ocall write_8
 582+	add 1 wz wz
 583+	
 584+dd 00100010 ld_ix_to_immed
 585+	z80_fetch_immed16
 586+	mov wz scratch2
 587+	mov ix scratch1
 588+	ocall write_8
 589+	add 1 wz wz
 590+	mov wz scratch2
 591+	lsr ix 8 scratch1
 592+	ocall write_8
 593+	add 1 wz wz
 594+	
 595+fd 00100010 ld_iy_to_immed
 596+	z80_fetch_immed16
 597+	mov wz scratch2
 598+	mov iy scratch1
 599+	ocall write_8
 600+	add 1 wz wz
 601+	mov wz scratch2
 602+	lsr iy 8 scratch1
 603+	ocall write_8
 604+	add 1 wz wz
 605+	
 606+z80_regpair_to_immed
 607+	z80_fetch_immed16
 608+	mov wz scratch2
 609+	mov low scratch1
 610+	ocall write_8
 611+	add 1 wz wz
 612+	mov high scratch1
 613+	mov wz scratch2
 614+	ocall write_8
 615+	add 1 wz wz
 616+	
 617+ed 01000011 ld_bc_to_immed
 618+	meta low c
 619+	meta high b
 620+	z80_regpair_to_immed
 621+
 622+ed 01010011 ld_de_to_immed
 623+	meta low e
 624+	meta high d
 625+	z80_regpair_to_immed
 626+	
 627+ed 01100011 ld_hl_to_immed_slow
 628+	meta low l
 629+	meta high h
 630+	z80_regpair_to_immed
 631+	
 632+ed 01110011 ld_sp_to_immed
 633+	meta low sp
 634+	local sph 8
 635+	lsr sp 8 sph
 636+	meta high sph
 637+	z80_regpair_to_immed
 638+
 639+11111001 ld_sp_hl
 640+	cycles 2
 641+	lsl h 8 sp
 642+	or l sp sp
 643+	
 644+dd 11111001 ld_sp_ix
 645+	cycles 2
 646+	mov ix sp
 647+
 648+fd 11111001 ld_sp_iy
 649+	cycles 2
 650+	mov iy sp
 651+
 652+z80_push
 653+	cycles 1
 654+	sub 1 sp sp
 655+	mov sp scratch2
 656+	mov high scratch1
 657+	ocall write_8
 658+	sub 1 sp sp
 659+	mov sp scratch2
 660+	mov low scratch1
 661+	ocall write_8
 662+
 663+11000101 push_bc
 664+	meta high b
 665+	meta low c
 666+	z80_push
 667+
 668+11010101 push_de
 669+	meta high d
 670+	meta low e
 671+	z80_push
 672+
 673+11100101 push_hl
 674+	meta high h
 675+	meta low l
 676+	z80_push
 677+
 678+11110101 push_af
 679+	meta high a
 680+	meta low f
 681+	z80_push
 682+	
 683+dd 11100101 push_ix
 684+	local ixh 8
 685+	lsr ix 8 ixh
 686+	meta high ixh
 687+	meta low ix
 688+	z80_push
 689+
 690+fd 11100101 push_iy
 691+	local iyh 8
 692+	lsr iy 8 iyh
 693+	meta high iyh
 694+	meta low iy
 695+	z80_push
 696+
 697+z80_pop
 698+	mov sp scratch1
 699+	ocall read_8
 700+	add 1 sp sp
 701+	mov scratch1 low
 702+	mov sp scratch1
 703+	ocall read_8
 704+	add 1 sp sp
 705+	mov scratch1 high
 706+
 707+11000001 pop_bc
 708+	meta high b
 709+	meta low c
 710+	z80_pop
 711+
 712+11010001 pop_de
 713+	meta high d
 714+	meta low e
 715+	z80_pop
 716+
 717+11100001 pop_hl
 718+	meta high h
 719+	meta low l
 720+	z80_pop
 721+
 722+11110001 pop_af
 723+	meta high a
 724+	meta low f
 725+	z80_pop
 726+
 727+dd 11100001 pop_ix
 728+	local ixh 16
 729+	meta high ixh
 730+	meta low ix
 731+	z80_pop
 732+	lsl ixh 8 ixh
 733+	or ixh ix ix
 734+
 735+fd 11100001 pop_iy
 736+	local iyh 16
 737+	meta high iyh
 738+	meta low iy
 739+	z80_pop
 740+	lsl iyh 8 iyh
 741+	or iyh iy iy
 742+
 743+11101011 ex_de_hl
 744+	xchg e l
 745+	xchg d h
 746+
 747+00001000 ex_af_af
 748+	xchg a a'
 749+	xchg f f'
 750+
 751+11011001 exx
 752+	xchg b b'
 753+	xchg c c'
 754+	xchg d d'
 755+	xchg e e'
 756+	xchg h h'
 757+	xchg l l'
 758+
 759+11100011 ex_sp_hl
 760+	mov sp scratch1
 761+	ocall read_8
 762+	xchg l scratch1
 763+	cycles 1
 764+	mov sp scratch2
 765+	ocall write_8
 766+	add 1 sp scratch1
 767+	ocall read_8
 768+	xchg h scratch1
 769+	cycles 2
 770+	add 1 sp scratch2
 771+	ocall write_8
 772+	lsl h 8 wz
 773+	or l wz wz
 774+	
 775+dd 11100011 ex_sp_ix
 776+	mov sp scratch1
 777+	ocall read_8
 778+	mov scratch1 wz
 779+	mov ix scratch1
 780+	cycles 1
 781+	mov sp scratch2
 782+	ocall write_8
 783+	add 1 sp scratch1
 784+	ocall read_8
 785+	lsl scratch1 8 scratch1
 786+	or scratch1 wz wz
 787+	lsr ix 8 scratch1
 788+	cycles 2
 789+	add 1 sp scratch2
 790+	ocall write_8
 791+	mov wz ix
 792+	
 793+fd 11100011 ex_sp_iy
 794+	mov sp scratch1
 795+	ocall read_8
 796+	mov scratch1 wz
 797+	mov iy scratch1
 798+	cycles 1
 799+	mov sp scratch2
 800+	ocall write_8
 801+	add 1 sp scratch1
 802+	ocall read_8
 803+	lsl scratch1 8 scratch1
 804+	or scratch1 wz wz
 805+	lsr iy 8 scratch1
 806+	cycles 2
 807+	add 1 sp scratch2
 808+	ocall write_8
 809+	mov wz iy
 810+
 811+10000RRR add_reg
 812+	add a main.R a
 813+	update_flags SZYHVXN0C
 814+	
 815+dd 10000100 add_ixh
 816+	lsr ix 8 scratch1
 817+	add a scratch1 a
 818+	update_flags SZYHVXN0C
 819+	
 820+dd 10000101 add_ixl
 821+	and ix 0xFF scratch1
 822+	add a scratch1 a
 823+	update_flags SZYHVXN0C
 824+	
 825+fd 10000100 add_iyh
 826+	lsr iy 8 scratch1
 827+	add a scratch1 a
 828+	update_flags SZYHVXN0C
 829+	
 830+fd 10000101 add_iyl
 831+	and iy 0xFF scratch1
 832+	add a scratch1 a
 833+	update_flags SZYHVXN0C
 834+	
 835+10000110 add_hl
 836+	z80_fetch_hl
 837+	add a scratch1 a
 838+	update_flags SZYHVXN0C
 839+	
 840+dd 10000110 add_ixd
 841+	z80_fetch_index ix
 842+	add a scratch1 a
 843+	update_flags SZYHVXN0C
 844+	
 845+fd 10000110 add_iyd
 846+	z80_fetch_index iy
 847+	add a scratch1 a
 848+	update_flags SZYHVXN0C
 849+
 850+11000110 add_immed
 851+	z80_fetch_immed
 852+	add a scratch1 a
 853+	update_flags SZYHVXN0C
 854+	
 855+z80_add16_hl
 856+	arg src 16
 857+	lsl h 8 hlt
 858+	or l hlt hlt
 859+	add 1 hlt wz
 860+	add src hlt hlt
 861+	update_flags YHXN0C
 862+	mov hlt l
 863+	lsr hlt 8 h
 864+	cycles 7
 865+	
 866+00001001 add_hl_bc
 867+	local hlw 16
 868+	local bcw 16
 869+	meta hlt hlw
 870+	lsl b 8 bcw
 871+	or c bcw bcw
 872+	z80_add16_hl bcw
 873+	
 874+00011001 add_hl_de
 875+	local hlw 16
 876+	local dew 16
 877+	meta hlt hlw
 878+	lsl d 8 dew
 879+	or e dew dew
 880+	z80_add16_hl dew
 881+	
 882+00101001 add_hl_hl
 883+	local hlw 16
 884+	meta hlt hlw
 885+	z80_add16_hl hlw
 886+	
 887+00111001 add_hl_sp
 888+	local hlw 16
 889+	meta hlt hlw
 890+	z80_add16_hl sp
 891+	
 892+dd 00001001 add_ix_bc
 893+	lsl b 8 scratch1
 894+	or c scratch1 scratch1
 895+	add scratch1 ix ix
 896+	update_flags YHXN0C
 897+	cycles 7
 898+	
 899+dd 00011001 add_ix_de
 900+	lsl d 8 scratch1
 901+	or e scratch1 scratch1
 902+	add scratch1 ix ix
 903+	update_flags YHXN0C
 904+	cycles 7
 905+	
 906+dd 00101001 add_ix_ix
 907+	add ix ix ix
 908+	update_flags YHXN0C
 909+	cycles 7
 910+	
 911+dd 00111001 add_ix_sp
 912+	add sp ix ix
 913+	update_flags YHXN0C
 914+	cycles 7
 915+	
 916+fd 00001001 add_iy_bc
 917+	lsl b 8 scratch1
 918+	or c scratch1 scratch1
 919+	add scratch1 iy iy
 920+	update_flags YHXN0C
 921+	cycles 7
 922+	
 923+fd 00011001 add_iy_de
 924+	lsl d 8 scratch1
 925+	or e scratch1 scratch1
 926+	add scratch1 iy iy
 927+	update_flags YHXN0C
 928+	cycles 7
 929+	
 930+fd 00101001 add_iy_iy
 931+	add iy iy iy
 932+	update_flags YHXN0C
 933+	cycles 7
 934+	
 935+fd 00111001 add_iy_sp
 936+	add sp iy iy
 937+	update_flags YHXN0C
 938+	cycles 7
 939+	
 940+10001RRR adc_reg
 941+	adc a main.R a
 942+	update_flags SZYHVXN0C
 943+	
 944+dd 10001100 adc_ixh
 945+	lsr ix 8 scratch1
 946+	adc a scratch1 a
 947+	update_flags SZYHVXN0C
 948+	
 949+dd 10001101 adc_ixl
 950+	and ix 0xFF scratch1
 951+	adc a scratch1 a
 952+	update_flags SZYHVXN0C
 953+	
 954+fd 10001100 adc_iyh
 955+	lsr iy 8 scratch1
 956+	adc a scratch1 a
 957+	update_flags SZYHVXN0C
 958+	
 959+fd 10001101 adc_iyl
 960+	and iy 0xFF scratch1
 961+	adc a scratch1 a
 962+	update_flags SZYHVXN0C
 963+
 964+10001110 adc_hl
 965+	z80_fetch_hl
 966+	adc a scratch1 a
 967+	update_flags SZYHVXN0C
 968+	
 969+dd 10001110 adc_ixd
 970+	z80_fetch_index ix
 971+	adc a scratch1 a
 972+	update_flags SZYHVXN0C
 973+	
 974+fd 10001110 adc_iyd
 975+	z80_fetch_index iy
 976+	adc a scratch1 a
 977+	update_flags SZYHVXN0C
 978+
 979+11001110 adc_immed
 980+	z80_fetch_immed
 981+	adc a scratch1 a
 982+	update_flags SZYHVXN0C
 983+	
 984+z80_adc16_hl
 985+	arg src 16
 986+	lsl h 8 hlt
 987+	or l hlt hlt
 988+	add 1 hlt wz
 989+	adc src hlt hlt
 990+	update_flags SZYHVXN0C
 991+	mov hlt l
 992+	lsr hlt 8 h
 993+	cycles 7
 994+	
 995+ed 01001010 adc_hl_bc
 996+	local hlw 16
 997+	local bcw 16
 998+	meta hlt hlw
 999+	lsl b 8 bcw
1000+	or c bcw bcw
1001+	z80_adc16_hl bcw
1002+	
1003+ed 01011010 adc_hl_de
1004+	local hlw 16
1005+	local dew 16
1006+	meta hlt hlw
1007+	lsl d 8 dew
1008+	or e dew dew
1009+	z80_adc16_hl dew
1010+	
1011+ed 01101010 adc_hl_hl
1012+	local hlw 16
1013+	meta hlt hlw
1014+	z80_adc16_hl hlw
1015+
1016+	
1017+ed 01111010 adc_hl_sp
1018+	local hlw 16
1019+	meta hlt hlw
1020+	z80_adc16_hl sp
1021+
1022+10010RRR sub_reg
1023+	sub main.R a a
1024+	update_flags SZYHVXN1C
1025+	
1026+dd 10010100 sub_ixh
1027+	lsr ix 8 scratch1
1028+	sub scratch1 a a
1029+	update_flags SZYHVXN1C
1030+	
1031+dd 10010101 sub_ixl
1032+	and ix 0xFF scratch1
1033+	sub scratch1 a a
1034+	update_flags SZYHVXN1C
1035+	
1036+fd 10010100 sub_iyh
1037+	lsr iy 8 scratch1
1038+	sub scratch1 a a
1039+	update_flags SZYHVXN1C
1040+	
1041+fd 10010101 sub_iyl
1042+	and iy 0xFF scratch1
1043+	sub scratch1 a a
1044+	update_flags SZYHVXN1C
1045+	
1046+10010110 sub_hl
1047+	z80_fetch_hl
1048+	sub scratch1 a a
1049+	update_flags SZYHVXN1C
1050+	
1051+dd 10010110 sub_ixd
1052+	z80_fetch_index ix
1053+	sub scratch1 a a
1054+	update_flags SZYHVXN1C
1055+
1056+fd 10010110 sub_iyd
1057+	z80_fetch_index iy
1058+	sub scratch1 a a
1059+	update_flags SZYHVXN1C
1060+
1061+11010110 sub_immed
1062+	z80_fetch_immed
1063+	sub scratch1 a a
1064+	update_flags SZYHVXN1C
1065+
1066+10011RRR sbc_reg
1067+	sbc main.R a a
1068+	update_flags SZYHVXN1C
1069+	
1070+dd 10011100 sbc_ixh
1071+	lsr ix 8 scratch1
1072+	sbc scratch1 a a
1073+	update_flags SZYHVXN1C
1074+	
1075+dd 10011101 sbc_ixl
1076+	and ix 0xFF scratch1
1077+	sbc scratch1 a a
1078+	update_flags SZYHVXN1C
1079+	
1080+fd 10011100 sbc_iyh
1081+	lsr iy 8 scratch1
1082+	sbc scratch1 a a
1083+	update_flags SZYHVXN1C
1084+	
1085+fd 10011101 sbc_iyl
1086+	and iy 0xFF scratch1
1087+	sbc scratch1 a a
1088+	update_flags SZYHVXN1C
1089+	
1090+	
1091+10011110 sbc_hl
1092+	z80_fetch_hl
1093+	sbc scratch1 a a
1094+	update_flags SZYHVXN1C
1095+	
1096+dd 10011110 sbc_ixd
1097+	z80_fetch_index ix
1098+	sbc scratch1 a a
1099+	update_flags SZYHVXN1C
1100+
1101+fd 10011110 sbc_iyd
1102+	z80_fetch_index iy
1103+	sbc scratch1 a a
1104+	update_flags SZYHVXN1C
1105+
1106+11011110 sbc_immed
1107+	z80_fetch_immed
1108+	sbc scratch1 a a
1109+	update_flags SZYHVXN1C
1110+	
1111+z80_sbc16_hl
1112+	arg src 16
1113+	lsl h 8 hlt
1114+	or l hlt hlt
1115+	add 1 hlt wz
1116+	sbc src hlt hlt
1117+	update_flags SZYHVXN1C
1118+	mov hlt l
1119+	lsr hlt 8 h
1120+	cycles 7
1121+	
1122+ed 01000010 sbc_hl_bc
1123+	local hlw 16
1124+	local bcw 16
1125+	meta hlt hlw
1126+	lsl b 8 bcw
1127+	or c bcw bcw
1128+	z80_sbc16_hl bcw
1129+	
1130+ed 01010010 sbc_hl_de
1131+	local hlw 16
1132+	local dew 16
1133+	meta hlt hlw
1134+	lsl d 8 dew
1135+	or e dew dew
1136+	z80_sbc16_hl dew
1137+	
1138+ed 01100010 sbc_hl_hl
1139+	local hlw 16
1140+	meta hlt hlw
1141+	z80_sbc16_hl hlw
1142+
1143+	
1144+ed 01110010 sbc_hl_sp
1145+	local hlw 16
1146+	meta hlt hlw
1147+	z80_sbc16_hl sp
1148+
1149+10100RRR and_reg
1150+	and a main.R a
1151+	update_flags SZYH1PXN0C0
1152+	
1153+dd 10100100 and_ixh
1154+	lsr ix 8 scratch1
1155+	and scratch1 a a
1156+	update_flags SZYH1PXN0C0
1157+	
1158+dd 10100101 and_ixl
1159+	and ix a a
1160+	update_flags SZYH1PXN0C0
1161+	
1162+fd 10100100 and_iyh
1163+	lsr iy 8 scratch1
1164+	and scratch1 a a
1165+	update_flags SZYH1PXN0C0
1166+	
1167+fd 10100101 and_iyl
1168+	and iy a a
1169+	update_flags SZYH1PXN0C0
1170+	
1171+10100110 and_hl
1172+	z80_fetch_hl
1173+	and a scratch1 a
1174+	update_flags SZYH1PXN0C0
1175+	
1176+dd 10100110 and_ixd
1177+	z80_fetch_index ix
1178+	and a scratch1 a
1179+	update_flags SZYH1PXN0C0
1180+	
1181+fd 10100110 and_iyd
1182+	z80_fetch_index iy
1183+	and a scratch1 a
1184+	update_flags SZYH1PXN0C0
1185+
1186+11100110 and_immed
1187+	z80_fetch_immed
1188+	and a scratch1 a
1189+	update_flags SZYH1PXN0C0
1190+	
1191+10110RRR or_reg
1192+	or a main.R a
1193+	update_flags SZYH0PXN0C0
1194+	
1195+dd 10110100 or_ixh
1196+	lsr ix 8 scratch1
1197+	or scratch1 a a
1198+	update_flags SZYH0PXN0C0
1199+	
1200+dd 10110101 or_ixl
1201+	or ix a a
1202+	update_flags SZYH0PXN0C0
1203+	
1204+fd 10110100 or_iyh
1205+	lsr iy 8 scratch1
1206+	or scratch1 a a
1207+	update_flags SZYH0PXN0C0
1208+	
1209+fd 10110101 or_iyl
1210+	or iy a a
1211+	update_flags SZYH0PXN0C0
1212+	
1213+10110110 or_hl
1214+	z80_fetch_hl
1215+	or a scratch1 a
1216+	update_flags SZYH0PXN0C0
1217+	
1218+dd 10110110 or_ixd
1219+	z80_fetch_index ix
1220+	or a scratch1 a
1221+	update_flags SZYH0PXN0C0
1222+	
1223+fd 10110110 or_iyd
1224+	z80_fetch_index iy
1225+	or a scratch1 a
1226+	update_flags SZYH0PXN0C0
1227+
1228+11110110 or_immed
1229+	z80_fetch_immed
1230+	or a scratch1 a
1231+	update_flags SZYH0PXN0C0
1232+	
1233+10101RRR xor_reg
1234+	xor a main.R a
1235+	update_flags SZYH0PXN0C0
1236+	
1237+dd 10101100 xor_ixh
1238+	lsr ix 8 scratch1
1239+	xor scratch1 a a
1240+	update_flags SZYH0PXN0C0
1241+	
1242+dd 10101101 xor_ixl
1243+	xor ix a a
1244+	update_flags SZYH0PXN0C0
1245+	
1246+fd 10101100 xor_iyh
1247+	lsr iy 8 scratch1
1248+	xor scratch1 a a
1249+	update_flags SZYH0PXN0C0
1250+	
1251+fd 10101101 xor_iyl
1252+	xor iy a a
1253+	update_flags SZYH0PXN0C0
1254+	
1255+10101110 xor_hl
1256+	z80_fetch_hl
1257+	xor a scratch1 a
1258+	update_flags SZYH0PXN0C0
1259+	
1260+dd 10101110 xor_ixd
1261+	z80_fetch_index ix
1262+	xor a scratch1 a
1263+	update_flags SZYH0PXN0C0
1264+	
1265+fd 10101110 xor_iyd
1266+	z80_fetch_index iy
1267+	xor a scratch1 a
1268+	update_flags SZYH0PXN0C0
1269+
1270+11101110 xor_immed
1271+	z80_fetch_immed
1272+	xor a scratch1 a
1273+	update_flags SZYH0PXN0C0
1274+
1275+10111RRR cp_reg
1276+	mov main.R last_flag_result
1277+	cmp main.R a
1278+	update_flags SZHVN1C
1279+	
1280+dd 10111100 cp_ixh
1281+	local tmp 8
1282+	lsr ix 8 tmp
1283+	mov tmp last_flag_result
1284+	cmp tmp a
1285+	update_flags SZHVN1C
1286+	
1287+dd 10111101 cp_ixl
1288+	local tmp 8
1289+	mov ix tmp
1290+	mov ix last_flag_result
1291+	cmp tmp a
1292+	update_flags SZHVN1C
1293+	
1294+fd 10111100 cp_iyh
1295+	local tmp 8
1296+	lsr iy 8 tmp
1297+	mov tmp last_flag_result
1298+	cmp tmp a
1299+	update_flags SZHVN1C
1300+	
1301+fd 10111101 cp_iyl
1302+	local tmp 8
1303+	mov iy tmp
1304+	mov iy last_flag_result
1305+	cmp tmp a
1306+	update_flags SZHVN1C
1307+	
1308+10111110 cp_hl
1309+	local tmp 8
1310+	z80_fetch_hl
1311+	mov scratch1 tmp
1312+	mov scratch1 last_flag_result
1313+	cmp tmp a
1314+	update_flags SZHVN1C
1315+	
1316+dd 10111110 cp_ixd
1317+	local tmp 8
1318+	z80_fetch_index ix
1319+	mov scratch1 tmp
1320+	mov scratch1 last_flag_result
1321+	cmp tmp a
1322+	update_flags SZHVN1C
1323+	
1324+fd 10111110 cp_iyd
1325+	local tmp 8
1326+	z80_fetch_index iy
1327+	mov scratch1 tmp
1328+	mov scratch1 last_flag_result
1329+	cmp tmp a
1330+	update_flags SZHVN1C
1331+
1332+11111110 cp_immed
1333+	local tmp 8
1334+	z80_fetch_immed
1335+	mov scratch1 tmp
1336+	mov scratch1 last_flag_result
1337+	cmp tmp a
1338+	update_flags SZHVN1C
1339+
1340+00RRR100 inc_reg
1341+	add 1 main.R main.R
1342+	update_flags SZYHVXN0
1343+	
1344+dd 00100100 inc_ixh
1345+	add 0x100 ix ix
1346+	update_flags SZYHVXN0
1347+	
1348+dd 00101100 inc_ixl
1349+	local tmp 8
1350+	mov ix tmp
1351+	add 1 tmp tmp
1352+	update_flags SZYHVXN0
1353+	and 0xFF00 ix ix
1354+	or tmp ix ix
1355+	
1356+fd 00100100 inc_iyh
1357+	add 0x100 iy iy
1358+	update_flags SZYHVXN0
1359+	
1360+fd 00101100 inc_iyl
1361+	local tmp 8
1362+	mov iy tmp
1363+	add 1 tmp tmp
1364+	update_flags SZYHVXN0
1365+	and 0xFF00 iy iy
1366+	or tmp iy iy
1367+	
1368+00110100 inc_hl
1369+	local tmp 8
1370+	z80_fetch_hl
1371+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1372+	#or add some syntax to force a certain size on an operation so they are unnecessary
1373+	mov scratch1 tmp
1374+	add 1 tmp tmp
1375+	update_flags SZYHVXN0
1376+	mov tmp scratch1
1377+	cycles 1
1378+	z80_store_hl
1379+	
1380+dd 00110100 inc_ixd
1381+	local tmp 8
1382+	z80_fetch_index ix
1383+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1384+	#or add some syntax to force a certain size on an operation so they are unnecessary
1385+	mov scratch1 tmp
1386+	add 1 tmp tmp
1387+	update_flags SZYHVXN0
1388+	mov tmp scratch1
1389+	cycles 1
1390+	z80_store_index
1391+
1392+fd 00110100 inc_iyd
1393+	local tmp 8
1394+	z80_fetch_index iy
1395+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1396+	#or add some syntax to force a certain size on an operation so they are unnecessary
1397+	mov scratch1 tmp
1398+	add 1 tmp tmp
1399+	update_flags SZYHVXN0
1400+	mov tmp scratch1
1401+	cycles 1
1402+	z80_store_index
1403+	
1404+z80_inc_pair
1405+	arg high 8
1406+	arg low 8
1407+	cycles 2
1408+	local word 16
1409+	lsl high 8 word
1410+	or low word word
1411+	add 1 word word
1412+	mov word low
1413+	lsr word 8 high
1414+	
1415+00000011 inc_bc
1416+	z80_inc_pair b c
1417+	
1418+00010011 inc_de
1419+	z80_inc_pair d e
1420+	
1421+00100011 inc16_hl
1422+	z80_inc_pair h l
1423+
1424+00110011 inc_sp
1425+	add 1 sp sp
1426+	
1427+dd 00100011 inc_ix
1428+	add 1 ix ix
1429+
1430+fd 00100011 inc_iy
1431+	add 1 iy iy
1432+
1433+00RRR101 dec_reg
1434+	sub 1 main.R main.R
1435+	update_flags SZYHVXN1
1436+	
1437+dd 00100101 dec_ixh
1438+	sub 0x100 ix ix
1439+	update_flags SZYHVXN1
1440+	
1441+dd 00101101 dec_ixl
1442+	local tmp 8
1443+	mov ix tmp
1444+	sub 1 tmp tmp
1445+	update_flags SZYHVXN1
1446+	and 0xFF00 ix ix
1447+	or tmp ix ix
1448+	
1449+fd 00100101 dec_iyh
1450+	sub 0x100 iy iy
1451+	update_flags SZYHVXN1
1452+	
1453+fd 00101101 dec_iyl
1454+	local tmp 8
1455+	mov iy tmp
1456+	sub 1 tmp tmp
1457+	update_flags SZYHVXN1
1458+	and 0xFF00 iy iy
1459+	or tmp iy iy
1460+	
1461+00110101 dec_hl
1462+	local tmp 8
1463+	z80_fetch_hl
1464+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1465+	#or add some syntax to force a certain size on an operation so they are unnecessary
1466+	mov scratch1 tmp
1467+	sub 1 tmp tmp
1468+	update_flags SZYHVXN1
1469+	mov tmp scratch1
1470+	cycles 1
1471+	z80_store_hl
1472+	
1473+dd 00110101 dec_ixd
1474+	local tmp 8
1475+	z80_fetch_index ix
1476+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1477+	#or add some syntax to force a certain size on an operation so they are unnecessary
1478+	mov scratch1 tmp
1479+	sub 1 tmp tmp
1480+	update_flags SZYHVXN1
1481+	mov tmp scratch1
1482+	cycles 1
1483+	z80_store_index
1484+
1485+fd 00110101 dec_iyd
1486+	local tmp 8
1487+	z80_fetch_index iy
1488+	#TODO: Either make DSL compiler smart enough to optimize these unnecessary moves out
1489+	#or add some syntax to force a certain size on an operation so they are unnecessary
1490+	mov scratch1 tmp
1491+	sub 1 tmp tmp
1492+	update_flags SZYHVXN1
1493+	mov tmp scratch1
1494+	cycles 1
1495+	z80_store_index
1496+	
1497+z80_dec_pair
1498+	arg high 8
1499+	arg low 8
1500+	local word 16
1501+	lsl high 8 word
1502+	or low word word
1503+	sub 1 word word
1504+	mov word low
1505+	lsr word 8 high
1506+	cycles 2
1507+	
1508+00001011 dec_bc
1509+	z80_dec_pair b c
1510+	
1511+00011011 dec_de
1512+	z80_dec_pair d e
1513+	
1514+00101011 dec16_hl
1515+	z80_dec_pair h l
1516+
1517+00111011 dec_sp
1518+	sub 1 sp sp
1519+	
1520+dd 00101011 dec_ix
1521+	sub 1 ix ix
1522+
1523+fd 00101011 dec_iy
1524+	sub 1 iy iy
1525+
1526+00101111 cpl
1527+	not a a
1528+	update_flags YH1XN1
1529+
1530+ed 01DDD100 neg
1531+	neg a a
1532+	update_flags SZYHVXN1C
1533+
1534+00111111 ccf
1535+	local tmp 8
1536+	and 0x80 last_flag_result last_flag_result
1537+	and 0x7F a tmp
1538+	or tmp last_flag_result last_flag_result
1539+	and 0x80 chflags chflags
1540+	lsr chflags 4 tmp
1541+	or tmp chflags chflags
1542+	xor 0x80 chflags chflags
1543+	update_flags N0
1544+
1545+00110111 scf
1546+	local tmp 8
1547+	and 0x80 last_flag_result last_flag_result
1548+	and 0x7F a tmp
1549+	or tmp last_flag_result last_flag_result
1550+	update_flags H0N0C1
1551+
1552+00000000 nop
1553+
1554+01110110 halt
1555+	cmp nmi_cycle cycles
1556+	if >=U
1557+	
1558+	else
1559+	cmp int_cycle cycles
1560+	if >=U
1561+	
1562+	if iff1
1563+	else
1564+	sub 1 pc pc
1565+	end
1566+	
1567+	else
1568+	sub 1 pc pc
1569+	end
1570+	end
1571+
1572+11110011 di
1573+	mov 0 iff1
1574+	mov 0 iff2
1575+	update_sync
1576+
1577+11111011 ei
1578+	mov 1 iff1
1579+	mov 1 iff2
1580+	update_sync
1581+	cmp int_cycle cycles
1582+	if >=U
1583+	
1584+	add 1 cycles int_cycle
1585+	
1586+	end
1587+
1588+ed 01D00110 im0
1589+	mov 0 imode
1590+
1591+ed 01D10110 im1
1592+	mov 1 imode
1593+
1594+ed 01D11110 im2
1595+	mov 2 imode
1596+	
1597+ed 01D01110 im3
1598+	#some sources call this mode 0/1, but unclear
1599+	#if the behavior is really different from im 0
1600+	mov 0 imode
1601+	
1602+11000011 jp
1603+	z80_fetch_immed16
1604+	mov wz pc
1605+	
1606+11101001 jp_hl
1607+	lsl h 8 pc
1608+	or l pc pc
1609+	
1610+dd 11101001 jp_ix
1611+	mov ix pc
1612+	
1613+fd 11101001 jp_iy
1614+	mov iy pc
1615+	
1616+11CCC010 jp_cc
1617+	z80_check_cond C
1618+	z80_fetch_immed16
1619+	if istrue
1620+	
1621+	mov wz pc
1622+	
1623+	end
1624+	
1625+00011000 jr
1626+	z80_fetch_immed
1627+	#TODO: determine if this updates wz
1628+	sext 16 scratch1 scratch1
1629+	add scratch1 pc pc
1630+	cycles 5
1631+	
1632+001CC000 jr_cc
1633+	z80_check_cond C
1634+	z80_fetch_immed
1635+	
1636+	if istrue
1637+	
1638+	sext 16 scratch1 scratch1
1639+	add scratch1 pc pc
1640+	cycles 5
1641+	
1642+	end
1643+	
1644+00010000 djnz
1645+	cycles 1
1646+	z80_fetch_immed
1647+	sub 1 b b
1648+	
1649+	if b
1650+	
1651+	sext 16 scratch1 scratch1
1652+	add scratch1 pc pc
1653+	cycles 5
1654+	
1655+	end
1656+	
1657+
1658+11001101 call_uncond
1659+	z80_fetch_immed16
1660+	local pch 8
1661+	lsr pc 8 pch
1662+	meta high pch
1663+	meta low pc
1664+	z80_push
1665+	mov wz pc
1666+	
1667+11CCC100 call_cond
1668+	local pch 8
1669+	z80_fetch_immed16
1670+	z80_check_cond C
1671+	
1672+	if istrue
1673+	
1674+	lsr pc 8 pch
1675+	meta high pch
1676+	meta low pc
1677+	z80_push
1678+	mov wz pc
1679+	
1680+	end
1681+	
1682+11TTT111 rst
1683+	local pch 8
1684+	lsr pc 8 pch
1685+	meta high pch
1686+	meta low pc
1687+	z80_push
1688+	lsl T 3 scratch1
1689+	mov scratch1 pc
1690+
1691+11001001 ret
1692+	local pch 16
1693+	meta high pch
1694+	meta low pc
1695+	z80_pop
1696+	lsl pch 8 pch
1697+	or pch pc pc
1698+	
1699+ed 01001101 reti
1700+	local pch 16
1701+	cycles 1
1702+	meta high pch
1703+	meta low pc
1704+	z80_pop
1705+	lsl pch 8 pch
1706+	or pch pc pc
1707+	
1708+ed 01NN1101 retn
1709+	mov iff2 iff1
1710+	local pch 16
1711+	cycles 1
1712+	meta high pch
1713+	meta low pc
1714+	z80_pop
1715+	lsl pch 8 pch
1716+	or pch pc pc
1717+	
1718+11CCC000 ret_cond
1719+	local pch 16
1720+	cycles 1
1721+	z80_check_cond C
1722+	if istrue
1723+	
1724+	meta high pch
1725+	meta low pc
1726+	z80_pop
1727+	lsl pch 8 pch
1728+	or pch pc pc
1729+	
1730+	end
1731+
1732+11011011 in_abs
1733+	z80_fetch_immed
1734+	ocall io_read8
1735+	mov scratch1 a
1736+	
1737+ed 01RRR000 in_bc
1738+	lsl b 8 scratch1
1739+	or c scratch1 scratch1
1740+	ocall io_read8
1741+	mov scratch1 main.R
1742+	
1743+z80_ini_ind
1744+	arg change 16
1745+	local tmp 8
1746+	cycles 1
1747+	
1748+	lsl 8 b wz
1749+	or c wz wz
1750+	add change wz wz
1751+	
1752+	sub 1 b b
1753+	update_flags SZYX
1754+	
1755+	lsl b 8 scratch1
1756+	or c scratch1 scratch1
1757+	ocall io_read8
1758+	
1759+	and 0x80 scratch1 nflag
1760+	
1761+	mov wz tmp
1762+	add tmp scratch1 tmp
1763+	update_flags C
1764+	
1765+	z80_store_hl
1766+	
1767+	lsl h 8 scratch2
1768+	or l scratch2 scratch2
1769+	add change scratch2 scratch2
1770+	mov scratch2 l
1771+	lsr scratch2 8 h
1772+	
1773+	and 7 tmp tmp
1774+	xor b tmp tmp
1775+	update_flags P
1776+	lsr chflags 4 tmp
1777+	or tmp chflags chflags
1778+	
1779+ed 10100010 ini
1780+	z80_ini_ind 1
1781+	
1782+ed 10110010 inir
1783+	z80_ini_ind 1
1784+	if zflag
1785+	else
1786+	sub 2 pc pc
1787+	cycles 5
1788+	end
1789+	
1790+ed 10101010 ind
1791+	z80_ini_ind -1
1792+	
1793+ed 10111010 indr
1794+	z80_ini_ind -1
1795+	if zflag
1796+	else
1797+	sub 2 pc pc
1798+	cycles 5
1799+	end
1800+	
1801+11010011 out_abs
1802+	z80_fetch_immed
1803+	mov scratch1 scratch2
1804+	mov a scratch1
1805+	ocall io_write8
1806+	
1807+ed 01RRR001 out_bc
1808+	lsl b 8 scratch2
1809+	or c scratch2 scratch2
1810+	mov main.R scratch1
1811+	ocall io_write8
1812+	
1813+z80_outi_outd
1814+	arg change 16
1815+	local tmp 8
1816+	cycles 1
1817+	z80_fetch_hl
1818+	
1819+	and 0x80 scratch1 nflag
1820+	
1821+	lsl h 8 scratch2
1822+	or l scratch2 scratch2
1823+	add change scratch2 scratch2
1824+	mov scratch2 l
1825+	lsr scratch2 8 h
1826+	
1827+	add l scratch1 tmp
1828+	update_flags C
1829+	and 7 tmp tmp
1830+	
1831+	lsl b 8 scratch2
1832+	or c scratch2 scratch2
1833+	ocall io_write8
1834+	
1835+	sub 1 b b
1836+	update_flags SZYX
1837+	
1838+	lsl 8 b wz
1839+	or c wz wz
1840+	add change wz wz
1841+	
1842+	xor b tmp tmp
1843+	update_flags P
1844+	lsr chflags 4 tmp
1845+	or tmp chflags chflags
1846+	
1847+ed 10100011 outi
1848+	z80_outi_outd 1
1849+
1850+ed 10110011 otir
1851+	z80_outi_outd 1
1852+	if zflag
1853+	else
1854+	sub 2 pc pc
1855+	cycles 5
1856+	end
1857+	
1858+ed 10101011 outd
1859+	z80_outi_outd -1
1860+	
1861+ed 10111011 otdr
1862+	z80_outi_outd -1
1863+	if zflag
1864+	else
1865+	sub 2 pc pc
1866+	cycles 5
1867+	end
1868+	
1869+00000111 rlca
1870+	rol a 1 a
1871+	update_flags YH0XN0C
1872+	
1873+00010111 rla
1874+	rlc a 1 a
1875+	update_flags YH0XN0C
1876+	
1877+00001111 rrca
1878+	ror a 1 a
1879+	update_flags YH0XN0C
1880+
1881+00011111 rra
1882+	rrc a 1 a
1883+	update_flags YH0XN0C
1884+	
1885+cb 00000RRR rlc
1886+	rol main.R 1 main.R
1887+	update_flags SZYH0PXN0C
1888+	
1889+cb 00000110 rlc_hl
1890+	local tmp 8
1891+	z80_fetch_hl
1892+	mov scratch1 tmp
1893+	rol tmp 1 tmp
1894+	update_flags SZYH0PXN0C
1895+	mov tmp scratch1
1896+	z80_store_hl
1897+	
1898+z80_rlc_index
1899+	arg tmp 8
1900+	mov wz scratch1
1901+	ocall read_8
1902+	cycles 1
1903+	mov scratch1 tmp
1904+	rol tmp 1 tmp
1905+	update_flags SZYH0PXN0C
1906+	mov tmp scratch1
1907+	z80_store_index
1908+	
1909+ddcb 00000110 rlc_ixd
1910+	local tmp 8
1911+	z80_rlc_index tmp
1912+	
1913+ddcb 00000RRR rlc_ixd_reg
1914+	z80_rlc_index main.R
1915+	
1916+fdcb 00000110 rlc_iyd
1917+	local tmp 8
1918+	z80_rlc_index tmp
1919+	
1920+fdcb 00000RRR rlc_iyd_reg
1921+	z80_rlc_index main.R
1922+	
1923+cb 00010RRR rl
1924+	rlc main.R 1 main.R
1925+	update_flags SZYH0PXN0C
1926+
1927+cb 00010110 rl_hl
1928+	local tmp 8
1929+	z80_fetch_hl
1930+	mov scratch1 tmp
1931+	rlc tmp 1 tmp
1932+	update_flags SZYH0PXN0C
1933+	mov tmp scratch1
1934+	z80_store_hl
1935+	
1936+z80_rl_index
1937+	arg tmp 8
1938+	mov wz scratch1
1939+	ocall read_8
1940+	cycles 1
1941+	mov scratch1 tmp
1942+	rlc tmp 1 tmp
1943+	update_flags SZYH0PXN0C
1944+	mov tmp scratch1
1945+	z80_store_index
1946+	
1947+ddcb 00010110 rl_ixd
1948+	local tmp 8
1949+	z80_rl_index tmp
1950+	
1951+fdcb 00010110 rl_iyd
1952+	local tmp 8
1953+	z80_rl_index tmp
1954+	
1955+	
1956+ddcb 00010RRR rl_ixd_reg
1957+	z80_rl_index main.R
1958+	
1959+fdcb 00010RRR rl_iyd_reg
1960+	z80_rl_index main.R
1961+	
1962+cb 00001RRR rrc
1963+	ror main.R 1 main.R
1964+	update_flags SZYH0PXN0C
1965+	
1966+cb 00001110 rrc_hl
1967+	local tmp 8
1968+	z80_fetch_hl
1969+	mov scratch1 tmp
1970+	ror tmp 1 tmp
1971+	update_flags SZYH0PXN0C
1972+	mov tmp scratch1
1973+	z80_store_hl
1974+	
1975+z80_rrc_index
1976+	arg tmp 8
1977+	mov wz scratch1
1978+	ocall read_8
1979+	cycles 1
1980+	mov scratch1 tmp
1981+	ror tmp 1 tmp
1982+	update_flags SZYH0PXN0C
1983+	mov tmp scratch1
1984+	z80_store_index
1985+	
1986+ddcb 00001110 rrc_ixd
1987+	local tmp 8
1988+	z80_rrc_index tmp
1989+	
1990+ddcb 00001RRR rrc_ixd_reg
1991+	z80_rrc_index main.R
1992+	
1993+fdcb 00001110 rrc_iyd
1994+	local tmp 8
1995+	z80_rrc_index tmp
1996+	
1997+fdcb 00001RRR rrc_iyd_reg
1998+	z80_rrc_index main.R
1999+	
2000+cb 00011RRR rr
2001+	rrc main.R 1 main.R
2002+	update_flags SZYH0PXN0C
2003+	
2004+cb 00011110 rr_hl
2005+	local tmp 8
2006+	z80_fetch_hl
2007+	mov scratch1 tmp
2008+	rrc tmp 1 tmp
2009+	update_flags SZYH0PXN0C
2010+	mov tmp scratch1
2011+	z80_store_hl
2012+	
2013+z80_rr_index
2014+	arg tmp 8
2015+	mov wz scratch1
2016+	ocall read_8
2017+	cycles 1
2018+	mov scratch1 tmp
2019+	rrc tmp 1 tmp
2020+	update_flags SZYH0PXN0C
2021+	mov tmp scratch1
2022+	z80_store_index
2023+	
2024+ddcb 00011110 rr_ixd
2025+	local tmp 8
2026+	z80_rr_index tmp
2027+	
2028+ddcb 00011RRR rr_ixd_reg
2029+	z80_rr_index main.R
2030+	
2031+fdcb 00011110 rr_iyd
2032+	local tmp 8
2033+	z80_rr_index tmp
2034+	
2035+fdcb 00011RRR rr_iyd_reg
2036+	z80_rr_index main.R
2037+	
2038+cb 00100RRR sla
2039+	lsl main.R 1 main.R
2040+	update_flags SZYH0PXN0C
2041+	
2042+cb 00100110 sla_hl
2043+	local tmp 8
2044+	z80_fetch_hl
2045+	mov scratch1 tmp
2046+	lsl tmp 1 tmp
2047+	update_flags SZYH0PXN0C
2048+	mov tmp scratch1
2049+	z80_store_hl
2050+	
2051+z80_sla_index
2052+	arg tmp 8
2053+	mov wz scratch1
2054+	ocall read_8
2055+	cycles 1
2056+	mov scratch1 tmp
2057+	lsl tmp 1 tmp
2058+	update_flags SZYH0PXN0C
2059+	mov tmp scratch1
2060+	z80_store_index
2061+	
2062+ddcb 00100110 sla_ixd
2063+	local tmp 8
2064+	z80_sla_index tmp
2065+	
2066+ddcb 00100RRR sla_ixd_reg
2067+	z80_sla_index main.R
2068+	
2069+fdcb 00100110 sla_iyd
2070+	local tmp 8
2071+	z80_sla_index tmp
2072+	
2073+fdcb 00100RRR sla_iyd_reg
2074+	z80_sla_index main.R
2075+	
2076+cb 00101RRR sra
2077+	asr main.R 1 main.R
2078+	update_flags SZYH0PXN0C
2079+	
2080+cb 00101110 sra_hl
2081+	local tmp 8
2082+	z80_fetch_hl
2083+	mov scratch1 tmp
2084+	asr tmp 1 tmp
2085+	update_flags SZYH0PXN0C
2086+	mov tmp scratch1
2087+	z80_store_hl
2088+	
2089+z80_sra_index
2090+	arg tmp 8
2091+	mov wz scratch1
2092+	ocall read_8
2093+	cycles 1
2094+	mov scratch1 tmp
2095+	asr tmp 1 tmp
2096+	update_flags SZYH0PXN0C
2097+	mov tmp scratch1
2098+	z80_store_index
2099+	
2100+ddcb 00101110 sra_ixd
2101+	local tmp 8
2102+	z80_sra_index tmp
2103+	
2104+ddcb 00101RRR sra_ixd_reg
2105+	z80_sra_index main.R
2106+	
2107+fdcb 00101110 sra_iyd
2108+	local tmp 8
2109+	z80_sra_index tmp
2110+	
2111+fdcb 00101RRR sra_iyd_reg
2112+	z80_sra_index main.R
2113+	
2114+cb 00110RRR sll
2115+	lsl main.R 1 main.R
2116+	update_flags SZ0YH0XN0C
2117+	or 1 main.R main.R
2118+	update_flags P
2119+	
2120+cb 00110110 sll_hl
2121+	local tmp 8
2122+	z80_fetch_hl
2123+	mov scratch1 tmp
2124+	lsl tmp 1 tmp
2125+	update_flags SZ0YH0XN0C
2126+	or 1 tmp tmp
2127+	update_flags P
2128+	mov tmp scratch1
2129+	z80_store_hl
2130+	
2131+z80_sll_index
2132+	arg tmp 8
2133+	mov wz scratch1
2134+	ocall read_8
2135+	cycles 1
2136+	mov scratch1 tmp
2137+	lsl tmp 1 tmp
2138+	update_flags SZ0YH0XN0C
2139+	or 1 tmp tmp
2140+	update_flags P
2141+	mov tmp scratch1
2142+	z80_store_index
2143+	
2144+ddcb 00110110 sll_ixd
2145+	local tmp 8
2146+	z80_sll_index tmp
2147+	
2148+ddcb 00110RRR sll_ixd_reg
2149+	z80_sll_index main.R
2150+	
2151+fdcb 00110110 sll_iyd
2152+	local tmp 8
2153+	z80_sll_index tmp
2154+	
2155+fdcb 00110RRR sll_iyd_reg
2156+	z80_sll_index main.R
2157+	
2158+cb 00111RRR srl
2159+	lsr main.R 1 main.R
2160+	update_flags SZYH0PXN0C
2161+	
2162+cb 00111110 srl_hl
2163+	local tmp 8
2164+	z80_fetch_hl
2165+	mov scratch1 tmp
2166+	lsr tmp 1 tmp
2167+	update_flags SZYH0PXN0C
2168+	mov tmp scratch1
2169+	z80_store_hl
2170+	
2171+z80_srl_index
2172+	arg tmp 8
2173+	mov wz scratch1
2174+	ocall read_8
2175+	cycles 1
2176+	mov scratch1 tmp
2177+	lsr tmp 1 tmp
2178+	update_flags SZYH0PXN0C
2179+	mov tmp scratch1
2180+	z80_store_index
2181+	
2182+ddcb 00111110 srl_ixd
2183+	local tmp 8
2184+	z80_srl_index tmp
2185+	
2186+ddcb 00111RRR srl_ixd_reg
2187+	z80_srl_index main.R
2188+	
2189+fdcb 00111110 srl_iyd
2190+	local tmp 8
2191+	z80_srl_index tmp
2192+	
2193+fdcb 00111RRR srl_iyd_reg
2194+	z80_srl_index main.R
2195+	
2196+cb 01BBBRRR bit_reg
2197+	local tmp 8
2198+	lsl 1 B tmp
2199+	mov main.R last_flag_result
2200+	and main.R tmp tmp
2201+	update_flags SZH1PN0
2202+	
2203+cb 01BBB110 bit_hl
2204+	local tmp 8
2205+	z80_fetch_hl
2206+	cycles 1
2207+	lsl 1 B tmp
2208+	lsr wz 8 last_flag_result
2209+	and scratch1 tmp tmp
2210+	update_flags SZH1PN0
2211+	
2212+	
2213+ddcb 01BBBRRR bit_ixd
2214+	local tmp 8
2215+	mov wz scratch1
2216+	ocall read_8
2217+	cycles 1
2218+	lsl 1 B tmp
2219+	lsr wz 8 last_flag_result
2220+	and scratch1 tmp tmp
2221+	update_flags SZH1PN0
2222+	
2223+fdcb 01BBBRRR bit_iyd
2224+	local tmp 8
2225+	mov wz scratch1
2226+	ocall read_8
2227+	cycles 1
2228+	lsl 1 B tmp
2229+	lsr wz 8 last_flag_result
2230+	and scratch1 tmp tmp
2231+	update_flags SZH1PN0
2232+	
2233+cb 10BBBRRR res_reg
2234+	local tmp 8
2235+	lsl 1 B tmp
2236+	not tmp tmp
2237+	and main.R tmp main.R
2238+	
2239+cb 10BBB110 res_hl
2240+	z80_fetch_hl
2241+	cycles 1
2242+	local tmp 8
2243+	lsl 1 B tmp
2244+	not tmp tmp
2245+	and scratch1 tmp scratch1
2246+	z80_store_hl
2247+	
2248+z80_res_index
2249+	arg bit 8
2250+	arg tmp 8
2251+	lsl 1 bit tmp
2252+	not tmp tmp
2253+	mov wz scratch1
2254+	ocall read_8
2255+	cycles 1
2256+	and scratch1 tmp tmp
2257+	mov tmp scratch1
2258+	z80_store_index
2259+	
2260+ddcb 10BBB110 res_ixd
2261+	local tmp 8
2262+	z80_res_index B tmp
2263+	
2264+ddcb 10BBBRRR res_ixd_reg
2265+	z80_res_index B main.R
2266+	
2267+fdcb 10BBB110 res_iyd
2268+	local tmp 8
2269+	z80_res_index B tmp
2270+	
2271+fdcb 10BBBRRR res_iyd_reg
2272+	z80_res_index B main.R
2273+	
2274+cb 11BBBRRR set_reg
2275+	local tmp 8
2276+	lsl 1 B tmp
2277+	or main.R tmp main.R
2278+	
2279+cb 11BBB110 set_hl
2280+	z80_fetch_hl
2281+	cycles 1
2282+	local tmp 8
2283+	lsl 1 B tmp
2284+	or scratch1 tmp scratch1
2285+	z80_store_hl
2286+	
2287+z80_set_index
2288+	arg bit 8
2289+	arg tmp 8
2290+	lsl 1 bit tmp
2291+	mov wz scratch1
2292+	ocall read_8
2293+	cycles 1
2294+	or scratch1 tmp tmp
2295+	mov tmp scratch1
2296+	z80_store_index
2297+	
2298+ddcb 11BBB110 set_ixd
2299+	local tmp 8
2300+	z80_set_index B tmp
2301+	
2302+ddcb 11BBBRRR set_ixd_reg
2303+	z80_set_index B main.R
2304+	
2305+fdcb 11BBB110 set_iyd
2306+	local tmp 8
2307+	z80_set_index B tmp
2308+	
2309+fdcb 11BBBRRR set_iyd_reg
2310+	z80_set_index B main.R
2311+	
2312+z80_fetch_mod_hl
2313+	local tmp 16
2314+	arg change 16
2315+	lsl h 8 tmp
2316+	or l tmp tmp
2317+	mov tmp scratch1
2318+	add change tmp tmp
2319+	mov tmp l
2320+	lsr tmp 8 h
2321+	ocall read_8
2322+	cycles 2
2323+	
2324+z80_ldd_ldi
2325+	arg change 16
2326+	local tmp 16
2327+	local tmp8 8
2328+	z80_fetch_mod_hl change
2329+	
2330+	add a scratch1 tmp8
2331+	update_flags H0XN0
2332+	
2333+	and 0x2 tmp8 tmp8
2334+	lsl tmp8 4 tmp8
2335+	and 0x88 last_flag_result last_flag_result
2336+	or tmp8 last_flag_result last_flag_result
2337+	
2338+	lsl d 8 tmp
2339+	or e tmp tmp
2340+	mov tmp scratch2
2341+	add change tmp tmp
2342+	mov tmp e
2343+	lsr tmp 8 d
2344+	ocall write_8
2345+	
2346+	lsl b 8 tmp
2347+	or c tmp tmp
2348+	sub 1 tmp tmp
2349+	
2350+	mov tmp c
2351+	lsr tmp 8 b
2352+	mov c pvflag
2353+	or b pvflag pvflag
2354+	
2355+
2356+ed 10100000 ldi
2357+	z80_ldd_ldi 1
2358+
2359+ed 10101000 ldd
2360+	z80_ldd_ldi -1
2361+
2362+ed 10110000 ldir
2363+	z80_ldd_ldi 1
2364+	if pvflag
2365+	
2366+	add 1 pc wz
2367+	sub 2 pc pc
2368+	cycles 5
2369+	
2370+	end
2371+
2372+ed 10111000 lddr
2373+	z80_ldd_ldi -1
2374+	if pvflag
2375+	
2376+	add 1 pc wz
2377+	sub 2 pc pc
2378+	cycles 5
2379+	
2380+	end
2381+	
2382+z80_cpd_cpi
2383+	local tmp 16
2384+	local tmp8 8
2385+	local hf 8
2386+	arg change 16
2387+	
2388+	z80_fetch_mod_hl change
2389+	sub scratch1 a tmp8
2390+	update_flags SZHN1
2391+	
2392+	lsr chflags 3 hf
2393+	and 1 hf hf
2394+	
2395+	sub hf tmp8 tmp8
2396+	update_flags X
2397+	
2398+	and 0x2 tmp8 tmp8
2399+	lsl tmp8 4 tmp8
2400+	and 0x88 last_flag_result last_flag_result
2401+	or tmp8 last_flag_result last_flag_result
2402+	
2403+	lsl b 8 tmp
2404+	or c tmp tmp
2405+	sub 1 tmp tmp
2406+	
2407+	mov tmp c
2408+	lsr tmp 8 b
2409+	mov c pvflag
2410+	or b pvflag pvflag
2411+	
2412+	cycles 5
2413+	
2414+ed 10100001 cpi
2415+	z80_cpd_cpi 1
2416+	
2417+ed 10101001 cpd
2418+	z80_cpd_cpi -1
2419+	
2420+ed 10110001 cpir
2421+	z80_cpd_cpi 1
2422+	if pvflag
2423+	
2424+	if zflag
2425+	
2426+	else
2427+	
2428+	add 1 pc wz
2429+	sub 2 pc pc
2430+	cycles 5
2431+	
2432+	end
2433+	end
2434+	
2435+ed 10111001 cpdr
2436+	z80_cpd_cpi -1
2437+	if pvflag
2438+	
2439+	if zflag
2440+	
2441+	else
2442+	
2443+	add 1 pc wz
2444+	sub 2 pc pc
2445+	cycles 5
2446+	
2447+	end
2448+	end
2449+
2450+00100111 daa
2451+	local diff 8
2452+	local tmp 8
2453+	local low 8
2454+	and 0xF a low
2455+	and 0x8 chflags tmp
2456+	if tmp
2457+	
2458+	mov 6 diff
2459+	
2460+	else
2461+	
2462+	cmp 0xA low
2463+	if >=U
2464+	mov 6 diff
2465+	else
2466+	mov 0 diff
2467+	end
2468+	
2469+	end
2470+	
2471+	and 0x80 chflags tmp
2472+	if tmp
2473+	
2474+	or 0x60 diff diff
2475+	update_flags C1
2476+	
2477+	else
2478+	
2479+	cmp 0x9A a
2480+	if >=U
2481+	or 0x60 diff diff
2482+	update_flags C1
2483+	else
2484+	update_flags C0
2485+	end
2486+	end
2487+	
2488+	if nflag
2489+	
2490+	sub diff a a
2491+	update_flags SZYHPX
2492+	
2493+	else
2494+	
2495+	add diff a a
2496+	update_flags SZYHPX
2497+	
2498+	end
2499+	
2500+dd OOOOOOOO dd_normal
2501+	dispatch O
2502+
2503+fd OOOOOOOO fd_normal
2504+	dispatch O
2505+	
2506+ed 01101111 rld
2507+	local tmp 8
2508+	local tmp2 8
2509+	z80_fetch_hl
2510+	cycles 4
2511+	
2512+	lsr scratch1 4 tmp
2513+	
2514+	lsl scratch1 4 scratch1
2515+	
2516+	and 0xF a tmp2
2517+	or tmp2 scratch1 scratch1
2518+	
2519+	and 0xF0 a a
2520+	or tmp a a
2521+	update_flags SZYH0XPN0
2522+	z80_store_hl
2523+	
2524+ed 01100111 rrd
2525+	local tmp 8
2526+	local tmp2 8
2527+	z80_fetch_hl
2528+	cycles 4
2529+	
2530+	and 0xF scratch1 tmp
2531+	lsr scratch1 4 scratch1
2532+	
2533+	lsl a 4 tmp2
2534+	or tmp2 scratch1 scratch1
2535+	
2536+	and 0xF0 a a
2537+	or tmp a a
2538+	update_flags SZYH0XPN0
2539+	z80_store_hl
2540+	
+3982, -0
   1@@ -0,0 +1,3982 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "z80inst.h"
   8+#include "z80_to_x86.h"
   9+#include "gen_x86.h"
  10+#include "mem.h"
  11+#include "util.h"
  12+#include <stdio.h>
  13+#include <stdlib.h>
  14+#include <stddef.h>
  15+#include <string.h>
  16+
  17+#define MODE_UNUSED (MODE_IMMED-1)
  18+#define MAX_MCYCLE_LENGTH 6
  19+#define NATIVE_CHUNK_SIZE 1024
  20+#define NATIVE_MAP_CHUNKS (0x10000 / NATIVE_CHUNK_SIZE)
  21+
  22+//#define DO_DEBUG_PRINT
  23+
  24+#ifdef DO_DEBUG_PRINT
  25+#define dprintf printf
  26+#else
  27+#define dprintf
  28+#endif
  29+
  30+uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst);
  31+void z80_handle_deferred(z80_context * context);
  32+
  33+uint8_t z80_size(z80inst * inst)
  34+{
  35+	uint8_t reg = (inst->reg & 0x1F);
  36+	if (reg != Z80_UNUSED && reg != Z80_USE_IMMED) {
  37+		return reg < Z80_BC ? SZ_B : SZ_W;
  38+	}
  39+	//TODO: Handle any necessary special cases
  40+	return SZ_B;
  41+}
  42+
  43+uint8_t zf_off(uint8_t flag)
  44+{
  45+	return offsetof(z80_context, flags) + flag;
  46+}
  47+
  48+uint8_t zaf_off(uint8_t flag)
  49+{
  50+	return offsetof(z80_context, alt_flags) + flag;
  51+}
  52+
  53+uint8_t zr_off(uint8_t reg)
  54+{
  55+	if (reg > Z80_A) {
  56+		reg = z80_low_reg(reg);
  57+	}
  58+	return offsetof(z80_context, regs) + reg;
  59+}
  60+
  61+uint8_t zar_off(uint8_t reg)
  62+{
  63+	if (reg > Z80_A) {
  64+		reg = z80_low_reg(reg);
  65+	}
  66+	return offsetof(z80_context, alt_regs) + reg;
  67+}
  68+
  69+void zreg_to_native(z80_options *opts, uint8_t reg, uint8_t native_reg)
  70+{
  71+	if (opts->regs[reg] >= 0) {
  72+		mov_rr(&opts->gen.code, opts->regs[reg], native_reg, reg > Z80_A ? SZ_W : SZ_B);
  73+	} else {
  74+		mov_rdispr(&opts->gen.code, opts->gen.context_reg, zr_off(reg), native_reg, reg > Z80_A ? SZ_W : SZ_B);
  75+	}
  76+}
  77+
  78+void native_to_zreg(z80_options *opts, uint8_t native_reg, uint8_t reg)
  79+{
  80+	if (opts->regs[reg] >= 0) {
  81+		mov_rr(&opts->gen.code, native_reg, opts->regs[reg], reg > Z80_A ? SZ_W : SZ_B);
  82+	} else {
  83+		mov_rrdisp(&opts->gen.code, native_reg, opts->gen.context_reg, zr_off(reg), reg > Z80_A ? SZ_W : SZ_B);
  84+	}
  85+}
  86+
  87+void translate_z80_reg(z80inst * inst, host_ea * ea, z80_options * opts)
  88+{
  89+	code_info *code = &opts->gen.code;
  90+	if (inst->reg == Z80_USE_IMMED) {
  91+		ea->mode = MODE_IMMED;
  92+		ea->disp = inst->immed;
  93+	} else if ((inst->reg & 0x1F) == Z80_UNUSED) {
  94+		ea->mode = MODE_UNUSED;
  95+	} else {
  96+		ea->mode = MODE_REG_DIRECT;
  97+		if (inst->reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
  98+			if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
  99+				mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
 100+				ror_ir(code, 8, opts->gen.scratch1, SZ_W);
 101+				ea->base = opts->gen.scratch1;
 102+			} else {
 103+				ea->base = opts->regs[Z80_IYL];
 104+				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 105+			}
 106+		} else if(opts->regs[inst->reg] >= 0) {
 107+			ea->base = opts->regs[inst->reg];
 108+			if (ea->base >= AH && ea->base <= BH) {
 109+				if ((inst->addr_mode & 0x1F) == Z80_REG) {
 110+					uint8_t other_reg = opts->regs[inst->ea_reg];
 111+					if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 112+						//we can't mix an *H reg with a register that requires the REX prefix
 113+						ea->base = opts->regs[z80_low_reg(inst->reg)];
 114+						ror_ir(code, 8, ea->base, SZ_W);
 115+					}
 116+				} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
 117+					//temp regs require REX prefix too
 118+					ea->base = opts->regs[z80_low_reg(inst->reg)];
 119+					ror_ir(code, 8, ea->base, SZ_W);
 120+				}
 121+			}
 122+		} else {
 123+			ea->mode = MODE_REG_DISPLACE8;
 124+			ea->base = opts->gen.context_reg;
 125+			ea->disp = zr_off(inst->reg);
 126+		}
 127+	}
 128+}
 129+
 130+void z80_save_reg(z80inst * inst, z80_options * opts)
 131+{
 132+	code_info *code = &opts->gen.code;
 133+	if (inst->reg == Z80_USE_IMMED || inst->reg == Z80_UNUSED) {
 134+		return;
 135+	}
 136+	if (inst->reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 137+		if ((inst->addr_mode & 0x1F) == Z80_REG && inst->ea_reg == Z80_IYL) {
 138+			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 139+			mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
 140+			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 141+		} else {
 142+			ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 143+		}
 144+	} else if (opts->regs[inst->reg] >= AH && opts->regs[inst->reg] <= BH) {
 145+		if ((inst->addr_mode & 0x1F) == Z80_REG) {
 146+			uint8_t other_reg = opts->regs[inst->ea_reg];
 147+			if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 148+				//we can't mix an *H reg with a register that requires the REX prefix
 149+				ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
 150+			}
 151+		} else if((inst->addr_mode & 0x1F) != Z80_UNUSED && (inst->addr_mode & 0x1F) != Z80_IMMED) {
 152+			//temp regs require REX prefix too
 153+			ror_ir(code, 8, opts->regs[z80_low_reg(inst->reg)], SZ_W);
 154+		}
 155+	}
 156+}
 157+
 158+void translate_z80_ea(z80inst * inst, host_ea * ea, z80_options * opts, uint8_t read, uint8_t modify)
 159+{
 160+	code_info *code = &opts->gen.code;
 161+	uint8_t size, areg;
 162+	int8_t reg;
 163+	ea->mode = MODE_REG_DIRECT;
 164+	areg = read ? opts->gen.scratch1 : opts->gen.scratch2;
 165+	switch(inst->addr_mode & 0x1F)
 166+	{
 167+	case Z80_REG:
 168+		if (inst->ea_reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 169+			if (inst->reg == Z80_IYL) {
 170+				mov_rr(code, opts->regs[Z80_IY], opts->gen.scratch1, SZ_W);
 171+				ror_ir(code, 8, opts->gen.scratch1, SZ_W);
 172+				ea->base = opts->gen.scratch1;
 173+			} else {
 174+				ea->base = opts->regs[Z80_IYL];
 175+				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 176+			}
 177+		} else if(opts->regs[inst->ea_reg] >= 0) {
 178+			ea->base = opts->regs[inst->ea_reg];
 179+			if (ea->base >= AH && ea->base <= BH && inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED) {
 180+				uint8_t other_reg = opts->regs[inst->reg];
 181+#ifdef X86_64
 182+				if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 183+					//we can't mix an *H reg with a register that requires the REX prefix
 184+					ea->base = opts->regs[z80_low_reg(inst->ea_reg)];
 185+					ror_ir(code, 8, ea->base, SZ_W);
 186+				}
 187+#endif
 188+			}
 189+		} else {
 190+			ea->mode = MODE_REG_DISPLACE8;
 191+			ea->base = opts->gen.context_reg;
 192+			ea->disp = zr_off(inst->ea_reg);
 193+		}
 194+		break;
 195+	case Z80_REG_INDIRECT:
 196+		zreg_to_native(opts, inst->ea_reg, areg);
 197+		size = z80_size(inst);
 198+		if (read) {
 199+			if (modify) {
 200+				//push_r(code, opts->gen.scratch1);
 201+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
 202+			}
 203+			if (size == SZ_B) {
 204+				call(code, opts->read_8);
 205+			} else {
 206+				call(code, opts->read_16);
 207+			}
 208+		}
 209+		ea->base = opts->gen.scratch1;
 210+		break;
 211+	case Z80_IMMED:
 212+		ea->mode = MODE_IMMED;
 213+		ea->disp = inst->immed;
 214+		break;
 215+	case Z80_IMMED_INDIRECT:
 216+		mov_ir(code, inst->immed, areg, SZ_W);
 217+		size = z80_size(inst);
 218+		if (read) {
 219+			/*if (modify) {
 220+				push_r(code, opts->gen.scratch1);
 221+			}*/
 222+			if (size == SZ_B) {
 223+				call(code, opts->read_8);
 224+			} else {
 225+				call(code, opts->read_16);
 226+			}
 227+		}
 228+		ea->base = opts->gen.scratch1;
 229+		break;
 230+	case Z80_IX_DISPLACE:
 231+	case Z80_IY_DISPLACE:
 232+		zreg_to_native(opts, (inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY, areg);
 233+		add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, areg, SZ_W);
 234+		size = z80_size(inst);
 235+		if (read) {
 236+			if (modify) {
 237+				//push_r(code, opts->gen.scratch1);
 238+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
 239+			}
 240+			if (size == SZ_B) {
 241+				call(code, opts->read_8);
 242+			} else {
 243+				call(code, opts->read_16);
 244+			}
 245+		}
 246+		ea->base = opts->gen.scratch1;
 247+		break;
 248+	case Z80_UNUSED:
 249+		ea->mode = MODE_UNUSED;
 250+		break;
 251+	default:
 252+		fatal_error("Unrecognized Z80 addressing mode %d\n", inst->addr_mode & 0x1F);
 253+	}
 254+}
 255+
 256+void z80_save_ea(code_info *code, z80inst * inst, z80_options * opts)
 257+{
 258+	if ((inst->addr_mode & 0x1F) == Z80_REG) {
 259+		if (inst->ea_reg == Z80_IYH && opts->regs[Z80_IYL] >= 0) {
 260+			if (inst->reg == Z80_IYL) {
 261+				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 262+				mov_rr(code, opts->gen.scratch1, opts->regs[Z80_IYL], SZ_B);
 263+				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 264+			} else {
 265+				ror_ir(code, 8, opts->regs[Z80_IY], SZ_W);
 266+			}
 267+		} else if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
 268+			uint8_t other_reg = opts->regs[inst->reg];
 269+#ifdef X86_64
 270+			if (other_reg >= R8 || (other_reg >= RSP && other_reg <= RDI)) {
 271+				//we can't mix an *H reg with a register that requires the REX prefix
 272+				ror_ir(code, 8, opts->regs[z80_low_reg(inst->ea_reg)], SZ_W);
 273+			}
 274+#endif
 275+		}
 276+	}
 277+}
 278+
 279+void z80_save_result(z80_options *opts, z80inst * inst)
 280+{
 281+	switch(inst->addr_mode & 0x1f)
 282+	{
 283+	case Z80_REG_INDIRECT:
 284+	case Z80_IMMED_INDIRECT:
 285+	case Z80_IX_DISPLACE:
 286+	case Z80_IY_DISPLACE:
 287+		if (inst->op != Z80_LD) {
 288+			mov_rdispr(&opts->gen.code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch2, SZ_W);
 289+		}
 290+		if (z80_size(inst) == SZ_B) {
 291+			call(&opts->gen.code, opts->write_8);
 292+		} else {
 293+			call(&opts->gen.code, opts->write_16_lowfirst);
 294+		}
 295+	}
 296+}
 297+
 298+enum {
 299+	DONT_READ=0,
 300+	READ
 301+};
 302+
 303+enum {
 304+	DONT_MODIFY=0,
 305+	MODIFY
 306+};
 307+
 308+void z80_print_regs_exit(z80_context * context)
 309+{
 310+	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n",
 311+		context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C],
 312+		context->regs[Z80_D], context->regs[Z80_E],
 313+		(context->regs[Z80_H] << 8) | context->regs[Z80_L],
 314+		(context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL],
 315+		(context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL],
 316+		context->sp, context->im, context->iff1, context->iff2);
 317+	puts("--Alternate Regs--");
 318+	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\n",
 319+		context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C],
 320+		context->alt_regs[Z80_D], context->alt_regs[Z80_E],
 321+		(context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L],
 322+		(context->alt_regs[Z80_IXH] << 8) | context->alt_regs[Z80_IXL],
 323+		(context->alt_regs[Z80_IYH] << 8) | context->alt_regs[Z80_IYL]);
 324+	exit(0);
 325+}
 326+
 327+void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address, uint8_t interp)
 328+{
 329+	uint32_t num_cycles;
 330+	host_ea src_op, dst_op;
 331+	uint8_t size;
 332+	z80_options *opts = context->options;
 333+	uint8_t * start = opts->gen.code.cur;
 334+	code_info *code = &opts->gen.code;
 335+	if (!interp) {
 336+		check_cycles_int(&opts->gen, address);
 337+		if (context->breakpoint_flags[address / 8] & (1 << (address % 8))) {
 338+			zbreakpoint_patch(context, address, start);
 339+		}
 340+		num_cycles = 4 * inst->opcode_bytes;
 341+		add_ir(code, inst->opcode_bytes > 1 ? 2 : 1, opts->regs[Z80_R], SZ_B);
 342+#ifdef Z80_LOG_ADDRESS
 343+		log_address(&opts->gen, address, "Z80: %X @ %d\n");
 344+#endif
 345+	}
 346+	switch(inst->op)
 347+	{
 348+	case Z80_LD:
 349+		size = z80_size(inst);
 350+		switch (inst->addr_mode & 0x1F)
 351+		{
 352+		case Z80_REG:
 353+		case Z80_REG_INDIRECT:
 354+			if (size != SZ_B) {
 355+				num_cycles += 2;
 356+			}
 357+			if (inst->reg == Z80_I || inst->ea_reg == Z80_I || inst->reg == Z80_R || inst->ea_reg == Z80_R) {
 358+				num_cycles += 1;
 359+			} else if (inst->reg == Z80_USE_IMMED) {
 360+				num_cycles += 3;
 361+			}
 362+			break;
 363+		case Z80_IMMED:
 364+			num_cycles += size == SZ_B ? 3 : 6;
 365+			break;
 366+		case Z80_IMMED_INDIRECT:
 367+			num_cycles += 6;
 368+			break;
 369+		case Z80_IX_DISPLACE:
 370+		case Z80_IY_DISPLACE:
 371+			num_cycles += 8; //3 for displacement, 5 for address addition
 372+			break;
 373+		}
 374+		cycles(&opts->gen, num_cycles);
 375+		if (inst->addr_mode & Z80_DIR) {
 376+			translate_z80_ea(inst, &dst_op, opts, DONT_READ, MODIFY);
 377+			translate_z80_reg(inst, &src_op, opts);
 378+		} else {
 379+			translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 380+			translate_z80_reg(inst, &dst_op, opts);
 381+		}
 382+		if (inst->reg == Z80_R) {
 383+			mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 384+			mov_rr(code, opts->regs[Z80_A], opts->regs[Z80_R], SZ_B);
 385+			and_ir(code, 0x80, opts->gen.scratch1, SZ_B);
 386+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zr_off(Z80_R), SZ_B);
 387+		} else if (inst->ea_reg == Z80_R && inst->addr_mode == Z80_REG) {
 388+			mov_rr(code, opts->regs[Z80_R], opts->regs[Z80_A], SZ_B);
 389+			and_ir(code, 0x7F, opts->regs[Z80_A], SZ_B);
 390+			or_rdispr(code, opts->gen.context_reg, zr_off(Z80_R), opts->regs[Z80_A], SZ_B);
 391+		} else if (src_op.mode == MODE_REG_DIRECT) {
 392+			if(dst_op.mode == MODE_REG_DISPLACE8) {
 393+				mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, size);
 394+			} else {
 395+				mov_rr(code, src_op.base, dst_op.base, size);
 396+			}
 397+		} else if(src_op.mode == MODE_IMMED) {
 398+			if(dst_op.mode == MODE_REG_DISPLACE8) {
 399+				mov_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, size);
 400+			} else {
 401+				mov_ir(code, src_op.disp, dst_op.base, size);
 402+			}
 403+		} else {
 404+			if(dst_op.mode == MODE_REG_DISPLACE8) {
 405+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, size);
 406+				mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, size);
 407+			} else {
 408+				mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, size);
 409+			}
 410+		}
 411+		if ((inst->ea_reg == Z80_I || inst->ea_reg == Z80_R) && inst->addr_mode == Z80_REG) {
 412+			//ld a, i and ld a, r sets some flags
 413+			cmp_ir(code, 0, dst_op.base, SZ_B);
 414+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 415+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 416+			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);;
 417+			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);;
 418+			mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch1, SZ_B);
 419+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 420+		}
 421+		z80_save_reg(inst, opts);
 422+		z80_save_ea(code, inst, opts);
 423+		if (inst->addr_mode & Z80_DIR) {
 424+			z80_save_result(opts, inst);
 425+		}
 426+		break;
 427+	case Z80_PUSH:
 428+		cycles(&opts->gen, num_cycles + 1);
 429+		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
 430+		if (inst->reg == Z80_AF) {
 431+			zreg_to_native(opts, Z80_A, opts->gen.scratch1);
 432+			shl_ir(code, 8, opts->gen.scratch1, SZ_W);
 433+			mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 434+			and_ir(code, 0x28, opts->gen.scratch1, SZ_B);
 435+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
 436+			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 437+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_N), opts->gen.scratch1, SZ_B);
 438+			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 439+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_PV), opts->gen.scratch1, SZ_B);
 440+			ror_ir(code, 2, opts->gen.scratch1, SZ_B);
 441+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch1, SZ_B);
 442+			ror_ir(code, 2, opts->gen.scratch1, SZ_B);
 443+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_Z), opts->gen.scratch1, SZ_B);
 444+			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 445+			or_rdispr(code, opts->gen.context_reg, zf_off(ZF_S), opts->gen.scratch1, SZ_B);
 446+			ror_ir(code, 1, opts->gen.scratch1, SZ_B);
 447+		} else {
 448+			zreg_to_native(opts, inst->reg, opts->gen.scratch1);
 449+		}
 450+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 451+		call(code, opts->write_16_highfirst);
 452+		//no call to save_z80_reg needed since there's no chance we'll use the only
 453+		//the upper half of a register pair
 454+		break;
 455+	case Z80_POP:
 456+		cycles(&opts->gen, num_cycles);
 457+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 458+		call(code, opts->read_16);
 459+		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
 460+		if (inst->reg == Z80_AF) {
 461+
 462+			bt_ir(code, 0, opts->gen.scratch1, SZ_W);
 463+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 464+			bt_ir(code, 1, opts->gen.scratch1, SZ_W);
 465+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
 466+			bt_ir(code, 2, opts->gen.scratch1, SZ_W);
 467+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_PV));
 468+			bt_ir(code, 4, opts->gen.scratch1, SZ_W);
 469+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 470+			bt_ir(code, 6, opts->gen.scratch1, SZ_W);
 471+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_Z));
 472+			bt_ir(code, 7, opts->gen.scratch1, SZ_W);
 473+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_S));
 474+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 475+			shr_ir(code, 8, opts->gen.scratch1, SZ_W);
 476+			native_to_zreg(opts, opts->gen.scratch1, Z80_A);
 477+		} else {
 478+			native_to_zreg(opts, opts->gen.scratch1, inst->reg);
 479+		}
 480+		//no call to save_z80_reg needed since there's no chance we'll use the only
 481+		//the upper half of a register pair
 482+		break;
 483+	case Z80_EX:
 484+		cycles(&opts->gen, num_cycles);
 485+		if (inst->addr_mode == Z80_REG) {
 486+			if(inst->reg == Z80_AF) {
 487+				zreg_to_native(opts, Z80_A, opts->gen.scratch1);
 488+				mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_A), opts->gen.scratch2, SZ_B);
 489+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_A), SZ_B);
 490+				native_to_zreg(opts, opts->gen.scratch2, Z80_A);
 491+
 492+				//Flags are currently word aligned, so we can move
 493+				//them efficiently a word at a time
 494+				for (int f = ZF_C; f < ZF_NUM; f+=2) {
 495+					mov_rdispr(code, opts->gen.context_reg, zf_off(f), opts->gen.scratch1, SZ_W);
 496+					mov_rdispr(code, opts->gen.context_reg, zaf_off(f), opts->gen.scratch2, SZ_W);
 497+					mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zaf_off(f), SZ_W);
 498+					mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(f), SZ_W);
 499+				}
 500+			} else {
 501+				if (opts->regs[Z80_DE] >= 0 && opts->regs[Z80_HL] >= 0) {
 502+					xchg_rr(code, opts->regs[Z80_DE], opts->regs[Z80_HL], SZ_W);
 503+				} else {
 504+					zreg_to_native(opts, Z80_DE, opts->gen.scratch1);
 505+					zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
 506+					native_to_zreg(opts, opts->gen.scratch1, Z80_HL);
 507+					native_to_zreg(opts, opts->gen.scratch2, Z80_DE);
 508+				}
 509+			}
 510+		} else {
 511+			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 512+			call(code, opts->read_8);
 513+			if (opts->regs[inst->reg] >= 0) {
 514+				xchg_rr(code, opts->regs[inst->reg], opts->gen.scratch1, SZ_B);
 515+			} else {
 516+				zreg_to_native(opts, inst->reg, opts->gen.scratch2);
 517+				xchg_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 518+				native_to_zreg(opts, opts->gen.scratch2, inst->reg);
 519+			}
 520+			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 521+			call(code, opts->write_8);
 522+			cycles(&opts->gen, 1);
 523+			uint8_t high_reg = z80_high_reg(inst->reg);
 524+			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
 525+			add_ir(code, 1, opts->gen.scratch1, SZ_W);
 526+			call(code, opts->read_8);
 527+			if (opts->regs[inst->reg] >= 0) {
 528+				//even though some of the upper halves can be used directly
 529+				//the limitations on mixing *H regs with the REX prefix
 530+				//prevent us from taking advantage of it
 531+				uint8_t use_reg = opts->regs[inst->reg];
 532+				ror_ir(code, 8, use_reg, SZ_W);
 533+				xchg_rr(code, use_reg, opts->gen.scratch1, SZ_B);
 534+				//restore reg to normal rotation
 535+				ror_ir(code, 8, use_reg, SZ_W);
 536+			} else {
 537+				zreg_to_native(opts, high_reg, opts->gen.scratch2);
 538+				xchg_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 539+				native_to_zreg(opts, opts->gen.scratch2, high_reg);
 540+			}
 541+			mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
 542+			add_ir(code, 1, opts->gen.scratch2, SZ_W);
 543+			call(code, opts->write_8);
 544+			cycles(&opts->gen, 2);
 545+		}
 546+		break;
 547+	case Z80_EXX:
 548+		cycles(&opts->gen, num_cycles);
 549+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
 550+		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_BC), opts->gen.scratch2, SZ_W);
 551+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_BC), SZ_W);
 552+		native_to_zreg(opts, opts->gen.scratch2, Z80_BC);
 553+
 554+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 555+		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_HL), opts->gen.scratch2, SZ_W);
 556+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_HL), SZ_W);
 557+		native_to_zreg(opts, opts->gen.scratch2, Z80_HL);
 558+
 559+		zreg_to_native(opts, Z80_DE, opts->gen.scratch1);
 560+		mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_DE), opts->gen.scratch2, SZ_W);
 561+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_DE), SZ_W);
 562+		native_to_zreg(opts, opts->gen.scratch2, Z80_DE);
 563+		break;
 564+	case Z80_LDI: {
 565+		cycles(&opts->gen, num_cycles);
 566+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 567+		call(code, opts->read_8);
 568+		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 569+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 570+		call(code, opts->write_8);
 571+		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 572+		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 573+		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 574+		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 575+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 576+		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 577+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 578+		cycles(&opts->gen, 2);
 579+		if (opts->regs[Z80_DE] >= 0) {
 580+			add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 581+		} else {
 582+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 583+		}
 584+		if (opts->regs[Z80_HL] >= 0) {
 585+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 586+		} else {
 587+			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 588+		}
 589+		if (opts->regs[Z80_BC] >= 0) {
 590+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 591+		} else {
 592+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 593+		}
 594+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 595+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 596+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 597+		break;
 598+	}
 599+	case Z80_LDIR: {
 600+		cycles(&opts->gen, num_cycles);
 601+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 602+		call(code, opts->read_8);
 603+		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 604+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 605+		call(code, opts->write_8);
 606+		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 607+		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 608+		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 609+		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 610+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 611+		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 612+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 613+		if (opts->regs[Z80_DE] >= 0) {
 614+			add_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 615+		} else {
 616+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 617+		}
 618+		if (opts->regs[Z80_HL] >= 0) {
 619+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 620+		} else {
 621+			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 622+		}
 623+		if (opts->regs[Z80_BC] >= 0) {
 624+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 625+		} else {
 626+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 627+		}
 628+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 629+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 630+		uint8_t * cont = code->cur+1;
 631+		jcc(code, CC_Z, code->cur+2);
 632+		cycles(&opts->gen, 7);
 633+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 634+		jmp(code, start);
 635+		*cont = code->cur - (cont + 1);
 636+		cycles(&opts->gen, 2);
 637+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 638+		break;
 639+	}
 640+	case Z80_LDD: {
 641+		cycles(&opts->gen, num_cycles);
 642+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 643+		call(code, opts->read_8);
 644+		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 645+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 646+		call(code, opts->write_8);
 647+		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 648+		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 649+		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 650+		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 651+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 652+		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 653+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 654+		cycles(&opts->gen, 2);
 655+		if (opts->regs[Z80_DE] >= 0) {
 656+			sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 657+		} else {
 658+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 659+		}
 660+		if (opts->regs[Z80_HL] >= 0) {
 661+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 662+		} else {
 663+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
 664+		}
 665+		if (opts->regs[Z80_BC] >= 0) {
 666+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 667+		} else {
 668+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_BC), SZ_W);
 669+		}
 670+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 671+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 672+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 673+		break;
 674+	}
 675+	case Z80_LDDR: {
 676+		cycles(&opts->gen, num_cycles);
 677+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 678+		call(code, opts->read_8);
 679+		zreg_to_native(opts, Z80_DE, opts->gen.scratch2);
 680+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 681+		call(code, opts->write_8);
 682+		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_XY), opts->gen.scratch1, SZ_B);
 683+		add_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
 684+		mov_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 685+		and_ir(code, 0x8, opts->gen.scratch1, SZ_B);
 686+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 687+		or_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 688+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 689+		if (opts->regs[Z80_DE] >= 0) {
 690+			sub_ir(code, 1, opts->regs[Z80_DE], SZ_W);
 691+		} else {
 692+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_DE), SZ_W);
 693+		}
 694+		if (opts->regs[Z80_HL] >= 0) {
 695+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 696+		} else {
 697+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_W);
 698+		}
 699+		if (opts->regs[Z80_BC] >= 0) {
 700+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 701+		} else {
 702+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_BC), SZ_W);
 703+		}
 704+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
 705+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 706+		uint8_t * cont = code->cur+1;
 707+		jcc(code, CC_Z, code->cur+2);
 708+		cycles(&opts->gen, 7);
 709+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 710+		jmp(code, start);
 711+		*cont = code->cur - (cont + 1);
 712+		cycles(&opts->gen, 2);
 713+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
 714+		break;
 715+	}
 716+	case Z80_CPI:
 717+		cycles(&opts->gen, num_cycles);//T-States 4,4
 718+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 719+		call(code, opts->read_8);//T-States 3
 720+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 721+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 722+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 723+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 724+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 725+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 726+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 727+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 728+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 729+		cycles(&opts->gen, 5);//T-States 5
 730+		if (opts->regs[Z80_HL] >= 0) {
 731+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 732+		} else {
 733+			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 734+		}
 735+		if (opts->regs[Z80_BC] >= 0) {
 736+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 737+		} else {
 738+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 739+		}
 740+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 741+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 742+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 743+		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 744+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 745+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 746+		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 747+		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 748+		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 749+		break;
 750+	case Z80_CPIR: {
 751+		cycles(&opts->gen, num_cycles);//T-States 4,4
 752+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 753+		call(code, opts->read_8);//T-States 3
 754+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 755+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 756+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 757+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 758+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 759+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 760+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 761+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 762+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 763+		cycles(&opts->gen, 5);//T-States 5
 764+		if (opts->regs[Z80_HL] >= 0) {
 765+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 766+		} else {
 767+			add_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 768+		}
 769+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 770+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 771+		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 772+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 773+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 774+		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 775+		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 776+		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 777+		if (opts->regs[Z80_BC] >= 0) {
 778+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 779+		} else {
 780+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 781+		}
 782+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 783+		uint8_t * cont = code->cur+1;
 784+		jcc(code, CC_Z, code->cur+2);
 785+		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
 786+		uint8_t * cont2 = code->cur+1;
 787+		jcc(code, CC_Z, code->cur+2);
 788+		//repeat case
 789+		cycles(&opts->gen, 5);//T-States 5
 790+		jmp(code, start);
 791+		*cont = code->cur - (cont + 1);
 792+		*cont2 = code->cur - (cont2 + 1);
 793+		break;
 794+	}
 795+	case Z80_CPD:
 796+		cycles(&opts->gen, num_cycles);//T-States 4,4
 797+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 798+		call(code, opts->read_8);//T-States 3
 799+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 800+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 801+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 802+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 803+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 804+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 805+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 806+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 807+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 808+		cycles(&opts->gen, 5);//T-States 5
 809+		if (opts->regs[Z80_HL] >= 0) {
 810+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 811+		} else {
 812+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 813+		}
 814+		if (opts->regs[Z80_BC] >= 0) {
 815+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 816+		} else {
 817+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 818+		}
 819+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 820+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 821+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 822+		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 823+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 824+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 825+		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 826+		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 827+		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 828+		break;
 829+	case Z80_CPDR: {
 830+		cycles(&opts->gen, num_cycles);//T-States 4,4
 831+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
 832+		call(code, opts->read_8);//T-States 3
 833+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 834+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 835+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 836+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 837+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 838+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 839+		xor_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 840+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
 841+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 842+		cycles(&opts->gen, 5);//T-States 5
 843+		if (opts->regs[Z80_HL] >= 0) {
 844+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
 845+		} else {
 846+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_HL), SZ_W);
 847+		}
 848+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
 849+		sub_rr(code, opts->gen.scratch1, opts->gen.scratch2, SZ_B);
 850+		sub_rdispr(code, opts->gen.context_reg, zf_off(ZF_H), opts->gen.scratch2, SZ_B);
 851+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 852+		shl_ir(code, 4, opts->gen.scratch2, SZ_B);
 853+		and_irdisp(code, 0x8, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 854+		and_ir(code, 0x20, opts->gen.scratch2, SZ_B);
 855+		or_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 856+		if (opts->regs[Z80_BC] >= 0) {
 857+			sub_ir(code, 1, opts->regs[Z80_BC], SZ_W);
 858+		} else {
 859+			sub_irdisp(code, 1, opts->gen.context_reg,  zr_off(Z80_BC), SZ_W);
 860+		}
 861+		setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV));
 862+		uint8_t * cont = code->cur+1;
 863+		jcc(code, CC_Z, code->cur+2);
 864+		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
 865+		uint8_t * cont2 = code->cur+1;
 866+		jcc(code, CC_Z, code->cur+2);
 867+		//repeat case
 868+		cycles(&opts->gen, 5);//T-States 5
 869+		jmp(code, start);
 870+		*cont = code->cur - (cont + 1);
 871+		*cont2 = code->cur - (cont2 + 1);
 872+		break;
 873+	}
 874+	case Z80_ADD:
 875+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
 876+			num_cycles += 8;
 877+		} else if(inst->addr_mode == Z80_IMMED) {
 878+			num_cycles += 3;
 879+		} else if(z80_size(inst) == SZ_W) {
 880+			num_cycles += 7;
 881+		}
 882+		cycles(&opts->gen, num_cycles);
 883+		translate_z80_reg(inst, &dst_op, opts);
 884+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 885+		if (dst_op.mode == MODE_REG_DIRECT) {
 886+			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 887+		} else {
 888+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 889+		}
 890+		if (src_op.mode == MODE_REG_DIRECT) {
 891+			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
 892+		} else if (src_op.mode == MODE_IMMED) {
 893+			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
 894+		} else {
 895+			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
 896+		}
 897+		if (dst_op.mode == MODE_REG_DIRECT) {
 898+			if (src_op.mode == MODE_REG_DIRECT) {
 899+				add_rr(code, src_op.base, dst_op.base, z80_size(inst));
 900+			} else if (src_op.mode == MODE_IMMED) {
 901+				add_ir(code, src_op.disp, dst_op.base, z80_size(inst));
 902+			} else {
 903+				add_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
 904+			}
 905+			if (z80_size(inst) == SZ_B) {
 906+				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 907+			}
 908+		} else {
 909+			if (src_op.mode == MODE_REG_DIRECT) {
 910+				add_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
 911+			} else if (src_op.mode == MODE_IMMED) {
 912+				add_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
 913+			} else {
 914+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
 915+				add_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
 916+			}
 917+			mov_rdispr(code, dst_op.base, dst_op.disp + (z80_size(inst) == SZ_B ? 0 : 1), opts->gen.scratch1, SZ_B);
 918+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 919+		}
 920+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 921+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 922+		if (z80_size(inst) == SZ_B) {
 923+			setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
 924+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 925+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 926+		}
 927+		if (dst_op.mode == MODE_REG_DIRECT) {
 928+			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 929+		} else {
 930+			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 931+		}
 932+		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
 933+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
 934+		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
 935+			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
 936+			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
 937+			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 938+		}
 939+		z80_save_reg(inst, opts);
 940+		z80_save_ea(code, inst, opts);
 941+		break;
 942+	case Z80_ADC:
 943+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
 944+			num_cycles += 8;
 945+		} else if(inst->addr_mode == Z80_IMMED) {
 946+			num_cycles += 3;
 947+		} else if(z80_size(inst) == SZ_W) {
 948+			num_cycles += 7;
 949+		}
 950+		cycles(&opts->gen, num_cycles);
 951+		translate_z80_reg(inst, &dst_op, opts);
 952+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
 953+		if (dst_op.mode == MODE_REG_DIRECT) {
 954+			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 955+		} else {
 956+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 957+		}
 958+		if (src_op.mode == MODE_REG_DIRECT) {
 959+			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
 960+		} else if (src_op.mode == MODE_IMMED) {
 961+			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
 962+		} else {
 963+			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
 964+		}
 965+		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
 966+		if (dst_op.mode == MODE_REG_DIRECT) {
 967+			if (src_op.mode == MODE_REG_DIRECT) {
 968+				adc_rr(code, src_op.base, dst_op.base, z80_size(inst));
 969+			} else if (src_op.mode == MODE_IMMED) {
 970+				adc_ir(code, src_op.disp, dst_op.base, z80_size(inst));
 971+			} else {
 972+				adc_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
 973+			}
 974+			if (z80_size(inst) == SZ_B) {
 975+				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 976+			}
 977+		} else {
 978+			if (src_op.mode == MODE_REG_DIRECT) {
 979+				adc_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
 980+			} else if (src_op.mode == MODE_IMMED) {
 981+				adc_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
 982+			} else {
 983+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
 984+				adc_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
 985+			}
 986+			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
 987+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
 988+		}
 989+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
 990+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
 991+		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
 992+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
 993+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
 994+		if (dst_op.mode == MODE_REG_DIRECT) {
 995+			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
 996+		} else {
 997+			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
 998+		}
 999+		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1000+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1001+		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1002+			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1003+			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1004+			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1005+		}
1006+		z80_save_reg(inst, opts);
1007+		z80_save_ea(code, inst, opts);
1008+		break;
1009+	case Z80_SUB:
1010+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1011+			num_cycles += 8;
1012+		} else if(inst->addr_mode == Z80_IMMED) {
1013+			num_cycles += 3;
1014+		}
1015+		cycles(&opts->gen, num_cycles);
1016+		translate_z80_reg(inst, &dst_op, opts);
1017+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1018+		if (dst_op.mode == MODE_REG_DIRECT) {
1019+			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1020+		} else {
1021+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1022+		}
1023+		if (src_op.mode == MODE_REG_DIRECT) {
1024+			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1025+		} else if (src_op.mode == MODE_IMMED) {
1026+			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1027+		} else {
1028+			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1029+		}
1030+		if (dst_op.mode == MODE_REG_DIRECT) {
1031+			if (src_op.mode == MODE_REG_DIRECT) {
1032+				sub_rr(code, src_op.base, dst_op.base, z80_size(inst));
1033+			} else if (src_op.mode == MODE_IMMED) {
1034+				sub_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1035+			} else {
1036+				sub_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1037+			}
1038+			if (z80_size(inst) == SZ_B) {
1039+				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1040+			}
1041+		} else {
1042+			if (src_op.mode == MODE_REG_DIRECT) {
1043+				sub_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
1044+			} else if (src_op.mode == MODE_IMMED) {
1045+				sub_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
1046+			} else {
1047+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
1048+				sub_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
1049+			}
1050+			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
1051+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1052+		}
1053+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1054+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1055+		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1056+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1057+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1058+		if (dst_op.mode == MODE_REG_DIRECT) {
1059+			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1060+		} else {
1061+			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1062+		}
1063+		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1064+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1065+		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1066+			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1067+			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1068+			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1069+		}
1070+		z80_save_reg(inst, opts);
1071+		z80_save_ea(code, inst, opts);
1072+		break;
1073+	case Z80_SBC:
1074+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1075+			num_cycles += 8;
1076+		} else if(inst->addr_mode == Z80_IMMED) {
1077+			num_cycles += 3;
1078+		} else if(z80_size(inst) == SZ_W) {
1079+			num_cycles += 7;
1080+		}
1081+		cycles(&opts->gen, num_cycles);
1082+		translate_z80_reg(inst, &dst_op, opts);
1083+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1084+		if (dst_op.mode == MODE_REG_DIRECT) {
1085+			mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1086+		} else {
1087+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1088+		}
1089+		if (src_op.mode == MODE_REG_DIRECT) {
1090+			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1091+		} else if (src_op.mode == MODE_IMMED) {
1092+			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1093+		} else {
1094+			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1095+		}
1096+		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1097+		if (dst_op.mode == MODE_REG_DIRECT) {
1098+			if (src_op.mode == MODE_REG_DIRECT) {
1099+				sbb_rr(code, src_op.base, dst_op.base, z80_size(inst));
1100+			} else if (src_op.mode == MODE_IMMED) {
1101+				sbb_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1102+			} else {
1103+				sbb_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1104+			}
1105+			if (z80_size(inst) == SZ_B) {
1106+				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1107+			}
1108+		} else {
1109+			if (src_op.mode == MODE_REG_DIRECT) {
1110+				sbb_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, z80_size(inst));
1111+			} else if (src_op.mode == MODE_IMMED) {
1112+				sbb_irdisp(code, src_op.disp, dst_op.base, dst_op.disp, z80_size(inst));
1113+			} else {
1114+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, z80_size(inst));
1115+				sbb_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, z80_size(inst));
1116+			}
1117+			mov_rdispr(code, dst_op.base, dst_op.disp + z80_size(inst) == SZ_B ? 0 : 8, opts->gen.scratch1, SZ_B);
1118+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1119+		}
1120+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1121+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1122+		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1123+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1124+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1125+		if (dst_op.mode == MODE_REG_DIRECT) {
1126+			xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1127+		} else {
1128+			xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, z80_size(inst));
1129+		}
1130+		bt_ir(code, z80_size(inst) == SZ_B ? 4 : 12, opts->gen.scratch2, z80_size(inst));
1131+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1132+		if (z80_size(inst) == SZ_W & dst_op.mode == MODE_REG_DIRECT) {
1133+			mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_W);
1134+			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1135+			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1136+		}
1137+		z80_save_reg(inst, opts);
1138+		z80_save_ea(code, inst, opts);
1139+		break;
1140+	case Z80_AND:
1141+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1142+			num_cycles += 8;
1143+		} else if(inst->addr_mode == Z80_IMMED) {
1144+			num_cycles += 3;
1145+		} else if(z80_size(inst) == SZ_W) {
1146+			num_cycles += 4;
1147+		}
1148+		cycles(&opts->gen, num_cycles);
1149+		translate_z80_reg(inst, &dst_op, opts);
1150+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1151+		if (src_op.mode == MODE_REG_DIRECT) {
1152+			and_rr(code, src_op.base, dst_op.base, z80_size(inst));
1153+		} else if (src_op.mode == MODE_IMMED) {
1154+			and_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1155+		} else {
1156+			and_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1157+		}
1158+		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1159+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1160+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1161+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1162+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1163+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1164+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1165+		z80_save_reg(inst, opts);
1166+		z80_save_ea(code, inst, opts);
1167+		break;
1168+	case Z80_OR:
1169+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1170+			num_cycles += 8;
1171+		} else if(inst->addr_mode == Z80_IMMED) {
1172+			num_cycles += 3;
1173+		} else if(z80_size(inst) == SZ_W) {
1174+			num_cycles += 4;
1175+		}
1176+		cycles(&opts->gen, num_cycles);
1177+		translate_z80_reg(inst, &dst_op, opts);
1178+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1179+		if (src_op.mode == MODE_REG_DIRECT) {
1180+			or_rr(code, src_op.base, dst_op.base, z80_size(inst));
1181+		} else if (src_op.mode == MODE_IMMED) {
1182+			or_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1183+		} else {
1184+			or_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1185+		}
1186+		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1187+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1188+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1189+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1190+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1191+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1192+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1193+		z80_save_reg(inst, opts);
1194+		z80_save_ea(code, inst, opts);
1195+		break;
1196+	case Z80_XOR:
1197+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1198+			num_cycles += 8;
1199+		} else if(inst->addr_mode == Z80_IMMED) {
1200+			num_cycles += 3;
1201+		} else if(z80_size(inst) == SZ_W) {
1202+			num_cycles += 4;
1203+		}
1204+		cycles(&opts->gen, num_cycles);
1205+		translate_z80_reg(inst, &dst_op, opts);
1206+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1207+		if (src_op.mode == MODE_REG_DIRECT) {
1208+			xor_rr(code, src_op.base, dst_op.base, z80_size(inst));
1209+		} else if (src_op.mode == MODE_IMMED) {
1210+			xor_ir(code, src_op.disp, dst_op.base, z80_size(inst));
1211+		} else {
1212+			xor_rdispr(code, src_op.base, src_op.disp, dst_op.base, z80_size(inst));
1213+		}
1214+		mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1215+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1216+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1217+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1218+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1219+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1220+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1221+		z80_save_reg(inst, opts);
1222+		z80_save_ea(code, inst, opts);
1223+		break;
1224+	case Z80_CP:
1225+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1226+			num_cycles += 8;
1227+		} else if(inst->addr_mode == Z80_IMMED) {
1228+			num_cycles += 3;
1229+		}
1230+		cycles(&opts->gen, num_cycles);
1231+		translate_z80_reg(inst, &dst_op, opts);
1232+		translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1233+		mov_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1234+		if (src_op.mode == MODE_REG_DIRECT) {
1235+			sub_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1236+			mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1237+		} else if (src_op.mode == MODE_IMMED) {
1238+			sub_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1239+			mov_irdisp(code, src_op.disp, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1240+		} else {
1241+			sub_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1242+			mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1243+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1244+		}
1245+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1246+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1247+		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1248+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1249+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1250+		xor_rr(code, dst_op.base, opts->gen.scratch2, z80_size(inst));
1251+		if (src_op.mode == MODE_REG_DIRECT) {
1252+			xor_rr(code, src_op.base, opts->gen.scratch2, z80_size(inst));
1253+		} else if (src_op.mode == MODE_IMMED) {
1254+			xor_ir(code, src_op.disp, opts->gen.scratch2, z80_size(inst));
1255+		} else {
1256+			xor_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch2, z80_size(inst));
1257+		}
1258+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
1259+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1260+		z80_save_reg(inst, opts);
1261+		z80_save_ea(code, inst, opts);
1262+		break;
1263+	case Z80_INC:
1264+	case Z80_DEC:
1265+		if(z80_size(inst) == SZ_W) {
1266+			num_cycles += 2;
1267+		} else if (inst->addr_mode == Z80_REG_INDIRECT) {
1268+			num_cycles += 1;
1269+		} else if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1270+			num_cycles += 9;
1271+		}
1272+		cycles(&opts->gen, num_cycles);
1273+		translate_z80_reg(inst, &dst_op, opts);
1274+		if (dst_op.mode == MODE_UNUSED) {
1275+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1276+		}
1277+		if (z80_size(inst) == SZ_B) {
1278+			if (dst_op.mode == MODE_REG_DIRECT) {
1279+				if (dst_op.base >= AH && dst_op.base <= BH) {
1280+					mov_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W);
1281+				} else {
1282+					mov_rr(code, dst_op.base, opts->gen.scratch2, SZ_B);
1283+				}
1284+			} else {
1285+				mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B);
1286+			}
1287+		}
1288+		if (inst->op == Z80_INC) {
1289+			if (dst_op.mode == MODE_REG_DIRECT) {
1290+				add_ir(code, 1, dst_op.base, z80_size(inst));
1291+			} else {
1292+				add_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst));
1293+			}
1294+		} else {
1295+			if (dst_op.mode == MODE_REG_DIRECT) {
1296+				sub_ir(code, 1, dst_op.base, z80_size(inst));
1297+			} else {
1298+				sub_irdisp(code, 1, dst_op.base, dst_op.disp, z80_size(inst));
1299+			}
1300+		}
1301+		if (z80_size(inst) == SZ_B) {
1302+			mov_irdisp(code, inst->op == Z80_DEC, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1303+			setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1304+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1305+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1306+			int bit = 4;
1307+			if (dst_op.mode == MODE_REG_DIRECT) {
1308+				mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1309+				if (dst_op.base >= AH && dst_op.base <= BH) {
1310+					bit = 12;
1311+					xor_rr(code, dst_op.base - AH, opts->gen.scratch2, SZ_W);
1312+				} else {
1313+					xor_rr(code, dst_op.base, opts->gen.scratch2, SZ_B);
1314+				}
1315+			} else {
1316+				mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1317+				xor_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch2, SZ_B);
1318+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1319+			}
1320+			bt_ir(code, bit, opts->gen.scratch2, SZ_W);
1321+			setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1322+		}
1323+		z80_save_reg(inst, opts);
1324+		z80_save_ea(code, inst, opts);
1325+		z80_save_result(opts, inst);
1326+		break;
1327+	case Z80_DAA: {
1328+		cycles(&opts->gen, num_cycles);
1329+		xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B);
1330+		zreg_to_native(opts, Z80_A, opts->gen.scratch1);
1331+		and_ir(code, 0xF, opts->gen.scratch1, SZ_B);
1332+		cmp_ir(code, 0xA, opts->gen.scratch1, SZ_B);
1333+		mov_ir(code, 0xA0, opts->gen.scratch1, SZ_B);
1334+		code_ptr corf_low_range = code->cur + 1;
1335+		jcc(code, CC_NC, code->cur+2);
1336+		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1337+		code_ptr corf_low = code->cur + 1;
1338+		jcc(code, CC_NZ, code->cur+2);
1339+		code_ptr no_corf_low = code->cur + 1;
1340+		jmp(code, code->cur + 2);
1341+		
1342+		*corf_low_range = code->cur - (corf_low_range + 1);
1343+		mov_ir(code, 0x90, opts->gen.scratch1, SZ_B);
1344+		*corf_low = code->cur - (corf_low + 1);
1345+		mov_ir(code, 0x06, opts->gen.scratch2, SZ_B);
1346+		
1347+		*no_corf_low = code->cur - (no_corf_low + 1);
1348+		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1349+		code_ptr corf_high = code->cur+1;
1350+		jcc(code, CC_NZ, code->cur+2);
1351+		cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1352+		code_ptr no_corf_high = code->cur+1;
1353+		jcc(code, CC_C, code->cur+2);
1354+		*corf_high = code->cur - (corf_high + 1);
1355+		or_ir(code, 0x60, opts->gen.scratch2, SZ_B);
1356+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1357+		*no_corf_high = code->cur - (no_corf_high + 1);
1358+		
1359+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1360+		xor_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_B);
1361+		
1362+		cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1363+		code_ptr not_sub = code->cur+1;
1364+		jcc(code, CC_Z, code->cur+2);
1365+		neg_r(code, opts->gen.scratch2, SZ_B);
1366+		*not_sub = code->cur - (not_sub + 1);
1367+		
1368+		add_rr(code, opts->gen.scratch2, opts->regs[Z80_A], SZ_B);
1369+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1370+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1371+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1372+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch1, SZ_B);
1373+		bt_ir(code, 4, opts->gen.scratch1, SZ_B);
1374+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1375+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1376+		break;
1377+	}
1378+	case Z80_CPL:
1379+		cycles(&opts->gen, num_cycles);
1380+		not_r(code, opts->regs[Z80_A], SZ_B);
1381+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1382+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1383+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1384+		break;
1385+	case Z80_NEG:
1386+		cycles(&opts->gen, num_cycles);
1387+		mov_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1388+		neg_r(code, opts->regs[Z80_A], SZ_B);
1389+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1390+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1391+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1392+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1393+		setcc_rdisp(code, CC_O, opts->gen.context_reg, zf_off(ZF_PV));
1394+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1395+		xor_rr(code, opts->regs[Z80_A], opts->gen.scratch2, SZ_B);
1396+		bt_ir(code, 4, opts->gen.scratch2, SZ_B);
1397+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
1398+		break;
1399+	case Z80_CCF:
1400+		cycles(&opts->gen, num_cycles);
1401+		mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B);
1402+		xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1403+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1404+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1405+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1406+		break;
1407+	case Z80_SCF:
1408+		cycles(&opts->gen, num_cycles);
1409+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1410+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1411+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1412+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1413+		break;
1414+	case Z80_NOP:
1415+		cycles(&opts->gen, num_cycles);
1416+		break;
1417+	case Z80_HALT: {
1418+		code_ptr loop_top = code->cur;
1419+		//this isn't terribly efficient, but it's good enough for now
1420+		cycles(&opts->gen, num_cycles);
1421+		check_cycles_int(&opts->gen, address+1);
1422+		jmp(code, loop_top);
1423+		break;
1424+	}
1425+	case Z80_DI:
1426+		cycles(&opts->gen, num_cycles);
1427+		mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1428+		mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
1429+		//turn cycles remaining into current cycle
1430+		neg_r(code, opts->gen.cycles, SZ_D);
1431+		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1432+		//set interrupt cycle to never and fetch the new target cycle from sync_cycle
1433+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.scratch1, SZ_D);
1434+		mov_irdisp(code, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D);
1435+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
1436+		//turn current cycle back into cycles remaining
1437+		neg_r(code, opts->gen.cycles, SZ_D);
1438+		add_rr(code, opts->gen.scratch1, opts->gen.cycles, SZ_D);
1439+		break;
1440+	case Z80_EI:
1441+		cycles(&opts->gen, num_cycles);
1442+		neg_r(code, opts->gen.cycles, SZ_D);
1443+		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1444+		mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
1445+		neg_r(code, opts->gen.cycles, SZ_D);
1446+		add_rdispr(code, opts->gen.context_reg, offsetof(z80_context, target_cycle), opts->gen.cycles, SZ_D);
1447+		mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
1448+		mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
1449+		//interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles
1450+		add_irdisp(code, 4*opts->gen.clock_divider, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D);
1451+		call(code, opts->do_sync);
1452+		break;
1453+	case Z80_IM:
1454+		cycles(&opts->gen, num_cycles);
1455+		mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B);
1456+		break;
1457+	case Z80_RLC:
1458+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1459+			num_cycles += 8;
1460+		}
1461+		cycles(&opts->gen, num_cycles);
1462+		if (inst->addr_mode != Z80_UNUSED) {
1463+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1464+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1465+			cycles(&opts->gen, 1);
1466+		} else {
1467+			src_op.mode = MODE_UNUSED;
1468+			translate_z80_reg(inst, &dst_op, opts);
1469+		}
1470+		if (dst_op.mode == MODE_REG_DIRECT) {
1471+			rol_ir(code, 1, dst_op.base, SZ_B);
1472+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1473+		} else {
1474+			rol_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1475+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1476+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1477+		}
1478+		if (src_op.mode == MODE_REG_DIRECT) {
1479+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1480+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1481+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1482+		}
1483+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1484+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1485+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1486+		if (inst->immed) {
1487+			//rlca does not set these flags
1488+			if (dst_op.mode == MODE_REG_DIRECT) {
1489+				cmp_ir(code, 0, dst_op.base, SZ_B);
1490+			} else {
1491+				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1492+			}
1493+			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1494+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1495+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1496+		}
1497+		if (inst->addr_mode != Z80_UNUSED) {
1498+			z80_save_result(opts, inst);
1499+			if (src_op.mode != MODE_UNUSED) {
1500+				z80_save_reg(inst, opts);
1501+			}
1502+		} else {
1503+			z80_save_reg(inst, opts);
1504+		}
1505+		break;
1506+	case Z80_RL:
1507+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1508+			num_cycles += 8;
1509+		}
1510+		cycles(&opts->gen, num_cycles);
1511+		if (inst->addr_mode != Z80_UNUSED) {
1512+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1513+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1514+			cycles(&opts->gen, 1);
1515+		} else {
1516+			src_op.mode = MODE_UNUSED;
1517+			translate_z80_reg(inst, &dst_op, opts);
1518+		}
1519+		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1520+		if (dst_op.mode == MODE_REG_DIRECT) {
1521+			rcl_ir(code, 1, dst_op.base, SZ_B);
1522+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1523+		} else {
1524+			rcl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1525+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1526+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1527+		}
1528+		if (src_op.mode == MODE_REG_DIRECT) {
1529+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1530+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1531+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1532+		}
1533+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1534+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1535+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1536+		if (inst->immed) {
1537+			//rla does not set these flags
1538+			if (dst_op.mode == MODE_REG_DIRECT) {
1539+				cmp_ir(code, 0, dst_op.base, SZ_B);
1540+			} else {
1541+				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1542+			}
1543+			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1544+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1545+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1546+		}
1547+		if (inst->addr_mode != Z80_UNUSED) {
1548+			z80_save_result(opts, inst);
1549+			if (src_op.mode != MODE_UNUSED) {
1550+				z80_save_reg(inst, opts);
1551+			}
1552+		} else {
1553+			z80_save_reg(inst, opts);
1554+		}
1555+		break;
1556+	case Z80_RRC:
1557+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1558+			num_cycles += 8;
1559+		}
1560+		cycles(&opts->gen, num_cycles);
1561+		if (inst->addr_mode != Z80_UNUSED) {
1562+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1563+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1564+			cycles(&opts->gen, 1);
1565+		} else {
1566+			src_op.mode = MODE_UNUSED;
1567+			translate_z80_reg(inst, &dst_op, opts);
1568+		}
1569+		if (dst_op.mode == MODE_REG_DIRECT) {
1570+			ror_ir(code, 1, dst_op.base, SZ_B);
1571+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1572+		} else {
1573+			ror_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1574+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1575+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1576+		}
1577+		if (src_op.mode == MODE_REG_DIRECT) {
1578+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1579+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1580+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1581+		}
1582+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1583+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1584+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1585+		if (inst->immed) {
1586+			//rrca does not set these flags
1587+			if (dst_op.mode == MODE_REG_DIRECT) {
1588+				cmp_ir(code, 0, dst_op.base, SZ_B);
1589+			} else {
1590+				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1591+			}
1592+			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1593+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1594+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1595+		}
1596+		if (inst->addr_mode != Z80_UNUSED) {
1597+			z80_save_result(opts, inst);
1598+			if (src_op.mode != MODE_UNUSED) {
1599+				z80_save_reg(inst, opts);
1600+			}
1601+		} else {
1602+			z80_save_reg(inst, opts);
1603+		}
1604+		break;
1605+	case Z80_RR:
1606+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1607+			num_cycles += 8;
1608+		}
1609+		cycles(&opts->gen, num_cycles);
1610+		if (inst->addr_mode != Z80_UNUSED) {
1611+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1612+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1613+			cycles(&opts->gen, 1);
1614+		} else {
1615+			src_op.mode = MODE_UNUSED;
1616+			translate_z80_reg(inst, &dst_op, opts);
1617+		}
1618+		bt_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
1619+		if (dst_op.mode == MODE_REG_DIRECT) {
1620+			rcr_ir(code, 1, dst_op.base, SZ_B);
1621+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1622+		} else {
1623+			rcr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1624+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1625+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1626+		}
1627+		if (src_op.mode == MODE_REG_DIRECT) {
1628+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1629+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1630+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1631+		}
1632+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1633+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1634+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1635+		if (inst->immed) {
1636+			//rra does not set these flags
1637+			if (dst_op.mode == MODE_REG_DIRECT) {
1638+				cmp_ir(code, 0, dst_op.base, SZ_B);
1639+			} else {
1640+				cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1641+			}
1642+			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1643+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1644+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1645+		}
1646+		if (inst->addr_mode != Z80_UNUSED) {
1647+			z80_save_result(opts, inst);
1648+			if (src_op.mode != MODE_UNUSED) {
1649+				z80_save_reg(inst, opts);
1650+			}
1651+		} else {
1652+			z80_save_reg(inst, opts);
1653+		}
1654+		break;
1655+	case Z80_SLA:
1656+	case Z80_SLL:
1657+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1658+			num_cycles += 8;
1659+		}
1660+		cycles(&opts->gen, num_cycles);
1661+		if (inst->addr_mode != Z80_UNUSED) {
1662+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1663+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1664+			cycles(&opts->gen, 1);
1665+		} else {
1666+			src_op.mode = MODE_UNUSED;
1667+			translate_z80_reg(inst, &dst_op, opts);
1668+		}
1669+		if (dst_op.mode == MODE_REG_DIRECT) {
1670+			shl_ir(code, 1, dst_op.base, SZ_B);
1671+		} else {
1672+			shl_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1673+		}
1674+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1675+		if (inst->op == Z80_SLL) {
1676+			if (dst_op.mode == MODE_REG_DIRECT) {
1677+				or_ir(code, 1, dst_op.base, SZ_B);
1678+			} else {
1679+				or_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1680+			}
1681+		}
1682+		if (src_op.mode == MODE_REG_DIRECT) {
1683+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1684+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1685+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1686+		}
1687+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1688+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1689+		if (dst_op.mode == MODE_REG_DIRECT) {
1690+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1691+			cmp_ir(code, 0, dst_op.base, SZ_B);
1692+		} else {
1693+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1694+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1695+			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1696+		}
1697+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1698+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1699+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1700+		if (inst->addr_mode != Z80_UNUSED) {
1701+			z80_save_result(opts, inst);
1702+			if (src_op.mode != MODE_UNUSED) {
1703+				z80_save_reg(inst, opts);
1704+			}
1705+		} else {
1706+			z80_save_reg(inst, opts);
1707+		}
1708+		break;
1709+	case Z80_SRA:
1710+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1711+			num_cycles += 8;
1712+		}
1713+		cycles(&opts->gen, num_cycles);
1714+		if (inst->addr_mode != Z80_UNUSED) {
1715+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1716+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1717+			cycles(&opts->gen, 1);
1718+		} else {
1719+			src_op.mode = MODE_UNUSED;
1720+			translate_z80_reg(inst, &dst_op, opts);
1721+		}
1722+		if (dst_op.mode == MODE_REG_DIRECT) {
1723+			sar_ir(code, 1, dst_op.base, SZ_B);
1724+		} else {
1725+			sar_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1726+		}
1727+		if (src_op.mode == MODE_REG_DIRECT) {
1728+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1729+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1730+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1731+		}
1732+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1733+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1734+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1735+		if (dst_op.mode == MODE_REG_DIRECT) {
1736+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1737+			cmp_ir(code, 0, dst_op.base, SZ_B);
1738+		} else {
1739+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1740+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1741+			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1742+		}
1743+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1744+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1745+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1746+		if (inst->addr_mode != Z80_UNUSED) {
1747+			z80_save_result(opts, inst);
1748+			if (src_op.mode != MODE_UNUSED) {
1749+				z80_save_reg(inst, opts);
1750+			}
1751+		} else {
1752+			z80_save_reg(inst, opts);
1753+		}
1754+		break;
1755+	case Z80_SRL:
1756+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1757+			num_cycles += 8;
1758+		}
1759+		cycles(&opts->gen, num_cycles);
1760+		if (inst->addr_mode != Z80_UNUSED) {
1761+			translate_z80_ea(inst, &dst_op, opts, READ, MODIFY);
1762+			translate_z80_reg(inst, &src_op, opts); //For IX/IY variants that also write to a register
1763+			cycles(&opts->gen, 1);
1764+		} else {
1765+			src_op.mode = MODE_UNUSED;
1766+			translate_z80_reg(inst, &dst_op, opts);
1767+		}
1768+		if (dst_op.mode == MODE_REG_DIRECT) {
1769+			shr_ir(code, 1, dst_op.base, SZ_B);
1770+		} else {
1771+			shr_irdisp(code, 1, dst_op.base, dst_op.disp, SZ_B);
1772+		}
1773+		if (src_op.mode == MODE_REG_DIRECT) {
1774+			mov_rr(code, dst_op.base, src_op.base, SZ_B);
1775+		} else if(src_op.mode == MODE_REG_DISPLACE8) {
1776+			mov_rrdisp(code, dst_op.base, src_op.base, src_op.disp, SZ_B);
1777+		}
1778+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
1779+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1780+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1781+		if (dst_op.mode == MODE_REG_DIRECT) {
1782+			mov_rrdisp(code, dst_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1783+			cmp_ir(code, 0, dst_op.base, SZ_B);
1784+		} else {
1785+			mov_rdispr(code, dst_op.base, dst_op.disp, opts->gen.scratch1, SZ_B);
1786+			mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1787+			cmp_irdisp(code, 0, dst_op.base, dst_op.disp, SZ_B);
1788+		}
1789+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1790+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1791+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1792+		if (inst->addr_mode != Z80_UNUSED) {
1793+			z80_save_result(opts, inst);
1794+			if (src_op.mode != MODE_UNUSED) {
1795+				z80_save_reg(inst, opts);
1796+			}
1797+		} else {
1798+			z80_save_reg(inst, opts);
1799+		}
1800+		break;
1801+	case Z80_RLD:
1802+		cycles(&opts->gen, num_cycles);
1803+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
1804+		call(code, opts->read_8);
1805+		//Before: (HL) = 0x12, A = 0x34
1806+		//After: (HL) = 0x24, A = 0x31
1807+		zreg_to_native(opts, Z80_A, opts->gen.scratch2);
1808+		shl_ir(code, 4, opts->gen.scratch1, SZ_W);
1809+		and_ir(code, 0xF, opts->gen.scratch2, SZ_W);
1810+		and_ir(code, 0xFFF, opts->gen.scratch1, SZ_W);
1811+		and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1812+		or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1813+		//opts->gen.scratch1 = 0x0124
1814+		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1815+		cycles(&opts->gen, 4);
1816+		or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1817+		//set flags
1818+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1819+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1820+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1821+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1822+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1823+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1824+
1825+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
1826+		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1827+		call(code, opts->write_8);
1828+		break;
1829+	case Z80_RRD:
1830+		cycles(&opts->gen, num_cycles);
1831+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
1832+		call(code, opts->read_8);
1833+		//Before: (HL) = 0x12, A = 0x34
1834+		//After: (HL) = 0x41, A = 0x32
1835+		zreg_to_native(opts, Z80_A, opts->gen.scratch2);
1836+		ror_ir(code, 4, opts->gen.scratch1, SZ_W);
1837+		shl_ir(code, 4, opts->gen.scratch2, SZ_W);
1838+		and_ir(code, 0xF00F, opts->gen.scratch1, SZ_W);
1839+		and_ir(code, 0xF0, opts->regs[Z80_A], SZ_B);
1840+		and_ir(code, 0xF0, opts->gen.scratch2, SZ_W);
1841+		//opts->gen.scratch1 = 0x2001
1842+		//opts->gen.scratch2 = 0x0040
1843+		or_rr(code, opts->gen.scratch2, opts->gen.scratch1, SZ_W);
1844+		//opts->gen.scratch1 = 0x2041
1845+		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1846+		cycles(&opts->gen, 4);
1847+		shr_ir(code, 4, opts->gen.scratch1, SZ_B);
1848+		or_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B);
1849+		//set flags
1850+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1851+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1852+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
1853+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
1854+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1855+		mov_rrdisp(code, opts->regs[Z80_A], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1856+
1857+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
1858+		ror_ir(code, 8, opts->gen.scratch1, SZ_W);
1859+		call(code, opts->write_8);
1860+		break;
1861+	case Z80_BIT: {
1862+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1863+			num_cycles += 4;
1864+		}
1865+		cycles(&opts->gen, num_cycles);
1866+		uint8_t bit;
1867+		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1868+			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1869+			src_op.mode = MODE_REG_DIRECT;
1870+			size = SZ_W;
1871+			bit = inst->immed + 8;
1872+		} else {
1873+			size = SZ_B;
1874+			bit = inst->immed;
1875+			translate_z80_ea(inst, &src_op, opts, READ, DONT_MODIFY);
1876+		}
1877+		if (inst->addr_mode != Z80_REG) {
1878+			//Reads normally take 3 cycles, but the read at the end of a bit instruction takes 4
1879+			cycles(&opts->gen, 1);
1880+		}
1881+		if (src_op.mode == MODE_REG_DIRECT) {
1882+			bt_ir(code, bit, src_op.base, size);
1883+		} else {
1884+			bt_irdisp(code, bit, src_op.base, src_op.disp, size);
1885+		}
1886+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_Z));
1887+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_PV));
1888+		mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
1889+		mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
1890+		if (inst->immed == 7) {
1891+			if (src_op.mode == MODE_REG_DIRECT) {
1892+				cmp_ir(code, 0, src_op.base, size);
1893+			} else {
1894+				cmp_irdisp(code, 0, src_op.base, src_op.disp, size);
1895+			}
1896+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
1897+		} else {
1898+			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
1899+		}
1900+		
1901+		if ((inst->addr_mode & 0x1F) == Z80_REG) {
1902+			if (src_op.mode == MODE_REG_DIRECT) {
1903+				if (size == SZ_W) {
1904+					mov_rr(code, src_op.base, opts->gen.scratch1, SZ_W);
1905+					shr_ir(code, 8, opts->gen.scratch1, SZ_W);
1906+					mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1907+				} else {
1908+					mov_rrdisp(code, src_op.base, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1909+				}
1910+			} else {
1911+				mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1912+				mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1913+			}
1914+		} else if((inst->addr_mode & 0x1F) != Z80_REG_INDIRECT) {
1915+			zreg_to_native(opts, (inst->addr_mode & 0x1F) == Z80_IX_DISPLACE ? Z80_IX : Z80_IY, opts->gen.scratch2);
1916+			add_ir(code, inst->ea_reg & 0x80 ? inst->ea_reg - 256 : inst->ea_reg, opts->gen.scratch2, SZ_W);
1917+			shr_ir(code, 8, opts->gen.scratch2, SZ_W);
1918+			mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
1919+		}
1920+		break;
1921+	}
1922+	case Z80_SET: {
1923+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1924+			num_cycles += 4;
1925+		}
1926+		cycles(&opts->gen, num_cycles);
1927+		uint8_t bit;
1928+		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1929+			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1930+			src_op.mode = MODE_REG_DIRECT;
1931+			size = SZ_W;
1932+			bit = inst->immed + 8;
1933+		} else {
1934+			size = SZ_B;
1935+			bit = inst->immed;
1936+			translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
1937+		}
1938+		if (inst->reg != Z80_USE_IMMED) {
1939+			translate_z80_reg(inst, &dst_op, opts);
1940+		}
1941+		if (inst->addr_mode != Z80_REG) {
1942+			//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
1943+			cycles(&opts->gen, 1);
1944+		}
1945+		if (src_op.mode == MODE_REG_DIRECT) {
1946+			bts_ir(code, bit, src_op.base, size);
1947+		} else {
1948+			bts_irdisp(code, bit, src_op.base, src_op.disp, size);
1949+		}
1950+		if (inst->reg != Z80_USE_IMMED) {
1951+			if (size == SZ_W) {
1952+#ifdef X86_64
1953+				if (dst_op.base >= R8) {
1954+					ror_ir(code, 8, src_op.base, SZ_W);
1955+					mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
1956+					ror_ir(code, 8, src_op.base, SZ_W);
1957+				} else {
1958+#endif
1959+					if (dst_op.mode == MODE_REG_DIRECT) {
1960+						zreg_to_native(opts, inst->ea_reg, dst_op.base);
1961+					} else {
1962+						zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
1963+						mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
1964+					}
1965+#ifdef X86_64
1966+				}
1967+#endif
1968+			} else {
1969+				if (dst_op.mode == MODE_REG_DIRECT) {
1970+					if (src_op.mode == MODE_REG_DIRECT) {
1971+						mov_rr(code, src_op.base, dst_op.base, SZ_B);
1972+					} else {
1973+						mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_B);
1974+					}
1975+				} else if (src_op.mode == MODE_REG_DIRECT) {
1976+					mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_B);
1977+				} else {
1978+					mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
1979+					mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
1980+				}
1981+			}
1982+		}
1983+		if ((inst->addr_mode & 0x1F) != Z80_REG) {
1984+			z80_save_result(opts, inst);
1985+			if (inst->reg != Z80_USE_IMMED) {
1986+				z80_save_reg(inst, opts);
1987+			}
1988+		}
1989+		break;
1990+	}
1991+	case Z80_RES: {
1992+		if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) {
1993+			num_cycles += 4;
1994+		}
1995+		cycles(&opts->gen, num_cycles);
1996+		uint8_t bit;
1997+		if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) {
1998+			src_op.base = opts->regs[z80_word_reg(inst->ea_reg)];
1999+			src_op.mode = MODE_REG_DIRECT;
2000+			size = SZ_W;
2001+			bit = inst->immed + 8;
2002+		} else {
2003+			size = SZ_B;
2004+			bit = inst->immed;
2005+			translate_z80_ea(inst, &src_op, opts, READ, MODIFY);
2006+		}
2007+		if (inst->reg != Z80_USE_IMMED) {
2008+			translate_z80_reg(inst, &dst_op, opts);
2009+		}
2010+		if (inst->addr_mode != Z80_REG) {
2011+			//Reads normally take 3 cycles, but the read in the middle of a set instruction takes 4
2012+			cycles(&opts->gen, 1);
2013+		}
2014+		if (src_op.mode == MODE_REG_DIRECT) {
2015+			btr_ir(code, bit, src_op.base, size);
2016+		} else {
2017+			btr_irdisp(code, bit, src_op.base, src_op.disp, size);
2018+		}
2019+		if (inst->reg != Z80_USE_IMMED) {
2020+			if (size == SZ_W) {
2021+#ifdef X86_64
2022+				if (dst_op.base >= R8) {
2023+					ror_ir(code, 8, src_op.base, SZ_W);
2024+					mov_rr(code, opts->regs[z80_low_reg(inst->ea_reg)], dst_op.base, SZ_B);
2025+					ror_ir(code, 8, src_op.base, SZ_W);
2026+				} else {
2027+#endif
2028+					if (dst_op.mode == MODE_REG_DIRECT) {
2029+						zreg_to_native(opts, inst->ea_reg, dst_op.base);
2030+					} else {
2031+						zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
2032+						mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2033+					}
2034+#ifdef X86_64
2035+				}
2036+#endif
2037+			} else {
2038+				if (dst_op.mode == MODE_REG_DIRECT) {
2039+					if (src_op.mode == MODE_REG_DIRECT) {
2040+						mov_rr(code, src_op.base, dst_op.base, SZ_B);
2041+					} else {
2042+						mov_rdispr(code, src_op.base, src_op.disp, dst_op.base, SZ_B);
2043+					}
2044+				} else if (src_op.mode == MODE_REG_DIRECT) {
2045+					mov_rrdisp(code, src_op.base, dst_op.base, dst_op.disp, SZ_B);
2046+				} else {
2047+					mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
2048+					mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2049+				}
2050+			}
2051+		}
2052+		if (inst->addr_mode != Z80_REG) {
2053+			z80_save_result(opts, inst);
2054+			if (inst->reg != Z80_USE_IMMED) {
2055+				z80_save_reg(inst, opts);
2056+			}
2057+		}
2058+		break;
2059+	}
2060+	case Z80_JP: {
2061+		if (inst->addr_mode != Z80_REG_INDIRECT) {
2062+			num_cycles += 6;
2063+		}
2064+		cycles(&opts->gen, num_cycles);
2065+		if (inst->addr_mode != Z80_REG_INDIRECT) {
2066+			code_ptr call_dst = z80_get_native_address(context, inst->immed);
2067+			if (!call_dst) {
2068+				opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2069+				//fake address to force large displacement
2070+				call_dst = code->cur + 256;
2071+			}
2072+			jmp(code, call_dst);
2073+		} else {
2074+			if (inst->addr_mode == Z80_REG_INDIRECT) {
2075+				zreg_to_native(opts, inst->ea_reg, opts->gen.scratch1);
2076+			} else {
2077+				mov_ir(code, inst->immed, opts->gen.scratch1, SZ_W);
2078+			}
2079+			call(code, opts->native_addr);
2080+			jmp_r(code, opts->gen.scratch1);
2081+		}
2082+		break;
2083+	}
2084+	case Z80_JPCC: {
2085+		cycles(&opts->gen, num_cycles + 6);//T States: 4,3,3
2086+		uint8_t cond = CC_Z;
2087+		switch (inst->reg)
2088+		{
2089+		case Z80_CC_NZ:
2090+			cond = CC_NZ;
2091+		case Z80_CC_Z:
2092+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2093+			break;
2094+		case Z80_CC_NC:
2095+			cond = CC_NZ;
2096+		case Z80_CC_C:
2097+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2098+			break;
2099+		case Z80_CC_PO:
2100+			cond = CC_NZ;
2101+		case Z80_CC_PE:
2102+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2103+			break;
2104+		case Z80_CC_P:
2105+			cond = CC_NZ;
2106+		case Z80_CC_M:
2107+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2108+			break;
2109+		}
2110+		uint8_t *no_jump_off = code->cur+1;
2111+		jcc(code, cond, code->cur+2);
2112+		uint16_t dest_addr = inst->immed;
2113+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2114+			if (!call_dst) {
2115+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2116+				//fake address to force large displacement
2117+			call_dst = code->cur + 256;
2118+			}
2119+		jmp(code, call_dst);
2120+		*no_jump_off = code->cur - (no_jump_off+1);
2121+		break;
2122+	}
2123+	case Z80_JR: {
2124+		cycles(&opts->gen, num_cycles + 8);//T States: 4,3,5
2125+		uint16_t dest_addr = address + inst->immed + 2;
2126+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2127+			if (!call_dst) {
2128+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2129+				//fake address to force large displacement
2130+			call_dst = code->cur + 256;
2131+			}
2132+		jmp(code, call_dst);
2133+		break;
2134+	}
2135+	case Z80_JRCC: {
2136+		cycles(&opts->gen, num_cycles + 3);//T States: 4,3
2137+		uint8_t cond = CC_Z;
2138+		switch (inst->reg)
2139+		{
2140+		case Z80_CC_NZ:
2141+			cond = CC_NZ;
2142+		case Z80_CC_Z:
2143+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2144+			break;
2145+		case Z80_CC_NC:
2146+			cond = CC_NZ;
2147+		case Z80_CC_C:
2148+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2149+			break;
2150+		}
2151+		uint8_t *no_jump_off = code->cur+1;
2152+		jcc(code, cond, code->cur+2);
2153+		cycles(&opts->gen, 5);//T States: 5
2154+		uint16_t dest_addr = address + inst->immed + 2;
2155+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2156+			if (!call_dst) {
2157+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2158+				//fake address to force large displacement
2159+			call_dst = code->cur + 256;
2160+			}
2161+		jmp(code, call_dst);
2162+		*no_jump_off = code->cur - (no_jump_off+1);
2163+		break;
2164+	}
2165+	case Z80_DJNZ: {
2166+		cycles(&opts->gen, num_cycles + 4);//T States: 5,3
2167+		if (opts->regs[Z80_B] >= 0) {
2168+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2169+		} else {
2170+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2171+		}
2172+		uint8_t *no_jump_off = code->cur+1;
2173+		jcc(code, CC_Z, code->cur+2);
2174+		cycles(&opts->gen, 5);//T States: 5
2175+		uint16_t dest_addr = address + inst->immed + 2;
2176+		code_ptr call_dst = z80_get_native_address(context, dest_addr);
2177+			if (!call_dst) {
2178+			opts->gen.deferred = defer_address(opts->gen.deferred, dest_addr, code->cur + 1);
2179+				//fake address to force large displacement
2180+			call_dst = code->cur + 256;
2181+			}
2182+		jmp(code, call_dst);
2183+		*no_jump_off = code->cur - (no_jump_off+1);
2184+		break;
2185+		}
2186+	case Z80_CALL: {
2187+		cycles(&opts->gen, num_cycles + 7);//T States: 4,3,4
2188+		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2189+		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
2190+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2191+		call(code, opts->write_16_highfirst);//T States: 3, 3
2192+		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2193+			if (!call_dst) {
2194+			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2195+				//fake address to force large displacement
2196+			call_dst = code->cur + 256;
2197+			}
2198+		jmp(code, call_dst);
2199+		break;
2200+	}
2201+	case Z80_CALLCC: {
2202+		cycles(&opts->gen, num_cycles + 6);//T States: 4,3,3 (false case)
2203+		uint8_t cond = CC_Z;
2204+		switch (inst->reg)
2205+		{
2206+		case Z80_CC_NZ:
2207+			cond = CC_NZ;
2208+		case Z80_CC_Z:
2209+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2210+			break;
2211+		case Z80_CC_NC:
2212+			cond = CC_NZ;
2213+		case Z80_CC_C:
2214+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2215+			break;
2216+		case Z80_CC_PO:
2217+			cond = CC_NZ;
2218+		case Z80_CC_PE:
2219+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2220+			break;
2221+		case Z80_CC_P:
2222+			cond = CC_NZ;
2223+		case Z80_CC_M:
2224+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2225+			break;
2226+		}
2227+		uint8_t *no_call_off = code->cur+1;
2228+		jcc(code, cond, code->cur+2);
2229+		cycles(&opts->gen, 1);//Last of the above T states takes an extra cycle in the true case
2230+		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2231+		mov_ir(code, address + 3, opts->gen.scratch1, SZ_W);
2232+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2233+		call(code, opts->write_16_highfirst);//T States: 3, 3
2234+		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2235+			if (!call_dst) {
2236+			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2237+				//fake address to force large displacement
2238+			call_dst = code->cur + 256;
2239+			}
2240+		jmp(code, call_dst);
2241+		*no_call_off = code->cur - (no_call_off+1);
2242+		break;
2243+		}
2244+	case Z80_RET:
2245+		cycles(&opts->gen, num_cycles);//T States: 4
2246+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2247+		call(code, opts->read_16);//T STates: 3, 3
2248+		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2249+		call(code, opts->native_addr);
2250+		jmp_r(code, opts->gen.scratch1);
2251+		break;
2252+	case Z80_RETCC: {
2253+		cycles(&opts->gen, num_cycles + 1);//T States: 5
2254+		uint8_t cond = CC_Z;
2255+		switch (inst->reg)
2256+		{
2257+		case Z80_CC_NZ:
2258+			cond = CC_NZ;
2259+		case Z80_CC_Z:
2260+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_Z), SZ_B);
2261+			break;
2262+		case Z80_CC_NC:
2263+			cond = CC_NZ;
2264+		case Z80_CC_C:
2265+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_C), SZ_B);
2266+			break;
2267+		case Z80_CC_PO:
2268+			cond = CC_NZ;
2269+		case Z80_CC_PE:
2270+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_PV), SZ_B);
2271+			break;
2272+		case Z80_CC_P:
2273+			cond = CC_NZ;
2274+		case Z80_CC_M:
2275+			cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_S), SZ_B);
2276+			break;
2277+		}
2278+		uint8_t *no_call_off = code->cur+1;
2279+		jcc(code, cond, code->cur+2);
2280+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2281+		call(code, opts->read_16);//T STates: 3, 3
2282+		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2283+		call(code, opts->native_addr);
2284+		jmp_r(code, opts->gen.scratch1);
2285+		*no_call_off = code->cur - (no_call_off+1);
2286+		break;
2287+	}
2288+	case Z80_RETI:
2289+		//For some systems, this may need a callback for signalling interrupt routine completion
2290+		cycles(&opts->gen, num_cycles);//T States: 4, 4
2291+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2292+		call(code, opts->read_16);//T STates: 3, 3
2293+		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2294+		call(code, opts->native_addr);
2295+		jmp_r(code, opts->gen.scratch1);
2296+		break;
2297+	case Z80_RETN:
2298+		cycles(&opts->gen, num_cycles);//T States: 4, 4
2299+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B);
2300+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W);
2301+		mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
2302+		call(code, opts->read_16);//T STates: 3, 3
2303+		add_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2304+		call(code, opts->native_addr);
2305+		jmp_r(code, opts->gen.scratch1);
2306+		break;
2307+	case Z80_RST: {
2308+		//RST is basically CALL to an address in page 0
2309+		cycles(&opts->gen, num_cycles + 1);//T States: 5
2310+		sub_ir(code, 2, opts->regs[Z80_SP], SZ_W);
2311+		mov_ir(code, address + 1, opts->gen.scratch1, SZ_W);
2312+		mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W);
2313+		call(code, opts->write_16_highfirst);//T States: 3, 3
2314+		code_ptr call_dst = z80_get_native_address(context, inst->immed);
2315+		if (!call_dst) {
2316+			opts->gen.deferred = defer_address(opts->gen.deferred, inst->immed, code->cur + 1);
2317+			//fake address to force large displacement
2318+			call_dst = code->cur + 256;
2319+		}
2320+		jmp(code, call_dst);
2321+		break;
2322+	}
2323+	case Z80_IN:
2324+		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2325+			num_cycles += 3;
2326+		}
2327+		cycles(&opts->gen, num_cycles);//T States: 4 3/4
2328+		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2329+			mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B);
2330+		} else {
2331+			zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2332+		}
2333+		call(code, opts->read_io);
2334+		if (inst->addr_mode != Z80_IMMED_INDIRECT) {
2335+			or_rr(code, opts->gen.scratch1, opts->gen.scratch1, SZ_B);
2336+			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B);
2337+			mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B);
2338+			setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2339+			setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2340+			setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2341+		}
2342+		if (inst->reg != Z80_UNUSED) {
2343+			translate_z80_reg(inst, &dst_op, opts);
2344+			if (dst_op.mode == MODE_REG_DIRECT) {
2345+				mov_rr(code, opts->gen.scratch1, dst_op.base, SZ_B);
2346+			} else {
2347+				mov_rrdisp(code, opts->gen.scratch1, dst_op.base, dst_op.disp, SZ_B);
2348+			}
2349+		}
2350+		z80_save_reg(inst, opts);
2351+		break;
2352+	case Z80_INI:
2353+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2354+		//read from IO (C)
2355+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2356+		call(code, opts->read_io);//T states 3
2357+		
2358+		//undocumented N flag behavior
2359+		//flag set on bit 7 of value written
2360+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2361+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2362+		//save value to be written for flag calculation, as the write func does not
2363+		//guarantee that it's preserved across the call
2364+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2365+		
2366+		//write to (HL)
2367+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2368+		call(code, opts->write_8);//T states 4
2369+		cycles(&opts->gen, 1);
2370+		
2371+		//increment HL
2372+		if (opts->regs[Z80_HL] >= 0) {
2373+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2374+		} else {
2375+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2376+		}
2377+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2378+		if (opts->regs[Z80_C] >= 0) {
2379+			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2380+		} else {
2381+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2382+		}
2383+		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2384+		//undocumented C and H flag behavior
2385+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2386+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2387+		//decrement B
2388+		if (opts->regs[Z80_B] >= 0) {
2389+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2390+			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2391+		} else {
2392+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2393+		}
2394+		//undocumented Z and S flag behavior, set based on decrement of B
2395+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2396+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2397+		//crazy undocumented P/V flag behavior
2398+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2399+		if (opts->regs[Z80_B] >= 0) {
2400+			//deal with silly x86-64 restrictions on *H registers
2401+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2402+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2403+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2404+		} else {
2405+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2406+		}
2407+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2408+		break;
2409+	case Z80_INIR: {
2410+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2411+		//read from IO (C)
2412+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2413+		call(code, opts->read_io);//T states 3
2414+		
2415+		//undocumented N flag behavior
2416+		//flag set on bit 7 of value written
2417+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2418+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2419+		//save value to be written for flag calculation, as the write func does not
2420+		//guarantee that it's preserved across the call
2421+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2422+		
2423+		//write to (HL)
2424+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2425+		call(code, opts->write_8);//T states 4
2426+		cycles(&opts->gen, 1);
2427+		
2428+		//increment HL
2429+		if (opts->regs[Z80_HL] >= 0) {
2430+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2431+		} else {
2432+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2433+		}
2434+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2435+		if (opts->regs[Z80_C] >= 0) {
2436+			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2437+		} else {
2438+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2439+		}
2440+		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2441+		//undocumented C and H flag behavior
2442+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2443+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2444+		//decrement B
2445+		if (opts->regs[Z80_B] >= 0) {
2446+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2447+			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2448+		} else {
2449+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2450+		}
2451+		//undocumented Z and S flag behavior, set based on decrement of B
2452+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2453+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2454+		//crazy undocumented P/V flag behavior
2455+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2456+		if (opts->regs[Z80_B] >= 0) {
2457+			//deal with silly x86-64 restrictions on *H registers
2458+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2459+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2460+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2461+		} else {
2462+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2463+		}
2464+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2465+		if (opts->regs[Z80_B] >= 0) {
2466+			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2467+		} else {
2468+			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2469+		}
2470+		code_ptr done = code->cur+1;
2471+		jcc(code, CC_Z, code->cur+2);
2472+		cycles(&opts->gen, 5);
2473+		jmp(code, start);
2474+		*done = code->cur - (done + 1);
2475+		break;
2476+	}
2477+	case Z80_IND:
2478+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2479+		//read from IO (C)
2480+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2481+		call(code, opts->read_io);//T states 3
2482+		
2483+		//undocumented N flag behavior
2484+		//flag set on bit 7 of value written
2485+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2486+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2487+		//save value to be written for flag calculation, as the write func does not
2488+		//guarantee that it's preserved across the call
2489+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2490+		
2491+		//write to (HL)
2492+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2493+		call(code, opts->write_8);//T states 4
2494+		cycles(&opts->gen, 1);
2495+		
2496+		//decrement HL
2497+		if (opts->regs[Z80_HL] >= 0) {
2498+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2499+		} else {
2500+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2501+		}
2502+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2503+		if (opts->regs[Z80_C] >= 0) {
2504+			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2505+		} else {
2506+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2507+		}
2508+		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2509+		//undocumented C and H flag behavior
2510+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2511+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2512+		//decrement B
2513+		if (opts->regs[Z80_B] >= 0) {
2514+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2515+			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2516+		} else {
2517+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2518+		}
2519+		//undocumented Z and S flag behavior, set based on decrement of B
2520+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2521+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2522+		//crazy undocumented P/V flag behavior
2523+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2524+		if (opts->regs[Z80_B] >= 0) {
2525+			//deal with silly x86-64 restrictions on *H registers
2526+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2527+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2528+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2529+		} else {
2530+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2531+		}
2532+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2533+		break;
2534+	case Z80_INDR: {
2535+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2536+		//read from IO (C)
2537+		zreg_to_native(opts, Z80_BC, opts->gen.scratch1);
2538+		call(code, opts->read_io);//T states 3
2539+		
2540+		//undocumented N flag behavior
2541+		//flag set on bit 7 of value written
2542+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2543+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_N));
2544+		//save value to be written for flag calculation, as the write func does not
2545+		//guarantee that it's preserved across the call
2546+		mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, offsetof(z80_context, scratch1), SZ_B);
2547+		
2548+		//write to (HL)
2549+		zreg_to_native(opts, Z80_HL, opts->gen.scratch2);
2550+		call(code, opts->write_8);//T states 4
2551+		cycles(&opts->gen, 1);
2552+		
2553+		//decrement HL
2554+		if (opts->regs[Z80_HL] >= 0) {
2555+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2556+		} else {
2557+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2558+		}
2559+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, scratch1), opts->gen.scratch1, SZ_B);
2560+		if (opts->regs[Z80_C] >= 0) {
2561+			add_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2562+		} else {
2563+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_C), opts->gen.scratch1, SZ_B);
2564+		}
2565+		add_ir(code, 1, opts->gen.scratch1, SZ_B);
2566+		//undocumented C and H flag behavior
2567+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2568+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2569+		//decrement B
2570+		if (opts->regs[Z80_B] >= 0) {
2571+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2572+			mov_rrdisp(code, opts->regs[Z80_B], opts->gen.context_reg, zf_off(ZF_XY), SZ_B);
2573+		} else {
2574+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2575+		}
2576+		//undocumented Z and S flag behavior, set based on decrement of B
2577+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2578+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2579+		//crazy undocumented P/V flag behavior
2580+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2581+		if (opts->regs[Z80_B] >= 0) {
2582+			//deal with silly x86-64 restrictions on *H registers
2583+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2584+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2585+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2586+		} else {
2587+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2588+		}
2589+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2590+		if (opts->regs[Z80_B] >= 0) {
2591+			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2592+		} else {
2593+			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2594+		}
2595+		code_ptr done = code->cur+1;
2596+		jcc(code, CC_Z, code->cur+2);
2597+		cycles(&opts->gen, 5);
2598+		jmp(code, start);
2599+		*done = code->cur - (done + 1);
2600+		break;
2601+	}
2602+	case Z80_OUT:
2603+		if (inst->addr_mode == Z80_IMMED_INDIRECT) {
2604+			num_cycles += 3;
2605+		}
2606+		cycles(&opts->gen, num_cycles);//T States: 4 3/4
2607+		if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) {
2608+			mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B);
2609+		} else {
2610+			zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2611+		}
2612+		translate_z80_reg(inst, &src_op, opts);
2613+		if (src_op.mode == MODE_REG_DIRECT) {
2614+			mov_rr(code, src_op.base, opts->gen.scratch1, SZ_B);
2615+		} else if (src_op.mode == MODE_IMMED) {
2616+			mov_ir(code, src_op.disp, opts->gen.scratch1, SZ_B);
2617+		} else {
2618+			mov_rdispr(code, src_op.base, src_op.disp, opts->gen.scratch1, SZ_B);
2619+		}
2620+		call(code, opts->write_io);
2621+		z80_save_reg(inst, opts);
2622+		break;
2623+	case Z80_OUTI:
2624+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2625+		//read from (HL)
2626+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2627+		call(code, opts->read_8);//T states 3
2628+		//undocumented N flag behavior
2629+		//flag set on bit 7 of value written
2630+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2631+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2632+		//write to IO (C)
2633+		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2634+		call(code, opts->write_io);//T states 4
2635+		//increment HL
2636+		if (opts->regs[Z80_HL] >= 0) {
2637+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2638+			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2639+		} else {
2640+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2641+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2642+		}
2643+		//undocumented C and H flag behavior
2644+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2645+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2646+		//decrement B
2647+		if (opts->regs[Z80_B] >= 0) {
2648+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2649+		} else {
2650+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2651+		}
2652+		//undocumented Z and S flag behavior, set based on decrement of B
2653+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2654+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2655+		//crazy undocumented P/V flag behavior
2656+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2657+		if (opts->regs[Z80_B] >= 0) {
2658+			//deal with silly x86-64 restrictions on *H registers
2659+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2660+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2661+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2662+		} else {
2663+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2664+		}
2665+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2666+		break;
2667+	case Z80_OTIR: {
2668+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2669+		//read from (HL)
2670+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2671+		call(code, opts->read_8);//T states 3
2672+		//undocumented N flag behavior
2673+		//flag set on bit 7 of value written
2674+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2675+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2676+		//write to IO (C)
2677+		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2678+		call(code, opts->write_io);//T states 4
2679+		//increment HL
2680+		if (opts->regs[Z80_HL] >= 0) {
2681+			add_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2682+			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2683+		} else {
2684+			add_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2685+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2686+		}
2687+		//undocumented C and H flag behavior
2688+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2689+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2690+		//decrement B
2691+		if (opts->regs[Z80_B] >= 0) {
2692+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2693+		} else {
2694+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2695+		}
2696+		//undocumented Z and S flag behavior, set based on decrement of B
2697+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2698+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2699+		//crazy undocumented P/V flag behavior
2700+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2701+		if (opts->regs[Z80_B] >= 0) {
2702+			//deal with silly x86-64 restrictions on *H registers
2703+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2704+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2705+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2706+		} else {
2707+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2708+		}
2709+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2710+		if (opts->regs[Z80_B] >= 0) {
2711+			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2712+		} else {
2713+			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2714+		}
2715+		code_ptr done = code->cur+1;
2716+		jcc(code, CC_Z, code->cur+2);
2717+		cycles(&opts->gen, 5);
2718+		jmp(code, start);
2719+		*done = code->cur - (done + 1);
2720+		break;
2721+	}
2722+	case Z80_OUTD:
2723+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2724+		//read from (HL)
2725+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2726+		call(code, opts->read_8);//T states 3
2727+		//undocumented N flag behavior
2728+		//flag set on bit 7 of value written
2729+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2730+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2731+		//write to IO (C)
2732+		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2733+		call(code, opts->write_io);//T states 4
2734+		//decrement HL
2735+		if (opts->regs[Z80_HL] >= 0) {
2736+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2737+			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2738+		} else {
2739+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2740+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2741+		}
2742+		//undocumented C and H flag behavior
2743+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2744+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2745+		//decrement B
2746+		if (opts->regs[Z80_B] >= 0) {
2747+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2748+		} else {
2749+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2750+		}
2751+		//undocumented Z and S flag behavior, set based on decrement of B
2752+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2753+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2754+		//crazy undocumented P/V flag behavior
2755+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2756+		if (opts->regs[Z80_B] >= 0) {
2757+			//deal with silly x86-64 restrictions on *H registers
2758+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2759+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2760+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2761+		} else {
2762+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2763+		}
2764+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2765+		break;
2766+	case Z80_OTDR: {
2767+		cycles(&opts->gen, num_cycles + 1);//T States: 4, 5
2768+		//read from (HL)
2769+		zreg_to_native(opts, Z80_HL, opts->gen.scratch1);
2770+		call(code, opts->read_8);//T states 3
2771+		//undocumented N flag behavior
2772+		//flag set on bit 7 of value written
2773+		bt_ir(code, 7, opts->gen.scratch1, SZ_B);
2774+		setcc_rdisp(code, CC_NC, opts->gen.context_reg, zf_off(ZF_N)); 
2775+		//write to IO (C)
2776+		zreg_to_native(opts, Z80_C, opts->gen.scratch2);
2777+		call(code, opts->write_io);//T states 4
2778+		//increment HL
2779+		if (opts->regs[Z80_HL] >= 0) {
2780+			sub_ir(code, 1, opts->regs[Z80_HL], SZ_W);
2781+			add_rr(code, opts->regs[Z80_L], opts->gen.scratch1, SZ_B);
2782+		} else {
2783+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_HL), SZ_B);
2784+			add_rdispr(code, opts->gen.context_reg, zr_off(Z80_L), opts->gen.scratch1, SZ_B);
2785+		}
2786+		//undocumented C and H flag behavior
2787+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_C));
2788+		setcc_rdisp(code, CC_C, opts->gen.context_reg, zf_off(ZF_H));
2789+		//decrement B
2790+		if (opts->regs[Z80_B] >= 0) {
2791+			sub_ir(code, 1, opts->regs[Z80_B], SZ_B);
2792+		} else {
2793+			sub_irdisp(code, 1, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2794+		}
2795+		//undocumented Z and S flag behavior, set based on decrement of B
2796+		setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z));
2797+		setcc_rdisp(code, CC_S, opts->gen.context_reg, zf_off(ZF_S));
2798+		//crazy undocumented P/V flag behavior
2799+		and_ir(code, 7, opts->gen.scratch1, SZ_B);
2800+		if (opts->regs[Z80_B] >= 0) {
2801+			//deal with silly x86-64 restrictions on *H registers
2802+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2803+			xor_rr(code, opts->regs[Z80_C], opts->gen.scratch1, SZ_B);
2804+			ror_ir(code, 8, opts->regs[Z80_BC], SZ_W);
2805+		} else {
2806+			xor_rdispr(code, opts->gen.context_reg, zr_off(Z80_B), opts->gen.scratch1, SZ_B);
2807+		}
2808+		setcc_rdisp(code, CC_P, opts->gen.context_reg, zf_off(ZF_PV));
2809+		if (opts->regs[Z80_B] >= 0) {
2810+			cmp_ir(code, 0, opts->regs[Z80_B], SZ_B);
2811+		} else {
2812+			cmp_irdisp(code, 0, opts->gen.context_reg, zr_off(Z80_B), SZ_B);
2813+		}
2814+		code_ptr done = code->cur+1;
2815+		jcc(code, CC_Z, code->cur+2);
2816+		cycles(&opts->gen, 5);
2817+		jmp(code, start);
2818+		*done = code->cur - (done + 1);
2819+		break;
2820+	}
2821+	default: {
2822+		char disbuf[80];
2823+		z80_disasm(inst, disbuf, address);
2824+		FILE * f = fopen("zram.bin", "wb");
2825+		fwrite(context->mem_pointers[0], 1, 8 * 1024, f);
2826+		fclose(f);
2827+		fatal_error("unimplemented Z80 instruction: %s at %X\nZ80 RAM has been saved to zram.bin for debugging", disbuf, address);
2828+	}
2829+	}
2830+}
2831+
2832+uint8_t * z80_interp_handler(uint8_t opcode, z80_context * context)
2833+{
2834+	if (!context->interp_code[opcode]) {
2835+		if (opcode == 0xCB || (opcode >= 0xDD && (opcode & 0xF) == 0xD)) {
2836+			fatal_error("Encountered prefix byte %X at address %X. Z80 interpeter doesn't support those yet.", opcode, context->pc);
2837+		}
2838+		uint8_t codebuf[8];
2839+		memset(codebuf, 0, sizeof(codebuf));
2840+		codebuf[0] = opcode;
2841+		z80inst inst;
2842+		uint8_t * after = z80_decode(codebuf, &inst);
2843+		if (after - codebuf > 1) {
2844+			fatal_error("Encountered multi-byte Z80 instruction at %X. Z80 interpeter doesn't support those yet.", context->pc);
2845+		}
2846+
2847+		z80_options * opts = context->options;
2848+		code_info *code = &opts->gen.code;
2849+		check_alloc_code(code, ZMAX_NATIVE_SIZE);
2850+		context->interp_code[opcode] = code->cur;
2851+		translate_z80inst(&inst, context, 0, 1);
2852+		mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, pc), opts->gen.scratch1, SZ_W);
2853+		add_ir(code, after - codebuf, opts->gen.scratch1, SZ_W);
2854+		call(code, opts->native_addr);
2855+		jmp_r(code, opts->gen.scratch1);
2856+		z80_handle_deferred(context);
2857+	}
2858+	return context->interp_code[opcode];
2859+}
2860+
2861+code_info z80_make_interp_stub(z80_context * context, uint16_t address)
2862+{
2863+	z80_options *opts = context->options;
2864+	code_info * code = &opts->gen.code;
2865+	check_alloc_code(code, 32);
2866+	code_info stub = {code->cur, NULL};
2867+	//TODO: make this play well with the breakpoint code
2868+	mov_ir(code, address, opts->gen.scratch1, SZ_W);
2869+	call(code, opts->read_8);
2870+	//opcode fetch M-cycles have one extra T-state
2871+	cycles(&opts->gen, 1);
2872+	//TODO: increment R
2873+	check_cycles_int(&opts->gen, address);
2874+	call(code, opts->gen.save_context);
2875+	mov_irdisp(code, address, opts->gen.context_reg, offsetof(z80_context, pc), SZ_W);
2876+	push_r(code, opts->gen.context_reg);
2877+	call_args(code, (code_ptr)z80_interp_handler, 2, opts->gen.scratch1, opts->gen.context_reg);
2878+	mov_rr(code, RAX, opts->gen.scratch1, SZ_PTR);
2879+	pop_r(code, opts->gen.context_reg);
2880+	call(code, opts->gen.load_context);
2881+	jmp_r(code, opts->gen.scratch1);
2882+	stub.last = code->cur;
2883+	return stub;
2884+}
2885+
2886+
2887+uint8_t * z80_get_native_address(z80_context * context, uint32_t address)
2888+{
2889+	z80_options *opts = context->options;
2890+	native_map_slot * native_code_map = opts->gen.native_code_map;
2891+	
2892+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
2893+	if (mem_chunk) {
2894+		//calculate the lowest alias for this address
2895+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2896+	}
2897+	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
2898+	if (!native_code_map[chunk].base) {
2899+		return NULL;
2900+	}
2901+	uint32_t offset = address % NATIVE_CHUNK_SIZE;
2902+	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET || native_code_map[chunk].offsets[offset] == EXTENSION_WORD) {
2903+		return NULL;
2904+	}
2905+	return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
2906+}
2907+
2908+uint8_t z80_get_native_inst_size(z80_options * opts, uint32_t address)
2909+{
2910+	uint32_t meta_off;
2911+	memmap_chunk const *chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
2912+	if (chunk) {
2913+		meta_off += (address - chunk->start) & chunk->mask;
2914+	}
2915+	uint32_t slot = meta_off/1024;
2916+	return opts->gen.ram_inst_sizes[slot][meta_off%1024];
2917+}
2918+
2919+void z80_map_native_address(z80_context * context, uint32_t address, uint8_t * native_address, uint8_t size, uint8_t native_size)
2920+{
2921+	z80_options * opts = context->options;
2922+	uint32_t meta_off;
2923+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
2924+	if (mem_chunk) {
2925+		if (mem_chunk->flags & MMAP_CODE) {
2926+			uint32_t masked = (address & mem_chunk->mask);
2927+			uint32_t final_off = masked + meta_off;
2928+			uint32_t ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
2929+			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
2930+
2931+			uint32_t slot = final_off / 1024;
2932+			if (!opts->gen.ram_inst_sizes[slot]) {
2933+				opts->gen.ram_inst_sizes[slot] = malloc(sizeof(uint8_t) * 1024);
2934+			}
2935+			opts->gen.ram_inst_sizes[slot][final_off % 1024] = native_size;
2936+
2937+			//TODO: Deal with case in which end of instruction is in a different memory chunk
2938+			masked = (address + size - 1) & mem_chunk->mask;
2939+			final_off = masked + meta_off;
2940+			ram_flags_off = final_off >> (opts->gen.ram_flags_shift + 3);
2941+			context->ram_code_flags[ram_flags_off] |= 1 << ((final_off >> opts->gen.ram_flags_shift) & 7);
2942+		}
2943+		//calculate the lowest alias for this address
2944+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2945+	} else {
2946+		address &= opts->gen.address_mask;
2947+	}
2948+	
2949+	native_map_slot *map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
2950+	if (!map->base) {
2951+		map->base = native_address;
2952+		map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2953+		memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2954+	}
2955+	map->offsets[address % NATIVE_CHUNK_SIZE] = native_address - map->base;
2956+	for(--size, address++; size; --size, address++) {
2957+		address &= opts->gen.address_mask;
2958+		map = opts->gen.native_code_map + address / NATIVE_CHUNK_SIZE;
2959+		if (!map->base) {
2960+			map->base = native_address;
2961+			map->offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2962+			memset(map->offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE);
2963+		}
2964+	
2965+		if (map->offsets[address % NATIVE_CHUNK_SIZE] == INVALID_OFFSET) {
2966+			//TODO: better handling of potentially overlapping instructions
2967+			map->offsets[address % NATIVE_CHUNK_SIZE] = EXTENSION_WORD;
2968+		}
2969+	}
2970+}
2971+
2972+#define INVALID_INSTRUCTION_START 0xFEEDFEED
2973+
2974+uint32_t z80_get_instruction_start(z80_context *context, uint32_t address)
2975+{	
2976+	z80_options *opts = context->options;
2977+	native_map_slot * native_code_map = opts->gen.native_code_map;
2978+	memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL);
2979+	if (mem_chunk) {
2980+		//calculate the lowest alias for this address
2981+		address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask);
2982+	}
2983+	
2984+	uint32_t chunk = address / NATIVE_CHUNK_SIZE;
2985+	if (!native_code_map[chunk].base) {
2986+		return INVALID_INSTRUCTION_START;
2987+	}
2988+	uint32_t offset = address % NATIVE_CHUNK_SIZE;
2989+	if (native_code_map[chunk].offsets[offset] == INVALID_OFFSET) {
2990+		return INVALID_INSTRUCTION_START;
2991+	}
2992+	while (native_code_map[chunk].offsets[offset] == EXTENSION_WORD)
2993+	{
2994+		--address;
2995+		chunk = address / NATIVE_CHUNK_SIZE;
2996+		offset = address % NATIVE_CHUNK_SIZE;
2997+	}
2998+	return address;
2999+}
3000+
3001+//Technically unbounded due to redundant prefixes, but this is the max useful size
3002+#define Z80_MAX_INST_SIZE 4
3003+
3004+z80_context * z80_handle_code_write(uint32_t address, z80_context * context)
3005+{
3006+	uint32_t inst_start = z80_get_instruction_start(context, address);
3007+	while (inst_start != INVALID_INSTRUCTION_START && (address - inst_start) < Z80_MAX_INST_SIZE) {
3008+		code_ptr dst = z80_get_native_address(context, inst_start);
3009+		code_info code = {dst, dst+32, 0};
3010+		z80_options * opts = context->options;
3011+		dprintf("patching code at %p for Z80 instruction at %X due to write to %X\n", code.cur, inst_start, address);
3012+		mov_ir(&code, inst_start, opts->gen.scratch1, SZ_D);
3013+		call(&code, opts->retrans_stub);
3014+		inst_start = z80_get_instruction_start(context, inst_start - 1);
3015+	}
3016+	return context;
3017+}
3018+
3019+void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end)
3020+{
3021+	z80_options *opts = context->options;
3022+	native_map_slot * native_code_map = opts->gen.native_code_map;
3023+	memmap_chunk const *mem_chunk = find_map_chunk(start, &opts->gen, 0, NULL);
3024+	if (mem_chunk) {
3025+		//calculate the lowest alias for this address
3026+		start = mem_chunk->start + ((start - mem_chunk->start) & mem_chunk->mask);
3027+	}
3028+	mem_chunk = find_map_chunk(end, &opts->gen, 0, NULL);
3029+	if (mem_chunk) {
3030+		//calculate the lowest alias for this address
3031+		end = mem_chunk->start + ((end - mem_chunk->start) & mem_chunk->mask);
3032+	}
3033+	uint32_t start_chunk = start / NATIVE_CHUNK_SIZE, end_chunk = end / NATIVE_CHUNK_SIZE;
3034+	for (uint32_t chunk = start_chunk; chunk <= end_chunk; chunk++)
3035+	{
3036+		if (native_code_map[chunk].base) {
3037+			uint32_t start_offset = chunk == start_chunk ? start % NATIVE_CHUNK_SIZE : 0;
3038+			uint32_t end_offset = chunk == end_chunk ? end % NATIVE_CHUNK_SIZE : NATIVE_CHUNK_SIZE;
3039+			for (uint32_t offset = start_offset; offset < end_offset; offset++)
3040+			{
3041+				if (native_code_map[chunk].offsets[offset] != INVALID_OFFSET && native_code_map[chunk].offsets[offset] != EXTENSION_WORD) {
3042+					code_info code;
3043+					code.cur = native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
3044+					code.last = code.cur + 32;
3045+					code.stack_off = 0;
3046+					mov_ir(&code, chunk * NATIVE_CHUNK_SIZE + offset, opts->gen.scratch1, SZ_D);
3047+					call(&code, opts->retrans_stub);
3048+				}
3049+			}
3050+		}
3051+	}
3052+}
3053+
3054+uint8_t * z80_get_native_address_trans(z80_context * context, uint32_t address)
3055+{
3056+	uint8_t * addr = z80_get_native_address(context, address);
3057+	if (!addr) {
3058+		translate_z80_stream(context, address);
3059+		addr = z80_get_native_address(context, address);
3060+		if (!addr) {
3061+			printf("Failed to translate %X to native code\n", address);
3062+		}
3063+	}
3064+	return addr;
3065+}
3066+
3067+void z80_handle_deferred(z80_context * context)
3068+{
3069+	z80_options * opts = context->options;
3070+	process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
3071+	if (opts->gen.deferred) {
3072+		translate_z80_stream(context, opts->gen.deferred->address);
3073+	}
3074+}
3075+
3076+extern void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start) asm("z80_retranslate_inst");
3077+void * z80_retranslate_inst(uint32_t address, z80_context * context, uint8_t * orig_start)
3078+{
3079+	char disbuf[80];
3080+	z80_options * opts = context->options;
3081+	uint8_t orig_size = z80_get_native_inst_size(opts, address);
3082+	code_info *code = &opts->gen.code;
3083+	uint8_t *after, *inst = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
3084+	z80inst instbuf;
3085+	dprintf("Retranslating code at Z80 address %X, native address %p\n", address, orig_start);
3086+	after = z80_decode(inst, &instbuf);
3087+	#ifdef DO_DEBUG_PRINT
3088+	z80_disasm(&instbuf, disbuf, address);
3089+	if (instbuf.op == Z80_NOP) {
3090+		printf("%X\t%s(%d)\n", address, disbuf, instbuf.immed);
3091+	} else {
3092+		printf("%X\t%s\n", address, disbuf);
3093+	}
3094+	#endif
3095+	if (orig_size != ZMAX_NATIVE_SIZE) {
3096+		check_alloc_code(code, ZMAX_NATIVE_SIZE);
3097+		code_ptr start = code->cur;
3098+		deferred_addr * orig_deferred = opts->gen.deferred;
3099+		translate_z80inst(&instbuf, context, address, 0);
3100+		/*
3101+		if ((native_end - dst) <= orig_size) {
3102+			uint8_t * native_next = z80_get_native_address(context, address + after-inst);
3103+			if (native_next && ((native_next == orig_start + orig_size) || (orig_size - (native_end - dst)) > 5)) {
3104+				remove_deferred_until(&opts->gen.deferred, orig_deferred);
3105+				native_end = translate_z80inst(&instbuf, orig_start, context, address, 0);
3106+				if (native_next == orig_start + orig_size && (native_next-native_end) < 2) {
3107+					while (native_end < orig_start + orig_size) {
3108+						*(native_end++) = 0x90; //NOP
3109+					}
3110+				} else {
3111+					jmp(native_end, native_next);
3112+				}
3113+				z80_handle_deferred(context);
3114+				return orig_start;
3115+			}
3116+		}*/
3117+		z80_map_native_address(context, address, start, after-inst, ZMAX_NATIVE_SIZE);
3118+		code_info tmp_code = {orig_start, orig_start + 16};
3119+		jmp(&tmp_code, start);
3120+		tmp_code = *code;
3121+		code->cur = start + ZMAX_NATIVE_SIZE;
3122+		if (!z80_is_terminal(&instbuf)) {
3123+			jmp(&tmp_code, z80_get_native_address_trans(context, address + after-inst));
3124+		}
3125+		z80_handle_deferred(context);
3126+		return start;
3127+	} else {
3128+		code_info tmp_code = *code;
3129+		code->cur = orig_start;
3130+		code->last = orig_start + ZMAX_NATIVE_SIZE;
3131+		translate_z80inst(&instbuf, context, address, 0);
3132+		code_info tmp2 = *code;
3133+		*code = tmp_code;
3134+		if (!z80_is_terminal(&instbuf)) {
3135+
3136+			jmp(&tmp2, z80_get_native_address_trans(context, address + after-inst));
3137+		}
3138+		z80_handle_deferred(context);
3139+		return orig_start;
3140+	}
3141+}
3142+
3143+void translate_z80_stream(z80_context * context, uint32_t address)
3144+{
3145+	char disbuf[80];
3146+	if (z80_get_native_address(context, address)) {
3147+		return;
3148+	}
3149+	z80_options * opts = context->options;
3150+	uint32_t start_address = address;
3151+
3152+	do
3153+	{
3154+		z80inst inst;
3155+		dprintf("translating Z80 code at address %X\n", address);
3156+		do {
3157+			uint8_t * existing = z80_get_native_address(context, address);
3158+			if (existing) {
3159+				jmp(&opts->gen.code, existing);
3160+				break;
3161+			}
3162+			uint8_t * encoded, *next;
3163+			encoded = get_native_pointer(address, (void **)context->mem_pointers, &opts->gen);
3164+			if (!encoded) {
3165+				code_info stub = z80_make_interp_stub(context, address);
3166+				z80_map_native_address(context, address, stub.cur, 1, stub.last - stub.cur);
3167+				break;
3168+			}
3169+			//make sure prologue is in a contiguous chunk of code
3170+			check_code_prologue(&opts->gen.code);
3171+			next = z80_decode(encoded, &inst);
3172+			#ifdef DO_DEBUG_PRINT
3173+			z80_disasm(&inst, disbuf, address);
3174+			if (inst.op == Z80_NOP) {
3175+				printf("%X\t%s(%d)\n", address, disbuf, inst.immed);
3176+			} else {
3177+				printf("%X\t%s\n", address, disbuf);
3178+			}
3179+			#endif
3180+			code_ptr start = opts->gen.code.cur;
3181+			translate_z80inst(&inst, context, address, 0);
3182+			z80_map_native_address(context, address, start, next-encoded, opts->gen.code.cur - start);
3183+			address += next-encoded;
3184+				address &= 0xFFFF;
3185+		} while (!z80_is_terminal(&inst));
3186+		process_deferred(&opts->gen.deferred, context, (native_addr_func)z80_get_native_address);
3187+		if (opts->gen.deferred) {
3188+			address = opts->gen.deferred->address;
3189+			dprintf("defferred address: %X\n", address);
3190+		}
3191+	} while (opts->gen.deferred);
3192+}
3193+
3194+void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask)
3195+{
3196+	memset(options, 0, sizeof(*options));
3197+
3198+	options->gen.memmap = chunks;
3199+	options->gen.memmap_chunks = num_chunks;
3200+	options->gen.address_size = SZ_W;
3201+	options->gen.address_mask = 0xFFFF;
3202+	options->gen.max_address = 0x10000;
3203+	options->gen.bus_cycles = 3;
3204+	options->gen.clock_divider = clock_divider;
3205+	options->gen.mem_ptr_off = offsetof(z80_context, mem_pointers);
3206+	options->gen.ram_flags_off = offsetof(z80_context, ram_code_flags);
3207+	options->gen.ram_flags_shift = 7;
3208+
3209+	options->flags = 0;
3210+#ifdef X86_64
3211+	options->regs[Z80_B] = BH;
3212+	options->regs[Z80_C] = RBX;
3213+	options->regs[Z80_D] = CH;
3214+	options->regs[Z80_E] = RCX;
3215+	options->regs[Z80_H] = AH;
3216+	options->regs[Z80_L] = RAX;
3217+	options->regs[Z80_IXH] = DH;
3218+	options->regs[Z80_IXL] = RDX;
3219+	options->regs[Z80_IYH] = -1;
3220+	options->regs[Z80_IYL] = R8;
3221+	options->regs[Z80_I] = -1;
3222+	options->regs[Z80_R] = RDI;
3223+	options->regs[Z80_A] = R10;
3224+	options->regs[Z80_BC] = RBX;
3225+	options->regs[Z80_DE] = RCX;
3226+	options->regs[Z80_HL] = RAX;
3227+	options->regs[Z80_SP] = R9;
3228+	options->regs[Z80_AF] = -1;
3229+	options->regs[Z80_IX] = RDX;
3230+	options->regs[Z80_IY] = R8;
3231+
3232+	options->gen.scratch1 = R13;
3233+	options->gen.scratch2 = R14;
3234+#else
3235+	memset(options->regs, -1, sizeof(options->regs));
3236+	options->regs[Z80_A] = RAX;
3237+	options->regs[Z80_R] = AH;
3238+	options->regs[Z80_H] = BH;
3239+	options->regs[Z80_L] = RBX;
3240+	options->regs[Z80_HL] = RBX;
3241+	
3242+	options->regs[Z80_SP] = RDI;
3243+
3244+	options->gen.scratch1 = RCX;
3245+	options->gen.scratch2 = RDX;
3246+#endif
3247+
3248+	options->gen.context_reg = RSI;
3249+	options->gen.cycles = RBP;
3250+	options->gen.limit = -1;
3251+
3252+	options->gen.native_code_map = malloc(sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
3253+	memset(options->gen.native_code_map, 0, sizeof(native_map_slot) * NATIVE_MAP_CHUNKS);
3254+	options->gen.deferred = NULL;
3255+	uint32_t inst_size_size = sizeof(uint8_t *) * ram_size(&options->gen) / 1024;
3256+	options->gen.ram_inst_sizes = malloc(inst_size_size);
3257+	memset(options->gen.ram_inst_sizes, 0, inst_size_size);
3258+
3259+	code_info *code = &options->gen.code;
3260+	init_code_info(code);
3261+
3262+	options->save_context_scratch = code->cur;
3263+	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch1), SZ_W);
3264+	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_W);
3265+
3266+	options->gen.save_context = code->cur;
3267+	for (int i = 0; i <= Z80_A; i++)
3268+	{
3269+		int reg;
3270+		uint8_t size;
3271+		if (i < Z80_I) {
3272+			reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
3273+			size = SZ_W;
3274+		} else {
3275+			reg = i;
3276+			size = SZ_B;
3277+		}
3278+		if (reg == Z80_R) {
3279+			and_ir(code, 0x7F, options->regs[Z80_R], SZ_B);
3280+			or_rrdisp(code, options->regs[Z80_R], options->gen.context_reg, zr_off(Z80_R), SZ_B);
3281+		} else if (options->regs[reg] >= 0) {
3282+			mov_rrdisp(code, options->regs[reg], options->gen.context_reg, zr_off(reg), size);
3283+		}
3284+		if (size == SZ_W) {
3285+			i++;
3286+		}
3287+	}
3288+	if (options->regs[Z80_SP] >= 0) {
3289+		mov_rrdisp(code, options->regs[Z80_SP], options->gen.context_reg, offsetof(z80_context, sp), SZ_W);
3290+	}
3291+	neg_r(code, options->gen.cycles, SZ_D);
3292+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3293+	mov_rrdisp(code, options->gen.cycles, options->gen.context_reg, offsetof(z80_context, current_cycle), SZ_D);
3294+	retn(code);
3295+
3296+	options->load_context_scratch = code->cur;
3297+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch1), options->gen.scratch1, SZ_W);
3298+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch2, SZ_W);
3299+	options->gen.load_context = code->cur;
3300+	for (int i = 0; i <= Z80_A; i++)
3301+	{
3302+		int reg;
3303+		uint8_t size;
3304+		if (i < Z80_I) {
3305+			reg = i /2 + Z80_BC + (i > Z80_H ? 2 : 0);
3306+			size = SZ_W;
3307+		} else {
3308+			reg = i;
3309+			size = SZ_B;
3310+		}
3311+		if (options->regs[reg] >= 0) {
3312+			mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + i, options->regs[reg], size);
3313+			if (reg == Z80_R) {
3314+				and_irdisp(code, 0x80, options->gen.context_reg, zr_off(reg), SZ_B);
3315+			}
3316+		}
3317+		if (size == SZ_W) {
3318+			i++;
3319+		}
3320+	}
3321+	if (options->regs[Z80_SP] >= 0) {
3322+		mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sp), options->regs[Z80_SP], SZ_W);
3323+	}
3324+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3325+	sub_rdispr(code, options->gen.context_reg, offsetof(z80_context, current_cycle), options->gen.cycles, SZ_D);
3326+	retn(code);
3327+
3328+	options->native_addr = code->cur;
3329+	call(code, options->gen.save_context);
3330+	push_r(code, options->gen.context_reg);
3331+	movzx_rr(code, options->gen.scratch1, options->gen.scratch1, SZ_W, SZ_D);
3332+	call_args(code, (code_ptr)z80_get_native_address_trans, 2, options->gen.context_reg, options->gen.scratch1);
3333+	mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
3334+	pop_r(code, options->gen.context_reg);
3335+	call(code, options->gen.load_context);
3336+	retn(code);
3337+
3338+	uint32_t tmp_stack_off;
3339+
3340+	options->gen.handle_cycle_limit = code->cur;
3341+	//calculate call/stack adjust size
3342+	sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3343+	call_noalign(code, options->gen.handle_cycle_limit);
3344+	uint32_t call_adjust_size = code->cur - options->gen.handle_cycle_limit;
3345+	code->cur = options->gen.handle_cycle_limit;
3346+	
3347+	neg_r(code, options->gen.cycles, SZ_D);
3348+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3349+	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
3350+	code_ptr no_sync = code->cur+1;
3351+	jcc(code, CC_B, no_sync);
3352+	neg_r(code, options->gen.cycles, SZ_D);
3353+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3354+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, pc), SZ_W);
3355+	call(code, options->save_context_scratch);
3356+	tmp_stack_off = code->stack_off;
3357+	pop_r(code, RAX); //return address in read/write func
3358+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3359+	pop_r(code, RBX); //return address in translated code
3360+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3361+	sub_ir(code, call_adjust_size, RAX, SZ_PTR); //adjust return address to point to the call + stack adjust that got us here
3362+	mov_rrdisp(code, RBX, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3363+	mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
3364+	restore_callee_save_regs(code);
3365+	//return to caller of z80_run
3366+	retn(code);
3367+	
3368+	*no_sync = code->cur - (no_sync + 1);
3369+	neg_r(code, options->gen.cycles, SZ_D);
3370+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3371+	retn(code);
3372+	code->stack_off = tmp_stack_off;
3373+
3374+	options->gen.handle_code_write = (code_ptr)z80_handle_code_write;
3375+
3376+	options->read_8 = gen_mem_fun(&options->gen, chunks, num_chunks, READ_8, &options->read_8_noinc);
3377+	options->write_8 = gen_mem_fun(&options->gen, chunks, num_chunks, WRITE_8, &options->write_8_noinc);
3378+
3379+	code_ptr skip_int = code->cur;
3380+	//calculate adjust size
3381+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3382+	uint32_t adjust_size = code->cur - skip_int;
3383+	code->cur = skip_int;
3384+	
3385+	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.cycles, SZ_D);
3386+	code_ptr skip_sync = code->cur + 1;
3387+	jcc(code, CC_B, skip_sync);
3388+	neg_r(code, options->gen.cycles, SZ_D);
3389+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3390+	//save PC
3391+	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, pc), SZ_D);
3392+	options->do_sync = code->cur;
3393+	call(code, options->gen.save_context);
3394+	tmp_stack_off = code->stack_off;
3395+	//pop return address off the stack and save for resume later
3396+	//pop_rind(code, options->gen.context_reg);
3397+	pop_r(code, RAX);
3398+	add_ir(code, adjust_size, RAX, SZ_PTR);
3399+	add_ir(code, 16-sizeof(void *), RSP, SZ_PTR);
3400+	mov_rrind(code, RAX, options->gen.context_reg, SZ_PTR);
3401+	
3402+	//restore callee saved registers
3403+	restore_callee_save_regs(code);
3404+	//return to caller of z80_run
3405+	retn(code);
3406+	*skip_sync = code->cur - (skip_sync+1);
3407+	neg_r(code, options->gen.cycles, SZ_D);
3408+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3409+	retn(code);
3410+	code->stack_off = tmp_stack_off;
3411+
3412+	options->gen.handle_cycle_limit_int = code->cur;
3413+	neg_r(code, options->gen.cycles, SZ_D);
3414+	add_rdispr(code, options->gen.context_reg, offsetof(z80_context, target_cycle), options->gen.cycles, SZ_D);
3415+	cmp_rdispr(code, options->gen.context_reg, offsetof(z80_context, int_cycle), options->gen.cycles, SZ_D);
3416+	jcc(code, CC_B, skip_int);
3417+	//set limit to the cycle limit
3418+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, sync_cycle), options->gen.scratch2, SZ_D);
3419+	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, target_cycle), SZ_D);
3420+	neg_r(code, options->gen.cycles, SZ_D);
3421+	add_rr(code, options->gen.scratch2, options->gen.cycles, SZ_D);
3422+	//disable interrupts
3423+	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3424+	code_ptr is_nmi = code->cur + 1;
3425+	jcc(code, CC_NZ, is_nmi);
3426+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
3427+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3428+	cycles(&options->gen, 6); //interupt ack cycle
3429+	code_ptr after_int_disable = code->cur + 1;
3430+	jmp(code, after_int_disable);
3431+	*is_nmi = code->cur - (is_nmi + 1);
3432+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, iff1), options->gen.scratch2, SZ_B);
3433+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, iff1), SZ_B);
3434+	mov_rrdisp(code, options->gen.scratch2, options->gen.context_reg, offsetof(z80_context, iff2), SZ_B);
3435+	cycles(&options->gen, 5); //NMI processing cycles
3436+	*after_int_disable = code->cur - (after_int_disable + 1);
3437+	//save return address (in scratch1) to Z80 stack
3438+	sub_ir(code, 2, options->regs[Z80_SP], SZ_W);
3439+	mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
3440+	//we need to do check_cycles and cycles outside of the write_8 call
3441+	//so that the stack has the correct depth if we need to return to C
3442+	//for a synchronization
3443+	check_cycles(&options->gen);
3444+	cycles(&options->gen, 3);
3445+	//save word to write before call to write_8_noinc
3446+	push_r(code, options->gen.scratch1);
3447+	call(code, options->write_8_noinc);
3448+	//restore word to write
3449+	pop_r(code, options->gen.scratch1);
3450+	//write high byte to SP+1
3451+	mov_rr(code, options->regs[Z80_SP], options->gen.scratch2, SZ_W);
3452+	add_ir(code, 1, options->gen.scratch2, SZ_W);
3453+	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3454+	check_cycles(&options->gen);
3455+	cycles(&options->gen, 3);
3456+	call(code, options->write_8_noinc);
3457+	//dispose of return address as we'll be jumping somewhere else
3458+	add_ir(code, 16, RSP, SZ_PTR);
3459+	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3460+	is_nmi = code->cur + 1;
3461+	jcc(code, CC_NZ, is_nmi);
3462+	//TODO: Support interrupt mode 0, not needed for Genesis sit it seems to read $FF during intack
3463+	//which is conveniently rst $38, i.e. the same thing that im 1 does
3464+	//check interrupt mode
3465+	cmp_irdisp(code, 2, options->gen.context_reg, offsetof(z80_context, im), SZ_B);
3466+	code_ptr im2 = code->cur + 1;
3467+	jcc(code, CC_Z, im2);
3468+	mov_ir(code, 0x38, options->gen.scratch1, SZ_W);
3469+	cycles(&options->gen, 1); //total time for mode 0/1 is 13 t-states
3470+	code_ptr after_int_dest = code->cur + 1;
3471+	jmp(code, after_int_dest);
3472+	*im2 = code->cur - (im2 + 1);
3473+	//read vector address from I << 8 | vector
3474+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, regs) + Z80_I, options->gen.scratch1, SZ_B);
3475+	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3476+	movzx_rdispr(code, options->gen.context_reg, offsetof(z80_context, im2_vector), options->gen.scratch2, SZ_B, SZ_W);
3477+	or_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3478+	push_r(code, options->gen.scratch1);
3479+	cycles(&options->gen, 3);
3480+	call(code, options->read_8_noinc);
3481+	pop_r(code, options->gen.scratch2);
3482+	push_r(code, options->gen.scratch1);
3483+	mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3484+	add_ir(code, 1, options->gen.scratch1, SZ_W);
3485+	cycles(&options->gen, 3);
3486+	call(code, options->read_8_noinc);
3487+	pop_r(code, options->gen.scratch2);
3488+	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3489+	movzx_rr(code, options->gen.scratch2, options->gen.scratch2, SZ_B, SZ_W);
3490+	or_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_W);
3491+	code_ptr after_int_dest2 = code->cur + 1;
3492+	jmp(code, after_int_dest2);
3493+	*is_nmi = code->cur - (is_nmi + 1);
3494+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, int_is_nmi), SZ_B);
3495+	mov_irdisp(code, CYCLE_NEVER, options->gen.context_reg, offsetof(z80_context, nmi_start), SZ_D);
3496+	mov_ir(code, 0x66, options->gen.scratch1, SZ_W);
3497+	*after_int_dest = code->cur - (after_int_dest + 1);
3498+	*after_int_dest2 = code->cur - (after_int_dest2 + 1);
3499+	call(code, options->native_addr);
3500+	mov_rrind(code, options->gen.scratch1, options->gen.context_reg, SZ_PTR);
3501+	tmp_stack_off = code->stack_off;
3502+	restore_callee_save_regs(code);
3503+	//return to caller of z80_run to sync
3504+	retn(code);
3505+	code->stack_off = tmp_stack_off;
3506+
3507+	//HACK
3508+	options->gen.address_size = SZ_D;
3509+	options->gen.address_mask = io_address_mask;
3510+	options->gen.bus_cycles = 4;
3511+	options->read_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, READ_8, NULL);
3512+	options->write_io = gen_mem_fun(&options->gen, io_chunks, num_io_chunks, WRITE_8, NULL);
3513+	options->gen.address_size = SZ_W;
3514+	options->gen.address_mask = 0xFFFF;
3515+	options->gen.bus_cycles = 3;
3516+
3517+	options->read_16 = code->cur;
3518+	cycles(&options->gen, 3);
3519+	check_cycles(&options->gen);
3520+	//TODO: figure out how to handle the extra wait state for word reads to bank area
3521+	//may also need special handling to avoid too much stack depth when access is blocked
3522+	push_r(code, options->gen.scratch1);
3523+	call(code, options->read_8_noinc);
3524+	mov_rr(code, options->gen.scratch1, options->gen.scratch2, SZ_B);
3525+#ifndef X86_64
3526+	//scratch 2 is a caller save register in 32-bit builds and may be clobbered by something called from the read8 fun
3527+	mov_rrdisp(code, options->gen.scratch1, options->gen.context_reg, offsetof(z80_context, scratch2), SZ_B);
3528+#endif
3529+	pop_r(code, options->gen.scratch1);
3530+	add_ir(code, 1, options->gen.scratch1, SZ_W);
3531+	cycles(&options->gen, 3);
3532+	check_cycles(&options->gen);
3533+	call(code, options->read_8_noinc);
3534+	shl_ir(code, 8, options->gen.scratch1, SZ_W);
3535+#ifdef X86_64
3536+	mov_rr(code, options->gen.scratch2, options->gen.scratch1, SZ_B);
3537+#else
3538+	mov_rdispr(code, options->gen.context_reg, offsetof(z80_context, scratch2), options->gen.scratch1, SZ_B);
3539+#endif
3540+	retn(code);
3541+
3542+	options->write_16_highfirst = code->cur;
3543+	cycles(&options->gen, 3);
3544+	check_cycles(&options->gen);
3545+	push_r(code, options->gen.scratch2);
3546+	push_r(code, options->gen.scratch1);
3547+	add_ir(code, 1, options->gen.scratch2, SZ_W);
3548+	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3549+	call(code, options->write_8_noinc);
3550+	pop_r(code, options->gen.scratch1);
3551+	pop_r(code, options->gen.scratch2);
3552+	cycles(&options->gen, 3);
3553+	check_cycles(&options->gen);
3554+	//TODO: Check if we can get away with TCO here
3555+	call(code, options->write_8_noinc);
3556+	retn(code);
3557+
3558+	options->write_16_lowfirst = code->cur;
3559+	cycles(&options->gen, 3);
3560+	check_cycles(&options->gen);
3561+	push_r(code, options->gen.scratch2);
3562+	push_r(code, options->gen.scratch1);
3563+	call(code, options->write_8_noinc);
3564+	pop_r(code, options->gen.scratch1);
3565+	pop_r(code, options->gen.scratch2);
3566+	add_ir(code, 1, options->gen.scratch2, SZ_W);
3567+	shr_ir(code, 8, options->gen.scratch1, SZ_W);
3568+	cycles(&options->gen, 3);
3569+	check_cycles(&options->gen);
3570+	//TODO: Check if we can get away with TCO here
3571+	call(code, options->write_8_noinc);
3572+	retn(code);
3573+
3574+	options->retrans_stub = code->cur;
3575+	tmp_stack_off = code->stack_off;
3576+	//calculate size of patch
3577+	mov_ir(code, 0x7FFF, options->gen.scratch1, SZ_D);
3578+	code->stack_off += sizeof(void *);
3579+	if (code->stack_off & 0xF) {
3580+		sub_ir(code, 16 - (code->stack_off & 0xF), RSP, SZ_PTR);
3581+	}
3582+	call_noalign(code, options->retrans_stub);
3583+	uint32_t patch_size = code->cur - options->retrans_stub;
3584+	code->cur = options->retrans_stub;
3585+	code->stack_off = tmp_stack_off;
3586+	
3587+	//pop return address
3588+	pop_r(code, options->gen.scratch2);
3589+	add_ir(code, 16-sizeof(void*), RSP, SZ_PTR);
3590+	code->stack_off = tmp_stack_off;
3591+	call(code, options->gen.save_context);
3592+	//adjust pointer before move and call instructions that got us here
3593+	sub_ir(code, patch_size, options->gen.scratch2, SZ_PTR);
3594+	push_r(code, options->gen.context_reg);
3595+	call_args(code, (code_ptr)z80_retranslate_inst, 3, options->gen.scratch1, options->gen.context_reg, options->gen.scratch2);
3596+	pop_r(code, options->gen.context_reg);
3597+	mov_rr(code, RAX, options->gen.scratch1, SZ_PTR);
3598+	call(code, options->gen.load_context);
3599+	jmp_r(code, options->gen.scratch1);
3600+
3601+	options->run = (z80_ctx_fun)code->cur;
3602+	tmp_stack_off = code->stack_off;
3603+	save_callee_save_regs(code);
3604+#ifdef X86_64
3605+	mov_rr(code, RDI, options->gen.context_reg, SZ_PTR);
3606+#else
3607+	mov_rdispr(code, RSP, 5 * sizeof(int32_t), options->gen.context_reg, SZ_PTR);
3608+#endif
3609+	call(code, options->load_context_scratch);
3610+	cmp_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3611+	code_ptr no_extra = code->cur+1;
3612+	jcc(code, CC_Z, no_extra);
3613+	sub_ir(code, 16-sizeof(void *), RSP, SZ_PTR);	
3614+	push_rdisp(code, options->gen.context_reg, offsetof(z80_context, extra_pc));
3615+	mov_irdisp(code, 0, options->gen.context_reg, offsetof(z80_context, extra_pc), SZ_PTR);
3616+	*no_extra = code->cur - (no_extra + 1);
3617+	jmp_rind(code, options->gen.context_reg);
3618+	code->stack_off = tmp_stack_off;
3619+}
3620+
3621+z80_context *init_z80_context(z80_options * options)
3622+{
3623+	size_t ctx_size = sizeof(z80_context) + ram_size(&options->gen) / (1 << options->gen.ram_flags_shift) / 8;
3624+	z80_context *context = calloc(1, ctx_size);
3625+	context->options = options;
3626+	context->int_cycle = CYCLE_NEVER;
3627+	context->int_pulse_start = CYCLE_NEVER;
3628+	context->int_pulse_end = CYCLE_NEVER;
3629+	context->nmi_start = CYCLE_NEVER;
3630+	
3631+	return context;
3632+}
3633+
3634+static void check_nmi(z80_context *context)
3635+{
3636+	if (context->nmi_start < context->int_cycle) {
3637+		context->int_cycle = context->nmi_start;
3638+		context->int_is_nmi = 1;
3639+	}
3640+}
3641+
3642+void z80_run(z80_context * context, uint32_t target_cycle)
3643+{
3644+	if (context->reset || context->busack) {
3645+		context->current_cycle = target_cycle;
3646+	} else {
3647+		if (context->current_cycle < target_cycle) {
3648+			//busreq is sampled at the end of an m-cycle
3649+			//we can approximate that by running for a single m-cycle after a bus request
3650+			context->sync_cycle = context->busreq ? context->current_cycle + 3*context->options->gen.clock_divider : target_cycle;
3651+			if (!context->native_pc) {
3652+				context->native_pc = z80_get_native_address_trans(context, context->pc);
3653+			}
3654+			while (context->current_cycle < context->sync_cycle)
3655+			{
3656+				if (context->next_int_pulse && (context->int_pulse_end < context->current_cycle || context->int_pulse_end == CYCLE_NEVER)) {
3657+					context->next_int_pulse(context);
3658+				}
3659+				if (context->iff1) {
3660+					context->int_cycle = context->int_pulse_start < context->int_enable_cycle ? context->int_enable_cycle : context->int_pulse_start;
3661+					context->int_is_nmi = 0;
3662+				} else {
3663+					context->int_cycle = CYCLE_NEVER;
3664+				}
3665+				check_nmi(context);
3666+				
3667+				context->target_cycle = context->sync_cycle < context->int_cycle ? context->sync_cycle : context->int_cycle;
3668+				dprintf("Running Z80 from cycle %d to cycle %d. Int cycle: %d (%d - %d)\n", context->current_cycle, context->sync_cycle, context->int_cycle, context->int_pulse_start, context->int_pulse_end);
3669+				context->options->run(context);
3670+				dprintf("Z80 ran to cycle %d\n", context->current_cycle);
3671+			}
3672+			if (context->busreq) {
3673+				context->busack = 1;
3674+				context->current_cycle = target_cycle;
3675+			}
3676+		}
3677+	}
3678+}
3679+
3680+void z80_options_free(z80_options *opts)
3681+{
3682+	for (uint32_t address = 0; address < opts->gen.address_mask; address += NATIVE_CHUNK_SIZE)
3683+	{
3684+		uint32_t chunk = address / NATIVE_CHUNK_SIZE;
3685+		if (opts->gen.native_code_map[chunk].base) {
3686+			free(opts->gen.native_code_map[chunk].offsets);
3687+		}
3688+	}
3689+	free(opts->gen.native_code_map);
3690+	uint32_t ram_inst_slots = ram_size(&opts->gen) / 1024;
3691+	for (uint32_t i = 0; i < ram_inst_slots; i++)
3692+	{
3693+		free(opts->gen.ram_inst_sizes[i]);
3694+	}
3695+	free(opts->gen.ram_inst_sizes);
3696+	free(opts);
3697+}
3698+
3699+void z80_assert_reset(z80_context * context, uint32_t cycle)
3700+{
3701+	z80_run(context, cycle);
3702+	context->reset = 1;
3703+}
3704+
3705+void z80_clear_reset(z80_context * context, uint32_t cycle)
3706+{
3707+	z80_run(context, cycle);
3708+	if (context->reset) {
3709+		//TODO: Handle case where reset is not asserted long enough
3710+		context->im = 0;
3711+		context->iff1 = context->iff2 = 0;
3712+		context->native_pc = NULL;
3713+		context->extra_pc = NULL;
3714+		context->pc = 0;
3715+		context->reset = 0;
3716+		if (context->busreq) {
3717+			//TODO: Figure out appropriate delay
3718+			context->busack = 1;
3719+		}
3720+	}
3721+}
3722+
3723+void z80_assert_busreq(z80_context * context, uint32_t cycle)
3724+{
3725+	z80_run(context, cycle);
3726+	context->busreq = 1;
3727+	//this is an imperfect aproximation since most M-cycles take less tstates than the max
3728+	//and a short 3-tstate m-cycle can take an unbounded number due to wait states
3729+	if (context->current_cycle - cycle > MAX_MCYCLE_LENGTH * context->options->gen.clock_divider) {
3730+		context->busack = 1;
3731+	}
3732+}
3733+
3734+void z80_clear_busreq(z80_context * context, uint32_t cycle)
3735+{
3736+	z80_run(context, cycle);
3737+	context->busreq = 0;
3738+	context->busack = 0;
3739+	//there appears to be at least a 1 Z80 cycle delay between busreq
3740+	//being released and resumption of execution
3741+	context->current_cycle += context->options->gen.clock_divider;
3742+}
3743+
3744+uint8_t z80_get_busack(z80_context * context, uint32_t cycle)
3745+{
3746+	z80_run(context, cycle);
3747+	return context->busack;
3748+}
3749+
3750+void z80_assert_nmi(z80_context *context, uint32_t cycle)
3751+{
3752+	context->nmi_start = cycle;
3753+	check_nmi(context);
3754+}
3755+
3756+void z80_adjust_cycles(z80_context * context, uint32_t deduction)
3757+{
3758+	if (context->current_cycle < deduction) {
3759+		fprintf(stderr, "WARNING: Deduction of %u cycles when Z80 cycle counter is only %u\n", deduction, context->current_cycle);
3760+		context->current_cycle = 0;
3761+	} else {
3762+		context->current_cycle -= deduction;
3763+	}
3764+	if (context->int_enable_cycle != CYCLE_NEVER) {
3765+		if (context->int_enable_cycle < deduction) {
3766+			context->int_enable_cycle = 0;
3767+		} else {
3768+			context->int_enable_cycle -= deduction;
3769+		}
3770+	}
3771+	if (context->int_pulse_start != CYCLE_NEVER) {
3772+		if (context->int_pulse_end < deduction) {
3773+			context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER;
3774+		} else {
3775+			if (context->int_pulse_end != CYCLE_NEVER) {
3776+				context->int_pulse_end -= deduction;
3777+			}
3778+			if (context->int_pulse_start < deduction) {
3779+				context->int_pulse_start = 0;
3780+			} else {
3781+				context->int_pulse_start -= deduction;
3782+			}
3783+		}
3784+	}
3785+}
3786+
3787+uint32_t zbreakpoint_patch(z80_context * context, uint16_t address, code_ptr dst)
3788+{
3789+	code_info code = {
3790+		dst, 
3791+		dst+32,
3792+#ifdef X86_64
3793+		8
3794+#else
3795+		0
3796+#endif
3797+	};
3798+	mov_ir(&code, address, context->options->gen.scratch1, SZ_W);
3799+	call(&code, context->bp_stub);
3800+	return code.cur-dst;
3801+}
3802+
3803+void zcreate_stub(z80_context * context)
3804+{
3805+	//FIXME: Stack offset stuff is probably broken on 32-bit
3806+	z80_options * opts = context->options;
3807+	code_info *code = &opts->gen.code;
3808+	uint32_t start_stack_off = code->stack_off;
3809+	check_code_prologue(code);
3810+	context->bp_stub = code->cur;
3811+
3812+	//Calculate length of prologue
3813+	check_cycles_int(&opts->gen, 0);
3814+	int check_int_size = code->cur-context->bp_stub;
3815+	code->cur = context->bp_stub;
3816+
3817+	//Calculate length of patch
3818+	int patch_size = zbreakpoint_patch(context, 0, code->cur);
3819+
3820+#ifdef X86_64
3821+	code->stack_off = 8;
3822+#endif
3823+	//Save context and call breakpoint handler
3824+	call(code, opts->gen.save_context);
3825+	push_r(code, opts->gen.scratch1);
3826+	call_args_abi(code, context->bp_handler, 2, opts->gen.context_reg, opts->gen.scratch1);
3827+	mov_rr(code, RAX, opts->gen.context_reg, SZ_PTR);
3828+		//Restore context
3829+	call(code, opts->gen.load_context);
3830+	pop_r(code, opts->gen.scratch1);
3831+		//do prologue stuff
3832+	cmp_ir(code, 1, opts->gen.cycles, SZ_D);
3833+	uint8_t * jmp_off = code->cur+1;
3834+	jcc(code, CC_NS, code->cur + 7);
3835+	pop_r(code, opts->gen.scratch1);
3836+	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3837+#ifdef X86_64
3838+	sub_ir(code, 8, RSP, SZ_PTR);
3839+#endif
3840+	push_r(code, opts->gen.scratch1);
3841+	jmp(code, opts->gen.handle_cycle_limit_int);
3842+	*jmp_off = code->cur - (jmp_off+1);
3843+		//jump back to body of translated instruction
3844+	pop_r(code, opts->gen.scratch1);
3845+	add_ir(code, check_int_size - patch_size, opts->gen.scratch1, SZ_PTR);
3846+	jmp_r(code, opts->gen.scratch1);
3847+	code->stack_off = start_stack_off;
3848+}
3849+
3850+void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)
3851+{
3852+	context->bp_handler = bp_handler;
3853+	uint8_t bit = 1 << (address % 8);
3854+	if (!(bit & context->breakpoint_flags[address / 8])) {
3855+		context->breakpoint_flags[address / 8] |= bit;
3856+		if (!context->bp_stub) {
3857+			zcreate_stub(context);
3858+		}
3859+		uint8_t * native = z80_get_native_address(context, address);
3860+		if (native) {
3861+			zbreakpoint_patch(context, address, native);
3862+		}
3863+	}
3864+}
3865+
3866+void zremove_breakpoint(z80_context * context, uint16_t address)
3867+{
3868+	context->breakpoint_flags[address / 8] &= ~(1 << (address % 8));
3869+	uint8_t * native = z80_get_native_address(context, address);
3870+	if (native) {
3871+		z80_options * opts = context->options;
3872+		code_info tmp_code = opts->gen.code;
3873+		opts->gen.code.cur = native;
3874+		opts->gen.code.last = native + 128;
3875+		check_cycles_int(&opts->gen, address);
3876+		opts->gen.code = tmp_code;
3877+	}
3878+}
3879+
3880+void z80_serialize(z80_context *context, serialize_buffer *buf)
3881+{
3882+	for (int i = 0; i <= Z80_A; i++)
3883+	{
3884+		save_int8(buf, context->regs[i]);
3885+	}
3886+	uint8_t f = context->flags[ZF_S];
3887+	f <<= 1;
3888+	f |= context->flags[ZF_Z] ;
3889+	f <<= 2;
3890+	f |= context->flags[ZF_H];
3891+	f <<= 2;
3892+	f |= context->flags[ZF_PV];
3893+	f <<= 1;
3894+	f |= context->flags[ZF_N];
3895+	f <<= 1;
3896+	f |= context->flags[ZF_C];
3897+	f |= context->flags[ZF_XY] & 0x28;
3898+	save_int8(buf, f);
3899+	for (int i = 0; i <= Z80_A; i++)
3900+	{
3901+		save_int8(buf, context->alt_regs[i]);
3902+	}
3903+	f = context->alt_flags[ZF_S];
3904+	f <<= 1;
3905+	f |= context->alt_flags[ZF_Z] ;
3906+	f <<= 2;
3907+	f |= context->alt_flags[ZF_H];
3908+	f <<= 2;
3909+	f |= context->alt_flags[ZF_PV];
3910+	f <<= 1;
3911+	f |= context->alt_flags[ZF_N];
3912+	f <<= 1;
3913+	f |= context->alt_flags[ZF_C];
3914+	f |= context->flags[ZF_XY] & 0x28;
3915+	save_int8(buf, f);
3916+	save_int16(buf, context->pc);
3917+	save_int16(buf, context->sp);
3918+	save_int8(buf, context->im);
3919+	save_int8(buf, context->iff1);
3920+	save_int8(buf, context->iff2);
3921+	save_int8(buf, context->int_is_nmi);
3922+	save_int8(buf, context->busack);
3923+	save_int32(buf, context->current_cycle);
3924+	save_int32(buf, context->int_cycle);
3925+	save_int32(buf, context->int_enable_cycle);
3926+	save_int32(buf, context->int_pulse_start);
3927+	save_int32(buf, context->int_pulse_end);
3928+	save_int32(buf, context->nmi_start);
3929+}
3930+
3931+void z80_deserialize(deserialize_buffer *buf, void *vcontext)
3932+{
3933+	z80_context *context = vcontext;
3934+	for (int i = 0; i <= Z80_A; i++)
3935+	{
3936+		context->regs[i] = load_int8(buf);
3937+	}
3938+	uint8_t f = load_int8(buf);
3939+	context->flags[ZF_XY] = f & 0x28;
3940+	context->flags[ZF_C] = f & 1;
3941+	f >>= 1;
3942+	context->flags[ZF_N] = f & 1;
3943+	f >>= 1;
3944+	context->flags[ZF_PV] = f & 1;
3945+	f >>= 2;
3946+	context->flags[ZF_H] = f & 1;
3947+	f >>= 2;
3948+	context->flags[ZF_Z] = f & 1;
3949+	f >>= 1;
3950+	context->flags[ZF_S] = f;
3951+	for (int i = 0; i <= Z80_A; i++)
3952+	{
3953+		context->alt_regs[i] = load_int8(buf);
3954+	}
3955+	f = load_int8(buf);
3956+	context->alt_flags[ZF_XY] = f & 0x28;
3957+	context->alt_flags[ZF_C] = f & 1;
3958+	f >>= 1;
3959+	context->alt_flags[ZF_N] = f & 1;
3960+	f >>= 1;
3961+	context->alt_flags[ZF_PV] = f & 1;
3962+	f >>= 2;
3963+	context->alt_flags[ZF_H] = f & 1;
3964+	f >>= 2;
3965+	context->alt_flags[ZF_Z] = f & 1;
3966+	f >>= 1;
3967+	context->alt_flags[ZF_S] = f;
3968+	context->pc = load_int16(buf);
3969+	context->sp = load_int16(buf);
3970+	context->im = load_int8(buf);
3971+	context->iff1 = load_int8(buf);
3972+	context->iff2 = load_int8(buf);
3973+	context->int_is_nmi = load_int8(buf);
3974+	context->busack = load_int8(buf);
3975+	context->current_cycle = load_int32(buf);
3976+	context->int_cycle = load_int32(buf);
3977+	context->int_enable_cycle = load_int32(buf);
3978+	context->int_pulse_start = load_int32(buf);
3979+	context->int_pulse_end = load_int32(buf);
3980+	context->nmi_start = load_int32(buf);
3981+	context->native_pc = context->extra_pc = NULL;
3982+}
3983+
+117, -0
  1@@ -0,0 +1,117 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef Z80_TO_X86_H_
  8+#define Z80_TO_X86_H_
  9+#include "z80inst.h"
 10+#include "backend.h"
 11+#include "serialize.h"
 12+
 13+#define ZNUM_MEM_AREAS 4
 14+#ifdef Z80_LOG_ADDRESS
 15+#define ZMAX_NATIVE_SIZE 255
 16+#else
 17+#define ZMAX_NATIVE_SIZE 160
 18+#endif
 19+
 20+enum {
 21+	ZF_C = 0,
 22+	ZF_N,
 23+	ZF_PV,
 24+	ZF_H,
 25+	ZF_Z,
 26+	ZF_S,
 27+	ZF_XY,
 28+	ZF_NUM
 29+};
 30+
 31+typedef struct z80_context z80_context;
 32+typedef void (*z80_ctx_fun)(z80_context * context);
 33+
 34+typedef struct {
 35+	cpu_options     gen;
 36+	code_ptr        save_context_scratch;
 37+	code_ptr        load_context_scratch;
 38+	code_ptr        native_addr;
 39+	code_ptr        retrans_stub;
 40+	code_ptr        do_sync;
 41+	code_ptr        read_8;
 42+	code_ptr        write_8;
 43+	code_ptr        read_8_noinc;
 44+	code_ptr        write_8_noinc;
 45+	code_ptr        read_16;
 46+	code_ptr        write_16_highfirst;
 47+	code_ptr        write_16_lowfirst;
 48+	code_ptr		read_io;
 49+	code_ptr		write_io;
 50+
 51+	uint32_t        flags;
 52+	int8_t          regs[Z80_UNUSED];
 53+	z80_ctx_fun     run;
 54+} z80_options;
 55+
 56+struct z80_context {
 57+	void *            native_pc;
 58+	uint16_t          sp;
 59+	uint8_t           flags[ZF_NUM];
 60+	uint16_t          bank_reg;
 61+	uint8_t           regs[Z80_A+1];
 62+	uint8_t           im;
 63+	uint8_t           alt_regs[Z80_A+1];
 64+	uint32_t          target_cycle;
 65+	uint32_t          current_cycle;
 66+	uint8_t           alt_flags[ZF_NUM];
 67+	uint8_t *         mem_pointers[ZNUM_MEM_AREAS];
 68+	uint8_t           iff1;
 69+	uint8_t           iff2;
 70+	uint16_t          scratch1;
 71+	uint16_t          scratch2;
 72+	void *            extra_pc;
 73+	uint32_t          sync_cycle;
 74+	uint32_t          int_cycle;
 75+	z80_options *     options;
 76+	void *            system;
 77+	uint32_t          int_enable_cycle;
 78+	uint16_t          pc;
 79+	uint32_t          int_pulse_start;
 80+	uint32_t          int_pulse_end;
 81+	uint32_t          nmi_start;
 82+	uint8_t           breakpoint_flags[(16 * 1024)/sizeof(uint8_t)];
 83+	uint8_t *         bp_handler;
 84+	uint8_t *         bp_stub;
 85+	uint8_t *         interp_code[256];
 86+	z80_ctx_fun       next_int_pulse;
 87+	uint8_t           reset;
 88+	uint8_t           busreq;
 89+	uint8_t           busack;
 90+	uint8_t           int_is_nmi;
 91+	uint8_t           im2_vector;
 92+	uint8_t           ram_code_flags[];
 93+};
 94+
 95+void translate_z80_stream(z80_context * context, uint32_t address);
 96+void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask);
 97+void z80_options_free(z80_options *opts);
 98+z80_context * init_z80_context(z80_options * options);
 99+code_ptr z80_get_native_address(z80_context * context, uint32_t address);
100+code_ptr z80_get_native_address_trans(z80_context * context, uint32_t address);
101+z80_context * z80_handle_code_write(uint32_t address, z80_context * context);
102+void z80_invalidate_code_range(z80_context *context, uint32_t start, uint32_t end);
103+void z80_reset(z80_context * context);
104+void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler);
105+void zremove_breakpoint(z80_context * context, uint16_t address);
106+void z80_run(z80_context * context, uint32_t target_cycle);
107+void z80_assert_reset(z80_context * context, uint32_t cycle);
108+void z80_clear_reset(z80_context * context, uint32_t cycle);
109+void z80_assert_busreq(z80_context * context, uint32_t cycle);
110+void z80_clear_busreq(z80_context * context, uint32_t cycle);
111+void z80_assert_nmi(z80_context *context, uint32_t cycle);
112+uint8_t z80_get_busack(z80_context * context, uint32_t cycle);
113+void z80_adjust_cycles(z80_context * context, uint32_t deduction);
114+void z80_serialize(z80_context *context, serialize_buffer *buf);
115+void z80_deserialize(deserialize_buffer *buf, void *vcontext);
116+
117+#endif //Z80_TO_X86_H_
118+
+341, -0
  1@@ -0,0 +1,341 @@
  2+#include <string.h>
  3+
  4+void z80_read_8(z80_context *context)
  5+{
  6+	context->cycles += 3 * context->opts->gen.clock_divider;
  7+	uint8_t *fast = context->fastread[context->scratch1 >> 10];
  8+	if (fast) {
  9+		context->scratch1 = fast[context->scratch1 & 0x3FF];
 10+	} else {
 11+		context->scratch1 = read_byte(context->scratch1, (void **)context->mem_pointers, &context->opts->gen, context);
 12+	}
 13+}
 14+
 15+void z80_write_8(z80_context *context)
 16+{
 17+	context->cycles += 3 * context->opts->gen.clock_divider;
 18+	uint8_t *fast = context->fastwrite[context->scratch2 >> 10];
 19+	if (fast) {
 20+		fast[context->scratch2 & 0x3FF] = context->scratch1;
 21+	} else {
 22+		write_byte(context->scratch2, context->scratch1, (void **)context->mem_pointers, &context->opts->gen, context);
 23+	}
 24+}
 25+
 26+void z80_io_read8(z80_context *context)
 27+{
 28+	uint32_t tmp_mask = context->opts->gen.address_mask;
 29+	memmap_chunk const *tmp_map = context->opts->gen.memmap;
 30+	uint32_t tmp_chunks = context->opts->gen.memmap_chunks;
 31+	
 32+	context->opts->gen.address_mask = context->io_mask;
 33+	context->opts->gen.memmap = context->io_map;
 34+	context->opts->gen.memmap_chunks = context->io_chunks;
 35+	
 36+	context->cycles += 4 * context->opts->gen.clock_divider;
 37+	context->scratch1 = read_byte(context->scratch1, (void **)context->mem_pointers, &context->opts->gen, context);
 38+	
 39+	context->opts->gen.address_mask = tmp_mask;
 40+	context->opts->gen.memmap = tmp_map;
 41+	context->opts->gen.memmap_chunks = tmp_chunks;
 42+}
 43+
 44+void z80_io_write8(z80_context *context)
 45+{
 46+	uint32_t tmp_mask = context->opts->gen.address_mask;
 47+	memmap_chunk const *tmp_map = context->opts->gen.memmap;
 48+	uint32_t tmp_chunks = context->opts->gen.memmap_chunks;
 49+	
 50+	context->opts->gen.address_mask = context->io_mask;
 51+	context->opts->gen.memmap = context->io_map;
 52+	context->opts->gen.memmap_chunks = context->io_chunks;
 53+	
 54+	context->cycles += 4 * context->opts->gen.clock_divider;
 55+	write_byte(context->scratch2, context->scratch1, (void **)context->mem_pointers, &context->opts->gen, context);
 56+	
 57+	context->opts->gen.address_mask = tmp_mask;
 58+	context->opts->gen.memmap = tmp_map;
 59+	context->opts->gen.memmap_chunks = tmp_chunks;
 60+}
 61+
 62+//quick hack until I get a chance to change which init method these get passed to
 63+static memmap_chunk const * tmp_io_chunks;
 64+static uint32_t tmp_num_io_chunks, tmp_io_mask;
 65+void init_z80_opts(z80_options * options, memmap_chunk const * chunks, uint32_t num_chunks, memmap_chunk const * io_chunks, uint32_t num_io_chunks, uint32_t clock_divider, uint32_t io_address_mask)
 66+{
 67+	memset(options, 0, sizeof(*options));
 68+	options->gen.memmap = chunks;
 69+	options->gen.memmap_chunks = num_chunks;
 70+	options->gen.address_mask = 0xFFFF;
 71+	options->gen.max_address = 0xFFFF;
 72+	options->gen.clock_divider = clock_divider;
 73+	tmp_io_chunks = io_chunks;
 74+	tmp_num_io_chunks = num_io_chunks;
 75+	tmp_io_mask = io_address_mask;
 76+}
 77+
 78+void z80_options_free(z80_options *opts)
 79+{
 80+	free(opts);
 81+}
 82+
 83+z80_context * init_z80_context(z80_options *options)
 84+{
 85+	z80_context *context = calloc(1, sizeof(z80_context));
 86+	context->opts = options;
 87+	context->io_map = (memmap_chunk *)tmp_io_chunks;
 88+	context->io_chunks = tmp_num_io_chunks;
 89+	context->io_mask = tmp_io_mask;
 90+	context->int_cycle = context->int_end_cycle = context->nmi_cycle = 0xFFFFFFFFU;
 91+	z80_invalidate_code_range(context, 0, 0xFFFF);
 92+	return context;
 93+}
 94+
 95+void z80_sync_cycle(z80_context *context, uint32_t target_cycle)
 96+{
 97+	if (context->iff1 && context->int_cycle < target_cycle) {
 98+		if (context->cycles > context->int_end_cycle) {
 99+			context->int_cycle = 0xFFFFFFFFU;
100+		} else {
101+			target_cycle = context->int_cycle;
102+		}
103+	};
104+	if (context->nmi_cycle < target_cycle) {
105+		target_cycle = context->nmi_cycle;
106+	}
107+	context->sync_cycle = target_cycle;
108+}
109+
110+void z80_run(z80_context *context, uint32_t target_cycle)
111+{
112+	if (context->reset || context->busack) {
113+		context->cycles = target_cycle;
114+	} else if (target_cycle > context->cycles) {
115+		if (context->busreq) {
116+			//busreq is sampled at the end of an m-cycle
117+			//we can approximate that by running for a single m-cycle after a bus request
118+			target_cycle = context->cycles + 4 * context->opts->gen.clock_divider;
119+		}
120+		z80_execute(context, target_cycle);
121+		if (context->busreq) {
122+			context->busack = 1;
123+		}
124+	}
125+}
126+
127+void z80_assert_reset(z80_context * context, uint32_t cycle)
128+{
129+	z80_run(context, cycle);
130+	context->reset = 1;
131+}
132+
133+void z80_clear_reset(z80_context * context, uint32_t cycle)
134+{
135+	z80_run(context, cycle);
136+	if (context->reset) {
137+		context->imode = 0;
138+		context->iff1 = context->iff2 = 0;
139+		context->pc = 0;
140+		context->reset = 0;
141+		if (context->busreq) {
142+			//TODO: Figure out appropriate delay
143+			context->busack = 1;
144+		}
145+	}
146+}
147+
148+#define MAX_MCYCLE_LENGTH 6
149+void z80_assert_busreq(z80_context * context, uint32_t cycle)
150+{
151+	z80_run(context, cycle);
152+	context->busreq = 1;
153+	//this is an imperfect aproximation since most M-cycles take less tstates than the max
154+	//and a short 3-tstate m-cycle can take an unbounded number due to wait states
155+	if (context->cycles - cycle > MAX_MCYCLE_LENGTH * context->opts->gen.clock_divider) {
156+		context->busack = 1;
157+	}
158+}
159+
160+void z80_clear_busreq(z80_context * context, uint32_t cycle)
161+{
162+	z80_run(context, cycle);
163+	context->busreq = 0;
164+	context->busack = 0;
165+	//there appears to be at least a 1 Z80 cycle delay between busreq
166+	//being released and resumption of execution
167+	context->cycles += context->opts->gen.clock_divider;
168+}
169+
170+void z80_assert_nmi(z80_context *context, uint32_t cycle)
171+{
172+	context->nmi_cycle = cycle;
173+}
174+
175+uint8_t z80_get_busack(z80_context * context, uint32_t cycle)
176+{
177+	z80_run(context, cycle);
178+	return context->busack;
179+}
180+
181+void z80_invalidate_code_range(z80_context *context, uint32_t startA, uint32_t endA)
182+{
183+	for(startA &= ~0x3FF; startA < endA; startA += 1024)
184+	{
185+		uint8_t *start = get_native_pointer(startA, (void**)context->mem_pointers, &context->opts->gen);
186+		if (start) {
187+			uint8_t *end = get_native_pointer(startA + 1023, (void**)context->mem_pointers, &context->opts->gen);
188+			if (!end || end - start != 1023) {
189+				start = NULL;
190+			}
191+		}
192+		context->fastread[startA >> 10] = start;
193+		start = get_native_write_pointer(startA, (void**)context->mem_pointers, &context->opts->gen);
194+		if (start) {
195+			uint8_t *end = get_native_write_pointer(startA + 1023, (void**)context->mem_pointers, &context->opts->gen);
196+			if (!end || end - start != 1023) {
197+				start = NULL;
198+			}
199+		}
200+		context->fastwrite[startA >> 10] = start;
201+	}
202+}
203+
204+void z80_adjust_cycles(z80_context * context, uint32_t deduction)
205+{
206+	context->cycles -= deduction;
207+	if (context->int_cycle != 0xFFFFFFFFU) {
208+		if (context->int_cycle > deduction) {
209+			context->int_cycle -= deduction;
210+		} else {
211+			context->int_cycle = 0;
212+		}
213+	}
214+	if (context->int_end_cycle != 0xFFFFFFFFU) {
215+		if (context->int_end_cycle > deduction) {
216+			context->int_end_cycle -= deduction;
217+		} else {
218+			context->int_end_cycle = 0;
219+		}
220+	}
221+	if (context->nmi_cycle != 0xFFFFFFFFU) {
222+		if (context->nmi_cycle > deduction) {
223+			context->nmi_cycle -= deduction;
224+		} else {
225+			context->nmi_cycle = 0;
226+		}
227+	}
228+}
229+
230+void z80_serialize(z80_context *context, serialize_buffer *buf)
231+{
232+	save_int8(buf, context->main[1]);//C
233+	save_int8(buf, context->main[0]);//B
234+	save_int8(buf, context->main[3]);//E
235+	save_int8(buf, context->main[2]);//D
236+	save_int8(buf, context->main[5]);//L
237+	save_int8(buf, context->main[4]);//H
238+	save_int8(buf, context->ix);//IXL
239+	save_int8(buf, context->ix >> 8);//IXH
240+	save_int8(buf, context->iy);//IYL
241+	save_int8(buf, context->iy >> 8);//IYH
242+	save_int8(buf, context->i);
243+	save_int8(buf, (context->rhigh & 0x80) | (context->r & 0x7F));
244+	save_int8(buf, context->main[7]);//A
245+	uint8_t f = context->last_flag_result & 0xA8
246+		| (context->zflag ? 0x40 : 0)
247+		| (context->chflags & 8 ? 0x10 : 0)
248+		| (context->pvflag ? 4 : 0)
249+		| (context->nflag ? 2 : 0)
250+		| (context->chflags & 0x80 ? 1 : 0);
251+	save_int8(buf, f);
252+	save_int8(buf, context->alt[1]);//C
253+	save_int8(buf, context->alt[0]);//B
254+	save_int8(buf, context->alt[3]);//E
255+	save_int8(buf, context->alt[2]);//D
256+	save_int8(buf, context->alt[5]);//L
257+	save_int8(buf, context->alt[4]);//H
258+	save_int8(buf, 0);//non-existant alt ixl
259+	save_int8(buf, 0);//non-existant alt ixh
260+	save_int8(buf, 0);//non-existant alt iyl
261+	save_int8(buf, 0);//non-existant alt iyh
262+	save_int8(buf, 0);//non-existant alt i
263+	save_int8(buf, 0);//non-existant alt r
264+	save_int8(buf, context->alt[7]);//A
265+	save_int8(buf, context->alt[6]);//F
266+	
267+	save_int16(buf, context->pc);
268+	save_int16(buf, context->sp);
269+	save_int8(buf, context->imode);
270+	save_int8(buf, context->iff1);
271+	save_int8(buf, context->iff2);
272+	uint8_t is_nmi = context->nmi_cycle != 0xFFFFFFFF && (context->nmi_cycle < context->int_cycle || !context->iff1);
273+	save_int8(buf,  is_nmi);//int_is_nmi
274+	save_int8(buf, context->busack);
275+	save_int32(buf, context->cycles);
276+	save_int32(buf, is_nmi ? context->nmi_cycle : context->int_cycle);//int_cycle
277+	save_int32(buf, 0);//int_enable_cycle
278+	save_int32(buf, context->int_cycle);
279+	save_int32(buf, context->int_end_cycle);
280+	save_int32(buf, context->nmi_cycle);
281+}
282+
283+void z80_deserialize(deserialize_buffer *buf, void *vcontext)
284+{
285+	z80_context *context = vcontext;
286+	context->main[1] = load_int8(buf);//C
287+	context->main[0] = load_int8(buf);//B
288+	context->main[3] = load_int8(buf);//E
289+	context->main[2] = load_int8(buf);//D
290+	context->main[5] = load_int8(buf);//L
291+	context->main[4] = load_int8(buf);//H
292+	context->ix = load_int8(buf);//IXL
293+	context->ix |= load_int8(buf) << 8;//IXH
294+	context->iy = load_int8(buf);//IYL
295+	context->iy |= load_int8(buf) << 8;//IYH
296+	context->i = load_int8(buf);
297+	context->r = load_int8(buf);
298+	context->rhigh = context->r & 0x80;
299+	context->main[7] = load_int8(buf);//A
300+	context->last_flag_result = load_int8(buf);
301+	context->zflag = context->last_flag_result & 0x40;
302+	context->chflags = context->last_flag_result & 0x10 ? 8 : 0;
303+	context->pvflag = context->last_flag_result & 4;
304+	context->nflag = context->last_flag_result & 2;
305+	context->chflags |= context->last_flag_result & 1 ? 0x80 : 0;
306+	context->alt[1] = load_int8(buf);//C
307+	context->alt[0] = load_int8(buf);//B
308+	context->alt[3] = load_int8(buf);//E
309+	context->alt[2] = load_int8(buf);//D
310+	context->alt[5] = load_int8(buf);//L
311+	context->alt[4] = load_int8(buf);//H
312+	load_int8(buf);//non-existant alt ixl
313+	load_int8(buf);//non-existant alt ixh
314+	load_int8(buf);//non-existant alt iyl
315+	load_int8(buf);//non-existant alt iyh
316+	load_int8(buf);//non-existant alt i
317+	load_int8(buf);//non-existant alt r
318+	context->alt[7] = load_int8(buf);//A
319+	context->alt[6] = load_int8(buf);//F
320+	
321+	context->pc = load_int16(buf);
322+	context->sp = load_int16(buf);
323+	context->imode = load_int8(buf);
324+	context->iff1 = load_int8(buf);
325+	context->iff2 = load_int8(buf);
326+	load_int8(buf);//int_is_nmi
327+	context->busack = load_int8(buf);
328+	context->cycles = load_int32(buf);
329+	load_int32(buf);//int_cycle
330+	load_int32(buf);//int_enable_cycle
331+	context->int_cycle = load_int32(buf);
332+	context->int_end_cycle = load_int32(buf);
333+	context->nmi_cycle = load_int32(buf);
334+}
335+
336+void zinsert_breakpoint(z80_context * context, uint16_t address, uint8_t * bp_handler)
337+{
338+}
339+
340+void zremove_breakpoint(z80_context * context, uint16_t address)
341+{
342+}
+1577, -0
   1@@ -0,0 +1,1577 @@
   2+/*
   3+ Copyright 2013 Michael Pavone
   4+ This file is part of BlastEm.
   5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
   6+*/
   7+#include "z80inst.h"
   8+#include <string.h>
   9+#include <stdio.h>
  10+#include <stddef.h>
  11+
  12+#define NOP {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}
  13+#define USE_MAIN {Z80_USE_MAIN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}
  14+
  15+z80inst z80_tbl_a[256] = {
  16+	//0
  17+	NOP,
  18+	{Z80_LD, Z80_BC, Z80_IMMED, Z80_UNUSED, 0},
  19+	{Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_BC, 0},
  20+	{Z80_INC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0},
  21+	{Z80_INC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0},
  22+	{Z80_DEC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0},
  23+	{Z80_LD, Z80_B, Z80_IMMED, Z80_UNUSED, 0},
  24+	{Z80_RLC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  25+	{Z80_EX, Z80_AF, Z80_REG, Z80_AF, 0},
  26+	{Z80_ADD, Z80_HL, Z80_REG, Z80_BC, 0},
  27+	{Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_BC, 0},
  28+	{Z80_DEC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0},
  29+	{Z80_INC, Z80_C, Z80_UNUSED, Z80_UNUSED, 0},
  30+	{Z80_DEC, Z80_C, Z80_UNUSED, Z80_UNUSED, 0},
  31+	{Z80_LD, Z80_C, Z80_IMMED, Z80_UNUSED, 0},
  32+	{Z80_RRC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  33+	//1
  34+	{Z80_DJNZ, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
  35+	{Z80_LD, Z80_DE, Z80_IMMED, Z80_UNUSED, 0},
  36+	{Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_DE, 0},
  37+	{Z80_INC, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0},
  38+	{Z80_INC, Z80_D, Z80_UNUSED, Z80_UNUSED, 0},
  39+	{Z80_DEC, Z80_D, Z80_UNUSED, Z80_UNUSED, 0},
  40+	{Z80_LD, Z80_D, Z80_IMMED, Z80_UNUSED, 0},
  41+	{Z80_RL, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  42+	{Z80_JR, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
  43+	{Z80_ADD, Z80_HL, Z80_REG, Z80_DE, 0},
  44+	{Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_DE, 0},
  45+	{Z80_DEC, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0},
  46+	{Z80_INC, Z80_E, Z80_UNUSED, Z80_UNUSED, 0},
  47+	{Z80_DEC, Z80_E, Z80_UNUSED, Z80_UNUSED, 0},
  48+	{Z80_LD, Z80_E, Z80_IMMED, Z80_UNUSED, 0},
  49+	{Z80_RR, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  50+	//2
  51+	{Z80_JRCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0},
  52+	{Z80_LD, Z80_HL, Z80_IMMED, Z80_UNUSED, 0},
  53+	{Z80_LD, Z80_HL, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
  54+	{Z80_INC, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0},
  55+	{Z80_INC, Z80_H, Z80_UNUSED, Z80_UNUSED, 0},
  56+	{Z80_DEC, Z80_H, Z80_UNUSED, Z80_UNUSED, 0},
  57+	{Z80_LD, Z80_H, Z80_IMMED, Z80_UNUSED, 0},
  58+	{Z80_DAA, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
  59+	{Z80_JRCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0},
  60+	{Z80_ADD, Z80_HL, Z80_REG, Z80_HL, 0},
  61+	{Z80_LD, Z80_HL, Z80_IMMED_INDIRECT, Z80_IMMED, 0},
  62+	{Z80_DEC, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0},
  63+	{Z80_INC, Z80_L, Z80_UNUSED, Z80_UNUSED, 0},
  64+	{Z80_DEC, Z80_L, Z80_UNUSED, Z80_UNUSED, 0},
  65+	{Z80_LD, Z80_L, Z80_IMMED, Z80_UNUSED, 0},
  66+	{Z80_CPL, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
  67+	//3
  68+	{Z80_JRCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0},
  69+	{Z80_LD, Z80_SP, Z80_IMMED, Z80_UNUSED, 0},
  70+	{Z80_LD, Z80_A, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
  71+	{Z80_INC, Z80_SP, Z80_UNUSED, Z80_UNUSED, 0},
  72+	{Z80_INC, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0},
  73+	{Z80_DEC, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0},
  74+	{Z80_LD, Z80_USE_IMMED, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
  75+	{Z80_SCF, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
  76+	{Z80_JRCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0},
  77+	{Z80_ADD, Z80_HL, Z80_REG, Z80_SP, 0},
  78+	{Z80_LD, Z80_A, Z80_IMMED_INDIRECT, Z80_IMMED, 0},
  79+	{Z80_DEC, Z80_SP, Z80_UNUSED, Z80_UNUSED, 0},
  80+	{Z80_INC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  81+	{Z80_DEC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
  82+	{Z80_LD, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
  83+	{Z80_CCF, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
  84+	//4
  85+	{Z80_LD, Z80_B, Z80_REG, Z80_B, 0},
  86+	{Z80_LD, Z80_B, Z80_REG, Z80_C, 0},
  87+	{Z80_LD, Z80_B, Z80_REG, Z80_D, 0},
  88+	{Z80_LD, Z80_B, Z80_REG, Z80_E, 0},
  89+	{Z80_LD, Z80_B, Z80_REG, Z80_H, 0},
  90+	{Z80_LD, Z80_B, Z80_REG, Z80_L, 0},
  91+	{Z80_LD, Z80_B, Z80_REG_INDIRECT, Z80_HL, 0},
  92+	{Z80_LD, Z80_B, Z80_REG, Z80_A, 0},
  93+	{Z80_LD, Z80_C, Z80_REG, Z80_B, 0},
  94+	{Z80_LD, Z80_C, Z80_REG, Z80_C, 0},
  95+	{Z80_LD, Z80_C, Z80_REG, Z80_D, 0},
  96+	{Z80_LD, Z80_C, Z80_REG, Z80_E, 0},
  97+	{Z80_LD, Z80_C, Z80_REG, Z80_H, 0},
  98+	{Z80_LD, Z80_C, Z80_REG, Z80_L, 0},
  99+	{Z80_LD, Z80_C, Z80_REG_INDIRECT, Z80_HL, 0},
 100+	{Z80_LD, Z80_C, Z80_REG, Z80_A, 0},
 101+	//5
 102+	{Z80_LD, Z80_D, Z80_REG, Z80_B, 0},
 103+	{Z80_LD, Z80_D, Z80_REG, Z80_C, 0},
 104+	{Z80_LD, Z80_D, Z80_REG, Z80_D, 0},
 105+	{Z80_LD, Z80_D, Z80_REG, Z80_E, 0},
 106+	{Z80_LD, Z80_D, Z80_REG, Z80_H, 0},
 107+	{Z80_LD, Z80_D, Z80_REG, Z80_L, 0},
 108+	{Z80_LD, Z80_D, Z80_REG_INDIRECT, Z80_HL, 0},
 109+	{Z80_LD, Z80_D, Z80_REG, Z80_A, 0},
 110+	{Z80_LD, Z80_E, Z80_REG, Z80_B, 0},
 111+	{Z80_LD, Z80_E, Z80_REG, Z80_C, 0},
 112+	{Z80_LD, Z80_E, Z80_REG, Z80_D, 0},
 113+	{Z80_LD, Z80_E, Z80_REG, Z80_E, 0},
 114+	{Z80_LD, Z80_E, Z80_REG, Z80_H, 0},
 115+	{Z80_LD, Z80_E, Z80_REG, Z80_L, 0},
 116+	{Z80_LD, Z80_E, Z80_REG_INDIRECT, Z80_HL, 0},
 117+	{Z80_LD, Z80_E, Z80_REG, Z80_A, 0},
 118+	//6
 119+	{Z80_LD, Z80_H, Z80_REG, Z80_B, 0},
 120+	{Z80_LD, Z80_H, Z80_REG, Z80_C, 0},
 121+	{Z80_LD, Z80_H, Z80_REG, Z80_D, 0},
 122+	{Z80_LD, Z80_H, Z80_REG, Z80_E, 0},
 123+	{Z80_LD, Z80_H, Z80_REG, Z80_H, 0},
 124+	{Z80_LD, Z80_H, Z80_REG, Z80_L, 0},
 125+	{Z80_LD, Z80_H, Z80_REG_INDIRECT, Z80_HL, 0},
 126+	{Z80_LD, Z80_H, Z80_REG, Z80_A, 0},
 127+	{Z80_LD, Z80_L, Z80_REG, Z80_B, 0},
 128+	{Z80_LD, Z80_L, Z80_REG, Z80_C, 0},
 129+	{Z80_LD, Z80_L, Z80_REG, Z80_D, 0},
 130+	{Z80_LD, Z80_L, Z80_REG, Z80_E, 0},
 131+	{Z80_LD, Z80_L, Z80_REG, Z80_H, 0},
 132+	{Z80_LD, Z80_L, Z80_REG, Z80_L, 0},
 133+	{Z80_LD, Z80_L, Z80_REG_INDIRECT, Z80_HL, 0},
 134+	{Z80_LD, Z80_L, Z80_REG, Z80_A, 0},
 135+	//7
 136+	{Z80_LD, Z80_B, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 137+	{Z80_LD, Z80_C, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 138+	{Z80_LD, Z80_D, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 139+	{Z80_LD, Z80_E, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 140+	{Z80_LD, Z80_H, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 141+	{Z80_LD, Z80_L, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 142+	{Z80_HALT, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 143+	{Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0},
 144+	{Z80_LD, Z80_A, Z80_REG, Z80_B, 0},
 145+	{Z80_LD, Z80_A, Z80_REG, Z80_C, 0},
 146+	{Z80_LD, Z80_A, Z80_REG, Z80_D, 0},
 147+	{Z80_LD, Z80_A, Z80_REG, Z80_E, 0},
 148+	{Z80_LD, Z80_A, Z80_REG, Z80_H, 0},
 149+	{Z80_LD, Z80_A, Z80_REG, Z80_L, 0},
 150+	{Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 151+	{Z80_LD, Z80_A, Z80_REG, Z80_A, 0},
 152+	//8
 153+	{Z80_ADD, Z80_A, Z80_REG, Z80_B, 0},
 154+	{Z80_ADD, Z80_A, Z80_REG, Z80_C, 0},
 155+	{Z80_ADD, Z80_A, Z80_REG, Z80_D, 0},
 156+	{Z80_ADD, Z80_A, Z80_REG, Z80_E, 0},
 157+	{Z80_ADD, Z80_A, Z80_REG, Z80_H, 0},
 158+	{Z80_ADD, Z80_A, Z80_REG, Z80_L, 0},
 159+	{Z80_ADD, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 160+	{Z80_ADD, Z80_A, Z80_REG, Z80_A, 0},
 161+	{Z80_ADC, Z80_A, Z80_REG, Z80_B, 0},
 162+	{Z80_ADC, Z80_A, Z80_REG, Z80_C, 0},
 163+	{Z80_ADC, Z80_A, Z80_REG, Z80_D, 0},
 164+	{Z80_ADC, Z80_A, Z80_REG, Z80_E, 0},
 165+	{Z80_ADC, Z80_A, Z80_REG, Z80_H, 0},
 166+	{Z80_ADC, Z80_A, Z80_REG, Z80_L, 0},
 167+	{Z80_ADC, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 168+	{Z80_ADC, Z80_A, Z80_REG, Z80_A, 0},
 169+	//9
 170+	{Z80_SUB, Z80_A, Z80_REG, Z80_B, 0},
 171+	{Z80_SUB, Z80_A, Z80_REG, Z80_C, 0},
 172+	{Z80_SUB, Z80_A, Z80_REG, Z80_D, 0},
 173+	{Z80_SUB, Z80_A, Z80_REG, Z80_E, 0},
 174+	{Z80_SUB, Z80_A, Z80_REG, Z80_H, 0},
 175+	{Z80_SUB, Z80_A, Z80_REG, Z80_L, 0},
 176+	{Z80_SUB, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 177+	{Z80_SUB, Z80_A, Z80_REG, Z80_A, 0},
 178+	{Z80_SBC, Z80_A, Z80_REG, Z80_B, 0},
 179+	{Z80_SBC, Z80_A, Z80_REG, Z80_C, 0},
 180+	{Z80_SBC, Z80_A, Z80_REG, Z80_D, 0},
 181+	{Z80_SBC, Z80_A, Z80_REG, Z80_E, 0},
 182+	{Z80_SBC, Z80_A, Z80_REG, Z80_H, 0},
 183+	{Z80_SBC, Z80_A, Z80_REG, Z80_L, 0},
 184+	{Z80_SBC, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 185+	{Z80_SBC, Z80_A, Z80_REG, Z80_A, 0},
 186+	//A
 187+	{Z80_AND, Z80_A, Z80_REG, Z80_B, 0},
 188+	{Z80_AND, Z80_A, Z80_REG, Z80_C, 0},
 189+	{Z80_AND, Z80_A, Z80_REG, Z80_D, 0},
 190+	{Z80_AND, Z80_A, Z80_REG, Z80_E, 0},
 191+	{Z80_AND, Z80_A, Z80_REG, Z80_H, 0},
 192+	{Z80_AND, Z80_A, Z80_REG, Z80_L, 0},
 193+	{Z80_AND, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 194+	{Z80_AND, Z80_A, Z80_REG, Z80_A, 0},
 195+	{Z80_XOR, Z80_A, Z80_REG, Z80_B, 0},
 196+	{Z80_XOR, Z80_A, Z80_REG, Z80_C, 0},
 197+	{Z80_XOR, Z80_A, Z80_REG, Z80_D, 0},
 198+	{Z80_XOR, Z80_A, Z80_REG, Z80_E, 0},
 199+	{Z80_XOR, Z80_A, Z80_REG, Z80_H, 0},
 200+	{Z80_XOR, Z80_A, Z80_REG, Z80_L, 0},
 201+	{Z80_XOR, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 202+	{Z80_XOR, Z80_A, Z80_REG, Z80_A, 0},
 203+	//B
 204+	{Z80_OR, Z80_A, Z80_REG, Z80_B, 0},
 205+	{Z80_OR, Z80_A, Z80_REG, Z80_C, 0},
 206+	{Z80_OR, Z80_A, Z80_REG, Z80_D, 0},
 207+	{Z80_OR, Z80_A, Z80_REG, Z80_E, 0},
 208+	{Z80_OR, Z80_A, Z80_REG, Z80_H, 0},
 209+	{Z80_OR, Z80_A, Z80_REG, Z80_L, 0},
 210+	{Z80_OR, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 211+	{Z80_OR, Z80_A, Z80_REG, Z80_A, 0},
 212+	{Z80_CP, Z80_A, Z80_REG, Z80_B, 0},
 213+	{Z80_CP, Z80_A, Z80_REG, Z80_C, 0},
 214+	{Z80_CP, Z80_A, Z80_REG, Z80_D, 0},
 215+	{Z80_CP, Z80_A, Z80_REG, Z80_E, 0},
 216+	{Z80_CP, Z80_A, Z80_REG, Z80_H, 0},
 217+	{Z80_CP, Z80_A, Z80_REG, Z80_L, 0},
 218+	{Z80_CP, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0},
 219+	{Z80_CP, Z80_A, Z80_REG, Z80_A, 0},
 220+	//C
 221+	{Z80_RETCC, Z80_CC_NZ, Z80_UNUSED, Z80_UNUSED, 0},
 222+	{Z80_POP, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0},
 223+	{Z80_JPCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0},
 224+	{Z80_JP, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
 225+	{Z80_CALLCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0},
 226+	{Z80_PUSH, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0},
 227+	{Z80_ADD, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 228+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x0},
 229+	{Z80_RETCC, Z80_CC_Z, Z80_UNUSED, Z80_UNUSED, 0},
 230+	{Z80_RET, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 231+	{Z80_JPCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0},
 232+	{0, 0, 0, 0, 0},//BITS Prefix
 233+	{Z80_CALLCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0},
 234+	{Z80_CALL, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
 235+	{Z80_ADC, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 236+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x8},
 237+	//D
 238+	{Z80_RETCC, Z80_CC_NC, Z80_UNUSED, Z80_UNUSED, 0},
 239+	{Z80_POP, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0},
 240+	{Z80_JPCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0},
 241+	{Z80_OUT, Z80_A, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 242+	{Z80_CALLCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0},
 243+	{Z80_PUSH, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0},
 244+	{Z80_SUB, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 245+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x10},
 246+	{Z80_RETCC, Z80_CC_C, Z80_UNUSED, Z80_UNUSED, 0},
 247+	{Z80_EXX, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 248+	{Z80_JPCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0},
 249+	{Z80_IN, Z80_A, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 250+	{Z80_CALLCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0},
 251+	{0, 0, 0, 0, 0},//IX Prefix
 252+	{Z80_SBC, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 253+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x18},
 254+	//E
 255+	{Z80_RETCC, Z80_CC_PO, Z80_UNUSED, Z80_UNUSED, 0},
 256+	{Z80_POP, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0},
 257+	{Z80_JPCC, Z80_CC_PO, Z80_IMMED, Z80_UNUSED, 0},
 258+	{Z80_EX, Z80_HL, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0},
 259+	{Z80_CALLCC, Z80_CC_PO, Z80_IMMED, Z80_UNUSED, 0},
 260+	{Z80_PUSH, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0},
 261+	{Z80_AND, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 262+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x20},
 263+	{Z80_RETCC, Z80_CC_PE, Z80_UNUSED, Z80_UNUSED, 0},
 264+	{Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0},
 265+	{Z80_JPCC, Z80_CC_PE, Z80_IMMED, Z80_UNUSED, 0},
 266+	{Z80_EX, Z80_DE, Z80_REG, Z80_HL, 0},
 267+	{Z80_CALLCC, Z80_CC_PE, Z80_IMMED, Z80_UNUSED, 0},
 268+	{0, 0, 0, 0, 0},//EXTD Prefix
 269+	{Z80_XOR, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 270+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x28},
 271+	//F
 272+	{Z80_RETCC, Z80_CC_P, Z80_UNUSED, Z80_UNUSED, 0},
 273+	{Z80_POP, Z80_AF, Z80_UNUSED, Z80_UNUSED, 0},
 274+	{Z80_JPCC, Z80_CC_P, Z80_IMMED, Z80_UNUSED, 0},
 275+	{Z80_DI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 276+	{Z80_CALLCC, Z80_CC_P, Z80_IMMED, Z80_UNUSED, 0},
 277+	{Z80_PUSH, Z80_AF, Z80_UNUSED, Z80_UNUSED, 0},
 278+	{Z80_OR, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 279+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x30},
 280+	{Z80_RETCC, Z80_CC_M, Z80_UNUSED, Z80_UNUSED, 0},
 281+	{Z80_LD, Z80_SP, Z80_REG, Z80_HL, 0},
 282+	{Z80_JPCC, Z80_CC_M, Z80_IMMED, Z80_UNUSED, 0},
 283+	{Z80_EI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 284+	{Z80_CALLCC, Z80_CC_M, Z80_IMMED, Z80_UNUSED, 0},
 285+	{0, 0, 0, 0, 0},//IY Prefix
 286+	{Z80_CP, Z80_A, Z80_IMMED, Z80_UNUSED, 0},
 287+	{Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x38}
 288+};
 289+
 290+z80inst z80_tbl_extd[0xC0-0x40] = {
 291+	//4
 292+	{Z80_IN, Z80_B, Z80_REG_INDIRECT, Z80_C, 0},
 293+	{Z80_OUT, Z80_B, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 294+	{Z80_SBC, Z80_HL, Z80_REG, Z80_BC, 0},
 295+	{Z80_LD, Z80_BC, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 296+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 297+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 298+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
 299+	{Z80_LD, Z80_I, Z80_REG, Z80_A, 0},
 300+	{Z80_IN, Z80_C, Z80_REG_INDIRECT, Z80_C, 0},
 301+	{Z80_OUT, Z80_C, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 302+	{Z80_ADC, Z80_HL, Z80_REG, Z80_BC, 0},
 303+	{Z80_LD, Z80_BC, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 304+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 305+	{Z80_RETI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 306+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 3},//Set undocumented mode 0/1
 307+	{Z80_LD, Z80_R, Z80_REG, Z80_A, 0},
 308+	//5
 309+	{Z80_IN, Z80_D, Z80_REG_INDIRECT, Z80_C, 0},
 310+	{Z80_OUT, Z80_D, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 311+	{Z80_SBC, Z80_HL, Z80_REG, Z80_DE, 0},
 312+	{Z80_LD, Z80_DE, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 313+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 314+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 315+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 1},
 316+	{Z80_LD, Z80_A, Z80_REG, Z80_I, 0},
 317+	{Z80_IN, Z80_E, Z80_REG_INDIRECT, Z80_C, 0},
 318+	{Z80_OUT, Z80_E, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 319+	{Z80_ADC, Z80_HL, Z80_REG, Z80_DE, 0},
 320+	{Z80_LD, Z80_DE, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 321+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 322+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 323+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 2},
 324+	{Z80_LD, Z80_A, Z80_REG, Z80_R, 0},
 325+	//6
 326+	{Z80_IN, Z80_H, Z80_REG_INDIRECT, Z80_C, 0},
 327+	{Z80_OUT, Z80_H, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 328+	{Z80_SBC, Z80_HL, Z80_REG, Z80_HL, 0},
 329+	{Z80_LD, Z80_HL, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 330+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 331+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 332+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0},
 333+	{Z80_RRD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 334+	{Z80_IN, Z80_L, Z80_REG_INDIRECT, Z80_C, 0},
 335+	{Z80_OUT, Z80_L, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 336+	{Z80_ADC, Z80_HL, Z80_REG, Z80_HL, 0},
 337+	{Z80_LD, Z80_HL, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 338+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 339+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 340+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 3},//Set undocumented mode 0/1
 341+	{Z80_RLD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 342+	//7
 343+	{Z80_IN, Z80_UNUSED, Z80_REG_INDIRECT, Z80_C, 0},
 344+	{Z80_OUT, Z80_USE_IMMED, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 345+	{Z80_SBC, Z80_HL, Z80_REG, Z80_SP, 0},
 346+	{Z80_LD, Z80_SP, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 347+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 348+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 349+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 1},
 350+	NOP,
 351+	{Z80_IN, Z80_A, Z80_REG_INDIRECT, Z80_C, 0},
 352+	{Z80_OUT, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0},
 353+	{Z80_ADC, Z80_HL, Z80_REG, Z80_SP, 0},
 354+	{Z80_LD, Z80_SP, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 355+	{Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0},
 356+	{Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 357+	{Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 2},
 358+	NOP,
 359+	//8
 360+	NOP,
 361+	NOP,
 362+	NOP,
 363+	NOP,
 364+	NOP,
 365+	NOP,
 366+	NOP,
 367+	NOP,
 368+	NOP,
 369+	NOP,
 370+	NOP,
 371+	NOP,
 372+	NOP,
 373+	NOP,
 374+	NOP,
 375+	NOP,
 376+	//9
 377+	NOP,
 378+	NOP,
 379+	NOP,
 380+	NOP,
 381+	NOP,
 382+	NOP,
 383+	NOP,
 384+	NOP,
 385+	NOP,
 386+	NOP,
 387+	NOP,
 388+	NOP,
 389+	NOP,
 390+	NOP,
 391+	NOP,
 392+	NOP,
 393+	//A
 394+	{Z80_LDI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 395+	{Z80_CPI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 396+	{Z80_INI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 397+	{Z80_OUTI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 398+	NOP,
 399+	NOP,
 400+	NOP,
 401+	NOP,
 402+	{Z80_LDD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 403+	{Z80_CPD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 404+	{Z80_IND, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 405+	{Z80_OUTD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 406+	NOP,
 407+	NOP,
 408+	NOP,
 409+	NOP,
 410+	//B
 411+	{Z80_LDIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 412+	{Z80_CPIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 413+	{Z80_INIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 414+	{Z80_OTIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 415+	NOP,
 416+	NOP,
 417+	NOP,
 418+	NOP,
 419+	{Z80_LDDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 420+	{Z80_CPDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 421+	{Z80_INDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 422+	{Z80_OTDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0},
 423+	NOP,
 424+	NOP,
 425+	NOP,
 426+	NOP
 427+};
 428+
 429+#define SHIFT_BLOCK(op) \
 430+	{op, Z80_B, Z80_UNUSED, Z80_UNUSED, 1},\
 431+	{op, Z80_C, Z80_UNUSED, Z80_UNUSED, 1},\
 432+	{op, Z80_D, Z80_UNUSED, Z80_UNUSED, 1},\
 433+	{op, Z80_E, Z80_UNUSED, Z80_UNUSED, 1},\
 434+	{op, Z80_H, Z80_UNUSED, Z80_UNUSED, 1},\
 435+	{op, Z80_L, Z80_UNUSED, Z80_UNUSED, 1},\
 436+	{op, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 1},\
 437+	{op, Z80_A, Z80_UNUSED, Z80_UNUSED, 1}
 438+
 439+#define BIT_BLOCK(op, bit) \
 440+	{op, Z80_USE_IMMED, Z80_REG, Z80_B, bit},\
 441+	{op, Z80_USE_IMMED, Z80_REG, Z80_C, bit},\
 442+	{op, Z80_USE_IMMED, Z80_REG, Z80_D, bit},\
 443+	{op, Z80_USE_IMMED, Z80_REG, Z80_E, bit},\
 444+	{op, Z80_USE_IMMED, Z80_REG, Z80_H, bit},\
 445+	{op, Z80_USE_IMMED, Z80_REG, Z80_L, bit},\
 446+	{op, Z80_USE_IMMED, Z80_REG_INDIRECT, Z80_HL, bit},\
 447+	{op, Z80_USE_IMMED, Z80_REG, Z80_A, bit}
 448+
 449+z80inst z80_tbl_bit[256] = {
 450+	//0
 451+	SHIFT_BLOCK(Z80_RLC),
 452+	SHIFT_BLOCK(Z80_RRC),
 453+	//1
 454+	SHIFT_BLOCK(Z80_RL),
 455+	SHIFT_BLOCK(Z80_RR),
 456+	//2
 457+	SHIFT_BLOCK(Z80_SLA),
 458+	SHIFT_BLOCK(Z80_SRA),
 459+	//3
 460+	SHIFT_BLOCK(Z80_SLL),
 461+	SHIFT_BLOCK(Z80_SRL),
 462+	//4
 463+	BIT_BLOCK(Z80_BIT, 0),
 464+	BIT_BLOCK(Z80_BIT, 1),
 465+	//5
 466+	BIT_BLOCK(Z80_BIT, 2),
 467+	BIT_BLOCK(Z80_BIT, 3),
 468+	//6
 469+	BIT_BLOCK(Z80_BIT, 4),
 470+	BIT_BLOCK(Z80_BIT, 5),
 471+	//7
 472+	BIT_BLOCK(Z80_BIT, 6),
 473+	BIT_BLOCK(Z80_BIT, 7),
 474+	//8
 475+	BIT_BLOCK(Z80_RES, 0),
 476+	BIT_BLOCK(Z80_RES, 1),
 477+	//9
 478+	BIT_BLOCK(Z80_RES, 2),
 479+	BIT_BLOCK(Z80_RES, 3),
 480+	//A
 481+	BIT_BLOCK(Z80_RES, 4),
 482+	BIT_BLOCK(Z80_RES, 5),
 483+	//B
 484+	BIT_BLOCK(Z80_RES, 6),
 485+	BIT_BLOCK(Z80_RES, 7),
 486+	//C
 487+	BIT_BLOCK(Z80_SET, 0),
 488+	BIT_BLOCK(Z80_SET, 1),
 489+	//D
 490+	BIT_BLOCK(Z80_SET, 2),
 491+	BIT_BLOCK(Z80_SET, 3),
 492+	//E
 493+	BIT_BLOCK(Z80_SET, 4),
 494+	BIT_BLOCK(Z80_SET, 5),
 495+	//F
 496+	BIT_BLOCK(Z80_SET, 6),
 497+	BIT_BLOCK(Z80_SET, 7)
 498+};
 499+
 500+z80inst z80_tbl_ix[256] = {
 501+	//0
 502+	USE_MAIN,
 503+	USE_MAIN,
 504+	USE_MAIN,
 505+	USE_MAIN,
 506+	USE_MAIN,
 507+	USE_MAIN,
 508+	USE_MAIN,
 509+	USE_MAIN,
 510+	USE_MAIN,
 511+	{Z80_ADD, Z80_IX, Z80_REG, Z80_BC, 0},
 512+	USE_MAIN,
 513+	USE_MAIN,
 514+	USE_MAIN,
 515+	USE_MAIN,
 516+	USE_MAIN,
 517+	USE_MAIN,
 518+	//1
 519+	USE_MAIN,
 520+	USE_MAIN,
 521+	USE_MAIN,
 522+	USE_MAIN,
 523+	USE_MAIN,
 524+	USE_MAIN,
 525+	USE_MAIN,
 526+	USE_MAIN,
 527+	USE_MAIN,
 528+	{Z80_ADD, Z80_IX, Z80_REG, Z80_DE, 0},
 529+	USE_MAIN,
 530+	USE_MAIN,
 531+	USE_MAIN,
 532+	USE_MAIN,
 533+	USE_MAIN,
 534+	USE_MAIN,
 535+	//2
 536+	USE_MAIN,
 537+	{Z80_LD, Z80_IX, Z80_IMMED, Z80_UNUSED, 0},
 538+	{Z80_LD, Z80_IX, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 539+	{Z80_INC, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0},
 540+	{Z80_INC, Z80_IXH, Z80_UNUSED, Z80_UNUSED, 0},
 541+	{Z80_DEC, Z80_IXH, Z80_UNUSED, Z80_UNUSED, 0},
 542+	{Z80_LD, Z80_IXH, Z80_IMMED, Z80_UNUSED, 0},
 543+	USE_MAIN,
 544+	USE_MAIN,
 545+	{Z80_ADD, Z80_IX, Z80_REG, Z80_IX, 0},
 546+	{Z80_LD, Z80_IX, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 547+	{Z80_DEC, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0},
 548+	{Z80_INC, Z80_IXL, Z80_UNUSED, Z80_UNUSED, 0},
 549+	{Z80_DEC, Z80_IXL, Z80_UNUSED, Z80_UNUSED, 0},
 550+	{Z80_LD, Z80_IXL, Z80_IMMED, Z80_UNUSED, 0},
 551+	USE_MAIN,
 552+	//3
 553+	USE_MAIN,
 554+	USE_MAIN,
 555+	USE_MAIN,
 556+	USE_MAIN,
 557+	{Z80_INC, Z80_UNUSED, Z80_IX_DISPLACE, 0, 0},
 558+	{Z80_DEC, Z80_UNUSED, Z80_IX_DISPLACE, 0, 0},
 559+	{Z80_LD, Z80_USE_IMMED, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 560+	USE_MAIN,
 561+	USE_MAIN,
 562+	{Z80_ADD, Z80_IX, Z80_REG, Z80_SP, 0},
 563+	USE_MAIN,
 564+	USE_MAIN,
 565+	USE_MAIN,
 566+	USE_MAIN,
 567+	USE_MAIN,
 568+	USE_MAIN,
 569+	//4
 570+	USE_MAIN,
 571+	USE_MAIN,
 572+	USE_MAIN,
 573+	USE_MAIN,
 574+	{Z80_LD, Z80_B, Z80_REG, Z80_IXH, 0},
 575+	{Z80_LD, Z80_B, Z80_REG, Z80_IXL, 0},
 576+	{Z80_LD, Z80_B, Z80_IX_DISPLACE, 0, 0},
 577+	USE_MAIN,
 578+	USE_MAIN,
 579+	USE_MAIN,
 580+	USE_MAIN,
 581+	USE_MAIN,
 582+	{Z80_LD, Z80_C, Z80_REG, Z80_IXH, 0},
 583+	{Z80_LD, Z80_C, Z80_REG, Z80_IXL, 0},
 584+	{Z80_LD, Z80_C, Z80_IX_DISPLACE, 0, 0},
 585+	USE_MAIN,
 586+	//5
 587+	USE_MAIN,
 588+	USE_MAIN,
 589+	USE_MAIN,
 590+	USE_MAIN,
 591+	{Z80_LD, Z80_D, Z80_REG, Z80_IXH, 0},
 592+	{Z80_LD, Z80_D, Z80_REG, Z80_IXL, 0},
 593+	{Z80_LD, Z80_D, Z80_IX_DISPLACE, 0, 0},
 594+	USE_MAIN,
 595+	USE_MAIN,
 596+	USE_MAIN,
 597+	USE_MAIN,
 598+	USE_MAIN,
 599+	{Z80_LD, Z80_E, Z80_REG, Z80_IXH, 0},
 600+	{Z80_LD, Z80_E, Z80_REG, Z80_IXL, 0},
 601+	{Z80_LD, Z80_E, Z80_IX_DISPLACE, 0, 0},
 602+	USE_MAIN,
 603+	//6
 604+	{Z80_LD, Z80_IXH, Z80_REG, Z80_B, 0},
 605+	{Z80_LD, Z80_IXH, Z80_REG, Z80_C, 0},
 606+	{Z80_LD, Z80_IXH, Z80_REG, Z80_D, 0},
 607+	{Z80_LD, Z80_IXH, Z80_REG, Z80_E, 0},
 608+	{Z80_LD, Z80_IXH, Z80_REG, Z80_IXH, 0},
 609+	{Z80_LD, Z80_IXH, Z80_REG, Z80_IXL, 0},
 610+	{Z80_LD, Z80_H, Z80_IX_DISPLACE, 0, 0},
 611+	{Z80_LD, Z80_IXH, Z80_REG, Z80_A, 0},
 612+	{Z80_LD, Z80_IXL, Z80_REG, Z80_B, 0},
 613+	{Z80_LD, Z80_IXL, Z80_REG, Z80_C, 0},
 614+	{Z80_LD, Z80_IXL, Z80_REG, Z80_D, 0},
 615+	{Z80_LD, Z80_IXL, Z80_REG, Z80_E, 0},
 616+	{Z80_LD, Z80_IXL, Z80_REG, Z80_IXH, 0},
 617+	{Z80_LD, Z80_IXL, Z80_REG, Z80_IXL, 0},
 618+	{Z80_LD, Z80_L, Z80_IX_DISPLACE, 0, 0},
 619+	{Z80_LD, Z80_IXL, Z80_REG, Z80_A, 0},
 620+	//7
 621+	{Z80_LD, Z80_B, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 622+	{Z80_LD, Z80_C, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 623+	{Z80_LD, Z80_D, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 624+	{Z80_LD, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 625+	{Z80_LD, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 626+	{Z80_LD, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 627+	USE_MAIN,
 628+	{Z80_LD, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, 0},
 629+	USE_MAIN,
 630+	USE_MAIN,
 631+	USE_MAIN,
 632+	USE_MAIN,
 633+	{Z80_LD, Z80_A, Z80_REG, Z80_IXH, 0},
 634+	{Z80_LD, Z80_A, Z80_REG, Z80_IXL, 0},
 635+	{Z80_LD, Z80_A, Z80_IX_DISPLACE, 0, 0},
 636+	USE_MAIN,
 637+	//8
 638+	USE_MAIN,
 639+	USE_MAIN,
 640+	USE_MAIN,
 641+	USE_MAIN,
 642+	{Z80_ADD, Z80_A, Z80_REG, Z80_IXH, 0},
 643+	{Z80_ADD, Z80_A, Z80_REG, Z80_IXL, 0},
 644+	{Z80_ADD, Z80_A, Z80_IX_DISPLACE, 0, 0},
 645+	USE_MAIN,
 646+	USE_MAIN,
 647+	USE_MAIN,
 648+	USE_MAIN,
 649+	USE_MAIN,
 650+	{Z80_ADC, Z80_A, Z80_REG, Z80_IXH, 0},
 651+	{Z80_ADC, Z80_A, Z80_REG, Z80_IXL, 0},
 652+	{Z80_ADC, Z80_A, Z80_IX_DISPLACE, 0, 0},
 653+	USE_MAIN,
 654+	//9
 655+	USE_MAIN,
 656+	USE_MAIN,
 657+	USE_MAIN,
 658+	USE_MAIN,
 659+	{Z80_SUB, Z80_A, Z80_REG, Z80_IXH, 0},
 660+	{Z80_SUB, Z80_A, Z80_REG, Z80_IXL, 0},
 661+	{Z80_SUB, Z80_A, Z80_IX_DISPLACE, 0, 0},
 662+	USE_MAIN,
 663+	USE_MAIN,
 664+	USE_MAIN,
 665+	USE_MAIN,
 666+	USE_MAIN,
 667+	{Z80_SBC, Z80_A, Z80_REG, Z80_IXH, 0},
 668+	{Z80_SBC, Z80_A, Z80_REG, Z80_IXL, 0},
 669+	{Z80_SBC, Z80_A, Z80_IX_DISPLACE, 0, 0},
 670+	USE_MAIN,
 671+	//A
 672+	USE_MAIN,
 673+	USE_MAIN,
 674+	USE_MAIN,
 675+	USE_MAIN,
 676+	{Z80_AND, Z80_A, Z80_REG, Z80_IXH, 0},
 677+	{Z80_AND, Z80_A, Z80_REG, Z80_IXL, 0},
 678+	{Z80_AND, Z80_A, Z80_IX_DISPLACE, 0, 0},
 679+	USE_MAIN,
 680+	USE_MAIN,
 681+	USE_MAIN,
 682+	USE_MAIN,
 683+	USE_MAIN,
 684+	{Z80_XOR, Z80_A, Z80_REG, Z80_IXH, 0},
 685+	{Z80_XOR, Z80_A, Z80_REG, Z80_IXL, 0},
 686+	{Z80_XOR, Z80_A, Z80_IX_DISPLACE, 0, 0},
 687+	USE_MAIN,
 688+	//B
 689+	USE_MAIN,
 690+	USE_MAIN,
 691+	USE_MAIN,
 692+	USE_MAIN,
 693+	{Z80_OR, Z80_A, Z80_REG, Z80_IXH, 0},
 694+	{Z80_OR, Z80_A, Z80_REG, Z80_IXL, 0},
 695+	{Z80_OR, Z80_A, Z80_IX_DISPLACE, 0, 0},
 696+	USE_MAIN,
 697+	USE_MAIN,
 698+	USE_MAIN,
 699+	USE_MAIN,
 700+	USE_MAIN,
 701+	{Z80_CP, Z80_A, Z80_REG, Z80_IXH, 0},
 702+	{Z80_CP, Z80_A, Z80_REG, Z80_IXL, 0},
 703+	{Z80_CP, Z80_A, Z80_IX_DISPLACE, 0, 0},
 704+	USE_MAIN,
 705+	//C
 706+	USE_MAIN,
 707+	USE_MAIN,
 708+	USE_MAIN,
 709+	USE_MAIN,
 710+	USE_MAIN,
 711+	USE_MAIN,
 712+	USE_MAIN,
 713+	USE_MAIN,
 714+	USE_MAIN,
 715+	USE_MAIN,
 716+	USE_MAIN,
 717+	USE_MAIN,
 718+	USE_MAIN,
 719+	USE_MAIN,
 720+	USE_MAIN,
 721+	USE_MAIN,
 722+	//D
 723+	USE_MAIN,
 724+	USE_MAIN,
 725+	USE_MAIN,
 726+	USE_MAIN,
 727+	USE_MAIN,
 728+	USE_MAIN,
 729+	USE_MAIN,
 730+	USE_MAIN,
 731+	USE_MAIN,
 732+	USE_MAIN,
 733+	USE_MAIN,
 734+	USE_MAIN,
 735+	USE_MAIN,
 736+	USE_MAIN,
 737+	USE_MAIN,
 738+	USE_MAIN,
 739+	//E
 740+	USE_MAIN,
 741+	{Z80_POP, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0},
 742+	USE_MAIN,
 743+	{Z80_EX, Z80_IX, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0},
 744+	USE_MAIN,
 745+	{Z80_PUSH, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0},
 746+	USE_MAIN,
 747+	USE_MAIN,
 748+	USE_MAIN,
 749+	{Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_IX, 0},
 750+	USE_MAIN,
 751+	USE_MAIN,
 752+	USE_MAIN,
 753+	USE_MAIN,
 754+	USE_MAIN,
 755+	USE_MAIN,
 756+	//F
 757+	USE_MAIN,
 758+	USE_MAIN,
 759+	USE_MAIN,
 760+	USE_MAIN,
 761+	USE_MAIN,
 762+	USE_MAIN,
 763+	USE_MAIN,
 764+	USE_MAIN,
 765+	USE_MAIN,
 766+	{Z80_LD, Z80_SP, Z80_REG, Z80_IX, 0},
 767+	USE_MAIN,
 768+	USE_MAIN,
 769+	USE_MAIN,
 770+	USE_MAIN,
 771+	USE_MAIN,
 772+	USE_MAIN
 773+};
 774+
 775+#define SHIFT_BLOCK_IX(op) \
 776+	{op, Z80_B, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 777+	{op, Z80_C, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 778+	{op, Z80_D, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 779+	{op, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 780+	{op, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 781+	{op, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 782+	{op, Z80_UNUSED, Z80_IX_DISPLACE | Z80_DIR, 0, 1},\
 783+	{op, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, 1}
 784+
 785+#define BIT_BLOCK_IX(bit) \
 786+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 787+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 788+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 789+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 790+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 791+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 792+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 793+	{Z80_BIT, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit}
 794+
 795+#define BIT_BLOCK_IX_REG(op, bit) \
 796+	{op, Z80_B, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 797+	{op, Z80_C, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 798+	{op, Z80_D, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 799+	{op, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 800+	{op, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 801+	{op, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, bit},\
 802+	{op, Z80_USE_IMMED, Z80_IX_DISPLACE, 0, bit},\
 803+	{op, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, bit}
 804+
 805+z80inst z80_tbl_ix_bit[256] = {
 806+	//0
 807+	SHIFT_BLOCK_IX(Z80_RLC),
 808+	SHIFT_BLOCK_IX(Z80_RRC),
 809+	//1
 810+	SHIFT_BLOCK_IX(Z80_RL),
 811+	SHIFT_BLOCK_IX(Z80_RR),
 812+	//2
 813+	SHIFT_BLOCK_IX(Z80_SLA),
 814+	SHIFT_BLOCK_IX(Z80_SRA),
 815+	//3
 816+	SHIFT_BLOCK_IX(Z80_SLL),
 817+	SHIFT_BLOCK_IX(Z80_SRL),
 818+	//4
 819+	BIT_BLOCK_IX(0),
 820+	BIT_BLOCK_IX(1),
 821+	//5
 822+	BIT_BLOCK_IX(2),
 823+	BIT_BLOCK_IX(3),
 824+	//6
 825+	BIT_BLOCK_IX(4),
 826+	BIT_BLOCK_IX(5),
 827+	//7
 828+	BIT_BLOCK_IX(6),
 829+	BIT_BLOCK_IX(7),
 830+	//8
 831+	BIT_BLOCK_IX_REG(Z80_RES, 0),
 832+	BIT_BLOCK_IX_REG(Z80_RES, 1),
 833+	//9
 834+	BIT_BLOCK_IX_REG(Z80_RES, 2),
 835+	BIT_BLOCK_IX_REG(Z80_RES, 3),
 836+	//A
 837+	BIT_BLOCK_IX_REG(Z80_RES, 4),
 838+	BIT_BLOCK_IX_REG(Z80_RES, 5),
 839+	//B
 840+	BIT_BLOCK_IX_REG(Z80_RES, 6),
 841+	BIT_BLOCK_IX_REG(Z80_RES, 7),
 842+	//C
 843+	BIT_BLOCK_IX_REG(Z80_SET, 0),
 844+	BIT_BLOCK_IX_REG(Z80_SET, 1),
 845+	//D
 846+	BIT_BLOCK_IX_REG(Z80_SET, 2),
 847+	BIT_BLOCK_IX_REG(Z80_SET, 3),
 848+	//E
 849+	BIT_BLOCK_IX_REG(Z80_SET, 4),
 850+	BIT_BLOCK_IX_REG(Z80_SET, 5),
 851+	//F
 852+	BIT_BLOCK_IX_REG(Z80_SET, 6),
 853+	BIT_BLOCK_IX_REG(Z80_SET, 7),
 854+};
 855+
 856+z80inst z80_tbl_iy[256] = {
 857+	//0
 858+	USE_MAIN,
 859+	USE_MAIN,
 860+	USE_MAIN,
 861+	USE_MAIN,
 862+	USE_MAIN,
 863+	USE_MAIN,
 864+	USE_MAIN,
 865+	USE_MAIN,
 866+	USE_MAIN,
 867+	{Z80_ADD, Z80_IY, Z80_REG, Z80_BC, 0},
 868+	USE_MAIN,
 869+	USE_MAIN,
 870+	USE_MAIN,
 871+	USE_MAIN,
 872+	USE_MAIN,
 873+	USE_MAIN,
 874+	//1
 875+	USE_MAIN,
 876+	USE_MAIN,
 877+	USE_MAIN,
 878+	USE_MAIN,
 879+	USE_MAIN,
 880+	USE_MAIN,
 881+	USE_MAIN,
 882+	USE_MAIN,
 883+	USE_MAIN,
 884+	{Z80_ADD, Z80_IY, Z80_REG, Z80_DE, 0},
 885+	USE_MAIN,
 886+	USE_MAIN,
 887+	USE_MAIN,
 888+	USE_MAIN,
 889+	USE_MAIN,
 890+	USE_MAIN,
 891+	//2
 892+	USE_MAIN,
 893+	{Z80_LD, Z80_IY, Z80_IMMED, Z80_UNUSED, 0},
 894+	{Z80_LD, Z80_IY, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0},
 895+	{Z80_INC, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0},
 896+	{Z80_INC, Z80_IYH, Z80_UNUSED, Z80_UNUSED, 0},
 897+	{Z80_DEC, Z80_IYH, Z80_UNUSED, Z80_UNUSED, 0},
 898+	{Z80_LD, Z80_IYH, Z80_IMMED, Z80_UNUSED, 0},
 899+	USE_MAIN,
 900+	USE_MAIN,
 901+	{Z80_ADD, Z80_IY, Z80_REG, Z80_IY, 0},
 902+	{Z80_LD, Z80_IY, Z80_IMMED_INDIRECT, Z80_UNUSED, 0},
 903+	{Z80_DEC, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0},
 904+	{Z80_INC, Z80_IYL, Z80_UNUSED, Z80_UNUSED, 0},
 905+	{Z80_DEC, Z80_IYL, Z80_UNUSED, Z80_UNUSED, 0},
 906+	{Z80_LD, Z80_IYL, Z80_IMMED, Z80_UNUSED, 0},
 907+	USE_MAIN,
 908+	//3
 909+	USE_MAIN,
 910+	USE_MAIN,
 911+	USE_MAIN,
 912+	USE_MAIN,
 913+	{Z80_INC, Z80_UNUSED, Z80_IY_DISPLACE, 0, 0},
 914+	{Z80_DEC, Z80_UNUSED, Z80_IY_DISPLACE, 0, 0},
 915+	{Z80_LD, Z80_USE_IMMED, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 916+	USE_MAIN,
 917+	USE_MAIN,
 918+	{Z80_ADD, Z80_IY, Z80_REG, Z80_SP, 0},
 919+	USE_MAIN,
 920+	USE_MAIN,
 921+	USE_MAIN,
 922+	USE_MAIN,
 923+	USE_MAIN,
 924+	USE_MAIN,
 925+	//4
 926+	USE_MAIN,
 927+	USE_MAIN,
 928+	USE_MAIN,
 929+	USE_MAIN,
 930+	{Z80_LD, Z80_B, Z80_REG, Z80_IYH, 0},
 931+	{Z80_LD, Z80_B, Z80_REG, Z80_IYL, 0},
 932+	{Z80_LD, Z80_B, Z80_IY_DISPLACE, 0, 0},
 933+	USE_MAIN,
 934+	USE_MAIN,
 935+	USE_MAIN,
 936+	USE_MAIN,
 937+	USE_MAIN,
 938+	{Z80_LD, Z80_C, Z80_REG, Z80_IYH, 0},
 939+	{Z80_LD, Z80_C, Z80_REG, Z80_IYL, 0},
 940+	{Z80_LD, Z80_C, Z80_IY_DISPLACE, 0, 0},
 941+	USE_MAIN,
 942+	//5
 943+	USE_MAIN,
 944+	USE_MAIN,
 945+	USE_MAIN,
 946+	USE_MAIN,
 947+	{Z80_LD, Z80_D, Z80_REG, Z80_IYH, 0},
 948+	{Z80_LD, Z80_D, Z80_REG, Z80_IYL, 0},
 949+	{Z80_LD, Z80_D, Z80_IY_DISPLACE, 0, 0},
 950+	USE_MAIN,
 951+	USE_MAIN,
 952+	USE_MAIN,
 953+	USE_MAIN,
 954+	USE_MAIN,
 955+	{Z80_LD, Z80_E, Z80_REG, Z80_IYH, 0},
 956+	{Z80_LD, Z80_E, Z80_REG, Z80_IYL, 0},
 957+	{Z80_LD, Z80_E, Z80_IY_DISPLACE, 0, 0},
 958+	USE_MAIN,
 959+	//6
 960+	{Z80_LD, Z80_IYH, Z80_REG, Z80_B, 0},
 961+	{Z80_LD, Z80_IYH, Z80_REG, Z80_C, 0},
 962+	{Z80_LD, Z80_IYH, Z80_REG, Z80_D, 0},
 963+	{Z80_LD, Z80_IYH, Z80_REG, Z80_E, 0},
 964+	{Z80_LD, Z80_IYH, Z80_REG, Z80_IYH, 0},
 965+	{Z80_LD, Z80_IYH, Z80_REG, Z80_IYL, 0},
 966+	{Z80_LD, Z80_H, Z80_IY_DISPLACE, 0, 0},
 967+	{Z80_LD, Z80_IYH, Z80_REG, Z80_A, 0},
 968+	{Z80_LD, Z80_IYL, Z80_REG, Z80_B, 0},
 969+	{Z80_LD, Z80_IYL, Z80_REG, Z80_C, 0},
 970+	{Z80_LD, Z80_IYL, Z80_REG, Z80_D, 0},
 971+	{Z80_LD, Z80_IYL, Z80_REG, Z80_E, 0},
 972+	{Z80_LD, Z80_IYL, Z80_REG, Z80_IYH, 0},
 973+	{Z80_LD, Z80_IYL, Z80_REG, Z80_IYL, 0},
 974+	{Z80_LD, Z80_L, Z80_IY_DISPLACE, 0, 0},
 975+	{Z80_LD, Z80_IYL, Z80_REG, Z80_A, 0},
 976+	//7
 977+	{Z80_LD, Z80_B, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 978+	{Z80_LD, Z80_C, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 979+	{Z80_LD, Z80_D, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 980+	{Z80_LD, Z80_E, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 981+	{Z80_LD, Z80_H, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 982+	{Z80_LD, Z80_L, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 983+	USE_MAIN,
 984+	{Z80_LD, Z80_A, Z80_IY_DISPLACE | Z80_DIR, 0, 0},
 985+	USE_MAIN,
 986+	USE_MAIN,
 987+	USE_MAIN,
 988+	USE_MAIN,
 989+	{Z80_LD, Z80_A, Z80_REG, Z80_IYH, 0},
 990+	{Z80_LD, Z80_A, Z80_REG, Z80_IYL, 0},
 991+	{Z80_LD, Z80_A, Z80_IY_DISPLACE, 0, 0},
 992+	USE_MAIN,
 993+	//8
 994+	USE_MAIN,
 995+	USE_MAIN,
 996+	USE_MAIN,
 997+	USE_MAIN,
 998+	{Z80_ADD, Z80_A, Z80_REG, Z80_IYH, 0},
 999+	{Z80_ADD, Z80_A, Z80_REG, Z80_IYL, 0},
1000+	{Z80_ADD, Z80_A, Z80_IY_DISPLACE, 0, 0},
1001+	USE_MAIN,
1002+	USE_MAIN,
1003+	USE_MAIN,
1004+	USE_MAIN,
1005+	USE_MAIN,
1006+	{Z80_ADC, Z80_A, Z80_REG, Z80_IYH, 0},
1007+	{Z80_ADC, Z80_A, Z80_REG, Z80_IYL, 0},
1008+	{Z80_ADC, Z80_A, Z80_IY_DISPLACE, 0, 0},
1009+	USE_MAIN,
1010+	//9
1011+	USE_MAIN,
1012+	USE_MAIN,
1013+	USE_MAIN,
1014+	USE_MAIN,
1015+	{Z80_SUB, Z80_A, Z80_REG, Z80_IYH, 0},
1016+	{Z80_SUB, Z80_A, Z80_REG, Z80_IYL, 0},
1017+	{Z80_SUB, Z80_A, Z80_IY_DISPLACE, 0, 0},
1018+	USE_MAIN,
1019+	USE_MAIN,
1020+	USE_MAIN,
1021+	USE_MAIN,
1022+	USE_MAIN,
1023+	{Z80_SBC, Z80_A, Z80_REG, Z80_IYH, 0},
1024+	{Z80_SBC, Z80_A, Z80_REG, Z80_IYL, 0},
1025+	{Z80_SBC, Z80_A, Z80_IY_DISPLACE, 0, 0},
1026+	USE_MAIN,
1027+	//A
1028+	USE_MAIN,
1029+	USE_MAIN,
1030+	USE_MAIN,
1031+	USE_MAIN,
1032+	{Z80_AND, Z80_A, Z80_REG, Z80_IYH, 0},
1033+	{Z80_AND, Z80_A, Z80_REG, Z80_IYL, 0},
1034+	{Z80_AND, Z80_A, Z80_IY_DISPLACE, 0, 0},
1035+	USE_MAIN,
1036+	USE_MAIN,
1037+	USE_MAIN,
1038+	USE_MAIN,
1039+	USE_MAIN,
1040+	{Z80_XOR, Z80_A, Z80_REG, Z80_IYH, 0},
1041+	{Z80_XOR, Z80_A, Z80_REG, Z80_IYL, 0},
1042+	{Z80_XOR, Z80_A, Z80_IY_DISPLACE, 0, 0},
1043+	USE_MAIN,
1044+	//B
1045+	USE_MAIN,
1046+	USE_MAIN,
1047+	USE_MAIN,
1048+	USE_MAIN,
1049+	{Z80_OR, Z80_A, Z80_REG, Z80_IYH, 0},
1050+	{Z80_OR, Z80_A, Z80_REG, Z80_IYL, 0},
1051+	{Z80_OR, Z80_A, Z80_IY_DISPLACE, 0, 0},
1052+	USE_MAIN,
1053+	USE_MAIN,
1054+	USE_MAIN,
1055+	USE_MAIN,
1056+	USE_MAIN,
1057+	{Z80_CP, Z80_A, Z80_REG, Z80_IYH, 0},
1058+	{Z80_CP, Z80_A, Z80_REG, Z80_IYL, 0},
1059+	{Z80_CP, Z80_A, Z80_IY_DISPLACE, 0, 0},
1060+	USE_MAIN,
1061+	//C
1062+	USE_MAIN,
1063+	USE_MAIN,
1064+	USE_MAIN,
1065+	USE_MAIN,
1066+	USE_MAIN,
1067+	USE_MAIN,
1068+	USE_MAIN,
1069+	USE_MAIN,
1070+	USE_MAIN,
1071+	USE_MAIN,
1072+	USE_MAIN,
1073+	USE_MAIN,
1074+	USE_MAIN,
1075+	USE_MAIN,
1076+	USE_MAIN,
1077+	USE_MAIN,
1078+	//D
1079+	USE_MAIN,
1080+	USE_MAIN,
1081+	USE_MAIN,
1082+	USE_MAIN,
1083+	USE_MAIN,
1084+	USE_MAIN,
1085+	USE_MAIN,
1086+	USE_MAIN,
1087+	USE_MAIN,
1088+	USE_MAIN,
1089+	USE_MAIN,
1090+	USE_MAIN,
1091+	USE_MAIN,
1092+	USE_MAIN,
1093+	USE_MAIN,
1094+	USE_MAIN,
1095+	//E
1096+	USE_MAIN,
1097+	{Z80_POP, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0},
1098+	USE_MAIN,
1099+	{Z80_EX, Z80_IY, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0},
1100+	USE_MAIN,
1101+	{Z80_PUSH, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0},
1102+	USE_MAIN,
1103+	USE_MAIN,
1104+	USE_MAIN,
1105+	{Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_IY, 0},
1106+	USE_MAIN,
1107+	USE_MAIN,
1108+	USE_MAIN,
1109+	USE_MAIN,
1110+	USE_MAIN,
1111+	USE_MAIN,
1112+	//F
1113+	USE_MAIN,
1114+	USE_MAIN,
1115+	USE_MAIN,
1116+	USE_MAIN,
1117+	USE_MAIN,
1118+	USE_MAIN,
1119+	USE_MAIN,
1120+	USE_MAIN,
1121+	USE_MAIN,
1122+	{Z80_LD, Z80_SP, Z80_REG, Z80_IY, 0},
1123+	USE_MAIN,
1124+	USE_MAIN,
1125+	USE_MAIN,
1126+	USE_MAIN,
1127+	USE_MAIN,
1128+	USE_MAIN
1129+};
1130+
1131+#define SHIFT_BLOCK_IY(op) \
1132+	{op, Z80_B, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1133+	{op, Z80_C, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1134+	{op, Z80_D, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1135+	{op, Z80_E, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1136+	{op, Z80_H, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1137+	{op, Z80_L, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1138+	{op, Z80_UNUSED, Z80_IY_DISPLACE | Z80_DIR, 0, 1},\
1139+	{op, Z80_A, Z80_IY_DISPLACE | Z80_DIR, 0, 1}
1140+
1141+#define BIT_BLOCK_IY(bit) \
1142+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1143+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1144+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1145+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1146+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1147+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1148+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1149+	{Z80_BIT, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit}
1150+
1151+#define BIT_BLOCK_IY_REG(op, bit) \
1152+	{op, Z80_B, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1153+	{op, Z80_C, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1154+	{op, Z80_D, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1155+	{op, Z80_E, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1156+	{op, Z80_H, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1157+	{op, Z80_L, Z80_IY_DISPLACE | Z80_DIR, 0, bit},\
1158+	{op, Z80_USE_IMMED, Z80_IY_DISPLACE, 0, bit},\
1159+	{op, Z80_A, Z80_IY_DISPLACE | Z80_DIR, 0, bit}
1160+
1161+z80inst z80_tbl_iy_bit[256] = {
1162+	//0
1163+	SHIFT_BLOCK_IY(Z80_RLC),
1164+	SHIFT_BLOCK_IY(Z80_RRC),
1165+	//1
1166+	SHIFT_BLOCK_IY(Z80_RL),
1167+	SHIFT_BLOCK_IY(Z80_RR),
1168+	//2
1169+	SHIFT_BLOCK_IY(Z80_SLA),
1170+	SHIFT_BLOCK_IY(Z80_SRA),
1171+	//3
1172+	SHIFT_BLOCK_IY(Z80_SLL),
1173+	SHIFT_BLOCK_IY(Z80_SRL),
1174+	//4
1175+	BIT_BLOCK_IY(0),
1176+	BIT_BLOCK_IY(1),
1177+	//5
1178+	BIT_BLOCK_IY(2),
1179+	BIT_BLOCK_IY(3),
1180+	//6
1181+	BIT_BLOCK_IY(4),
1182+	BIT_BLOCK_IY(5),
1183+	//7
1184+	BIT_BLOCK_IY(6),
1185+	BIT_BLOCK_IY(7),
1186+	//8
1187+	BIT_BLOCK_IY_REG(Z80_RES, 0),
1188+	BIT_BLOCK_IY_REG(Z80_RES, 1),
1189+	//9
1190+	BIT_BLOCK_IY_REG(Z80_RES, 2),
1191+	BIT_BLOCK_IY_REG(Z80_RES, 3),
1192+	//A
1193+	BIT_BLOCK_IY_REG(Z80_RES, 4),
1194+	BIT_BLOCK_IY_REG(Z80_RES, 5),
1195+	//B
1196+	BIT_BLOCK_IY_REG(Z80_RES, 6),
1197+	BIT_BLOCK_IY_REG(Z80_RES, 7),
1198+	//C
1199+	BIT_BLOCK_IY_REG(Z80_SET, 0),
1200+	BIT_BLOCK_IY_REG(Z80_SET, 1),
1201+	//D
1202+	BIT_BLOCK_IY_REG(Z80_SET, 2),
1203+	BIT_BLOCK_IY_REG(Z80_SET, 3),
1204+	//E
1205+	BIT_BLOCK_IY_REG(Z80_SET, 4),
1206+	BIT_BLOCK_IY_REG(Z80_SET, 5),
1207+	//F
1208+	BIT_BLOCK_IY_REG(Z80_SET, 6),
1209+	BIT_BLOCK_IY_REG(Z80_SET, 7),
1210+};
1211+
1212+enum {
1213+	NORMAL,
1214+	USE_IX,
1215+	USE_IY
1216+};
1217+
1218+uint8_t * z80_decode(uint8_t * istream, z80inst * decoded)
1219+{
1220+	uint8_t tmp;
1221+	uint8_t *start = istream;
1222+	uint8_t ixiy = NORMAL;
1223+	uint16_t ixiy_disp = 0x100;
1224+	z80inst *base = NULL;
1225+	while(!base)
1226+	{
1227+		switch (*istream)
1228+		{
1229+		case 0xCB:
1230+			istream++;
1231+			if (ixiy == NORMAL) {
1232+				base = z80_tbl_bit + *istream;
1233+			} else if (ixiy == USE_IX) {
1234+				ixiy_disp = *(istream++);
1235+				base = z80_tbl_ix_bit + *istream;
1236+			} else {
1237+				ixiy_disp = *(istream++);
1238+				base = z80_tbl_iy_bit + *istream;
1239+			}
1240+			break;
1241+		case 0xED:
1242+			istream++;
1243+			ixiy = NORMAL;
1244+			if (*istream < 0x40 || *istream >= 0xC0) {
1245+				base = z80_tbl_extd + 0xBF;
1246+			} else {
1247+				base = z80_tbl_extd + *istream - 0x40;
1248+			}
1249+			break;
1250+		case 0xDD:
1251+			istream++;
1252+			ixiy = USE_IX;
1253+			break;
1254+		case 0xFD:
1255+			istream++;
1256+			ixiy = USE_IY;
1257+			break;
1258+		default:
1259+			if (ixiy == NORMAL) {
1260+				base = z80_tbl_a + *istream;
1261+			} else if (ixiy == USE_IX) {
1262+				base = z80_tbl_ix + *istream;
1263+			} else {
1264+				base = z80_tbl_iy + *istream;
1265+			}
1266+		}
1267+	}
1268+	if (base->op == Z80_USE_MAIN) {
1269+		base = z80_tbl_a + *istream;
1270+		ixiy = NORMAL;
1271+	}
1272+	memcpy(decoded, base, offsetof(z80inst, opcode_bytes));
1273+	decoded->opcode_bytes = istream - start + 1;
1274+	if (ixiy != NORMAL) {
1275+		if (ixiy_disp < 0x100) {
1276+			decoded->ea_reg = ixiy_disp;
1277+			//don't count displacement byte as an opcode byte
1278+			decoded->opcode_bytes--;
1279+		} else if ((decoded->addr_mode & 0x1F) == Z80_IX_DISPLACE || (decoded->addr_mode & 0x1F) == Z80_IY_DISPLACE) {
1280+			decoded->ea_reg = *(++istream);
1281+		}
1282+	}
1283+	
1284+	if ((decoded->addr_mode & 0x1F) == Z80_IMMED && decoded->op != Z80_RST && decoded->op != Z80_IM) {
1285+		decoded->immed = *(++istream);
1286+		if ((decoded->reg >= Z80_BC && decoded->reg < Z80_UNUSED) || decoded->op == Z80_CALL || decoded->op == Z80_CALLCC || decoded->op == Z80_JP || decoded->op == Z80_JPCC) {
1287+			decoded->immed |= *(++istream) << 8;
1288+		} else if (decoded->immed & 0x80) {
1289+			decoded->immed |= 0xFF00;
1290+		}
1291+	} else if ((decoded->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) {
1292+		decoded->immed = *(++istream);
1293+		if (decoded->op != Z80_OUT && decoded->op != Z80_IN) {
1294+			decoded->immed |= *(++istream) << 8;
1295+		}
1296+	}
1297+	if (decoded->reg == Z80_USE_IMMED && decoded->op != Z80_BIT && decoded->op != Z80_RES && decoded->op != Z80_SET && decoded->op != Z80_OUT) {
1298+		decoded->immed = *(++istream);
1299+	}
1300+	return istream+1;
1301+}
1302+
1303+char *z80_mnemonics[Z80_OTDR+1] = {
1304+	"ld",
1305+	"push",
1306+	"pop",
1307+	"ex",
1308+	"exx",
1309+	"ldi",
1310+	"ldir",
1311+	"ldd",
1312+	"lddr",
1313+	"cpi",
1314+	"cpir",
1315+	"cpd",
1316+	"cpdr",
1317+	"add",
1318+	"adc",
1319+	"sub",
1320+	"sbc",
1321+	"and",
1322+	"or",
1323+	"xor",
1324+	"cp",
1325+	"inc",
1326+	"dec",
1327+	"daa",
1328+	"cpl",
1329+	"neg",
1330+	"ccf",
1331+	"scf",
1332+	"nop",
1333+	"halt",
1334+	"di",
1335+	"ei",
1336+	"im",
1337+	"rlc",
1338+	"rl",
1339+	"rrc",
1340+	"rr",
1341+	"sla",
1342+	"sra",
1343+	"sll",
1344+	"srl",
1345+	"rld",
1346+	"rrd",
1347+	"bit",
1348+	"set",
1349+	"res",
1350+	"jp",
1351+	"jp",
1352+	"jr",
1353+	"jr",
1354+	"djnz",
1355+	"call",
1356+	"call",
1357+	"ret",
1358+	"ret",
1359+	"reti",
1360+	"retn",
1361+	"rst",
1362+	"in",
1363+	"ini",
1364+	"inir",
1365+	"ind",
1366+	"indr",
1367+	"out",
1368+	"outi",
1369+	"otir",
1370+	"outd",
1371+	"otdr"
1372+};
1373+
1374+char * z80_regs[Z80_USE_IMMED] = {
1375+	"c",
1376+	"b",
1377+	"e",
1378+	"d",
1379+	"l",
1380+	"h",
1381+	"ixl",
1382+	"ixh",
1383+	"iyl",
1384+	"iyh",
1385+	"i",
1386+	"r",
1387+	"a",
1388+	"bc",
1389+	"de",
1390+	"hl",
1391+	"sp",
1392+	"af",
1393+	"ix",
1394+	"iy",
1395+};
1396+
1397+char * z80_conditions[Z80_CC_M+1] = {
1398+	"nz",
1399+	"z",
1400+	"nc",
1401+	"c",
1402+	"po",
1403+	"pe",
1404+	"p",
1405+	"m"
1406+};
1407+
1408+int z80_disasm(z80inst * decoded, char * dst, uint16_t address)
1409+{
1410+	int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]);
1411+	uint8_t needcomma;
1412+	if (decoded->addr_mode & Z80_DIR) {
1413+		needcomma = 1;
1414+		switch (decoded->addr_mode & 0x1F)
1415+		{
1416+		case Z80_REG:
1417+			len += sprintf(dst+len,  " %s", z80_regs[decoded->ea_reg]);
1418+			break;
1419+		case Z80_REG_INDIRECT:
1420+			len += sprintf(dst+len,  " (%s)", z80_regs[decoded->ea_reg]);
1421+			break;
1422+		case Z80_IMMED:
1423+			if (decoded->immed >= 63 || decoded->op == Z80_JP || decoded->op == Z80_JPCC || decoded->op == Z80_CALL || decoded->op == Z80_CALLCC || decoded->op == Z80_RST)
1424+			{
1425+				len += sprintf(dst+len, " $%X", decoded->immed);
1426+			} else {
1427+				len += sprintf(dst+len, " %d", decoded->immed);
1428+			}
1429+			break;
1430+		case Z80_IMMED_INDIRECT:
1431+			len += sprintf(dst+len, " ($%X)", decoded->immed);
1432+			break;
1433+		case Z80_IX_DISPLACE:
1434+			len += sprintf(dst+len, " (ix+%d)", decoded->ea_reg & 0x80 ? decoded->ea_reg - 256 : decoded->ea_reg);
1435+			break;
1436+		case Z80_IY_DISPLACE:
1437+			len += sprintf(dst+len, " (iy+%d)", decoded->ea_reg & 0x80 ? decoded->ea_reg - 256 : decoded->ea_reg);
1438+			break;
1439+		default:
1440+			needcomma = 0;
1441+		}
1442+		if (decoded->reg & Z80_IMMED_FLAG) {
1443+			len += sprintf(dst+len, "%s %d", needcomma ? "," : "", decoded->immed);
1444+		}
1445+		if ((decoded->reg & 0x1F) != Z80_UNUSED) {
1446+			if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) {
1447+				len += sprintf(dst+len,  "%s %s", needcomma ? "," : "", z80_conditions[decoded->reg & 0x1F]);
1448+			} else {
1449+				len += sprintf(dst+len,  "%s %s", needcomma ? "," : "", z80_regs[decoded->reg & 0x1F]);
1450+			}
1451+		}
1452+	} else {
1453+		needcomma = 0;
1454+		if (decoded->reg & Z80_IMMED_FLAG) {
1455+			len += sprintf(dst+len, " %d", decoded->immed);
1456+			needcomma = 1;
1457+		}
1458+		if ((decoded->reg & 0x1F) != Z80_UNUSED) {
1459+			if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) {
1460+				len += sprintf(dst+len,  " %s", z80_conditions[decoded->reg & 0x1F]);
1461+			} else {
1462+				len += sprintf(dst+len,  " %s", z80_regs[decoded->reg & 0x1F]);
1463+			}
1464+			needcomma = 1;
1465+		}
1466+		switch (decoded->addr_mode)
1467+		{
1468+		case Z80_REG:
1469+			len += sprintf(dst+len,  "%s %s", needcomma ? "," : "" , z80_regs[decoded->ea_reg]);
1470+			break;
1471+		case Z80_REG_INDIRECT:
1472+			len += sprintf(dst+len,  "%s (%s)", needcomma ? "," : "" , z80_regs[decoded->ea_reg]);
1473+			break;
1474+		case Z80_IMMED:
1475+			if (decoded->op == Z80_JR || decoded->op == Z80_JRCC || decoded->op == Z80_DJNZ) {
1476+					address += 2 + decoded->immed;
1477+					len += sprintf(dst+len, "%s %X", needcomma ? "," : "" , address);
1478+			} else if (decoded->immed >= 63 || decoded->op == Z80_JP || decoded->op == Z80_JPCC || decoded->op == Z80_CALL || decoded->op == Z80_CALLCC || decoded->op == Z80_RST)
1479+			{
1480+				len += sprintf(dst+len, "%s $%X", needcomma ? "," : "" , decoded->immed);
1481+			} else {
1482+				len += sprintf(dst+len, "%s %d", needcomma ? "," : "" , decoded->immed);
1483+			}
1484+			break;
1485+		case Z80_IMMED_INDIRECT:
1486+			len += sprintf(dst+len, "%s ($%X)", needcomma ? "," : "" , decoded->immed);
1487+			break;
1488+		case Z80_IX_DISPLACE:
1489+			len += sprintf(dst+len, "%s (ix+%d)", needcomma ? "," : "" , decoded->ea_reg & 0x80 ? decoded->ea_reg - 256 : decoded->ea_reg);
1490+			break;
1491+		case Z80_IY_DISPLACE:
1492+			len += sprintf(dst+len, "%s (iy+%d)", needcomma ? "," : "" , decoded->ea_reg & 0x80 ? decoded->ea_reg - 256 : decoded->ea_reg);
1493+			break;
1494+		}
1495+	}
1496+	return len;
1497+}
1498+
1499+uint8_t z80_high_reg(uint8_t reg)
1500+{
1501+	switch(reg)
1502+	{
1503+	case Z80_C:
1504+	case Z80_BC:
1505+		return Z80_B;
1506+	case Z80_E:
1507+	case Z80_DE:
1508+		return Z80_D;
1509+	case Z80_L:
1510+	case Z80_HL:
1511+		return Z80_H;
1512+	case Z80_IXL:
1513+	case Z80_IX:
1514+		return Z80_IXH;
1515+	case Z80_IYL:
1516+	case Z80_IY:
1517+		return Z80_IYH;
1518+	default:
1519+		return Z80_UNUSED;
1520+	}
1521+}
1522+
1523+uint8_t z80_low_reg(uint8_t reg)
1524+{
1525+	switch(reg)
1526+	{
1527+	case Z80_B:
1528+	case Z80_BC:
1529+		return Z80_C;
1530+	case Z80_D:
1531+	case Z80_DE:
1532+		return Z80_E;
1533+	case Z80_H:
1534+	case Z80_HL:
1535+		return Z80_L;
1536+	case Z80_IXH:
1537+	case Z80_IX:
1538+		return Z80_IXL;
1539+	case Z80_IYH:
1540+	case Z80_IY:
1541+		return Z80_IYL;
1542+	default:
1543+		return Z80_UNUSED;
1544+	}
1545+}
1546+
1547+uint8_t z80_word_reg(uint8_t reg)
1548+{
1549+	switch(reg)
1550+	{
1551+	case Z80_B:
1552+	case Z80_C:
1553+		return Z80_BC;
1554+	case Z80_D:
1555+	case Z80_E:
1556+		return Z80_DE;
1557+	case Z80_H:
1558+	case Z80_L:
1559+		return Z80_HL;
1560+	case Z80_IXH:
1561+	case Z80_IXL:
1562+		return Z80_IX;
1563+	case Z80_IYH:
1564+	case Z80_IYL:
1565+		return Z80_IY;
1566+	default:
1567+		return Z80_UNUSED;
1568+	}
1569+}
1570+
1571+uint8_t z80_is_terminal(z80inst * inst)
1572+{
1573+	return inst->op == Z80_RET || inst->op == Z80_RETI || inst->op == Z80_RETN || inst->op == Z80_JP
1574+		|| inst->op == Z80_JR || inst->op == Z80_HALT || (inst->op == Z80_NOP && inst->immed == 42);
1575+}
1576+
1577+
1578+
+148, -0
  1@@ -0,0 +1,148 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm. 
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#ifndef Z80INST_H_
  8+#define Z80INST_H_
  9+
 10+#include <stdint.h>
 11+
 12+enum {
 13+	Z80_LD,
 14+	Z80_PUSH,
 15+	Z80_POP,
 16+	Z80_EX,
 17+	Z80_EXX,
 18+	Z80_LDI,
 19+	Z80_LDIR,
 20+	Z80_LDD,
 21+	Z80_LDDR,
 22+	Z80_CPI,
 23+	Z80_CPIR,
 24+	Z80_CPD,
 25+	Z80_CPDR,
 26+	Z80_ADD,
 27+	Z80_ADC,
 28+	Z80_SUB,
 29+	Z80_SBC,
 30+	Z80_AND,
 31+	Z80_OR,
 32+	Z80_XOR,
 33+	Z80_CP,
 34+	Z80_INC,
 35+	Z80_DEC,
 36+	Z80_DAA,
 37+	Z80_CPL,
 38+	Z80_NEG,
 39+	Z80_CCF,
 40+	Z80_SCF,
 41+	Z80_NOP,
 42+	Z80_HALT,
 43+	Z80_DI,
 44+	Z80_EI,
 45+	Z80_IM,
 46+	Z80_RLC,
 47+	Z80_RL,
 48+	Z80_RRC,
 49+	Z80_RR,
 50+	Z80_SLA,
 51+	Z80_SRA,
 52+	Z80_SLL,
 53+	Z80_SRL,
 54+	Z80_RLD,
 55+	Z80_RRD,
 56+	Z80_BIT,
 57+	Z80_SET,
 58+	Z80_RES,
 59+	Z80_JP,
 60+	Z80_JPCC,
 61+	Z80_JR,
 62+	Z80_JRCC,
 63+	Z80_DJNZ,
 64+	Z80_CALL,
 65+	Z80_CALLCC,
 66+	Z80_RET,
 67+	Z80_RETCC,
 68+	Z80_RETI,
 69+	Z80_RETN,
 70+	Z80_RST,
 71+	Z80_IN,
 72+	Z80_INI,
 73+	Z80_INIR,
 74+	Z80_IND,
 75+	Z80_INDR,
 76+	Z80_OUT,
 77+	Z80_OUTI,
 78+	Z80_OTIR,
 79+	Z80_OUTD,
 80+	Z80_OTDR,
 81+	Z80_USE_MAIN
 82+};
 83+
 84+enum {
 85+	Z80_C=0,
 86+	Z80_B,
 87+	Z80_E,
 88+	Z80_D,
 89+	Z80_L,
 90+	Z80_H,
 91+	Z80_IXL,
 92+	Z80_IXH,
 93+	Z80_IYL,
 94+	Z80_IYH,
 95+	Z80_I,
 96+	Z80_R,
 97+	Z80_A,
 98+	Z80_BC,
 99+	Z80_DE,
100+	Z80_HL,
101+	Z80_SP,
102+	Z80_AF,
103+	Z80_IX,
104+	Z80_IY,
105+	Z80_UNUSED
106+};
107+
108+#define Z80_IMMED_FLAG 0x80
109+#define Z80_USE_IMMED (Z80_IMMED_FLAG|Z80_UNUSED)
110+
111+enum {
112+	Z80_CC_NZ,
113+	Z80_CC_Z,
114+	Z80_CC_NC,
115+	Z80_CC_C,
116+	Z80_CC_PO,
117+	Z80_CC_PE,
118+	Z80_CC_P,
119+	Z80_CC_M
120+};
121+
122+enum {
123+	Z80_REG,
124+	Z80_REG_INDIRECT,
125+	Z80_IMMED,
126+	Z80_IMMED_INDIRECT,
127+	Z80_IX_DISPLACE,
128+	Z80_IY_DISPLACE
129+};
130+#define Z80_DIR 0x80
131+
132+typedef struct {
133+	uint8_t  op;
134+	uint8_t  reg;
135+	uint8_t  addr_mode;
136+	uint8_t  ea_reg;
137+	uint16_t immed;
138+	uint16_t  opcode_bytes;
139+} z80inst;
140+
141+uint8_t * z80_decode(uint8_t * istream, z80inst * decoded);
142+int z80_disasm(z80inst * decoded, char * dst, uint16_t address);
143+uint8_t z80_high_reg(uint8_t reg);
144+uint8_t z80_low_reg(uint8_t reg);
145+uint8_t z80_word_reg(uint8_t reg);
146+uint8_t z80_is_terminal(z80inst * inst);
147+
148+#endif //Z80INST_H_
149+
+58, -0
 1@@ -0,0 +1,58 @@
 2+#!/usr/bin/env python
 3+from glob import glob
 4+import subprocess
 5+from sys import exit,argv
 6+
 7+prefixes = []
 8+skip = set()
 9+for i in range(1, len(argv)):
10+	if '.' in argv[i]:
11+		f = open(argv[i])
12+		for line in f:
13+			parts = line.split()
14+			for part in parts:
15+				if part.endswith('.bin'):
16+					skip.add(part)
17+		f.close()
18+		print 'Skipping',len(skip),'entries from previous report.'
19+	else:
20+		prefixes.append(argv[i])
21+
22+for path in glob('ztests/*/*.bin'):
23+	if path in skip:
24+		continue
25+	if prefixes:
26+		good = False
27+		fname = path.split('/')[-1]
28+		for prefix in prefixes:
29+			if fname.startswith(prefix):
30+				good = True
31+				break
32+		if not good:
33+			continue
34+	try:
35+		b = subprocess.check_output(['./ztestrun', path])
36+		try:
37+			m = subprocess.check_output(['gxz80/gxzrun', path])
38+			#_,_,b = b.partition('\n')
39+			if b != m:
40+				print '-----------------------------'
41+				print 'Mismatch in ' + path
42+				print 'blastem output:'
43+				print b
44+				print 'gxz80 output:'
45+				print m
46+				print '-----------------------------'
47+			else:
48+				print path, 'passed'
49+		except subprocess.CalledProcessError as e:
50+			print '-----------------------------'
51+			print 'gxz80 exited with code', e.returncode, 'for test', path
52+			print 'blastem output:'
53+			print b
54+			print '-----------------------------'
55+	except subprocess.CalledProcessError as e:
56+		print '-----------------------------'
57+		print 'blastem exited with code', e.returncode, 'for test', path
58+		print '-----------------------------'
59+
A zdis.c
+221, -0
  1@@ -0,0 +1,221 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm. 
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "z80inst.h"
  8+#include <stdio.h>
  9+#include <stdlib.h>
 10+#include <stdarg.h>
 11+
 12+uint8_t visited[(64*1024)/8];
 13+uint8_t label[(64*1024)/8];
 14+
 15+void fatal_error(char *format, ...)
 16+{
 17+	va_list args;
 18+	va_start(args, format);
 19+	vfprintf(stderr, format, args);
 20+	va_end(args);
 21+	exit(1);
 22+}
 23+
 24+void visit(uint16_t address)
 25+{
 26+	visited[address/8] |= 1 << (address % 8);
 27+}
 28+
 29+void reference(uint16_t address)
 30+{
 31+	//printf("referenced: %X\n", address);
 32+	label[address/8] |= 1 << (address % 8);
 33+}
 34+
 35+uint8_t is_visited(uint16_t address)
 36+{
 37+	return visited[address/8] & (1 << (address % 8));
 38+}
 39+
 40+uint8_t is_label(uint16_t address)
 41+{
 42+	return label[address/8] & (1 << (address % 8));
 43+}
 44+
 45+typedef struct deferred {
 46+	uint16_t address;
 47+	struct deferred *next;
 48+} deferred;
 49+
 50+deferred * defer(uint16_t address, deferred * next)
 51+{
 52+	if (is_visited(address)) {
 53+		return next;
 54+	}
 55+	//printf("deferring %X\n", address);
 56+	deferred * d = malloc(sizeof(deferred));
 57+	d->address = address;
 58+	d->next = next;
 59+	return d;
 60+}
 61+
 62+uint8_t labels = 0;
 63+uint8_t addr = 0;
 64+uint8_t only = 0;
 65+
 66+int main(int argc, char ** argv)
 67+{
 68+	long filesize;
 69+	uint8_t *filebuf;
 70+	char disbuf[1024];
 71+	z80inst instbuf;
 72+	uint8_t * cur;
 73+	FILE * f = fopen(argv[1], "rb");
 74+	fseek(f, 0, SEEK_END);
 75+	filesize = ftell(f);
 76+	fseek(f, 0, SEEK_SET);
 77+	filebuf = malloc(filesize);
 78+	fread(filebuf, 1, filesize, f);
 79+	fclose(f);
 80+	deferred *def = NULL, *tmpd;
 81+	uint16_t offset = 0;
 82+	for(uint8_t opt = 2; opt < argc; ++opt) {
 83+		if (argv[opt][0] == '-') {
 84+			FILE * address_log;
 85+			switch (argv[opt][1])
 86+			{
 87+			case 'l':
 88+				labels = 1;
 89+				break;
 90+			case 'a':
 91+				addr = 1;
 92+				break;
 93+			case 'o':
 94+				only = 1;
 95+				break;
 96+			case 'f':
 97+				opt++;
 98+				if (opt >= argc) {
 99+					fputs("-f must be followed by a filename\n", stderr);
100+					exit(1);
101+				}
102+				address_log = fopen(argv[opt], "r");
103+				if (!address_log) {
104+					fprintf(stderr, "Failed to open %s for reading\n", argv[opt]);
105+					exit(1);
106+				}
107+				while (fgets(disbuf, sizeof(disbuf), address_log)) {
108+				 	if (disbuf[0]) {
109+						uint16_t address = strtol(disbuf, NULL, 16);
110+						if (address) {
111+							def = defer(address, def);
112+							reference(address);
113+						}
114+					}
115+				}
116+				fclose(address_log);
117+				break;
118+			case 's':
119+				opt++;
120+				if (opt >= argc) {
121+					fputs("-s must be followed by a start offset in hex\n", stderr);
122+					exit(1);
123+				}
124+				offset = strtol(argv[opt], NULL, 16);
125+				break;
126+			}
127+		} else {
128+			uint16_t address = strtol(argv[opt], NULL, 16);
129+			def = defer(address, def);
130+			reference(address);
131+		}
132+	}
133+	uint16_t start = offset;
134+	uint8_t *encoded, *next;
135+	uint32_t size;
136+	if (!def || !only) {
137+		def = defer(start, def);
138+	}
139+	uint16_t address;
140+	while(def) {
141+		do {
142+			encoded = NULL;
143+			address = def->address;
144+			if (!is_visited(address)) {
145+				encoded = filebuf + address - offset;
146+			}
147+			tmpd = def;
148+			def = def->next;
149+			free(tmpd);
150+		} while(def && encoded == NULL);
151+		if (!encoded) {
152+			break;
153+		}
154+		for(;;) {
155+			if ((address - offset) > filesize || is_visited(address) || address < offset) {
156+				break;
157+			}
158+			visit(address);
159+			next = z80_decode(encoded, &instbuf);
160+			address += (next-encoded);
161+			encoded = next;
162+			
163+			//z80_disasm(&instbuf, disbuf);
164+			//printf("%X: %s\n", address, disbuf);
165+			switch (instbuf.op)
166+			{
167+			case Z80_JR:
168+				address += instbuf.immed;
169+				encoded = filebuf + address - offset;
170+				break;
171+			case Z80_JRCC:
172+				reference(address + instbuf.immed);
173+				def = defer(address + instbuf.immed, def);
174+				break;
175+			case Z80_JP:
176+				address = instbuf.immed;
177+				encoded = filebuf + address - offset;
178+				break;
179+			case Z80_JPCC:
180+			case Z80_CALL:
181+			case Z80_CALLCC:
182+			case Z80_RST:
183+				reference(instbuf.immed);
184+				def = defer(instbuf.immed, def);
185+				break;
186+			default:
187+				if (z80_is_terminal(&instbuf)) {
188+					address = filesize + 1;
189+				}
190+			}
191+		}
192+	}
193+	if (labels) {
194+		for (address = filesize; address < (64*1024); address++) {
195+			if (is_label(address)) {
196+				printf("ADR_%X equ $%X\n", address, address);
197+			}
198+		}
199+		puts("");
200+	}
201+	for (address = offset; address < filesize + offset; address++) {
202+		if (is_visited(address)) {
203+			encoded = filebuf + address - offset;
204+			z80_decode(encoded, &instbuf);
205+			if (labels) {
206+				/*m68k_disasm_labels(&instbuf, disbuf);
207+				if (is_label(instbuf.address)) {
208+					printf("ADR_%X:\n", instbuf.address);
209+				}
210+				if (addr) {
211+					printf("\t%s\t;%X\n", disbuf, instbuf.address);
212+				} else {
213+					printf("\t%s\n", disbuf);
214+				}*/
215+			} else {
216+				z80_disasm(&instbuf, disbuf, address);
217+				printf("%X: %s\n", address, disbuf);
218+			}
219+		}
220+	}
221+	return 0;
222+}
A zip.c
+196, -0
  1@@ -0,0 +1,196 @@
  2+#include <stdio.h>
  3+#include <stdlib.h>
  4+#include <stddef.h>
  5+#include <string.h>
  6+#include "util.h"
  7+#include "zip.h"
  8+#include <zlib.h>
  9+
 10+static const char cdfd_magic[4] = {'P', 'K', 1, 2};
 11+static const char eocd_magic[4] = {'P', 'K', 5, 6};
 12+#define MIN_EOCD_SIZE 22
 13+#define MIN_CDFD_SIZE 46
 14+#define ZIP_MAX_EOCD_OFFSET (64*1024+MIN_EOCD_SIZE)
 15+
 16+enum {
 17+	ZIP_STORE = 0,
 18+	ZIP_DEFLATE = 8
 19+};
 20+
 21+zip_file *zip_open(const char *filename)
 22+{
 23+	FILE *f = fopen(filename, "rb");
 24+	if (!f) {
 25+		return NULL;
 26+	}
 27+	long fsize = file_size(f);
 28+	if (fsize < MIN_EOCD_SIZE) {
 29+		//too small to be a zip file
 30+		goto fail;
 31+	}
 32+	
 33+	long max_offset = fsize > ZIP_MAX_EOCD_OFFSET ? ZIP_MAX_EOCD_OFFSET : fsize;
 34+	fseek(f, -max_offset, SEEK_END);
 35+	uint8_t *buf = malloc(max_offset);
 36+	if (max_offset != fread(buf, 1, max_offset, f)) {
 37+		goto fail;
 38+	}
 39+	
 40+	long current_offset;
 41+	uint32_t cd_start, cd_size;
 42+	uint16_t cd_count;
 43+	for (current_offset = max_offset - MIN_EOCD_SIZE; current_offset >= 0; current_offset--)
 44+	{
 45+		if (memcmp(eocd_magic, buf + current_offset, sizeof(eocd_magic))) {
 46+			continue;
 47+		}
 48+		uint16_t comment_size = buf[current_offset + 20] | buf[current_offset + 21] << 8;
 49+		if (comment_size != (max_offset - current_offset - MIN_EOCD_SIZE)) {
 50+			continue;
 51+		}
 52+		cd_start = buf[current_offset + 16] | buf[current_offset + 17] << 8
 53+			| buf[current_offset + 18] << 16 | buf[current_offset + 19] << 24;
 54+		if (cd_start > (fsize - (max_offset - current_offset))) {
 55+			continue;
 56+		}
 57+		cd_size = buf[current_offset + 12] | buf[current_offset + 13] << 8
 58+			| buf[current_offset + 14] << 16 | buf[current_offset + 15] << 24;
 59+		if ((cd_start + cd_size) > (fsize - (max_offset - current_offset))) {
 60+			continue;
 61+		}
 62+		cd_count = buf[current_offset + 10] | buf[current_offset + 11] << 8;
 63+		break;
 64+	}
 65+	free(buf);
 66+	if (current_offset < 0) {
 67+		//failed to find EOCD
 68+		goto fail;
 69+	}
 70+	buf = malloc(cd_size);
 71+	fseek(f, cd_start, SEEK_SET);
 72+	if (cd_size != fread(buf, 1, cd_size, f)) {
 73+		goto fail_free;
 74+	}
 75+	zip_entry *entries = calloc(cd_count, sizeof(zip_entry));
 76+	uint32_t cd_max_last = cd_size - MIN_CDFD_SIZE;
 77+	zip_entry *cur_entry = entries;
 78+	for (uint32_t off = 0; cd_count && off <= cd_max_last; cur_entry++, cd_count--)
 79+	{
 80+		if (memcmp(buf + off, cdfd_magic, sizeof(cdfd_magic))) {
 81+			goto fail_entries;
 82+		}
 83+		uint32_t name_length = buf[off + 28] | buf[off + 29] << 8;
 84+		uint32_t extra_length = buf[off + 30] | buf[off + 31] << 8;
 85+		//TODO: verify name length doesn't go past end of CD
 86+		
 87+		cur_entry->name = malloc(name_length + 1);
 88+		memcpy(cur_entry->name, buf + off + MIN_CDFD_SIZE, name_length);
 89+		cur_entry->name[name_length] = 0;
 90+		
 91+		cur_entry->compressed_size = buf[off + 20] | buf[off + 21] << 8 
 92+			| buf[off + 22] << 16 | buf[off + 23] << 24;
 93+		cur_entry->size = buf[off + 24] | buf[off + 25] << 8 
 94+			| buf[off + 26] << 16 | buf[off + 27] << 24;
 95+			
 96+		cur_entry->local_header_off = buf[off + 42] | buf[off + 43] << 8 
 97+			| buf[off + 44] << 16 | buf[off + 45] << 24;
 98+			
 99+		cur_entry->compression_method = buf[off + 10] | buf[off + 11] << 8;
100+		
101+		off += name_length + extra_length + MIN_CDFD_SIZE;
102+	}
103+	
104+	zip_file *z = malloc(sizeof(zip_file));
105+	z->entries = entries;
106+	z->file = f;
107+	z->num_entries = cur_entry - entries;
108+	return z;
109+	
110+fail_entries:
111+	for (cur_entry--; cur_entry >= entries; cur_entry--)
112+	{
113+		free(cur_entry->name);
114+	}
115+	free(entries);
116+fail_free:
117+	free(buf);
118+fail:
119+	fclose(f);
120+	return NULL;
121+}
122+
123+uint8_t *zip_read(zip_file *f, uint32_t index, size_t *out_size)
124+{
125+	
126+	fseek(f->file, f->entries[index].local_header_off + 26, SEEK_SET);
127+	uint8_t tmp[4];
128+	if (sizeof(tmp) != fread(tmp, 1, sizeof(tmp), f->file)) {
129+		return NULL;
130+	}
131+	uint32_t local_variable = (tmp[0] | tmp[1] << 8) + (tmp[2] | tmp[3] << 8);
132+	fseek(f->file, f->entries[index].local_header_off + local_variable + 30, SEEK_SET);
133+	
134+	size_t int_size;
135+	if (!out_size) {
136+		out_size = &int_size;
137+		int_size = f->entries[index].size;
138+	}
139+	
140+	uint8_t *buf = malloc(*out_size);
141+	if (*out_size > f->entries[index].size) {
142+		*out_size = f->entries[index].size;
143+	}
144+	switch(f->entries[index].compression_method)
145+	{
146+	case ZIP_STORE:
147+		if (*out_size != fread(buf, 1, *out_size, f->file)) {
148+			free(buf);
149+			return NULL;
150+		}
151+		break;
152+	case ZIP_DEFLATE: {
153+		//note in unzip.c in zlib/contrib suggests a dummy byte is needed, so we allocate an extra byte here
154+		uint8_t *src_buf = malloc(f->entries[index].compressed_size + 1);
155+		if (f->entries[index].compressed_size != fread(src_buf, 1, f->entries[index].compressed_size, f->file)) {
156+			free(src_buf);
157+			return NULL;
158+		}
159+		uLongf destLen = *out_size;
160+		z_stream stream;
161+		memset(&stream, 0, sizeof(stream));
162+		stream.avail_in = f->entries[index].compressed_size + 1;
163+		stream.next_in = src_buf;
164+		stream.next_out = buf;
165+		stream.avail_out = *out_size;
166+		if (Z_OK == inflateInit2(&stream, -15)) {
167+			int result = inflate(&stream, Z_FINISH);
168+			*out_size = stream.total_out;
169+			free(src_buf);
170+			inflateEnd(&stream);
171+			if (result != Z_OK && result != Z_STREAM_END && result != Z_BUF_ERROR) {
172+				free(buf);
173+				return NULL;
174+			}
175+		}
176+		break;
177+	}
178+	default:
179+		free(buf);
180+		return NULL;
181+	}
182+	
183+	return buf;
184+}
185+
186+void zip_close(zip_file *f)
187+{
188+	fclose(f->file);
189+	for (uint32_t i = 0; i < f->num_entries; i++)
190+	{
191+		free(f->entries[i].name);
192+	}
193+	free(f->entries);
194+	free(f);
195+}
196+
197+ 
A zip.h
+25, -0
 1@@ -0,0 +1,25 @@
 2+#ifndef ZIP_H_
 3+#define ZIP_H_
 4+
 5+#include <stdint.h>
 6+#include <stdio.h>
 7+
 8+typedef struct {
 9+	uint64_t compressed_size;
10+	uint64_t size;
11+	uint64_t local_header_off;
12+	char     *name;
13+	uint16_t compression_method;
14+} zip_entry;
15+
16+typedef struct {
17+	zip_entry *entries;
18+	FILE      *file;
19+	uint32_t  num_entries;
20+} zip_file;
21+
22+zip_file *zip_open(const char *filename);
23+uint8_t *zip_read(zip_file *f, uint32_t index, size_t *out_size);
24+void zip_close(zip_file *f);
25+
26+#endif //ZIP_H_
+437, -0
  1@@ -0,0 +1,437 @@
  2+z_inccycles_io:
  3+	cmp %edi, %ebp
  4+	jnb do_limit
  5+no_sync_io:
  6+	add $4, %ebp
  7+	ret
  8+do_limit_io:
  9+	cmp 112(%rsi), %ebp
 10+	jb no_sync_io
 11+	jmp sync_io
 12+
 13+z_inccycles:
 14+	cmp %edi, %ebp
 15+	jnb do_limit
 16+no_sync:
 17+	add $3, %ebp
 18+	ret
 19+do_limit:
 20+	cmp 112(%rsi), %ebp
 21+	jb no_sync
 22+sync_io:
 23+	movw $0, 164(%rsi)
 24+	call z80_save_context_scratch
 25+	pop %rax /*return address in read/write func*/
 26+	pop 104(%rsi) /*return address in native code*/
 27+	sub $5, %rax /* adjust return addres to point to the call instruction that got us here */
 28+	mov %rax, (%rsi)
 29+
 30+	pop %r15 /* restore callee saved regsiters */
 31+	pop %r14
 32+	pop %r13
 33+	pop %r12
 34+	pop %rbp
 35+	pop %rbx
 36+	ret /* return to caller of z80_run */
 37+
 38+forced_sync:
 39+	movw $0, 164(%rsi)
 40+	call z80_save_context_scratch
 41+	pop (%rsi) /*return address in read/write func*/
 42+	pop 104(%rsi) /*return address in native code*/
 43+
 44+	pop %r15 /* restore callee saved regsiters */
 45+	pop %r14
 46+	pop %r13
 47+	pop %r12
 48+	pop %rbp
 49+	pop %rbx
 50+	ret /* return to caller of z80_run */
 51+
 52+	.global z80_handle_cycle_limit_int
 53+z80_handle_cycle_limit_int:
 54+	cmp 116(%rsi), %ebp
 55+	jb zskip_int
 56+	mov 112(%rsi), %ebp /* set cycle limit to sync cycle */
 57+	/* not sure this is really necessary now that IFF1 and IFF2 are geting cleared */
 58+	movl $0xFFFFFFFF, 116(%rsi) /* make sure the interrupt doesn't fire more than once */
 59+	/* disable interrupts */
 60+	movb $0, 96(%rsi)
 61+	movb $0, 97(%rsi)
 62+	add $7, %ebp
 63+	sub $2, %r9w
 64+	mov %r9w, %r14w
 65+	call z_inccycles
 66+	push %r13
 67+	call z80_write_byte_noinc
 68+	pop %r13
 69+	mov %r9w, %r14w
 70+	add $1, %r14w
 71+	shr $8, %r13w
 72+	call z_inccycles
 73+	call z80_write_byte_noinc
 74+	pop %r14 /*dispose of return address */
 75+	/* TODO: Support interrupt mode 0 and 2 */
 76+	mov $0x38, %r13w
 77+	call z80_native_addr
 78+	jmp *%r13
 79+zskip_int:
 80+	cmp 112(%rsi), %ebp
 81+	jb zskip_sync
 82+mov %r13w, 164(%rsi)
 83+	.global z80_do_sync
 84+z80_do_sync:
 85+	call z80_save_context
 86+	pop (%rsi) /*return address in native code*/
 87+	pop %r15 /* restore callee saved regsiters */
 88+	pop %r14
 89+	pop %r13
 90+	pop %r12
 91+	pop %rbp
 92+	pop %rbx
 93+zskip_sync:
 94+	ret
 95+
 96+	.global z80_halt
 97+z80_halt:
 98+	mov %edi, %r14d
 99+	sub %ebp, %r14d
100+	and $0xFFFFFFFC, %r14d
101+	add %r14d, %ebp
102+	cmp %edi, %ebp
103+	jnb z80_handle_cycle_limit_int
104+	add $4, %ebp
105+	jmp z80_handle_cycle_limit_int
106+
107+	.global z80_read_byte
108+z80_read_byte:
109+	call z_inccycles
110+z80_read_byte_noinc:
111+	cmp $0x4000, %r13w
112+	jb z80_read_ram
113+	cmp $0x8000, %r13w
114+	jae z80_read_bank
115+	cmp $0x6000, %r13w
116+	jb z80_read_ym2612
117+	/* TODO: Bank reg, YM-2612, PSG/VDP */
118+	mov $0xFF, %r13b
119+	ret
120+z80_read_ram:
121+	and $0x1FFF, %r13
122+	mov (%r11, %r13), %r13b
123+	ret
124+z80_read_bank:
125+	/* approximation of wait states for normal 68K bus access */
126+	add $3, %ebp
127+	push %rsi
128+	mov 144(%rsi), %rsi /* get system context pointer */
129+	cmpb $0, 120(%rsi) /* check bus busy flag */
130+	pop %rsi
131+	jne bus_busy
132+z80_read_bank_cont:
133+	and $0x7FFF, %r13
134+	cmp $0, %r12
135+	je slow_bank_read
136+	/* 68K memory is byte swapped */
137+	xor $1, %r13
138+	mov (%r12, %r13), %r13b
139+	ret
140+slow_bank_read:
141+	/* TODO: Call into C to implement this */
142+	ret
143+bus_busy:
144+	cmp %ebp, %edi
145+	jbe no_adjust
146+	mov %edi, %ebp
147+no_adjust:
148+	call forced_sync
149+	jmp z80_read_bank_cont
150+z80_read_ym2612:
151+	call z80_save_context
152+	mov %r13w, %di
153+	push %rsi
154+	test $8, %rsp
155+	jnz 0f
156+	call z80_read_ym
157+	jmp 1f
158+0:
159+	sub $8, %rsp
160+	call z80_read_ym
161+	add $8, %rsp
162+1:
163+	pop %rsi
164+	mov %al, %r13b
165+	call z80_load_context
166+	ret
167+
168+	.global z80_write_byte
169+z80_write_byte:
170+	call z_inccycles
171+z80_write_byte_noinc:
172+	cmp $0x4000, %r14w
173+	jb z80_write_ram
174+	cmp $0x8000, %r14w
175+	jae z80_write_bank
176+	cmp $0x6000, %r14w
177+	jb z80_write_ym2612
178+	cmp $0x6100, %r14w
179+	jb z80_write_bank_reg
180+	cmp $0x7F00, %r14w
181+	jae z80_write_vdp
182+	ret
183+z80_write_ram:
184+	and $0x1FFF, %r14
185+	mov %r13b, (%r11, %r14)
186+	mov %r14d, %r13d
187+	shr $7, %r13d
188+	bt %r13d, 152(%rsi)
189+	jnc not_code
190+	call z80_save_context
191+	mov %r14d, %edi
192+	call z80_handle_code_write
193+	mov %rax, %rsi
194+	call z80_load_context
195+not_code:
196+	ret
197+z80_write_bank:
198+slow_bank_write:
199+	/* approximation of wait states for 68K bus access */
200+	add $3, %ebp
201+	/* TODO: Call into C to implement this */
202+	ret
203+z80_write_ym2612:
204+	and $0x3, %r14w
205+	call z80_save_context
206+	mov %r14w, %di
207+	mov %r13b, %dl
208+	test $8, %rsp
209+	jnz 0f
210+	call z80_write_ym
211+	jmp 1f
212+0:
213+	sub $8, %rsp
214+	call z80_write_ym
215+	add $8, %rsp
216+1:
217+	mov %rax, %rsi
218+	jmp z80_load_context
219+z80_write_bank_reg:
220+	and $1, %r13w
221+	shr %r15w
222+	shl $8, %r13w
223+	xor %r12, %r12
224+	or %r13w, %r15w
225+	and $0x1FF, %r15w
226+	cmp $0x80, %r15w
227+	jb update_bank_ptr
228+	ret
229+update_bank_ptr:
230+	mov %r15w, %r12w
231+	shl $15, %r12
232+	add 80(%rsi), %r12
233+	ret
234+z80_write_vdp:
235+	and $0xFF, %r14w
236+	call z80_save_context
237+	mov %r14w, %di
238+	mov %r13b, %dl
239+	test $8, %rsp
240+	jnz 0f
241+	call z80_vdp_port_write
242+	jmp 1f
243+0:
244+	sub $8, %rsp
245+	call z80_vdp_port_write
246+	add $8, %rsp
247+1:
248+	mov %rax, %rsi
249+	jmp z80_load_context
250+
251+	.global z80_read_word
252+z80_read_word:
253+	call z_inccycles
254+	cmp $0x8000, %r13w
255+	jae z80_read_bank_word
256+	push %r13
257+	call z80_read_byte_noinc
258+	mov %r13b, %r14b
259+	pop %r13
260+	inc %r13
261+	call z_inccycles
262+	call z80_read_byte_noinc
263+	shl $8, %r13w
264+	mov %r14b, %r13b
265+	ret
266+
267+z80_read_bank_word:
268+	add $3, %ebp /* first read typically has 3 wait states */
269+	push %rsi
270+	mov 144(%rsi), %rsi /* get system context pointer */
271+	cmpb $0, 120(%rsi) /* check bus busy flag */
272+	pop %rsi
273+	jne bus_busy_word
274+z80_read_bank_word_cont:
275+	push %r13
276+	call z80_read_bank_cont
277+	mov %r13b, %r14b
278+	pop %r13
279+	inc %r13
280+	call z_inccycles
281+	add $4, %ebp /* second read typically has 4 wait states */
282+	push %rsi
283+	mov 144(%rsi), %rsi /* get system context pointer */
284+	cmpb $0, 120(%rsi) /* check bus busy flag */
285+	pop %rsi
286+	jne bus_busy_word2
287+z80_read_bank_word_cont2:
288+	call z80_read_bank_cont
289+	shl $8, %r13w
290+	mov %r14b, %r13b
291+	ret
292+
293+bus_busy_word:
294+	cmp %ebp, %edi
295+	jb no_adjust_word
296+	mov %edi, %ebp
297+no_adjust_word:
298+	call forced_sync
299+	jmp z80_read_bank_word_cont
300+
301+foofoo:
302+	jmp foofoo
303+
304+bus_busy_word2:
305+	cmp %ebp, %edi
306+	jb no_adjust_word2
307+	mov %edi, %ebp
308+no_adjust_word2:
309+	call forced_sync
310+	jmp z80_read_bank_word_cont2
311+blahblah:
312+	jmp blahblah
313+
314+	.global z80_write_word_highfirst
315+z80_write_word_highfirst:
316+	call z_inccycles
317+	push %r14
318+	push %r13
319+	add $1, %r14w
320+	shr $8, %r13w
321+	call z80_write_byte_noinc
322+	pop %r13
323+	pop %r14
324+	call z_inccycles
325+	call z80_write_byte_noinc
326+	ret
327+
328+	.global z80_write_word_lowfirst
329+z80_write_word_lowfirst:
330+	call z_inccycles
331+	push %r14
332+	push %r13
333+	call z80_write_byte_noinc
334+	pop %r13
335+	pop %r14
336+	add $1, %r14w
337+	shr $8, %r13w
338+	call z_inccycles
339+	call z80_write_byte_noinc
340+	ret
341+
342+	.global z80_io_read
343+z80_io_read:
344+	call z_inccycles_io
345+	/* genesis Z80 has no IO port hardware and always returns FF */
346+	mov $0xFF, %r13
347+	ret
348+
349+	.global z80_io_write
350+z80_io_write:
351+	call z_inccycles_io
352+	/* genesis Z80 has no IO port hardware and writes have no effect */
353+	ret
354+
355+	.global z80_retrans_stub
356+z80_retrans_stub:
357+	pop %r14
358+	call z80_save_context
359+	/* adjust for mov and call instructions */
360+	sub $11, %r14
361+	mov %r13d, %edi
362+	mov %r14, %rdx
363+	push %rsi
364+	call z80_retranslate_inst
365+	pop %rsi
366+	mov %rax, %r13
367+	call z80_load_context
368+	jmp *%r13
369+
370+	.global z80_native_addr
371+z80_native_addr:
372+	call z80_save_context
373+	push %rsi
374+	mov %rsi, %rdi
375+	movzx %r13w, %esi
376+	call z80_get_native_address_trans
377+	mov %rax, %r13
378+	pop %rsi
379+	call z80_load_context
380+	ret
381+
382+z80_save_context_scratch:
383+	mov %r13w, 98(%rsi)  /* scratch1 */
384+	mov %r14w, 100(%rsi) /* scratch2 */
385+
386+	.global z80_save_context
387+z80_save_context:
388+	mov %r9w, 8(%rsi)    /* SP */
389+	mov %r15w, 16(%rsi)  /* bank register */
390+	mov %bx, 18(%rsi)    /* BC */
391+	mov %cx, 20(%rsi)    /* DE */
392+	mov %ax, 22(%rsi)    /* HL */
393+	mov %dx, 24(%rsi)    /* IX */
394+	mov %r8w, 26(%rsi)   /* IY */
395+	mov %r10b, 30(%rsi)  /* A */
396+	mov %edi, 48(%rsi)   /* target_cycle */
397+	mov %ebp, 52(%rsi)   /* current_cycle */
398+	mov %r12, 72(%rsi)   /* cartridge bank pointer */
399+	ret
400+
401+
402+z80_load_context_scratch:
403+	mov 98(%rsi), %r13w  /* scratch1 */
404+	mov 100(%rsi), %r14w /* scratch2 */
405+
406+	.global z80_load_context
407+z80_load_context:
408+	mov 8(%rsi), %r9w    /* SP */
409+	mov 16(%rsi), %r15w  /* bank register */
410+	mov 18(%rsi), %bx    /* BC */
411+	mov 20(%rsi), %cx    /* DE */
412+	mov 22(%rsi), %ax    /* HL */
413+	mov 24(%rsi), %dx    /* IX */
414+	mov 26(%rsi), %r8w   /* IY */
415+	mov 30(%rsi), %r10b  /* A */
416+	mov 48(%rsi), %edi   /* target_cycle */
417+	mov 52(%rsi), %ebp   /* current_cycle */
418+	mov 64(%rsi), %r11	 /* z80 RAM */
419+	mov 72(%rsi), %r12   /* cartridge bank pointer */
420+	ret
421+
422+	.global z80_run
423+z80_run:
424+	push %rbx
425+	push %rbp
426+	push %r12
427+	push %r13
428+	push %r14
429+	push %r15
430+	mov %rdi, %rsi
431+	call z80_load_context_scratch
432+	cmpq $0, 104(%rsi)
433+	je no_extra
434+	push 104(%rsi)
435+	movq $0, 104(%rsi)
436+no_extra:
437+	jmp *(%rsi)
438+
+537, -0
  1@@ -0,0 +1,537 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "z80inst.h"
  8+#include <stdlib.h>
  9+#include <string.h>
 10+#include <stdint.h>
 11+#include <stdio.h>
 12+#include <sys/stat.h>
 13+#include <sys/types.h>
 14+#include <errno.h>
 15+#include <time.h>
 16+
 17+extern z80inst z80_tbl_a[256];
 18+extern z80inst z80_tbl_extd[0xC0-0x40];
 19+extern z80inst z80_tbl_bit[256];
 20+extern z80inst z80_tbl_ix[256];
 21+extern z80inst z80_tbl_iy[256];
 22+extern z80inst z80_tbl_ix_bit[256];
 23+extern z80inst z80_tbl_iy_bit[256];
 24+extern char *z80_mnemonics[Z80_OTDR+1];
 25+extern char * z80_regs[Z80_USE_IMMED];
 26+#define PRE_IX  0xDD
 27+#define PRE_IY  0xFD
 28+#define LD_IR16 0x01
 29+#define INC_R8  0x04
 30+#define LD_IR8  0x06
 31+#define LD_RR8  0x40
 32+#define AND_R   0xA0
 33+#define PUSH    0xC5
 34+#define POP     0xC1
 35+
 36+uint8_t * ld_ir16(uint8_t * dst, uint8_t reg, uint16_t val)
 37+{
 38+	if (reg == Z80_IX) {
 39+		*(dst++) = PRE_IX;
 40+		return ld_ir16(dst, Z80_HL, val);
 41+	} else if(reg == Z80_IY) {
 42+		*(dst++) = PRE_IY;
 43+		return ld_ir16(dst, Z80_HL, val);
 44+	} else {
 45+		*(dst++) = LD_IR16 | ((reg - Z80_BC) << 4);
 46+		*(dst++) = val & 0xFF;
 47+		*(dst++) = val >> 8;
 48+		return dst;
 49+	}
 50+}
 51+
 52+uint8_t * ld_ir8(uint8_t * dst, uint8_t reg, uint8_t val)
 53+{
 54+	if (reg <= Z80_H) {
 55+		reg = (reg - Z80_C) ^ 1;
 56+	} else {
 57+		reg = 0x7;
 58+	}
 59+	*(dst++) = LD_IR8 | (reg << 3);
 60+	*(dst++) = val;
 61+	return dst;
 62+}
 63+
 64+uint8_t * ld_rr8(uint8_t * dst, uint8_t src, uint8_t dstr)
 65+{
 66+	if (src <= Z80_H) {
 67+		src = (src - Z80_C) ^ 1;
 68+	} else {
 69+		src = 0x7;
 70+	}
 71+	if (dstr <= Z80_H) {
 72+		dstr = (dstr - Z80_C) ^ 1;
 73+	} else {
 74+		dstr = 0x7;
 75+	}
 76+	*(dst++) = LD_RR8 | (dstr << 3) | src;
 77+	return dst;
 78+}
 79+
 80+uint8_t * ld_amem(uint8_t * dst, uint16_t address)
 81+{
 82+	*(dst++) = 0x32;
 83+	*(dst++) = address & 0xFF;
 84+	*(dst++) = address >> 8;
 85+	return dst;
 86+}
 87+
 88+uint8_t * ld_mema(uint8_t * dst, uint16_t address)
 89+{
 90+	*(dst++) = 0x3A;
 91+	*(dst++) = address & 0xFF;
 92+	*(dst++) = address >> 8;
 93+	return dst;
 94+}
 95+
 96+uint8_t * push(uint8_t * dst, uint8_t reg)
 97+{
 98+	if (reg == Z80_IX) {
 99+		*(dst++) = PRE_IX;
100+		return push(dst, Z80_HL);
101+	} else if(reg == Z80_IY) {
102+		*(dst++) = PRE_IY;
103+		return push(dst, Z80_HL);
104+	} else {
105+		if (reg == Z80_AF) {
106+			reg--;
107+		}
108+		*(dst++) = PUSH | ((reg - Z80_BC) << 4);
109+		return dst;
110+	}
111+}
112+
113+uint8_t * pop(uint8_t * dst, uint8_t reg)
114+{
115+	if (reg == Z80_IX) {
116+		*(dst++) = PRE_IX;
117+		return pop(dst, Z80_HL);
118+	} else if(reg == Z80_IY) {
119+		*(dst++) = PRE_IY;
120+		return pop(dst, Z80_HL);
121+	} else {
122+		if (reg == Z80_AF) {
123+			reg--;
124+		}
125+		*(dst++) = POP | ((reg - Z80_BC) << 4);
126+		return dst;
127+	}
128+}
129+
130+uint8_t * and_r(uint8_t * dst, uint8_t reg)
131+{
132+	if (reg == Z80_IXH || reg == Z80_IXL) {
133+		*(dst++) = PRE_IX;
134+		return and_r(dst, reg - (Z80_IXL - Z80_L));
135+	} else if(reg == Z80_IYH || reg == Z80_IYL) {
136+		*(dst++) = PRE_IY;
137+		return and_r(dst, reg - (Z80_IYL - Z80_L));
138+	} else {
139+		if (reg == Z80_A) {
140+			reg = 7;
141+		} else {
142+			reg = (reg - Z80_C) ^ 1;
143+		}
144+		*(dst++) = AND_R | reg;
145+		return dst;
146+	}
147+}
148+
149+uint8_t * inc_r(uint8_t *dst, uint8_t reg)
150+{
151+	if (reg == Z80_IXH || reg == Z80_IXL) {
152+		*(dst++) = PRE_IX;
153+		return inc_r(dst, reg - (Z80_IXL - Z80_L));
154+	} else if(reg == Z80_IYH || reg == Z80_IYL) {
155+		*(dst++) = PRE_IY;
156+		return inc_r(dst, reg - (Z80_IYL - Z80_L));
157+	} else {
158+		*(dst++) = INC_R8 | reg << 3;
159+		return dst;
160+	}
161+}
162+
163+void mark_used8(uint8_t *reg_usage, uint16_t *reg_values, uint8_t reg, uint8_t init_value)
164+{
165+	reg_usage[reg] = 1;
166+	reg_values[reg] = init_value;
167+	uint8_t word_reg = z80_word_reg(reg);
168+	if (word_reg != Z80_UNUSED) {
169+		reg_usage[word_reg] = 1;
170+		reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF);
171+	}
172+}
173+
174+uint8_t alloc_reg8(uint8_t *reg_usage, uint16_t *reg_values, uint8_t init_value)
175+{
176+	for (uint8_t reg = 0; reg < Z80_BC; reg++)
177+	{
178+		if (!reg_usage[reg]) {
179+			mark_used8(reg_usage, reg_values, reg, init_value);
180+			return reg;
181+		}
182+	}
183+	return Z80_UNUSED;
184+}
185+
186+void z80_gen_test(z80inst * inst, uint8_t *instbuf, uint8_t instlen)
187+{
188+	z80inst copy;
189+	uint16_t reg_values[Z80_UNUSED];
190+	uint8_t reg_usage[Z80_UNUSED];
191+	memset(reg_values, 0, sizeof(reg_values));
192+	memset(reg_usage, 0, sizeof(reg_usage));
193+	uint8_t addr_mode = inst->addr_mode & 0x1F;
194+	uint8_t word_sized = ((inst->reg != Z80_USE_IMMED && inst->reg != Z80_UNUSED && inst->reg >= Z80_BC) || (addr_mode == Z80_REG && inst->ea_reg >= Z80_BC)) ? 1 : 0;
195+
196+	if (inst->reg == Z80_USE_IMMED || addr_mode == Z80_IMMED || addr_mode == Z80_IMMED_INDIRECT
197+		|| addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE)
198+	{
199+		memcpy(&copy, inst, sizeof(copy));
200+		inst = &copy;
201+		if ((inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET)
202+			|| (addr_mode == Z80_IMMED && inst->op != Z80_IM))
203+		{
204+			copy.immed = rand() % (word_sized ? 65536 : 256);
205+		}
206+		if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) {
207+			copy.ea_reg = rand() % 256;
208+		}
209+		if (addr_mode == Z80_IMMED_INDIRECT) {
210+			copy.immed = 0x1000 + (rand() % 256 - 128);
211+		}
212+	}
213+	uint8_t is_mem = 0;
214+	uint16_t address;
215+	int16_t offset;
216+	switch(addr_mode)
217+	{
218+	case Z80_REG:
219+		reg_usage[inst->ea_reg] = 1;
220+		if (word_sized) {
221+			reg_values[inst->ea_reg] = rand() % 65536;
222+			reg_values[z80_high_reg(inst->ea_reg)] = reg_values[inst->ea_reg] >> 8;
223+			reg_usage[z80_high_reg(inst->ea_reg)] = 1;
224+			reg_values[z80_low_reg(inst->ea_reg)] = reg_values[inst->ea_reg] & 0xFF;
225+			reg_usage[z80_low_reg(inst->ea_reg)] = 1;
226+		} else {
227+			mark_used8(reg_usage, reg_values, inst->ea_reg, rand() % 256);
228+		}
229+		break;
230+	case Z80_REG_INDIRECT:
231+		is_mem = 1;
232+		reg_values[inst->ea_reg] = 0x1000 + (rand() % 256 - 128);
233+		reg_usage[inst->ea_reg] = 1;
234+		address = reg_values[inst->ea_reg];
235+		reg_usage[z80_high_reg(inst->ea_reg)] = 1;
236+		reg_values[z80_high_reg(inst->ea_reg)] = reg_values[inst->ea_reg] >> 8;
237+		reg_usage[z80_low_reg(inst->ea_reg)] = 1;
238+		reg_values[z80_low_reg(inst->ea_reg)] = reg_values[inst->ea_reg] & 0xFF;
239+		break;
240+	case Z80_IMMED_INDIRECT:
241+		is_mem = 1;
242+		address = inst->immed;
243+		break;
244+	case Z80_IX_DISPLACE:
245+		reg_values[Z80_IX] = 0x1000;
246+		reg_usage[Z80_IX] = 1;
247+		reg_values[Z80_IXH] = 0x10;
248+		reg_usage[Z80_IXH] = 1;
249+		reg_values[Z80_IXL] = 0;
250+		reg_usage[Z80_IXL] = 1;
251+		is_mem = 1;
252+		offset = inst->ea_reg;
253+		if (offset > 0x7F) {
254+			offset -= 256;
255+		}
256+		address = 0x1000 + offset;
257+		break;
258+	case Z80_IY_DISPLACE:
259+		reg_values[Z80_IY] = 0x1000;
260+		reg_usage[Z80_IY] = 1;
261+		reg_values[Z80_IYH] = 0x10;
262+		reg_usage[Z80_IYH] = 1;
263+		reg_values[Z80_IYL] = 0;
264+		reg_usage[Z80_IYL] = 1;
265+		is_mem = 1;
266+		offset = inst->ea_reg;
267+		if (offset > 0x7F) {
268+			offset -= 256;
269+		}
270+		address = 0x1000 + offset;
271+		break;
272+	}
273+	if (inst->reg != Z80_UNUSED && inst->reg != Z80_USE_IMMED) {
274+
275+		if (word_sized) {
276+			reg_values[inst->reg] = rand() % 65536;
277+			reg_usage[z80_high_reg(inst->reg)] = 1;
278+			reg_values[z80_high_reg(inst->reg)] = reg_values[inst->reg] >> 8;
279+			reg_usage[z80_low_reg(inst->reg)] = 1;
280+			reg_values[z80_low_reg(inst->reg)] = reg_values[inst->reg] & 0xFF;
281+		} else {
282+			if (!reg_usage[inst->reg]) {
283+				reg_values[inst->reg] = rand() % 255;
284+				uint8_t word_reg = z80_word_reg(inst->reg);
285+				if (word_reg != Z80_UNUSED) {
286+					reg_usage[word_reg] = 1;
287+					reg_values[word_reg] = (reg_values[z80_high_reg(word_reg)] << 8) | (reg_values[z80_low_reg(word_reg)] & 0xFF);
288+				}
289+			}
290+		}
291+		reg_usage[inst->reg] = 1;
292+	}
293+	uint8_t counter_reg = Z80_UNUSED;
294+	if (inst->op >= Z80_JP && inst->op <= Z80_JRCC) {
295+		counter_reg = alloc_reg8(reg_usage, reg_values, 0);
296+	}
297+	puts("--------------");
298+	for (uint8_t reg = 0; reg < Z80_UNUSED; reg++) {
299+		if (reg_values[reg]) {
300+			printf("%s: %X\n", z80_regs[reg], reg_values[reg]);
301+		}
302+	}
303+	char disbuf[80];
304+	z80_disasm(inst, disbuf, 0);
305+	puts(disbuf);
306+	char pathbuf[128];
307+	sprintf(pathbuf, "ztests/%s", z80_mnemonics[inst->op]);
308+	if (mkdir(pathbuf, 0777) != 0) {
309+		if (errno != EEXIST) {
310+			fprintf(stderr, "Failed to create directory %s\n", disbuf);
311+			exit(1);
312+		}
313+	}
314+	uint8_t prog[200];
315+	uint8_t *cur = prog;
316+	uint8_t mem_val;
317+	//disable interrupts
318+	*(cur++) = 0xF3;
319+	//setup SP
320+	cur = ld_ir16(cur, Z80_SP, 0x2000);
321+	for (int i = 0; i < 2; i ++) {
322+		//setup memory
323+		if (is_mem) {
324+			mem_val = rand() % 256;
325+			cur = ld_ir8(cur, Z80_A, mem_val);
326+			cur = ld_amem(cur, address);
327+		}
328+		//setup AF
329+		cur = ld_ir16(cur, Z80_BC, reg_values[Z80_A] << 8 | (i ? 0xFF : 0));
330+		cur = push(cur, Z80_BC);
331+		cur = pop(cur, Z80_AF);
332+
333+		//setup other regs
334+		for (uint8_t reg = Z80_BC; reg <= Z80_IY; reg++) {
335+			if (reg != Z80_AF && reg != Z80_SP && (inst->op != Z80_JP || addr_mode != Z80_REG_INDIRECT || inst->ea_reg != reg)) {
336+				if (i == 1 && (z80_high_reg(reg) == counter_reg || z80_low_reg(reg) == counter_reg)) {
337+					if (z80_high_reg(reg) == counter_reg) {
338+						if (reg_usage[z80_low_reg(reg)]) {
339+							cur = ld_ir8(cur, z80_low_reg(reg), reg_values[z80_low_reg(reg)]);
340+						}
341+					} else if (reg_usage[z80_high_reg(reg)]) {
342+						cur = ld_ir8(cur, z80_high_reg(reg), reg_values[z80_high_reg(reg)]);
343+					}
344+				} else {
345+					cur = ld_ir16(cur, reg, reg_values[reg]);
346+				}
347+			}
348+		}
349+
350+		if (inst->op == Z80_JP && addr_mode == Z80_REG_INDIRECT) {
351+			uint16_t address = cur - prog + (inst->ea_reg == Z80_HL ? 3 : 4) + instlen + 1 + i;
352+			cur = ld_ir16(cur, inst->ea_reg, address);
353+		}
354+
355+		//copy instruction
356+		if (instlen == 3) {
357+			memcpy(cur, instbuf, 2);
358+			cur += 2;
359+		} else {
360+			memcpy(cur, instbuf, instlen);
361+			cur += instlen;
362+		}
363+
364+		//immed/displacement byte(s)
365+		if (addr_mode == Z80_IX_DISPLACE || addr_mode == Z80_IY_DISPLACE) {
366+			*(cur++) = inst->ea_reg;
367+		} else if ((inst->op == Z80_JP || inst->op == Z80_JPCC) && addr_mode == Z80_IMMED) {
368+			uint16_t address = cur - prog + 3 + i; //2 for immed address, 1/2 for instruction(s) to skip
369+			*(cur++) = address;
370+			*(cur++) = address >> 8;
371+		} else if(inst->op == Z80_JR || inst->op == Z80_JRCC) {
372+			*(cur++) = 1 + i; //skip one or 2 instructions based on value of i
373+		} else if (addr_mode == Z80_IMMED & inst->op != Z80_IM) {
374+			*(cur++) = inst->immed & 0xFF;
375+			if (word_sized) {
376+				*(cur++) = inst->immed >> 8;
377+			}
378+		} else if (addr_mode == Z80_IMMED_INDIRECT) {
379+			*(cur++) = inst->immed & 0xFF;
380+			*(cur++) = inst->immed >> 8;
381+		}
382+		if (inst->reg == Z80_USE_IMMED && inst->op != Z80_BIT && inst->op != Z80_RES && inst->op != Z80_SET) {
383+			*(cur++) = inst->immed & 0xFF;
384+		}
385+		if (instlen == 3) {
386+			*(cur++) = instbuf[2];
387+		}
388+		if (inst->op >= Z80_JP && inst->op <= Z80_JRCC) {
389+			cur = inc_r(cur, counter_reg);
390+			if (i) {
391+				//inc twice on second iteration so we can differentiate the two
392+				cur = inc_r(cur, counter_reg);
393+			}
394+		}
395+		if (!i) {
396+			//Save AF from first run
397+			cur = push(cur, Z80_AF);
398+			if (is_mem) {
399+				//Save memory location from frist run
400+				cur = ld_mema(cur, address);
401+				cur = push(cur, Z80_AF);
402+			}
403+		} else {
404+			//Pop AF from first run for final result
405+			for (int reg = Z80_BC; reg <= Z80_IY; reg++) {
406+				if (reg != Z80_AF && !reg_usage[reg]) {
407+					cur = pop(cur, reg);
408+					cur = push(cur, Z80_AF);
409+					cur = ld_ir8(cur, Z80_A, 0xC7);
410+					cur = and_r(cur, z80_low_reg(reg));
411+					cur = ld_rr8(cur, Z80_A, z80_low_reg(reg));
412+					cur = pop(cur, Z80_AF);
413+					reg_usage[reg] = 1;
414+					reg_usage[z80_low_reg(reg)] = 1;
415+					break;
416+				}
417+			}
418+			if (is_mem) {
419+				//Pop memory location from frist run
420+				for (int reg = Z80_BC; reg <= Z80_IY; reg++) {
421+					if (reg != Z80_AF && !reg_usage[reg]) {
422+						cur = pop(cur, reg);
423+						cur = push(cur, Z80_AF);
424+						cur = ld_mema(cur, address);
425+						cur = ld_rr8(cur, Z80_A, z80_low_reg(reg));
426+						cur = pop(cur, Z80_AF);
427+						reg_usage[reg] = 1;
428+						reg_usage[z80_low_reg(reg)] = 1;
429+						break;
430+					}
431+				}
432+			}
433+		}
434+	}
435+
436+	for (char * cur = disbuf; *cur != 0; cur++) {
437+		if (*cur == ',' || *cur == ' ') {
438+			*cur = '_';
439+		}
440+	}
441+	//save memory result
442+	if (is_mem) {
443+		if (reg_usage[Z80_A]) {
444+			cur = push(cur, Z80_AF);
445+		}
446+		cur = ld_mema(cur, address);
447+		if (reg_usage[Z80_A]) {
448+			for (int reg = 0; reg < Z80_I; reg++) {
449+				if (!reg_usage[reg]) {
450+					cur = ld_rr8(cur, Z80_A, reg);
451+					break;
452+				}
453+			}
454+			cur = pop(cur, Z80_AF);
455+		}
456+	}
457+
458+	//halt
459+	*(cur++) = 0x76;
460+	sprintf(pathbuf + strlen(pathbuf), "/%s.bin", disbuf);
461+	FILE * progfile = fopen(pathbuf, "wb");
462+	fwrite(prog, 1, cur - prog, progfile);
463+	fclose(progfile);
464+}
465+
466+
467+uint8_t should_skip(z80inst * inst)
468+{
469+	return inst->op >= Z80_DJNZ || (inst->op >= Z80_LDI && inst->op <= Z80_CPDR) || inst->op == Z80_HALT
470+		|| inst->op == Z80_RLD || inst->op == Z80_RRD || inst->op == Z80_NOP
471+		|| inst->op == Z80_DI || inst->op == Z80_EI;
472+}
473+
474+void z80_gen_all()
475+{
476+	uint8_t inst[3];
477+	for (int op = 0; op < 256; op++) {
478+		inst[0] = op;
479+		if (op == 0xCB) {
480+			for (int subop = 0; subop < 256; subop++) {
481+				if (!should_skip(z80_tbl_bit + subop)) {
482+					inst[1] = subop;
483+					z80_gen_test(z80_tbl_bit + subop, inst, 2);
484+				}
485+			}
486+		} else if(op == 0xDD) {
487+			for (int ixop = 0; ixop < 256; ixop++) {
488+				inst[1] = ixop;
489+				if (ixop == 0xCB) {
490+					for (int subop = 0; subop < 256; subop++) {
491+						if (!should_skip(z80_tbl_ix_bit + subop)) {
492+							inst[2] = subop;
493+							z80_gen_test(z80_tbl_ix_bit + subop, inst, 3);
494+						}
495+					}
496+				} else {
497+					if (!should_skip(z80_tbl_ix + ixop)) {
498+						z80_gen_test(z80_tbl_ix + ixop, inst, 2);
499+					}
500+				}
501+			}
502+		} else if(op == 0xED) {
503+			for (int subop = 0; subop < sizeof(z80_tbl_extd)/sizeof(z80inst); subop++) {
504+				if (!should_skip(z80_tbl_extd + subop)) {
505+					inst[1] = subop + 0x40;
506+					z80_gen_test(z80_tbl_extd + subop, inst, 2);
507+				}
508+			}
509+		} else if(op == 0xFD) {
510+			for (int iyop = 0; iyop < 256; iyop++) {
511+				inst[1] = iyop;
512+				if (iyop == 0xCB) {
513+					for (int subop = 0; subop < 256; subop++) {
514+						if (!should_skip(z80_tbl_iy_bit + subop)) {
515+							inst[2] = subop;
516+							z80_gen_test(z80_tbl_iy_bit + subop, inst, 3);
517+						}
518+					}
519+				} else {
520+					if (!should_skip(z80_tbl_iy + iyop)) {
521+						z80_gen_test(z80_tbl_iy + iyop, inst, 2);
522+					}
523+				}
524+			}
525+		} else {
526+			if (!should_skip(z80_tbl_a + op)) {
527+				z80_gen_test(z80_tbl_a + op, inst, 1);
528+			}
529+		}
530+	}
531+}
532+
533+int main(int argc, char ** argv)
534+{
535+	srand(time(NULL));
536+	z80_gen_all();
537+	return 0;
538+}
+126, -0
  1@@ -0,0 +1,126 @@
  2+/*
  3+ Copyright 2013 Michael Pavone
  4+ This file is part of BlastEm.
  5+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
  6+*/
  7+#include "z80inst.h"
  8+#include "z80_to_x86.h"
  9+#include "mem.h"
 10+#include "vdp.h"
 11+#include <stdio.h>
 12+#include <stdlib.h>
 13+#include <stddef.h>
 14+#include <stdarg.h>
 15+
 16+void fatal_error(char *format, ...)
 17+{
 18+	va_list args;
 19+	va_start(args, format);
 20+	vfprintf(stderr, format, args);
 21+	va_end(args);
 22+	exit(1);
 23+}
 24+
 25+uint8_t z80_ram[0x2000];
 26+
 27+uint8_t z80_unmapped_read(uint32_t location, void * context)
 28+{
 29+	return 0xFF;
 30+}
 31+
 32+void * z80_unmapped_write(uint32_t location, void * context, uint8_t value)
 33+{
 34+	return context;
 35+}
 36+
 37+const memmap_chunk z80_map[] = {
 38+	{ 0x0000, 0x4000,  0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, z80_ram, NULL, NULL, NULL,              NULL },
 39+	{ 0x4000, 0x10000, 0xFFFF, 0, 0, 0,                                  NULL,    NULL, NULL, z80_unmapped_read, z80_unmapped_write}
 40+};
 41+
 42+const memmap_chunk port_map[] = {
 43+	{ 0x0000, 0x100, 0xFF, 0, 0, 0,                                  NULL,    NULL, NULL, z80_unmapped_read, z80_unmapped_write}
 44+};
 45+
 46+void z80_next_int_pulse(z80_context * context)
 47+{
 48+	context->int_pulse_start = context->int_pulse_end = CYCLE_NEVER;
 49+}
 50+
 51+int main(int argc, char ** argv)
 52+{
 53+	long filesize;
 54+	uint8_t *filebuf;
 55+	z80_options opts;
 56+	z80_context *context;
 57+	char *fname = NULL;
 58+	uint8_t retranslate = 0;
 59+	for (int i = 1; i < argc; i++)
 60+	{
 61+		if (argv[i][0] == '-') {
 62+			switch(argv[i][1])
 63+			{
 64+			case 'r':
 65+				retranslate = 1;
 66+				break;
 67+			default:
 68+				fprintf(stderr, "Unrecognized switch -%c\n", argv[i][1]);
 69+				exit(1);
 70+			}
 71+		} else if (!fname) {
 72+			fname = argv[i];
 73+		}
 74+	}
 75+	if (!fname) {
 76+		fputs("usage: ztestrun zrom [cartrom]\n", stderr);
 77+		exit(1);
 78+	}
 79+	FILE * f = fopen(fname, "rb");
 80+	if (!f) {
 81+		fprintf(stderr, "unable to open file %s\n", fname);
 82+		exit(1);
 83+	}
 84+	fseek(f, 0, SEEK_END);
 85+	filesize = ftell(f);
 86+	fseek(f, 0, SEEK_SET);
 87+	filesize = filesize < sizeof(z80_ram) ? filesize : sizeof(z80_ram);
 88+	if (fread(z80_ram, 1, filesize, f) != filesize) {
 89+		fprintf(stderr, "error reading %s\n",fname);
 90+		exit(1);
 91+	}
 92+	fclose(f);
 93+	init_z80_opts(&opts, z80_map, 2, port_map, 1, 1, 0xFF);
 94+	context = init_z80_context(&opts);
 95+	//Z80 RAM
 96+	context->mem_pointers[0] = z80_ram;
 97+	if (retranslate) {
 98+		//run core long enough to translate code
 99+		z80_run(context, 1);
100+		for (int i = 0; i < filesize; i++)
101+		{
102+			z80_handle_code_write(i, context);
103+		}
104+		z80_assert_reset(context, context->current_cycle);
105+		z80_clear_reset(context, context->current_cycle + 3);
106+		z80_adjust_cycles(context, context->current_cycle);
107+	}
108+	z80_run(context, 1000);
109+	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\nIX: %X\nIY: %X\nSP: %X\n\nIM: %d, IFF1: %d, IFF2: %d\n",
110+		context->regs[Z80_A], context->regs[Z80_B], context->regs[Z80_C],
111+		context->regs[Z80_D], context->regs[Z80_E],
112+		(context->regs[Z80_H] << 8) | context->regs[Z80_L],
113+		(context->regs[Z80_IXH] << 8) | context->regs[Z80_IXL],
114+		(context->regs[Z80_IYH] << 8) | context->regs[Z80_IYL],
115+		context->sp, context->im, context->iff1, context->iff2);
116+	printf("Flags: SZYHXVNC\n"
117+	       "       %d%d%d%d%d%d%d%d\n", 
118+			context->flags[ZF_S], context->flags[ZF_Z], context->flags[ZF_XY] >> 5 & 1, context->flags[ZF_H], 
119+			context->flags[ZF_XY] >> 3 & 1, context->flags[ZF_PV], context->flags[ZF_N], context->flags[ZF_C]
120+	);
121+	puts("--Alternate Regs--");
122+	printf("A: %X\nB: %X\nC: %X\nD: %X\nE: %X\nHL: %X\n",
123+		context->alt_regs[Z80_A], context->alt_regs[Z80_B], context->alt_regs[Z80_C],
124+		context->alt_regs[Z80_D], context->alt_regs[Z80_E],
125+		(context->alt_regs[Z80_H] << 8) | context->alt_regs[Z80_L]);
126+	return 0;
127+}