<commit_before>//
//  DspController.cpp
//  C700
//
//  Created by osoumen on 2015/11/14.
//
//

#include "DspController.h"

//-----------------------------------------------------------------------------
unsigned char DspController::dspregAccCode[] =
{
    0x8F ,0x30 ,0xF1 //       	mov SPC_CONTROL,#$30
    ,0x8F ,0x6C ,0xF2 //       	mov SPC_REGADDR,#DSP_FLG
    ,0x8F ,0x00 ,0xF3 //       	mov SPC_REGDATA,#$a0
    ,0x8D ,0x00       //     	mov y,#0
    ,0xE8 ,0x00       //     	mov a,#0
    ,0x8F ,0x00 ,0x04 //       	mov $04,#$00
    ,0x8F ,0x06 ,0x05 //       	mov $05,#$06
    // initloop:
    ,0xD7 ,0x04       //     	mov [$04]+y,a	; 7
    ,0x3A ,0x04       //     	incw $04		; 6
    ,0x78 ,0x7E ,0x05 //       	cmp $05,#$7e	; 5
    ,0xD0 ,0xF7       //     	bne initloop	; 4
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0
    // ack:
    ,0x8F ,0x77 ,0xF7 //       	mov SPC_PORT3,#$77
    // loop:
    ,0x64 ,0xF4       //     	cmp a,SPC_PORT0		; 3
    ,0xF0 ,0xFC       //     	beq loop			; 2
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0		; 3
    ,0x30 ,0x18       //     	bmi toram			; 2
    ,0xF8 ,0xF6       //     	mov x,SPC_PORT2		; 3
    ,0xD8 ,0xF2       //     	mov SPC_REGADDR,x	; 4
    ,0xFA ,0xF5 ,0xF3 //       	mov SPC_REGDATA,SPC_PORT1
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a		; 4
    // 	; wait 64 - 32 cycle
    ,0xC8 ,0x4C       //     	cmp x,#DSP_KON	; 3
    ,0xF0 ,0x04       //     	beq wait	; 4
    ,0xC8 ,0x5C       //     	cmp x,#DSP_KOF	; 3
    ,0xD0 ,0xE7       //     	bne loop	; 4
    // wait:
    ,0x8D ,0x05       //     	mov y,#5	; 2
    // -
    ,0xFE ,0xFE       //     	dbnz y,-	; 4/6
    ,0x00             //   	nop			; 2
    ,0x2F ,0xE0       //     	bra loop	; 4
    // toram:
    ,0x5D             //   	mov x,a
    ,0x28 ,0x40       //     	and a,#$40
    ,0xD0 ,0x0B       //     	bne blockTrans
    ,0x8D ,0x00       //     	mov y,#0
    ,0xE4 ,0xF5       //     	mov a,SPC_PORT1
    ,0xD7 ,0xF6       //     	mov [SPC_PORT2]+y,a
    ,0x7D             //   	mov a,x
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    ,0x2F ,0xD0       //     	bra loop
    // blockTrans:
    ,0xFA ,0xF6 ,0x04 //       	mov $04,SPC_PORT2
    ,0xFA ,0xF7 ,0x05 //       	mov $05,SPC_PORT3
    ,0x7D             //   	mov a,x
    ,0x8D ,0x00       //     	mov y,#0
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    // loop2:
    ,0x64 ,0xF4       //     	cmp a,SPC_PORT0
    ,0xF0 ,0xFC       //     	beq loop2
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0
    ,0x30 ,0xBA       //     	bmi ack
    ,0x5D             //   	mov x,a
    ,0xE4 ,0xF5       //     	mov a,SPC_PORT1
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0xE4 ,0xF6       //     	mov a,SPC_PORT2
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0xE4 ,0xF7       //     	mov a,SPC_PORT3
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0x7D             //   	mov a,x
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    ,0x2F ,0xE0       //     	bra loop2
};

