/***************************************************************************
 *   Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team              *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
 ***************************************************************************/

#ifndef __SPU_H__
#define __SPU_H__

#ifdef __cplusplus
extern "C" {
#endif

#include "psxcommon.h"
#include "plugins.h"
#include "r3000a.h"
#include "psxmem.h"

#define H_SPUirqAddr     0x0da4
#define H_SPUaddr        0x0da6
#define H_SPUdata        0x0da8
#define H_SPUctrl        0x0daa
#define H_SPUstat        0x0dae
#define H_SPUon1         0x0d88
#define H_SPUon2         0x0d8a
#define H_SPUoff1        0x0d8c
#define H_SPUoff2        0x0d8e

void CALLBACK SPUirq(void);

#ifdef __cplusplus
}
#endif

#ifdef VIOPSF_REMOVED
#else
struct drvimpl_buffer
{
	u8 * ptr;
	u32 len;
	u32 fil;
	u32 cur;
};
extern struct drvimpl_buffer sound_buffer;

#define SPU_SAMPLE_RENDER \
{ \
	while (psxRegs.cycle - psxRegs.intCycle[PSXINT_SPUASYNC].sCycle >= psxRegs.intCycle[PSXINT_SPUASYNC].cycle)  \
	{ \
		SPU_render(sound_buffer.ptr + sound_buffer.fil, 4); \
		sound_buffer.fil += 4; \
		/*オーバーフロー防止のため念のため。 本来実行されてはいけない*/ \
		if (sound_buffer.fil >= sound_buffer.len) \
		{ \
			sound_buffer.cur = 0; \
			sound_buffer.fil = 0; \
		} \
		psxRegs.intCycle[PSXINT_SPUASYNC].sCycle += psxRegs.intCycle[PSXINT_SPUASYNC].cycle; \
	} \
}

#define SPU_SAMPLE_RENDER_REC \
{ \
	iStoreCycle(); \
	pcold = pc; \
	\
	j32Ptr[0] = (u32*)x86Ptr; \
	MOV32MtoR(EDX, (u32)&psxRegs.cycle); \
	SUB32MtoR(EDX, (u32)&psxRegs.intCycle[PSXINT_SPUASYNC].sCycle); \
	CMP32MtoR(EDX, (u32)&psxRegs.intCycle[PSXINT_SPUASYNC].cycle); \
	j8Ptr[0] = JB8(0); \
	PUSH32I(4); \
	MOV32MtoR(EAX, (u32)&sound_buffer.ptr); \
	ADD32MtoR(EAX, (u32)&sound_buffer.fil); \
	PUSH32R(EAX); \
	CALL32M((u32)&SPU_render); \
	\
	MOV32MtoR(EAX,(u32) &sound_buffer.fil); \
	ADD32ItoR(EAX, 4); \
	MOV32RtoM((u32)&sound_buffer.fil, EAX); \
	/*MOV32MtoR(EAX, (u32)&sound_buffer.fil);*/ \
	CMP32MtoR(EAX, (u32)&sound_buffer.len); \
	j8Ptr[1] = JB8(0); \
	MOV32ItoM((u32)&sound_buffer.fil, 0); \
	MOV32ItoM((u32)&sound_buffer.cur, 0); \
	x86SetJ8(j8Ptr[1]); \
	\
	MOV32MtoR(ECX, (u32)&psxRegs.intCycle[PSXINT_SPUASYNC].sCycle); \
	ADD32MtoR(ECX, (u32)&psxRegs.intCycle[PSXINT_SPUASYNC].cycle); \
	MOV32RtoM((u32)&psxRegs.intCycle[PSXINT_SPUASYNC].sCycle, ECX); \
	\
	j32Ptr[1] = JMP32(0); \
	*(j32Ptr[1]) = (s8*)(j32Ptr[0]) - x86Ptr; \
	\
	x86SetJ8(j8Ptr[0]); \
}
#endif

#endif
