adding ym2413
authorhiroshica <hiroshica@gmail.com>
Mon, 24 Feb 2020 04:42:53 +0000 (13:42 +0900)
committerkub <derkub@gmail.com>
Tue, 28 Jul 2020 20:04:32 +0000 (22:04 +0200)
squashed commits:
YM2413追加中
一通り実装したけどポートへの書き込み方が不明でまだ音が出ない
細かい修正(未テスト)
resetで初期化されるのをなんとかしたい
sound 初期化と終了を追加してみた
SN76496を参考にYM2413のアップデート方法を変更してみた
stereoフラグをアップデートサイズに変更
処理順番を整理したら音が出た
stateセーブに対応してみた
addition: Support for the Japanese Mark-III extended FM sound source unit

17 files changed:
.gitignore
.gitmodules
AUTHORS
pico/pico.c
pico/pico.h
pico/pico_int.h
pico/sms.c
pico/sound/emu2413 [new submodule]
pico/sound/sound.c
pico/state.c
platform/common/common.mak
platform/common/menu_pico.c
platform/common/menu_pico.h
platform/gizmondo/Makefile
platform/gizmondo/menu.c
platform/libretro/libretro.c
platform/psp/menu.c

index b7ef852..022f987 100644 (file)
@@ -19,3 +19,7 @@ obj/
 .opk_data
 PicoDrive
 PicoDrive.opk
+pico_int_offs.h
+amalgamate
+textfilter
+
index 36091a2..b778188 100644 (file)
@@ -4,3 +4,6 @@
 [submodule "cpu/cyclone"]
        path = cpu/cyclone
        url = https://github.com/notaz/cyclone68000.git
+[submodule "pico/sound/emu2413"]
+       path = pico/sound/emu2413
+       url = https://github.com/digital-sound-antiques/emu2413.git
diff --git a/AUTHORS b/AUTHORS
index d479110..36dd861 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -53,4 +53,5 @@ Additional thanks
 * Paul Cercueil for OpenDingux port.
 * Inder for some graphics.
 * squarepusher for some libretro fixes
+* Hiroshica for support of japanese Mark-III extended YM2413 sound
 * Anyone else I forgot. Let me know if it's you.
index 579cdd0..577701b 100644 (file)
@@ -38,6 +38,7 @@ void PicoInit(void)
   PicoInitMCD();\r
   PicoSVPInit();\r
   Pico32xInit();\r
+  PsndInit();\r
 \r
   PicoDrawInit();\r
   PicoDraw2Init();\r
@@ -50,6 +51,7 @@ void PicoExit(void)
     PicoExitMCD();\r
   PicoCartUnload();\r
   z80_exit();\r
+  PsndExit();\r
 \r
   free(Pico.sv.data);\r
   Pico.sv.data = NULL;\r
index d8c5959..5dac5c2 100644 (file)
@@ -55,7 +55,7 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
 #define POPT_EN_Z80         (1<< 2)\r
 #define POPT_EN_STEREO      (1<< 3)\r
 #define POPT_ALT_RENDERER   (1<< 4) // 00 00x0\r
-// unused                   (1<< 5)\r
+#define POPT_EN_YM2413      (1<< 5)\r
 // unused                   (1<< 6)\r
 #define POPT_ACC_SPRITES    (1<< 7)\r
 #define POPT_DIS_32C_BORDER (1<< 8) // 00 0x00\r
index 2d688a9..1a1205f 100644 (file)
@@ -434,6 +434,7 @@ struct PicoSound
   unsigned int dac_pos;                 // last DAC position in Q20\r
   unsigned int fm_pos;                  // last FM position in Q20\r
   unsigned int psg_pos;                 // last PSG position in Q16\r
+  unsigned int ym2413_pos;              // last YM2413 position\r
 };\r
 \r
 // run tools/mkoffsets pico/pico_int_offs.h if you change these\r
@@ -897,10 +898,13 @@ PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m);
 PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m);\r
 \r
 // sound/sound.c\r
