Skip to content

Commit

Permalink
Implemented proper VRC6 audio emulation for mappers 24 and 26
Browse files Browse the repository at this point in the history
Fixes DS-Homebrew#15, related to sound in these titles:
- Esper Dream 2.
- Mouryou Senki Madara.
- Mega Man RushJet VRC6 edition.
- Mega Man II RushJet VRC6 edition.
- super Mario Bros VRC6 expanded.
  • Loading branch information
Dartz150 committed Jun 5, 2024
1 parent 8f2bc2f commit 77a89b7
Show file tree
Hide file tree
Showing 6 changed files with 435 additions and 226 deletions.
77 changes: 70 additions & 7 deletions arm7/include/s_vrc6.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,76 @@
extern "C" {
#endif

void VRC6SoundInstall(void);
Int32 VRC6SoundRender1(void);
Int32 VRC6SoundRender2(void);
Int32 VRC6SoundRender3(void);
void VRC6SoundWrite9000(Uint address, Uint value);
void VRC6SoundWriteA000(Uint address, Uint value);
void VRC6SoundWriteB000(Uint address, Uint value);
#include <string.h>
#include "nestypes.h"
#include "audiosys.h"
#include "handler.h"
#include "nsf6502.h"
#include "nsdout.h"

#define NES_BASECYCLES (21477270)
#define CPS_SHIFT 16

typedef struct
{
Uint32 cps;
Int32 cycles;
Uint32 spd;
Uint8 regs[3];
Uint8 update;
Uint8 adr;
Uint8 mute;
} VRC6_SQUARE;

typedef struct
{
Uint32 cps;
Int32 cycles;
Uint32 spd;
Uint32 output;
Uint8 regs[3];
Uint8 update;
Uint8 adr;
Uint8 mute;
} VRC6_SAW;

typedef struct
{
VRC6_SQUARE square[2];
VRC6_SAW saw;
Uint32 mastervolume;
} VRC6SOUND;

extern VRC6SOUND vrc6s;

//TODO: Move DivFix to a common header file
Uint32 DivFix(Uint32 p1, Uint32 p2, Uint32 fix);

void VRC6SoundSquareReset(VRC6_SQUARE *ch);
void VRC6SoundSawReset(VRC6_SAW *ch);
void VRC6SoundReset(void);

// VRC6 Mapper 24 Install and Render
void VRC6SoundInstall_24(void);
Int32 VRC6SoundRender1_24(void);
Int32 VRC6SoundRender2_24(void);
Int32 VRC6SoundRender3_24(void);

// VRC6 Mapper 26 Install and Render
void VRC6SoundInstall_26(void);
Int32 VRC6SoundRender1_26(void);
Int32 VRC6SoundRender2_26(void);
Int32 VRC6SoundRender3_26(void);

// VRC6 Mapper 24 Write functions
void VRC6SoundWrite9000_24(Uint address, Uint value);
void VRC6SoundWriteA000_24(Uint address, Uint value);
void VRC6SoundWriteB000_24(Uint address, Uint value);

// VRC6 Mapper 26 Write functions
void VRC6SoundWrite9000_26(Uint address, Uint value);
void VRC6SoundWriteA000_26(Uint address, Uint value);
void VRC6SoundWriteB000_26(Uint address, Uint value);

#ifdef __cplusplus
}
Expand Down
29 changes: 26 additions & 3 deletions arm7/source/arm7main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "calc_lut.h"
#include "mixer.h"
#include "audio_capture.h"
#include "s_vrc6.h"


s16 buffer [MIXBUFSIZE * 20]; // Sound Samples Buffer Size, adjust size if necessary

Expand Down Expand Up @@ -333,7 +335,8 @@ int32_t VRC6SoundRender2();
int32_t VRC6SoundRender3();

// VRC must be inited to get raw pcm data from ARM9
void VRC6SoundInstall();
void VRC6SoundInstall_24();
void VRC6SoundInstall_26();
void FDSSoundInstall();
void readAPU();

