.opk_data
PicoDrive
PicoDrive.opk
+pico_int_offs.h
+amalgamate
+textfilter
+
[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
* 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.
PicoInitMCD();\r
PicoSVPInit();\r
Pico32xInit();\r
+ PsndInit();\r
\r
PicoDrawInit();\r
PicoDraw2Init();\r
PicoExitMCD();\r
PicoCartUnload();\r
z80_exit();\r
+ PsndExit();\r
\r
free(Pico.sv.data);\r
Pico.sv.data = NULL;\r
#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
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
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
#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)
{
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;
}
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;
+ }
}
}
{
z80_reset();
PsndReset(); // pal must be known here
+ ymflag = 0xffff;
}
void PicoPowerMS(void)
--- /dev/null
+Subproject commit 9f1dcf848d0e33e775e49352f7bc83a9c0e87a81
#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
// 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
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
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
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
{\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
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
\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
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
//\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
"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
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
\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
# 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
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),
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 */
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
{ "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, ¤tConfig.EmuOpt, 0x8000, 0, 0, 1, 1 },\r
{ "Wait for V-sync (slow)", MB_ONOFF, MA_OPT2_VSYNC, ¤tConfig.EmuOpt, 0x2000, 0, 0, 1, 1 },\r
{ "gzip savestates", MB_ONOFF, MA_OPT2_GZIP_STATES, ¤tConfig.EmuOpt, 0x0008, 0, 0, 1, 1 },\r
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;
{ "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, ¤tConfig.EmuOpt, 0x00008, 0, 0, 1, 1 },
{ "Don't save last used ROM", MB_ONOFF, MA_OPT2_NO_LAST_ROM, ¤tConfig.EmuOpt, 0x00020, 0, 0, 1, 1 },
{ "Status line in main menu", MB_ONOFF, MA_OPT2_STATUS_LINE, ¤tConfig.EmuOpt, 0x20000, 0, 0, 1, 1 },