+PICO_INTERNAL void PsndInit(void);\r
+PICO_INTERNAL void PsndExit(void);\r
 PICO_INTERNAL void PsndReset(void);\r
 PICO_INTERNAL void PsndStartFrame(void);\r
 PICO_INTERNAL void PsndDoDAC(int cycle_to);\r
 PICO_INTERNAL void PsndDoPSG(int line_to);\r
+PICO_INTERNAL void PsndDoYM2413(int line_to);\r
 PICO_INTERNAL void PsndDoFM(int line_to);\r
 PICO_INTERNAL void PsndClear(void);\r
 PICO_INTERNAL void PsndGetSamples(int y);\r
index 0f4a48a..5ddbebd 100644 (file)
 #include "pico_int.h"
 #include "memory.h"
 #include "sound/sn76496.h"
+#include "sound/emu2413/emu2413.h"
+
+extern void YM2413_regWrite(unsigned reg);
+extern void YM2413_dataWrite(unsigned data);
+
+
+static unsigned short ymflag = 0xffff;
 
 static unsigned char vdp_data_read(void)
 {
@@ -100,42 +107,61 @@ static unsigned char z80_sms_in(unsigned short a)
   unsigned char d = 0;
 
   elprintf(EL_IO, "z80 port %04x read", a);
-  a &= 0xc1;
-  switch (a)
-  {
-    case 0x00:
-    case 0x01:
-      d = 0xff;
-      break;
-
-    case 0x40: /* V counter */
-      d = Pico.video.v_counter;
-      elprintf(EL_HVCNT, "V counter read: %02x", d);
-      break;
-
-    case 0x41: /* H counter */
-      d = Pico.m.rotate++;
-      elprintf(EL_HVCNT, "H counter read: %02x", d);
-      break;
-
-    case 0x80:
-      d = vdp_data_read();
-      break;
-
-    case 0x81:
-      d = vdp_ctl_read();
+  if((a&0xff)>= 0xf0){
+    switch((a&0xff))
+    {
+    case 0xf0:
+      // FM reg port
       break;
-
-    case 0xc0: /* I/O port A and B */
-      d = ~((PicoIn.pad[0] & 0x3f) | (PicoIn.pad[1] << 6));
+    case 0xf1:
+      // FM data port
       break;
-
-    case 0xc1: /* I/O port B and miscellaneous */
-      d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30;
-      d |= ~(PicoIn.pad[1] >> 2) & 0x0f;
+    case 0xf2:
+      // bit 0 = 1 active FM Pac
+      if (PicoIn.opt & POPT_EN_YM2413){
+        d = ymflag;
+        //printf("read FM Check = %02x\n", d);
+      }
       break;
+    }
+  }
+  else{
+    a &= 0xc1;
+    switch (a)
+    {
+      case 0x00:
+      case 0x01:
+        d = 0xff;
+        break;
+
+      case 0x40: /* V counter */
+        d = Pico.video.v_counter;
+        elprintf(EL_HVCNT, "V counter read: %02x", d);
+        break;
+
+      case 0x41: /* H counter */
+        d = Pico.m.rotate++;
+        elprintf(EL_HVCNT, "H counter read: %02x", d);
+        break;
+
+      case 0x80:
+        d = vdp_data_read();
+        break;
+
+      case 0x81:
+        d = vdp_ctl_read();
+        break;
+
+      case 0xc0: /* I/O port A and B */
+        d = ~((PicoIn.pad[0] & 0x3f) | (PicoIn.pad[1] << 6));
+        break;
+
+      case 0xc1: /* I/O port B and miscellaneous */
+        d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30;
+        d |= ~(PicoIn.pad[1] >> 2) & 0x0f;
+        break;
+    }
   }
-
   elprintf(EL_IO, "ret = %02x", d);
   return d;
 }
@@ -143,27 +169,52 @@ static unsigned char z80_sms_in(unsigned short a)
 static void z80_sms_out(unsigned short a, unsigned char d)
 {
   elprintf(EL_IO, "z80 port %04x write %02x", a, d);
-  a &= 0xc1;
-  switch (a)
-  {
-    case 0x01:
-      Pico.ms.io_ctl = d;
-      break;
-
-    case 0x40:
-    case 0x41:
-      if ((d & 0x90) == 0x90)
-        PsndDoPSG(Pico.m.scanline);
-      SN76496Write(d);
-      break;
 
-    case 0x80:
-      vdp_data_write(d);
-      break;
-
-    case 0x81:
-      vdp_ctl_write(d);
-      break;
+  if((a&0xff)>= 0xf0){
+    switch((a&0xff))
+    {
+      case 0xf0:
+        // FM reg port
+        YM2413_regWrite(d);
+        //printf("write FM register = %02x\n", d);
+        break;
+      case 0xf1:
+        // FM data port
+        YM2413_dataWrite(d);
+        //printf("write FM data = %02x\n", d);
+        break;
+      case 0xf2:
+        // bit 0 = 1 active FM Pac
+        if (PicoIn.opt & POPT_EN_YM2413){
+          ymflag = d;
+          //printf("write FM Check = %02x\n", d);
+        }
+        break;
+    }
+  }
+  else{
+    a &= 0xc1;
+    switch (a)
+    {
+      case 0x01:
+        Pico.ms.io_ctl = d;
+        break;
+
+      case 0x40:
+      case 0x41:
+        if ((d & 0x90) == 0x90)
+          PsndDoPSG(Pico.m.scanline);
+        SN76496Write(d);
+        break;
+
+      case 0x80:
+        vdp_data_write(d);
+        break;
+
+      case 0x81:
+        vdp_ctl_write(d);
+        break;
+    }
   }
 }
 
@@ -212,6 +263,7 @@ void PicoResetMS(void)
 {
   z80_reset();
   PsndReset(); // pal must be known here
+  ymflag = 0xffff;
 }
 
 void PicoPowerMS(void)
diff --git a/pico/sound/emu2413 b/pico/sound/emu2413
new file mode 160000 (submodule)
index 0000000..9f1dcf8
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 9f1dcf848d0e33e775e49352f7bc83a9c0e87a81
index 0b371f2..6204a66 100644 (file)
@@ -13,6 +13,7 @@
 #include "../pico_int.h"\r
 #include "../cd/cue.h"\r
 #include "mix.h"\r
+#include "emu2413/emu2413.h"\r
 \r
 void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo;\r
 \r
@@ -25,6 +26,25 @@ short cdda_out_buffer[2*1152];
 // sn76496\r
 extern int *sn76496_regs;\r
 \r
+// ym2413\r
+#define YM2413_CLK 3579545\r
+OPLL old_opll;\r
+static OPLL *opll = NULL;\r
+unsigned YM2413_reg;\r
+\r
+\r
+PICO_INTERNAL void PsndInit(void)\r
+{\r
+  opll = OPLL_new(YM2413_CLK, PicoIn.sndRate);\r
+  OPLL_setChipType(opll,0);\r
+  OPLL_reset(opll);\r
+}\r
+\r
+PICO_INTERNAL void PsndExit(void)\r
+{\r
+  OPLL_delete(opll);\r
+  opll = NULL;\r
+}\r
 \r
 PICO_INTERNAL void PsndReset(void)\r
 {\r
@@ -59,6 +79,12 @@ void PsndRerate(int preserve_state)
   SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PicoIn.sndRate);\r
   if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state\r
 \r
+  if(opll != NULL){\r
+    if (preserve_state) memcpy(&old_opll, opll, sizeof(OPLL)); // remember old state\r
+    OPLL_setRate(opll, PicoIn.sndRate);\r
+    OPLL_reset(opll);\r
+  }\r
+\r
   if (state)\r
     free(state);\r
 \r
@@ -161,6 +187,48 @@ PICO_INTERNAL void PsndDoPSG(int line_to)
   SN76496Update(PicoIn.sndOut + pos, len, stereo);\r
 }\r
 \r
+#if 0\r
+PICO_INTERNAL void PsndDoYM2413(int line_to)\r
+{\r
+  int pos, len;\r
+  int stereo = 0;\r
+  short *buf;\r
+\r
+  // Q16, number of samples since last call\r
+  len = ((line_to+1) * Pico.snd.smpl_mult) - Pico.snd.ym2413_pos;\r
+  if (len <= 0)\r
+    return;\r
+\r
+  // update position and calculate buffer offset and length\r
+  pos = (Pico.snd.ym2413_pos+0x8000) >> 16;\r
+  Pico.snd.ym2413_pos += len;\r
+  len = ((Pico.snd.ym2413_pos+0x8000) >> 16) - pos;\r
+\r
+  if (!PicoIn.sndOut || !(PicoIn.opt & POPT_EN_YM2413))\r
+    return;\r
+\r
+  if (PicoIn.opt & POPT_EN_STEREO) {\r
+    stereo = 1;\r
+    pos <<= 1;\r
+  }\r
+\r
+  buf = PicoIn.sndOut + pos;\r
+  while (len-- > 0) {\r
+    int16_t getdata = OPLL_calc(opll) * 3;\r
+    *buf++ += getdata;\r
+    buf += stereo; // only left for stereo, to be mixed to right later\r
+  }\r
+}\r
+#endif\r
+\r
+void YM2413_regWrite(unsigned data){\r
+  OPLL_writeIO(opll,0,data);\r
+}\r
+void YM2413_dataWrite(unsigned data){\r
+  OPLL_writeIO(opll,1,data);\r
+}\r
+\r
+\r
 PICO_INTERNAL void PsndDoFM(int cyc_to)\r
 {\r
   int pos, len;\r
@@ -249,7 +317,7 @@ PICO_INTERNAL void PsndClear(void)
   if (!(PicoIn.opt & POPT_EN_FM))\r
     memset32(PsndBuffer, 0, PicoIn.opt & POPT_EN_STEREO ? len*2 : len);\r
   // drop pos remainder to avoid rounding errors (not entirely correct though)\r
-  Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = 0;\r
+  Pico.snd.dac_pos = Pico.snd.fm_pos = Pico.snd.psg_pos = Pico.snd.ym2413_pos = 0;\r
 }\r
 \r
 \r
@@ -344,6 +412,7 @@ static int PsndRenderMS(int offset, int length)
 {\r
   int stereo = (PicoIn.opt & 8) >> 3;\r
   int psglen = ((Pico.snd.psg_pos+0x8000) >> 16);\r
+  int ym2413len = ((Pico.snd.ym2413_pos+0x8000) >> 16);\r
 \r
   pprof_start(sound);\r
 \r
@@ -355,11 +424,25 @@ static int PsndRenderMS(int offset, int length)
       SN76496Update(psgbuf, length-psglen, stereo);\r
   }\r
 \r
+  if (length-ym2413len > 0) {\r
+    short *ym2413buf = PicoIn.sndOut + (ym2413len << stereo);\r
+    Pico.snd.ym2413_pos += (length-ym2413len) << 16;\r
+    int len = (length-ym2413len);\r
+    if (PicoIn.opt & POPT_EN_YM2413){\r
+      while (len-- > 0) {\r
+        int16_t getdata = OPLL_calc(opll) * 3;\r
+        *ym2413buf += getdata;\r
+        ym2413buf += 1<<stereo;\r
+      }\r
+    }\r
+  }\r
+\r
   // upmix to "stereo" if needed\r
   if (PicoIn.opt & POPT_EN_STEREO) {\r
-    int i, *p;\r
-    for (i = length, p = (void *)PicoIn.sndOut; i > 0; i--, p++)\r
-      *p |= *p << 16;\r
+    int i;\r
+    short *p;\r
+    for (i = length, p = (short *)PicoIn.sndOut; i > 0; i--, p+=2)\r
+      *(p + 1) = *p;\r
   }\r
 \r
   pprof_end(sound);\r
index b0b6a33..da6b6fd 100644 (file)
 \r
 #include "../cpu/sh2/sh2.h"\r
 #include "sound/ym2612.h"\r
+#include "sound/emu2413/emu2413.h"\r
 #include "state.h"\r
 \r
-// sn76496\r
+// sn76496 & ym2413\r
 extern int *sn76496_regs;\r
+extern OPLL old_opll;\r
 \r
 static arearw    *areaRead;\r
 static arearw    *areaWrite;\r
@@ -123,6 +125,8 @@ typedef enum {
   CHUNK_DRAM,\r
   CHUNK_32XPAL,\r
   CHUNK_32X_EVT,\r
+  CHUNK_YM2413,   //40\r
+  //rename\r
   CHUNK_32X_FIRST = CHUNK_MSH2,\r
   CHUNK_32X_LAST = CHUNK_32X_EVT,\r
   // add new stuff here\r
@@ -133,6 +137,7 @@ typedef enum {
   //\r
   CHUNK_DEFAULT_COUNT,\r
   CHUNK_CARTHW_ = CHUNK_CARTHW,  // 64 (defined in PicoInt)\r
+\r
 } chunk_name_e;\r
 \r
 static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {\r
@@ -179,6 +184,7 @@ static const char * const chunk_names[CHUNK_DEFAULT_COUNT] = {
   "DRAM",\r
   "PAL",\r
   "events",\r
+  "YM2413",   //40\r
 };\r
 \r
 static int write_chunk(chunk_name_e name, int len, void *data, void *file)\r
@@ -283,6 +289,8 @@ static int state_save(void *file)
     memcpy(buff, pcd_event_times, sizeof(pcd_event_times));\r
     CHECKED_WRITE(CHUNK_CD_EVT, 0x40, buff);\r
 \r
+    CHECKED_WRITE(CHUNK_YM2413, sizeof(OPLL), &old_opll);\r
+\r
     len = gfx_context_save(buf2);\r
     CHECKED_WRITE(CHUNK_CD_GFX, len, buf2);\r
     len = cdc_context_save(buf2);\r
@@ -442,6 +450,7 @@ static int state_load(void *file)
 \r
       case CHUNK_IOPORTS: CHECKED_READ_BUFF(PicoMem.ioports); break;\r
       case CHUNK_PSG:     CHECKED_READ2(28*4, sn76496_regs); break;\r
+      case CHUNK_YM2413:  CHECKED_READ2(sizeof(OPLL), &old_opll); break;\r
       case CHUNK_FM:\r
         ym2612_regs = YM2612GetRegs();\r
         CHECKED_READ2(0x200+4, ym2612_regs);\r
index 599f246..8afe5d3 100644 (file)
@@ -124,6 +124,7 @@ endif
 # sound
 SRCS_COMMON += $(R)pico/sound/sound.c
 SRCS_COMMON += $(R)pico/sound/sn76496.c $(R)pico/sound/ym2612.c
+SRCS_COMMON += $(R)pico/sound/emu2413/emu2413.c
 ifneq "$(ARCH)$(asm_mix)" "arm1"
 SRCS_COMMON += $(R)pico/sound/mix.c
 endif
index 1d46e63..2e0e127 100644 (file)
@@ -501,6 +501,7 @@ static menu_entry e_menu_adv_options[] =
        mee_onoff     ("Emulate YM2612 (FM)",      MA_OPT2_ENABLE_YM2612, PicoIn.opt, POPT_EN_FM),
        mee_onoff     ("Disable YM2612 SSG-EG",    MA_OPT2_DISABLE_YM_SSG,PicoIn.opt, POPT_DIS_FM_SSGEG),
        mee_onoff     ("Emulate SN76496 (PSG)",    MA_OPT2_ENABLE_SN76496,PicoIn.opt, POPT_EN_PSG),
+       mee_onoff     ("Emulate YM2413 (FM)",      MA_OPT2_ENABLE_YM2413 ,PicoIn.opt, POPT_EN_YM2413),
        mee_onoff     ("gzip savestates",          MA_OPT2_GZIP_STATES,   currentConfig.EmuOpt, EOPT_GZIP_SAVES),
        mee_onoff     ("Don't save last used ROM", MA_OPT2_NO_LAST_ROM,   currentConfig.EmuOpt, EOPT_NO_AUTOSVCFG),
        mee_onoff     ("Disable idle loop patching",MA_OPT2_NO_IDLE_LOOPS,PicoIn.opt, POPT_DIS_IDLE_DET),
index d15113f..0abbfb0 100644 (file)
@@ -50,6 +50,7 @@ typedef enum
        MA_OPT2_ENABLE_YM2612,
        MA_OPT2_DISABLE_YM_SSG,
        MA_OPT2_ENABLE_SN76496,
+       MA_OPT2_ENABLE_YM2413,
        MA_OPT2_GZIP_STATES,
        MA_OPT2_NO_LAST_ROM,
        MA_OPT2_RAMTIMINGS,     /* gp2x */
index 7228be5..31530d7 100644 (file)
@@ -64,6 +64,7 @@ OBJS += pico/sound/sound.o
 endif\r
 OBJS += pico/sound/mix_asm.o\r
 OBJS += pico/sound/sn76496.o pico/sound/ym2612.o\r
+OBJS += pico/sound/emu2413/emu2413.o\r
 # zlib\r
 OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \\r
        zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o\r
index 1045f47..47778be 100644 (file)
@@ -931,6 +931,7 @@ menu_entry opt2_entries[] =
        { "Emulate Z80",               MB_ONOFF, MA_OPT2_ENABLE_Z80,    &PicoIn.opt, 0x00004, 0, 0, 1, 1 },\r
        { "Emulate YM2612 (FM)",       MB_ONOFF, MA_OPT2_ENABLE_YM2612, &PicoIn.opt, 0x00001, 0, 0, 1, 1 },\r
        { "Emulate SN76496 (PSG)",     MB_ONOFF, MA_OPT2_ENABLE_SN76496,&PicoIn.opt, 0x00002, 0, 0, 1, 1 },\r
+       { "Emulate YM2413 (FM)",       MB_ONOFF, MA_OPT2_ENABLE_YM2413, &PicoIn.opt, 0x00020, 0, 0, 1, 1 },\r
        { "Double buffering",          MB_ONOFF, MA_OPT2_DBLBUFF,       &currentConfig.EmuOpt, 0x8000, 0, 0, 1, 1 },\r
        { "Wait for V-sync (slow)",    MB_ONOFF, MA_OPT2_VSYNC,         &currentConfig.EmuOpt, 0x2000, 0, 0, 1, 1 },\r
        { "gzip savestates",           MB_ONOFF, MA_OPT2_GZIP_STATES,   &currentConfig.EmuOpt, 0x0008, 0, 0, 1, 1 },\r
index 0794f55..23cd3df 100644 (file)
@@ -1366,7 +1366,7 @@ void retro_init(void)
    sceBlock = getVMBlock();
 #endif
 
-   PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80
+   PicoIn.opt = POPT_EN_STEREO|POPT_EN_FM|POPT_EN_PSG|POPT_EN_Z80|POPT_EN_YM2413
       | POPT_EN_MCD_PCM|POPT_EN_MCD_CDDA|POPT_EN_MCD_GFX
       | POPT_EN_32X|POPT_EN_PWM
       | POPT_ACC_SPRITES|POPT_DIS_32C_BORDER;
index fc31b8e..1b71423 100644 (file)
@@ -1119,6 +1119,7 @@ menu_entry opt2_entries[] =
        { "Emulate Z80",               MB_ONOFF, MA_OPT2_ENABLE_Z80,     &PicoIn.opt, 0x00004, 0, 0, 1, 1 },
        { "Emulate YM2612 (FM)",       MB_ONOFF, MA_OPT2_ENABLE_YM2612,  &PicoIn.opt, 0x00001, 0, 0, 1, 1 },
        { "Emulate SN76496 (PSG)",     MB_ONOFF, MA_OPT2_ENABLE_SN76496, &PicoIn.opt, 0x00002, 0, 0, 1, 1 },
+       { "Emulate YM2413 (FM)",       MB_ONOFF, MA_OPT2_ENABLE_YM2413,  &PicoIn.opt, 0x00020, 0, 0, 1, 1 },
        { "gzip savestates",           MB_ONOFF, MA_OPT2_GZIP_STATES,    &currentConfig.EmuOpt, 0x00008, 0, 0, 1, 1 },
        { "Don't save last used ROM",  MB_ONOFF, MA_OPT2_NO_LAST_ROM,    &currentConfig.EmuOpt, 0x00020, 0, 0, 1, 1 },
        { "Status line in main menu",  MB_ONOFF, MA_OPT2_STATUS_LINE,    &currentConfig.EmuOpt, 0x20000, 0, 0, 1, 1 },