Expand Down Expand Up @@ -422,6 +425,25 @@ static short int accum;
void mix(int chan)
{
int mapper = IPC_MAPPER;

int32_t (*VRC6SoundRender1)();
int32_t (*VRC6SoundRender2)();
int32_t (*VRC6SoundRender3)();

if (mapper == 24) {
VRC6SoundRender1 = VRC6SoundRender1_24;
VRC6SoundRender2 = VRC6SoundRender2_24;
VRC6SoundRender3 = VRC6SoundRender3_24;
} else if (mapper == 26) {
VRC6SoundRender1 = VRC6SoundRender1_26;
VRC6SoundRender2 = VRC6SoundRender2_26;
VRC6SoundRender3 = VRC6SoundRender3_26;
} else {
VRC6SoundRender1 = NULL;
VRC6SoundRender2 = NULL;
VRC6SoundRender3 = NULL;
}

if (!APU_paused)
{
int i;
Expand Down Expand Up @@ -482,7 +504,7 @@ void mix(int chan)
}

//pcmBuffer+=MIXBUFSIZE;
if (mapper == 24 || mapper == 26 || mapper == 256)
if (VRC6SoundRender1 && VRC6SoundRender2 && VRC6SoundRender3)
{
pcmBuffer+=MIXBUFSIZE;
for (i = 0; i < MIXBUFSIZE; i++)
Expand Down Expand Up @@ -717,7 +739,8 @@ void nesmain()
// Change func name to "DPCMSoundInstall();"
APUSoundInstall();
FDSSoundInstall();
VRC6SoundInstall();
VRC6SoundInstall_24();
VRC6SoundInstall_26();

resetAPU();
NESVolume(0);
Expand Down
56 changes: 36 additions & 20 deletions arm7/source/s_apu.c
Original file line number Diff line number Diff line change
Expand Up @@ -809,15 +809,31 @@ void APUSoundWrite(Uint address, Uint value)
{
if(0x9000 <= address && address <= 0x9002)
{
VRC6SoundWrite9000(address, value);
VRC6SoundWrite9000_24(address, value);
}
else if(0xA000 <= address && address <= 0xA002)
{
VRC6SoundWriteA000(address, value);
VRC6SoundWriteA000_24(address, value);
}
else if(0xB000 <= address && address <= 0xB002)
{
VRC6SoundWriteB000(address, value);
VRC6SoundWriteB000_24(address, value);
}
}

else if(0x8000 <= address && address < 0xffff)
{
if(0x9000 <= address && address <= 0x9002)
{
VRC6SoundWrite9000_26(address, value);
}
else if(0xA000 <= address && address <= 0xA002)
{
VRC6SoundWriteA000_26(address, value);
}
else if(0xB000 <= address && address <= 0xB002)
{
VRC6SoundWriteB000_26(address, value);
}
}
}
Expand Down Expand Up @@ -881,23 +897,23 @@ void __fastcall APU4015Reg()
}
}

static Uint32 DivFix(Uint32 p1, Uint32 p2, Uint32 fix)
{
Uint32 ret;
ret = p1 / p2;
p1 = p1 % p2;/* p1 = p1 - p2 * ret; */
while (fix--)
{
p1 += p1;
ret += ret;
if (p1 >= p2)
{
p1 -= p2;
ret++;
}
}
return ret;
}
// Uint32 DivFix(Uint32 p1, Uint32 p2, Uint32 fix)
// {
// Uint32 ret;
// ret = p1 / p2;
// p1 = p1 % p2;/* p1 = p1 - p2 * ret; */
// while (fix--)
// {
// p1 += p1;
// ret += ret;
// if (p1 >= p2)
// {
// p1 -= p2;
// ret++;
// }
// }
// return ret;
// }

static void NESAPUSoundSquareReset(NESAPU_SQUARE *ch)
{
Expand Down
Loading

0 comments on commit 77a89b7

Please sign in to comment.