summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/config.c9
-rw-r--r--source/main.c9
-rw-r--r--source/spec.c49
-rw-r--r--source/z80.c16
4 files changed, 77 insertions, 6 deletions
diff --git a/source/config.c b/source/config.c
index 8198290..b16f1b3 100644
--- a/source/config.c
+++ b/source/config.c
@@ -40,7 +40,8 @@ const char *conf_filename = "SPEC48.CFG";
const char *conf_entry[DSSPEC_NUM_CONFIG_ITEMS]=
{
"sticky_shift",
- "load_default_snapshot"
+ "load_default_snapshot",
+ "sound"
};
@@ -49,7 +50,8 @@ const char *conf_entry[DSSPEC_NUM_CONFIG_ITEMS]=
int DSSPEC_Config[DSSPEC_NUM_CONFIG_ITEMS]=
{
TRUE,
- FALSE
+ FALSE,
+ TRUE
};
@@ -126,6 +128,9 @@ const char *ConfigDesc(DSSPEC_ConfigItem item)
case DSSPEC_LOAD_DEFAULT_SNAPSHOT:
return "LOAD DEFAULT SNAPSHOT";
+ case DSSPEC_SOUND:
+ return "SOUND";
+
default:
return "UNKNOWN";
}
diff --git a/source/main.c b/source/main.c
index 46eccfe..b7d3318 100644
--- a/source/main.c
+++ b/source/main.c
@@ -235,8 +235,16 @@ int main(int argc, char *argv[])
{
Z80 *z80;
int quit = FALSE;
+ float mix[12] = {1.0, 1.0};
gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, FALSE);
+ ndspInit();
+
+ ndspSetOutputMode(NDSP_OUTPUT_MONO);
+ ndspChnSetInterp(0, NDSP_INTERP_NONE);
+ ndspChnSetRate(0, SAMPLE_RATE);
+ ndspChnSetFormat(0, NDSP_FORMAT_MONO_PCM8);
+ ndspChnSetMix(0, mix);
FB_Init();
@@ -352,6 +360,7 @@ int main(int argc, char *argv[])
}
}
+ ndspExit();
gfxExit();
return 0;
diff --git a/source/spec.c b/source/spec.c
index 6cdc7c6..ef132d4 100644
--- a/source/spec.c
+++ b/source/spec.c
@@ -59,6 +59,7 @@
#define ED_LOAD 0xf1
#define SCAN_CYCLES 224
+#define FRAME_CYCLES 69888
/* The 3DS screen
*/
@@ -153,6 +154,17 @@ static struct
{7,0x10}, {7,0x08}, {7,0x04}, {7,0x02}, {7,0x01} /* B - SPACE */
};
+/* Sound
+*/
+#define SAMPLE_BUFF_SZ (SAMPLE_RATE/60)
+
+#define SAMPLE_CYCLE (FRAME_CYCLES/SAMPLE_BUFF_SZ)
+
+static u8 *sample[2];
+static int sound_buffer;
+static u8 sound_level;
+static int sound_ptr;
+static ndspWaveBuf wave_buff[2];
/* ---------------------------------------- PRIVATE FUNCTIONS
*/
@@ -160,7 +172,7 @@ static void RomPatch(void)
{
static const Z80Byte save[]=
{
- 0xed, ED_SAVE, /* (SAVE) */
+ 0xed, ED_SAVE, /* (SAVE) */
0xc9, /* RET */
0xff /* End of patch */
};
@@ -263,6 +275,13 @@ static int CheckTimers(Z80 *z80, Z80Val val)
{
int ret = TRUE;
+ if (DSSPEC_Config[DSSPEC_SOUND] &&
+ Z80GetTimer(z80, Z80_TIMER_1) >= SAMPLE_CYCLE)
+ {
+ Z80SetTimer(z80, Z80_TIMER_1, 0);
+ sample[sound_buffer][sound_ptr++] = sound_level;
+ }
+
if (val > SCAN_CYCLES)
{
int y;
@@ -287,6 +306,15 @@ static int CheckTimers(Z80 *z80, Z80Val val)
Z80Interrupt(z80,0xff);
+ if (DSSPEC_Config[DSSPEC_SOUND])
+ {
+ ndspChnWaveBufAdd(0, wave_buff + sound_buffer);
+ sound_buffer = !sound_buffer;
+ memset(sample[sound_buffer], 0, SAMPLE_BUFF_SZ);
+ sound_ptr = 0;
+ Z80SetTimer(z80, Z80_TIMER_1, 0);
+ }
+
ret = FALSE;
}
@@ -298,8 +326,6 @@ static int CheckTimers(Z80 *z80, Z80Val val)
{
DrawScanline(y, scanline);
}
-
- /* TODO: Process sound emulation */
}
return ret;
@@ -361,6 +387,18 @@ void SPECInit(Z80 *z80)
Z80LodgeCallback(z80,eZ80_EDHook,EDCallback);
Z80LodgeCallback(z80,eZ80_Instruction,CheckTimers);
+ /* Create sound buffers and wave vars
+ */
+ sample[0] = linearAlloc(SAMPLE_BUFF_SZ);
+ sample[1] = linearAlloc(SAMPLE_BUFF_SZ);
+
+ wave_buff[0].data_vaddr = sample[0];
+ wave_buff[0].nsamples = SAMPLE_BUFF_SZ;
+ wave_buff[1].data_vaddr = sample[1];
+ wave_buff[1].nsamples = SAMPLE_BUFF_SZ;
+
+ sound_buffer = 0;
+
SPECReset(z80);
}
@@ -465,6 +503,7 @@ void SPECWritePort(Z80 *z80, Z80Word port, Z80Byte val)
{
case 0xfe: /* ULA */
border = val & 0x07;
+ sound_level = val & 0x10 ? 128:0;
break;
case 0xfb: /* ZX Printer */
@@ -486,11 +525,13 @@ void SPECReset(Z80 *z80)
matrix[f]=0x1f;
Z80Reset(z80);
- Z80ResetCycles(z80,0);
border = 0;
scanline = 0;
+ sound_buffer = 0;
+ sound_ptr = 0;
+
/* Set up screen
*/
c=0;
diff --git a/source/z80.c b/source/z80.c
index e5f6c92..790aeec 100644
--- a/source/z80.c
+++ b/source/z80.c
@@ -170,6 +170,10 @@ Z80 *Z80Init(Z80ReadMemory read_memory,
void Z80Reset(Z80 *cpu)
{
PRIV->cycle=0;
+ PRIV->timer[Z80_TIMER_1]=0;
+ PRIV->timer[Z80_TIMER_2]=0;
+ PRIV->timer[Z80_TIMER_3]=0;
+
cpu->PC=0;
cpu->AF.w=0xffff;
@@ -209,6 +213,18 @@ void Z80ResetCycles(Z80 *cpu, Z80Val cycles)
}
+Z80Val Z80GetTimer(Z80 *cpu, Z80Timer timer)
+{
+ return PRIV->timer[timer];
+}
+
+
+void Z80SetTimer(Z80 *cpu, Z80Timer timer, Z80Val cycles)
+{
+ PRIV->timer[timer] = cycles;
+}
+
+
int Z80LodgeCallback(Z80 *cpu, Z80CallbackReason reason, Z80Callback callback)
{
int f;