#include "turbofm.h"
#include "mame/Ym2203_Emu.h"
#include <string.h>

void tfm_write(TFM *TFM,int chip,int reg,unsigned char val) {
	switch(chip)
	{
	case 0:
		YM2203Write(TFM->chip0,0,reg);
		YM2203Write(TFM->chip0,1,val);
		break;
	case 1:
		YM2203Write(TFM->chip1,0,reg);
		YM2203Write(TFM->chip1,1,val);
		break;
	}
}

static void tfm_frame(TFM *TFM) {
	if(TFM->tfc) tfc_frame(&TFM->TFCP); else tfd_frame(&TFM->TFDP);
}

static inline void tfm_render(TFM *TFM,short int *buf,int size) {
	memset(buf,0,size*sizeof(short int));
	YM2203UpdateOne(TFM->chip0,buf,size);
	YM2203UpdateOne(TFM->chip1,buf,size);
}

void tfm_player_render(TFM *TFM,short int *buf,int size) {
    int frameLen;
	
    frameLen=TFM->rate/50;
	
    if(TFM->scount+size<frameLen)
    {
        tfm_render(TFM,buf,size);
        TFM->scount+=size;
    }
    else
    {
        tfm_render(TFM,buf,frameLen-TFM->scount);
        buf+=(frameLen-TFM->scount);
        size-=(frameLen-TFM->scount);
        TFM->scount=0;
        tfm_frame(TFM);
		
        while(1)
        {
            if(size<frameLen)
            {
                TFM->scount=size;
                tfm_render(TFM,buf,size);
                break;
            }
            else
            {
                tfm_render(TFM,buf,frameLen);
                tfm_frame(TFM);
				
                buf+=frameLen;
                size-=frameLen;
            }
        }
    }
}

BOOL tfm_open(TFM *TFM,const char *filename,unsigned char *data,int size,int clock,int rate) {
	TFM->data = data;
	TFM->size = size;
	
	TFM->rate=rate;
	TFM->scount=0;

	TFM->chip0=YM2203Init(clock,rate);
	TFM->chip1=YM2203Init(clock,rate);
	
	if(!TFM->chip0||!TFM->chip1)
	{
		free(TFM->data);
		return FALSE;
	}
	
	YM2203ResetChip(TFM->chip0);
	YM2203ResetChip(TFM->chip1);
	tfm_write(TFM,0,0x27,0);
	tfm_write(TFM,1,0x27,0);
	
	if(filename[strlen(filename)-1]=='c'||filename[strlen(filename)-1]=='C')
	{
		TFM->tfc=TRUE;
		tfc_init(&TFM->TFCP,TFM,TFM->data);
		tfc_play(&TFM->TFCP,TRUE);
	}
	else
	{
		TFM->tfc=FALSE;
		tfd_init(&TFM->TFDP,TFM,TFM->data);
		tfd_play(&TFM->TFDP,TRUE);
	}

	return TRUE;
}

void tfm_close(TFM *TFM) {
	YM2203Shutdown(TFM->chip0);
	YM2203Shutdown(TFM->chip1);
}
