NSFPlay/NSFplug メモ/修正箇所

デバッグ版でビルドしたり共有 DLL の使用の有無を変えると nsfplug_ui.dll の
ダイアログを表示時に落ちる

nsfplug_ui.h の

class NSFplug_Model
{
public:
  xgm::NSF *sdat;           // データラッパへのポインタ
  xgm::NSFPlayer *pl;       // プレイヤーへのポインタ
  xgm::NSFPlayerConfigIni *cf; // プレイヤーのコンフィグ情報
  bool no_save_config;
};

cf の内部データを kbnsfplug.kpi と nsfplug_ui.dll の両側から読み書きしてメモリエラーが
発生する可能性がある

nsfplug_ui.dll をプラグインに内蔵させることで回避

ダイアログ表示時に落ちるのは、ダイアログ表示や解放等の前に

    AFX_MANAGE_STATE(AfxGetStaticModuleState( ));

を呼ぶことで回避

/////////////////////////////////////////////////////////////////////////

NSInfoDialog.cpp

BOOL NSFInfoDialog::OnInitDialog() 
{
...
	for (int i=0; i<CHILDREN; ++i)
	{
		//GetDlgItem(m_child[i])->GetWindowRect(m_child_rect[i]);
        //by Kobarin
		CWnd *w = GetDlgItem(m_child[i]);
        if(!w)continue;
        w->GetWindowRect(m_child_rect[i]);}
		//ここまで
        ScreenToClient(m_child_rect[i]); // MoveWindow uses WindowRect relative to Client
	}

