/*
	WinSTon

	Programmable Sound Generator (YM-2149) - PSG
*/

#include "..\includes\winston.h"
#include "..\includes\memory.h"
#include "..\includes\memorysnapshot.h"
#include "..\includes\sound.h"

unsigned char PSGRegisterSelect = 0;									// 0xff8800 (read/write)
unsigned char PSGRegisters[16] = { 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 };	// Register in PSG, see PSG_REG_xxxx

//-----------------------------------------------------------------------
/*
	Reset variables used in PSG
*/
void PSG_Reset(void)
{
	PSGRegisterSelect = 0;
	Memory_Clear(PSGRegisters,sizeof(unsigned char)*16);
}

//-----------------------------------------------------------------------
/*
	Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
*/
void PSG_MemorySnapShot_Capture(BOOL bSave)
{
	// Save/Restore details
	MemorySnapShot_Store(&PSGRegisterSelect,sizeof(PSGRegisterSelect));
	MemorySnapShot_Store(PSGRegisters,sizeof(PSGRegisters));
}

//-----------------------------------------------------------------------
/*
	Write byte to 0xff88000, this is used as a selector for when we read/write to address 0xff8802
*/
NAKED void PSG_WriteSelectRegister(void)
{
	__asm {
		mov		[PSGRegisterSelect],bl		// Store register to select (value in bits 0-3)
		and		[PSGRegisterSelect],0x0f	// Just store lower bits 0-3		
		ret
	}
}

//-----------------------------------------------------------------------
/*
	Read byte from 0xff8800, returns to PSG data
*/
NAKED void PSG_ReadSelectRegister(void)
{
	// Read data last selected by register
	__asm {
		xor		ebx,ebx
		mov		bl,[PSGRegisterSelect]
		mov		bl,PSGRegisters[ebx]		// Return value from PSGRegisters[]
		ret
	}
}

//-----------------------------------------------------------------------
/*
	Write byte to 0xff8802, stores according to PSG select register(write 0xff8800)
*/
NAKED void PSG_WriteDataRegister(void)
{
	__asm {
		call	Sound_Update				// Create samples up until this point with current values

		push	ecx
		xor		ecx,ecx
		mov		cl,[PSGRegisterSelect]		// Use PSGRegisterSelect as index in array
		mov		PSGRegisters[ecx],bl		// Write value to PSGRegisters[]

		cmp		cl,13						// Whenever 'write' to register 13, cause envelope to reset
		jne		not_wave
		mov		DWORD PTR [bEnvelopeFreqFlag],TRUE
		mov		DWORD PTR [bWriteEnvelopeFreq],TRUE
not_wave:
		// Check registers 8,9 and 10 which are 'amplitude' for each channel and store if wrote to(to check for sample playback)
		cmp		cl,8
		jne		not_channel_a_amp
		mov		DWORD PTR [bWriteChannelAAmp],TRUE
not_channel_a_amp:
		cmp		cl,9
		jne		not_channel_b_amp
		mov		DWORD PTR [bWriteChannelBAmp],TRUE
not_channel_b_amp:
		cmp		cl,10
		jne		not_channel_c_amp
		mov		DWORD PTR [bWriteChannelCAmp],TRUE
not_channel_c_amp:
		pop		ecx
		ret
	}
}

//-----------------------------------------------------------------------
/*
	Read byte from 0xff8802, returns 0xff
*/
NAKED void PSG_ReadDataRegister(void)
{
	__asm {
		xor		ebx,ebx
		mov		bl,0xff	
		ret
	}
}