DspController::DspController()
{
    mIsHwAvailable = false;
    
    pthread_mutex_init(&mEmuMtx, 0);
    pthread_mutex_init(&mHwMtx, 0);
    
#ifndef USE_OPENSPC
    mDsp.init();
#endif
    unsigned char spcdata[0x10200] = "SNES-SPC700 Sound File Data v0.30\x1A\x1A";
    memset(spcdata+33, 0, 0x10200-33);
    spcdata[0x25] = dspAccCodeAddr & 0xff;
    spcdata[0x26] = (dspAccCodeAddr >> 8) & 0xff;
    spcdata[0x2b] = 0xef;
    spcdata[0x100 + 0xf0] = 0x0a;
    memcpy(&spcdata[0x100 + dspAccCodeAddr], dspregAccCode, sizeof(dspregAccCode));
#ifndef USE_OPENSPC
    mDsp.load_spc(spcdata, 0x10200);
#else
    OSPC_Init(spcdata, 0x10200);
#endif
    mPort0stateEmu = 0x01;
    mWaitPort = -1;
    mWaitByte = 0;
#ifndef USE_OPENSPC
    do {
        mDsp.play(2, NULL);
    } while (mDsp.read_port(0, 3) != 0x77);
#else
    do {
        OSPC_Run(1, NULL, 0);
    } while ((unsigned char)OSPC_ReadPort3() != 0x77);
#endif
    
    memset(mDspMirror, 0xef, 128 * sizeof(int));
    WriteDsp(DSP_EDL, 0x00, true);
    WriteDsp(DSP_ESA, 0x06, true);
    WriteDsp(DSP_FLG, 0x00, true);
    WriteDsp(DSP_EFB, 0x00, true);
    
    // エコー音量をオフ
    WriteDsp(DSP_EVOLL, 0x00, true);
    WriteDsp(DSP_EVOLR, 0x00, true);
    
    // NONをオフ
    WriteDsp(DSP_NON, 0x00, true);
    
    // PMONをオフ
    WriteDsp(DSP_PMON, 0x00, true);

    mSpcDev.setDeviceAddedFunc(onDeviceAdded, this);
    mSpcDev.setDeviceRemovedFunc(onDeviceRemoved, this);
    mSpcDev.Init();
}

DspController::~DspController()
{
    mSpcDev.Close();
    mFifo.Clear();
    pthread_mutex_destroy(&mHwMtx);
    pthread_mutex_destroy(&mEmuMtx);
}

