/*
 *	buf.c
 *
 *	dpmucc - ミュージック・データ・コンバーター
 *	Copyright (C) 2015-2018 Naoyuki Sawa
 *
 *	* Thu Jan 22 00:43:59 JST 2015 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sat Jan 24 05:36:54 JST 2015 Naoyuki Sawa
 *	- mmlEnd()のループ処理が間違っていたのを修正しました。
 *	  元のmucc.exeのソース(\usr\PIECE\tools\mucc\mmlcv.c)は正しくて、自分で再実装した際のエンバグです。
 *	* Tue Feb 03 20:30:54 JST 2015 Naoyuki Sawa
 *	- コマンドラインオプション'-p'を追加しました。
 *	* Sun Feb 21 21:02:01 JST 2016 Naoyuki Sawa
 *	- 「Boehm GC」をマルチスレッド対応にした事,及び,それに伴ってclipbpe.cモジュールを修正した事に伴い、当ツールもプロジェクト設定の変更を行ってリビルドしました。
 *	  詳細は、/clip/tool/gc/README.TXT と /clip/clipbpe.c の2015/11/03のコメントを参照して下さい。
 *	- libclipのライブラリ化の伴い、以下の変更を行いました。
 *	  ・extclip.hとextclip.cを削除しました。extclip.hとextclip.cはlibclipに含まれるようになったからです。
 *	  ・"CLiP Files"を削除しました。CLiPライブラリの各モジュールはlibclipに含まれるようになったからです。
 *	  当ツールの動作には変更有りません。
 *	* Tue May 09 22:14:45 JST 2017 Naoyuki Sawa
 *	- ライブラリのバグ修正に伴う、ツールのリビルドを行いました。
 *	  詳細は、clipmisc.cの'Sun May 07 09:13:01 JST 2017 Naoyuki Sawa'のコメントを参照して下さい。
 *	- 前回更新後〜本日までの間に、他のツール群に対して行ったのと同じビルド設定の変更を、当ツールにも対しても適用しました。
 *	* Fri Aug 18 22:11:50 JST 2017 Naoyuki Sawa
 *	- '-p'オプションが指定された時に、pm.exeではなく、内蔵プレイヤーを使用するように変更しました。
 *	  これによって、再生前にpmdファイルを生成する必要は無くなったので、'-p'オプションが指定されたらpmdファイルを生成しないように変更しました。
 *	  '-p'オプションが指定されたらファイルを生成しないようになったので、'-o'オプションと'-p'オプションを同時に指定する事は出来なくなりました。
 *	* Thu Aug 24 22:42:57 JST 2017 Naoyuki Sawa
 *	- mmlファイルの先頭で、'#Title'又は'#Title2'コマンドに空文字列を指定すると、壊れた文字列を指すpmdデータが生成されていたバグを修正しました。
 *	  詳細は、mml.cのdoTitle()の修正箇所のコメントを参照して下さい。
 *	* Thu May 03 23:59:59 JST 2018 Naoyuki Sawa
 *	- Boehm GCを修正した事に伴い、当ツールもリビルドしました。
 *	  詳細は、/clip/tool/gc/README.TXTの'Wed May 02 23:59:59 JST 2018 Naoyuki Sawa'のコメントを参照して下さい。
 */
#include "app.h"
/****************************************************************************
 *	ローカル変数
 ****************************************************************************/
#define OUTBUFSIZE	65536			//出力バッファサイズ	変更不可。ファイル内のアドレスを2バイトで表現するので、最大ファイルサイズは65536バイトです。
static unsigned char	outBuf[OUTBUFSIZE];	//出力バッファ
static int		outSize;		//出力サイズ
/****************************************************************************
 *	getAddr
 ****************************************************************************/
//次に出力するデータのアドレス(=現在の出力サイズ)を返す。
int getAddr() {
	return outSize;
}
/****************************************************************************
 *	getByte
 ****************************************************************************/
//指定されたアドレスに有るバイトデータを返す。
int getByte(int addr) {
	if((unsigned)addr >= (unsigned)outSize) { DIE(); }		//エラー:まだ出力していない位置のデータを取得しようとした。もし発生したら当プログラムのバグです。
	return outBuf[addr];
}
/****************************************************************************
 *	getWord
 ****************************************************************************/
//指定されたアドレスに有るワードデータを返す。
int getWord(int addr) {
	return (getByte(addr + 0) << 0)		//1バイト目=下位バイト
	     | (getByte(addr + 1) << 8);	//2バイト目=上位バイト
}
/****************************************************************************
 *	addByte
 ****************************************************************************/
//出力バッファにバイトデータを追加する。
void addByte(int data) {
	if((unsigned)outSize >= (unsigned)OUTBUFSIZE) { DIE(); }	//エラー:出力バッファ溢れ。まず発生しないと思うので、丁寧なエラーメッセージは不要だろう。
	outBuf[outSize++] = data;
}
/****************************************************************************
 *	addWord
 ****************************************************************************/
//出力バッファにワードデータを追加する。
void addWord(int data) {
	addByte(data >> 0);			//1バイト目=下位バイト
	addByte(data >> 8);			//2バイト目=上位バイト
}
/****************************************************************************
 *	addLen
 ****************************************************************************/
//出力バッファに長さデータを追加する。
void addLen(int len) {
	if(len < 127) {								//┐
		addByte(len);		//(  0〜126)				//│
	} else if(len < 127 + 256) {						//├\usr\PIECE\docs\資料\musbin.txt「● 0x7f : 拡張音長」参照
		addByte(SEQ_LEX);	//(127〜255)⇒SEQ_LEX,(127〜255)	//│
		addByte(len);		//(256〜382)⇒SEQ_LEX,(  0〜126)	//┘
	} else {
		DIE();							//エラー:長さが範囲外。まず発生しないと思うので、丁寧なエラーメッセージは不要だろう。
	}
}
/****************************************************************************
 *	putByte
 ****************************************************************************/
//指定されたアドレスに有るバイトデータを書き換える。
void putByte(int addr, int data) {
	if((unsigned)addr >= (unsigned)outSize) { DIE(); }		//エラー:まだ出力していない位置のデータを書き換えようとした。もし発生したら当プログラムのバグです。
	outBuf[addr] = data;
}
/****************************************************************************
 *	putWord
 ****************************************************************************/
//指定されたアドレスに有るワードデータを書き換える。
void putWord(int addr, int data) {
	putByte(addr + 0, data >> 0);		//1バイト目=下位バイト
	putByte(addr + 1, data >> 8);		//2バイト目=上位バイト
}
