--- /dev/null
+#include "../pico_int.h"
+#include "../memory.h"
+
+static const char str_mars[] = "MARS";
+
+struct Pico32xMem {
+  u8 sdram[0x40000];
+  u8 dram[0x40000]; // AKA fb
+  u8 m68k_rom[M68K_BANK_SIZE]; // 0x100
+};
+
+static struct Pico32xMem *Pico32xMem;
+
+static u32 p32x_reg_read16(u32 a)
+{
+  a &= 0x3e;
+
+  return Pico32x.regs[a / 2];
+}
+
+static void p32x_reg_write16(u32 a, u32 d)
+{
+  a &= 0x3e;
+
+  if (a == 0 && !(Pico32x.regs[0] & 1)) {
+    Pico32x.regs[0] |= 1;
+    Pico32xStartup();
+    return;
+  }
+}
+
+static void p32x_reg_write8(u32 a, u32 d)
+{
+  a &= 0x3f;
+
+  if (a == 1 && !(Pico32x.regs[0] & 1)) {
+    Pico32x.regs[0] |= 1;
+    Pico32xStartup();
+    return;
+  }
+}
+
+// VDP regs
+static u32 p32x_vdp_read16(u32 a)
+{
+  a &= 0x0e;
+
+  return Pico32x.vdp_regs[a / 2];
+}
+
+static void p32x_vdp_write16(u32 a, u32 d)
+{
+  a &= 0x0e;
+
+  switch (a) {
+    case 0x0a:
+      Pico32x.pending_fb = d & 1;
+      if (Pico.video.status & 8) {
+        Pico32x.vdp_regs[0x0a/2] &= ~1;
+        Pico32x.vdp_regs[0x0a/2] |= d & 1;
+      }
+      break;
+  }
+}
+
+static void p32x_vdp_write8(u32 a, u32 d)
+{
+  a &= 0x0f;
+
+  switch (a) {
+    case 0x0b:
+      Pico32x.pending_fb = d & 1;
+      if (Pico.video.status & 8) {
+        Pico32x.vdp_regs[0x0a/2] &= ~1;
+        Pico32x.vdp_regs[0x0a/2] |= d & 1;
+      }
+      break;
+  }
+}
+
+// default 32x handlers
+u32 PicoRead8_32x(u32 a)
+{
+  u32 d = 0;
+  if ((a & 0xffc0) == 0x5100) { // a15100
+    d = p32x_reg_read16(a);
+    goto out_16to8;
+  }
+
+  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) {
+    d = p32x_vdp_read16(a);
+    goto out_16to8;
+  }
+
+  if ((a & 0xfffc) == 0x30ec) { // a130ec
+    d = str_mars[a & 3];
+    goto out;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
+  return d;
+
+out_16to8:
+  if (a & 1)
+    d &= 0xff;
+  else
+    d >>= 8;
+
+out:
+  elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
+  return d;
+}
+
+u32 PicoRead16_32x(u32 a)
+{
+  u32 d = 0;
+  if ((a & 0xffc0) == 0x5100) { // a15100
+    d = p32x_reg_read16(a);
+    goto out;
+  }
+
+  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+    d = p32x_vdp_read16(a);
+    goto out;
+  }
+
+  if ((a & 0xfffc) == 0x30ec) { // a130ec
+    d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
+    goto out;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
+  return d;
+
+out:
+  elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
+  return d;
+}
+
+void PicoWrite8_32x(u32 a, u32 d)
+{
+  if ((a & 0xfc00) == 0x5000)
+    elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+
+  if ((a & 0xffc0) == 0x5100) { // a15100
+    p32x_reg_write8(a, d);
+    return;
+  }
+
+  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+    p32x_vdp_write8(a, d);
+    return;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+}
+
+void PicoWrite16_32x(u32 a, u32 d)
+{
+  if ((a & 0xfc00) == 0x5000)
+    elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
+
+  if ((a & 0xffc0) == 0x5100) { // a15100
+    p32x_reg_write16(a, d);
+    return;
+  }
+
+  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+    p32x_vdp_write16(a, d);
+    return;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
+}
+
+// hint vector is writeable
+static void PicoWrite8_hint(u32 a, u32 d)
+{
+  if ((a & 0xfffc) == 0x0070) {
+    Pico32xMem->m68k_rom[a ^ 1] = d;
+    return;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+}
+
+static void PicoWrite16_hint(u32 a, u32 d)
+{
+  if ((a & 0xfffc) == 0x0070) {
+    ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
+    return;
+  }
+
+  elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
+}
+
+#define HWSWAP(x) (((x) << 16) | ((x) >> 16))
+void PicoMemSetup32x(void)
+{
+  unsigned short *ps;
+  unsigned int *pl;
+  unsigned int rs, rs1;
+  int i;
+
+  Pico32xMem = calloc(1, sizeof(*Pico32xMem));
+  if (Pico32xMem == NULL) {
+    elprintf(EL_STATUS, "OOM");
+    return;
+  }
+
+  // generate 68k ROM
+  ps = (unsigned short *)Pico32xMem->m68k_rom;
+  pl = (unsigned int *)Pico32xMem->m68k_rom;
+  for (i = 1; i < 0xc0/4; i++)
+    pl[i] = HWSWAP(0x880200 + i * 6);
+
+  // fill with nops
+  for (i = 0xc0/2; i < 0x100/2; i++)
+    ps[i] = 0x4e71;
+
+  ps[0xc0/2] = 0x46fc;
+  ps[0xc2/2] = 0x2700; // move #0x2700,sr
+  ps[0xfe/2] = 0x60fe; // jump to self
+
+  // fill remaining mem with ROM
+  memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, M68K_BANK_SIZE - 0x100);
+
+  // cartridge area becomes unmapped
+  // XXX: we take the easy way and don't unmap ROM,
+  // so that we can avoid handling the RV bit.
+  // m68k_map_unmap(0x000000, 0x3fffff);
+
+  // MD ROM area
+  cpu68k_map_set(m68k_read8_map,   0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
+  cpu68k_map_set(m68k_read16_map,  0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
+  cpu68k_map_set(m68k_write8_map,  0x000000, M68K_BANK_SIZE - 1, PicoWrite8_hint, 1); // TODO verify
+  cpu68k_map_set(m68k_write16_map, 0x000000, M68K_BANK_SIZE - 1, PicoWrite16_hint, 1);
+
+  // 32X ROM (unbanked, XXX: consider mirroring?)
+  rs1 = rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
+  if (rs1 > 0x80000)
+    rs1 = 0x80000;
+  cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs1 - 1, Pico.rom, 0);
+  cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs1 - 1, Pico.rom, 0);
+
+  // 32X ROM (banked)
+  if (rs > 0x100000)
+    rs = 0x100000;
+  cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom, 0);
+  cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom, 0);
+}
+
 
   unsigned char pal;           // 08 1=PAL 0=NTSC\r
   unsigned char sram_reg;      // 09 SRAM reg. See SRR_* below\r
   unsigned short z80_bank68k;  // 0a\r