void DspController::onDeviceAdded(void *ref)
{
    DspController   *This = reinterpret_cast<DspController*>(ref);
    
    int err = 0;
    
    pthread_mutex_lock(&This->mHwMtx);
    
    // ハードウェアリセット
    This->mSpcDev.HwReset();
    // ソフトウェアリセット
    This->mSpcDev.SwReset();
    
    // $BBAA 待ち
    err = This->mSpcDev.WaitReady();
    if (err) {
        return;
    }
    
    // ノイズ回避のため音量を0に
    unsigned char dspWrite[2];
    err = 0xcc-1;
    dspWrite[0] = DSP_MVOLL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_MVOLR;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_EVOLL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_EVOLR;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    
    // EDL,ESAを初期化
    dspWrite[0] = DSP_EDL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_ESA;
    dspWrite[1] = 0x06; // DIRの直後
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    usleep(240000); // EDL,ESAを変更したので240ms待ち
    
    // DSPアクセス用コードを転送<commit_msg>Emuとの一貫性を改善<commit_after>//
//  DspController.cpp
//  C700
//
//  Created by osoumen on 2015/11/14.
//
//

#include "DspController.h"

//-----------------------------------------------------------------------------
unsigned char DspController::dspregAccCode[] =
{
    0x8F ,0x00 ,0xF1 //       	mov SPC_CONTROL,#$00
    ,0x8F ,0x6C ,0xF2 //       	mov SPC_REGADDR,#DSP_FLG
    ,0x8F ,0x00 ,0xF3 //       	mov SPC_REGDATA,#$00
    ,0x8D ,0x00       //     	mov y,#0
    ,0xE8 ,0x00       //     	mov a,#0
    ,0x8F ,0x00 ,0x04 //       	mov $04,#$00
    ,0x8F ,0x06 ,0x05 //       	mov $05,#$06
    // initloop:
    ,0xD7 ,0x04       //     	mov [$04]+y,a	; 7
    ,0x3A ,0x04       //     	incw $04		; 6
    ,0x78 ,0x7E ,0x05 //       	cmp $05,#$7e	; 5
    ,0xD0 ,0xF7       //     	bne initloop	; 4
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0
    // ack:
    ,0x8F ,0x77 ,0xF7 //       	mov SPC_PORT3,#$77
    // loop:
    ,0x64 ,0xF4       //     	cmp a,SPC_PORT0		; 3
    ,0xF0 ,0xFC       //     	beq loop			; 2
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0		; 3
    ,0x30 ,0x18       //     	bmi toram			; 2
    ,0xF8 ,0xF6       //     	mov x,SPC_PORT2		; 3
    ,0xD8 ,0xF2       //     	mov SPC_REGADDR,x	; 4
    ,0xFA ,0xF5 ,0xF3 //       	mov SPC_REGDATA,SPC_PORT1
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a		; 4
    // 	; wait 64 - 32 cycle
    ,0xC8 ,0x4C       //     	cmp x,#DSP_KON	; 3
    ,0xF0 ,0x04       //     	beq wait	; 4
    ,0xC8 ,0x5C       //     	cmp x,#DSP_KOF	; 3
    ,0xD0 ,0xE7       //     	bne loop	; 4
    // wait:
    ,0x8D ,0x05       //     	mov y,#5	; 2
    // -
    ,0xFE ,0xFE       //     	dbnz y,-	; 4/6
    ,0x00             //   	nop			; 2
    ,0x2F ,0xE0       //     	bra loop	; 4
    // toram:
    ,0x5D             //   	mov x,a
    ,0x28 ,0x40       //     	and a,#$40
    ,0xD0 ,0x0B       //     	bne blockTrans
    ,0x8D ,0x00       //     	mov y,#0
    ,0xE4 ,0xF5       //     	mov a,SPC_PORT1
    ,0xD7 ,0xF6       //     	mov [SPC_PORT2]+y,a
    ,0x7D             //   	mov a,x
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    ,0x2F ,0xD0       //     	bra loop
    // blockTrans:
    ,0xFA ,0xF6 ,0x04 //       	mov $04,SPC_PORT2
    ,0xFA ,0xF7 ,0x05 //       	mov $05,SPC_PORT3
    ,0x7D             //   	mov a,x
    ,0x8D ,0x00       //     	mov y,#0
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    // loop2:
    ,0x64 ,0xF4       //     	cmp a,SPC_PORT0
    ,0xF0 ,0xFC       //     	beq loop2
    ,0xE4 ,0xF4       //     	mov a,SPC_PORT0
    ,0x30 ,0xBA       //     	bmi ack
    ,0x5D             //   	mov x,a
    ,0xE4 ,0xF5       //     	mov a,SPC_PORT1
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0xE4 ,0xF6       //     	mov a,SPC_PORT2
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0xE4 ,0xF7       //     	mov a,SPC_PORT3
    ,0xD7 ,0x04       //     	mov [$04]+y,a
    ,0x3A ,0x04       //     	incw $04
    ,0x7D             //   	mov a,x
    ,0xC4 ,0xF4       //     	mov SPC_PORT0,a
    ,0x2F ,0xE0       //     	bra loop2
};

DspController::DspController()
{
    mIsHwAvailable = false;
    
    pthread_mutex_init(&mEmuMtx, 0);
    pthread_mutex_init(&mHwMtx, 0);
    
#ifndef USE_OPENSPC
    mDsp.init();
#endif
    unsigned char spcdata[0x10200] = "SNES-SPC700 Sound File Data v0.30\x1A\x1A";
    memset(spcdata+33, 0, 0x10200-33);
    spcdata[0x25] = dspAccCodeAddr & 0xff;
    spcdata[0x26] = (dspAccCodeAddr >> 8) & 0xff;
    spcdata[0x2b] = 0xef;
    spcdata[0x100 + 0xf0] = 0x0a;
    spcdata[0x10100 + DSP_MVOLL] = 0;
    spcdata[0x10100 + DSP_MVOLR] = 0;
    spcdata[0x10100 + DSP_EVOLL] = 0;
    spcdata[0x10100 + DSP_EVOLR] = 0;
    spcdata[0x10100 + DSP_FLG] = 0x20;
    spcdata[0x10100 + DSP_EDL] = 0x00;
    spcdata[0x10100 + DSP_ESA] = 0x06;
    memcpy(&spcdata[0x100 + dspAccCodeAddr], dspregAccCode, sizeof(dspregAccCode));
#ifndef USE_OPENSPC
    mDsp.load_spc(spcdata, 0x10200);
#else
    OSPC_Init(spcdata, 0x10200);
#endif
    mPort0stateEmu = 0x01;
    mWaitPort = -1;
    mWaitByte = 0;
#ifndef USE_OPENSPC
    do {
        mDsp.play(2, NULL);
    } while (mDsp.read_port(0, 3) != 0x77);
#else
    do {
        OSPC_Run(1, NULL, 0);
    } while ((unsigned char)OSPC_ReadPort3() != 0x77);
#endif
    
    memset(mDspMirror, 0xef, 128 * sizeof(int));
    // NONをオフ
    WriteDsp(DSP_NON, 0x00, true);
    
    // PMONをオフ
    WriteDsp(DSP_PMON, 0x00, true);

    mSpcDev.setDeviceAddedFunc(onDeviceAdded, this);
    mSpcDev.setDeviceRemovedFunc(onDeviceRemoved, this);
    mSpcDev.Init();
}

DspController::~DspController()
{
    mSpcDev.Close();
    mFifo.Clear();
    pthread_mutex_destroy(&mHwMtx);
    pthread_mutex_destroy(&mEmuMtx);
}

void DspController::onDeviceAdded(void *ref)
{
    DspController   *This = reinterpret_cast<DspController*>(ref);
    
    int err = 0;
    
    pthread_mutex_lock(&This->mHwMtx);
    
    // ハードウェアリセット
    This->mSpcDev.HwReset();
    // ソフトウェアリセット
    This->mSpcDev.SwReset();
    
    // $BBAA 待ち
    err = This->mSpcDev.WaitReady();
    if (err) {
        return;
    }
    
    // ノイズ回避のため音量を0に
    unsigned char dspWrite[2];
    err = 0xcc-1;
    dspWrite[0] = DSP_MVOLL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_MVOLR;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_EVOLL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_EVOLR;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    
    // EDL,ESAを初期化
    dspWrite[0] = DSP_FLG;
    dspWrite[1] = 0x20;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_EDL;
    dspWrite[1] = 0;
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    dspWrite[0] = DSP_ESA;
    dspWrite[1] = 0x06; // DIRの直後
    err = This->mSpcDev.UploadRAMDataIPL(dspWrite, 0x00f2, 2, err+1);
    if (err < 0) {
        return;
    }
    usleep(240000); // EDL,ESAを変更したので240ms待ち
    
    // DSPアクセス用コードを転送
{'fraction_non_alphanumeric': 0.15134963983218555, 'fraction_numerical': 0.09229794981397926, 'mean_word_length': 1.5947833230642843, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6153708', 'n_tokens_mistral': 6337, 'n_tokens_neox': 5876, 'n_words': 1030}