void NSFInfoDialog::OnSize(UINT nType, int cx, int cy)
{
	int dx = cx - m_base_size.cx;
	int dy = cy - m_base_size.cy;
	for (int i=0; i<CHILDREN; ++i)
	{
		CWnd* w = GetDlgItem(m_child[i]);
        if(!w)continue;//by Kobarin
        ...


void NSFInfoDialog::SetInfo(NSF *nsf)
{
  CString ss;
  //static char buf[4096], *p;//del by Kobarin
  int i=0;
  ...
  m_info = "";//(CString)(buf);//by Kobarin
  m_song = (nsf->song+1);
  m_songslider.SetRange(1, nsf->songs);
  ...

/////////////////////////////////////////////////////////////////////////

KeyDialog.cpp

//void KeyDialog::OnTimer(UINT nIDEvent)
void KeyDialog::OnTimer(UINT_PTR nIDEvent) //by Kobarin

/////////////////////////////////////////////////////////////////////////

KeyDialog.h

  //afx_msg void OnTimer(UINT nIDEvent);
  afx_msg void OnTimer(UINT_PTR nIDEvent);//by Kobarin

/////////////////////////////////////////////////////////////////////////

NSFMemoryDialog.cpp

//void NSFMemoryDialog::OnTimer(UINT nIDEvent) 
void NSFMemoryDialog::OnTimer(UINT_PTR nIDEvent) //by Kobarin

BEGIN_MESSAGE_MAP(NSFMemoryDialog, CDialog)
	//{{AFX_MSG_MAP(NSFMemoryDialog)
...
    ON_WM_CLOSE() //by Kobarin
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//by Kobarin
void NSFMemoryDialog::OnClose(void)
{
    CDialog::OnClose();
    KillTimer(1);
}
//ここまで

/////////////////////////////////////////////////////////////////////////

NSFMemoryDialog.h

//afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnTimer(UINT_PTR nIDEvent);//by Kobarin
...
afx_msg void OnClose();//by Kobarin

/////////////////////////////////////////////////////////////////////////

NSFTrackDialog.cpp

//void NSFTrackDialog::OnTimer(UINT nIDEvent)
void NSFTrackDialog::OnTimer(UINT_PTR nIDEvent) //by Kobarin

BEGIN_MESSAGE_MAP(NSFTrackDialog, CDialog)
...
ON_NOTIFY(NM_RCLICK, IDC_TRACKINFO, OnNMRclickTrackinfo)
ON_WM_CLOSE() //by Kobarin
END_MESSAGE_MAP()

void NSFTrackDialog::OnShowWindow(BOOL bShow, UINT nStatus)
{
  __super::OnShowWindow(bShow, nStatus);

  //m_trkinfo.SetFocus(); // in case someone uses mouse scroll before clicking on it,
  if(bShow)m_trkinfo.SetFocus(); //by Kobarin(一瞬手前に表示されるので閉じるときはSetFocusしない)
...

//by Kobarin
void NSFTrackDialog::OnClose(void)
{
  __super::OnClose();
  OnShowWindow(FALSE, 0);
}
//ここまで

/////////////////////////////////////////////////////////////////////////

NSFTrackDialog.h

//afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnTimer(UINT_PTR nIDEvent);//by Kobarin
...
afx_msg void OnClose(void);//by Kobarin

/////////////////////////////////////////////////////////////////////////

nsf_setup.cpp::

//static HANDLE hDbgfile;
HINSTANCE g_hKpi = NULL; //by Kobarin
BOOL Cnsf_setupApp::InitInstance()
{
	CWinApp::InitInstance();
    g_hKpi = m_hInstance;
    DisableThreadLibraryCalls(g_hKpi);
#if defined(_MSC_VER)
#ifdef _DEBUG
    //hDbgfile = CreateFile("C:\\in_nsf_ui.log", GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
    //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) ;
    //_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ) ;
    //_CrtSetReportFile( _CRT_WARN, (HANDLE)hDbgfile ) ;

    //メモリリーク検出
    int tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
    //tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
    tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
    //tmpDbgFlag |= _CRTDBG_CHECK_ALWAYS_DF;
    _CrtSetDbgFlag(tmpDbgFlag);

#endif
#endif
	return TRUE;
}

#if 0 //by Kobarin
extern "C" __declspec( dllexport ) NSFplug_UI *CreateNSFplug_UI(NSFplug_Model *cf, int mode)
{
    return new NSFDialogManager(cf,mode);
}

extern "C" __declspec( dllexport ) void DeleteNSFplug_UI(NSFplug_UI *p)
{
    delete p;
}

extern "C" __declspec( dllexport ) const char* VersionNSFplug_UI()
{
  return NSFPLAY_VERSION;
}
#endif //by Kobarin

/////////////////////////////////////////////////////////////////////////

nsf.cpp

  NSF::NSF ():SoundDataMSP ()
  {
  //by Kobarin 変数初期化
  //初期化しておかないと info ダイアログでその他の情報の"FILE="以下が文字化けする(NSF::filename)
  //念の為他の変数も初期化しておく
  //全部書くのが面倒なので magic 〜 title_unknown までの変数を一括でゼロクリア
    int size = offsetof(NSF, title_unknown) - offsetof(NSF, magic);
    ZeroMemory(&magic, size);
    title_unknown = true;//↑ではこれだけクリアされない(この変数の初期値は true の方が自然)
    playtime_unknown = true;//初期値は true の方が自然
  //ここまで

/////////////////////////////////////////////////////////////////////////

debugout.h

  class __DebugOut
  {
  public:
    static void printf (const char *format, ...)
    {
  #ifdef _DEBUG //by Kobarin
      static char buf[1024];
      va_list argl;

        va_start (argl, format);
        _vsnprintf (buf, 1024, format, argl);
        OutputDebugString (buf);
        va_end (argl);
  #endif //by Kobarin
    }
  };

/////////////////////////////////////////////////////////////////////////

nsfplay.cpp

  UINT32 NSFPlayer::Render (double * b, UINT32 length)//by Kobarin(64bit float対応)
  {
    INT32 buf[2];
    //INT32 out[2];
    //INT32 outm;
...
      /* del by Kobarin
      out[0] = buf[0];
      out[1] = buf[1];
      out[0] = (out[0]*master_volume)>>8;
      out[1] = (out[1]*master_volume)>>8;

      if     (out[0]<-32767) out[0]=-32767;
      else if( 32767<out[0]) out[0]= 32767;

      if     (out[1]<-32767) out[1]=-32767;
      else if( 32767<out[1]) out[1]= 32767;
      */
      out[0] = (double)buf[0] * master_volume / (256*32768);
      out[1] = (double)buf[1] * master_volume / (256*32768);
...
      if (nch == 2)
      {
          b[0] = out[0];
          b[1] = out[1];
      }
      else // if not 2 channels, presume mono
      {
          //outm = (out[0] + out[1]) >> 1;
          outm = (out[0] + out[1]) / 2;
          for (int i=0; i < nch; ++i)
              b[0] = outm;
      }

/////////////////////////////////////////////////////////////////////////

nsfplay.h

  class NSFPlayer : public PlayerMSP
  {
  protected:
...
    //INT32 last_out;
    double last_out; //by Kobarin
    int silent_length;

/////////////////////////////////////////////////////////////////////////

rconv.cpp

inline UINT32 RateConverter::FastRender (INT32 b[2])
{
  assert (target);

  //double out[2];
  INT64 out[2];
  //static INT32 t[2];
  /*static*/ INT32 t[2];//by Kobarin クロスフェード時のノイズ修正
  ...

/////////////////////////////////////////////////////////////////////////

NSFTrackSetupDialog.cpp

BOOL NSFTrackSetupDialog::OnInitDialog()
{
...
  m_delay.SetPageSize(/*250*/100);//by Kobarin (250=>100)
  m_delay.SetLineSize(/*50*/5);   //by Kobarin (50=>5)
...

/////////////////////////////////////////////////////////////////////////