-  unsigned short z80_lastaddr; // this is for Z80 faking\r
-  unsigned char  pad0;\r
+  unsigned short pad0;\r
+  unsigned char  pad1;\r
   unsigned char  z80_reset;    // z80 reset held\r
   unsigned char  padDelay[2];  // 10 gamepad phase time outs, so we count a delay\r
   unsigned short eeprom_addr;  // EEPROM address register\r
   unsigned char  eeprom_cycle; // EEPROM cycle number\r
   unsigned char  eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs\r
   unsigned char  eeprom_status;\r
-  unsigned char  pad1;\r
+  unsigned char  pad2;\r
   unsigned short dma_xfers;    // 18\r
   unsigned char  eeprom_wb[2]; // EEPROM latch/write buffer\r
   unsigned int  frame_count;   // 1c for movies and idle det\r
        Rot_Comp rot_comp;\r
 } mcd_state;\r
 \r
+// XXX: this will need to be reworked for cart+cd support.\r
 #define Pico_mcd ((mcd_state *)Pico.rom)\r
 \r
+// 32X\r
+struct Pico32x\r
+{\r
+  unsigned short regs[0x20];\r
+  unsigned short vdp_regs[0x10];\r
+  unsigned char pending_fb;\r
+  unsigned char pad[3];\r
+};\r
 \r
 // area.c\r
 PICO_INTERNAL void PicoAreaPackCpu(unsigned char *cpu, int is_sub);\r
 void PicoFrameMS(void);\r
 void PicoFrameDrawOnlyMS(void);\r
 \r
+// 32x/32x.c\r
+extern struct Pico32x Pico32x;\r
+void Pico32xInit(void);\r
+void Pico32xStartup(void);\r
+void PicoReset32x(void);\r
+\r
+// 32x/memory.c\r
+unsigned int PicoRead8_32x(unsigned int a);\r
+unsigned int PicoRead16_32x(unsigned int a);\r
+void PicoWrite8_32x(unsigned int a, unsigned int d);\r
+void PicoWrite16_32x(unsigned int a, unsigned int d);\r
+void PicoMemSetup32x(void);\r
+\r
 /* avoid dependency on newer glibc */\r
 static __inline int isspace_(int c)\r
 {\r
 #define EL_IDLE    0x00010000 /* idle loop det. */\r
 #define EL_CDREGS  0x00020000 /* MCD: register access */\r
 #define EL_CDREG3  0x00040000 /* MCD: register 3 only */\r
+#define EL_32X     0x00080000\r
 \r
 #define EL_STATUS  0x40000000 /* status messages */\r
 #define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */\r