/* ReC98
 * -----
 * Function numbers for the PMD and MMD drivers, according to PMDDATA.DOC and
 * MMDFUNC.DOC. Functions prefixed with KAJA are available in both drivers.
 * Only includes functions that are actually used in the games.
 */

#include "platform.h"

typedef enum {
	KAJA_SONG_PLAY = 0x00,
	KAJA_SONG_STOP = 0x01,
	KAJA_SONG_FADE = 0x02,
	KAJA_GET_SONG_MEASURE = 0x05,
	KAJA_GET_SONG_ADDRESS = 0x06,
	KAJA_GET_VOLUME = 0x08,

	// Returns the type of PMD driver in AL, as well as its version in DX.
	// AL values relevant for PC-98 Touhou:
	// • AL = 0xFF: Resident but no sound source
	// • AL = 0x00: PMD.COM (for PC-9801-26K / OPN)
	// • AL ≥ 0x01: Any other driver compatible to the PC-9801-86 / OPNA
	PMD_GET_DRIVER_TYPE_AND_VERSION = 0x09,

	PMD_GET_SE_ADDRESS = 0x0B,
	PMD_SE_PLAY = 0x0C,
	PMD_GET_WORKAREA_ADDRESS = 0x10,

	// Returns the sizes of the song (AL), instrument (AH), and sound effect
	// (DL) buffers, in KiB. These can be customized on the PMD command line
	// with the /M, /V and /E options respectively.
	PMD_GET_BUFFER_SIZES = 0x22,
} kaja_func_t;

#define PMD 0x60
#define MMD 0x61

// Memory structure of a KAJA interrupt service routine, pointed to by its
// address stored in the x86 interrupt vector. Used for identifying whether
// PMD or MMD are installed at a certain IRQ#, by checking [magic].
typedef struct {
	uint8_t jmp[2];  	// JMP to the code
	uint8_t magic[3];	// "PMD" or "MMD"
} kaja_isr_t;

#define kaja_isr_magic_matches(isr, magic1, magic2, magic3) \
	(((kaja_isr_t *)(isr))->magic[0] == magic1) && \
	(((kaja_isr_t *)(isr))->magic[1] == magic2) && \
	(((kaja_isr_t *)(isr))->magic[2] == magic3)

// MMDFUNC.DOC and https://gist.github.com/devinacker/bdc58cfdba6a1ee80449
// both imply that this is a hardcoded property of the MMD format
#define MMD_TICKS_PER_QUARTER_NOTE 48

// Work area structure names and fields taken from pmdwin.h
// --------------------------------------------------------
#define ONKAI_REST (-1)
#define ONKAI_OCTAVE_MASK (0xF0)
#define ONKAI_NOTE_MASK (0x0F)

// 演奏中のデータエリア
typedef struct qqtag {

	// 演奏中のアドレス (曲データ先頭番地+1からのoffset)
	unsigned char near *address;
	//  演奏が終わった時の戻り先アドレス (同上)
	unsigned char near *partloop;
	// 現在発音中の音符の 残り Length 値;
	unsigned char leng;
	// gatetime値。gatetime ≧ 残りLength が成立した時点で、Keyoff
	unsigned char qdat;

	// (TH05 doesn't use those and we can't know the signedness of a lot of
	// these, so...)
	char dummy[79];

	// 演奏中の音階 オクターブ×16 + 音階(c~b=0~11),rest=255
	char onkai;
} QQ;

typedef struct OpenWorktag {
	QQ near *FMPart[6];
	QQ near *SSGPart[3];
	QQ near *PCMPart[1];
	QQ near *RhythmPart[1];
} OPEN_WORK;
// --------------------------------------------------------