diff --git a/PC9801/Makefile b/PC9801/Makefile index 4767862..ef958e9 100644 --- a/PC9801/Makefile +++ b/PC9801/Makefile @@ -7,7 +7,7 @@ CFLAGS += $(DEFINES) OUTPUT = GAME.EXE -SOURCES = ./main.c gfx.c input.c +SOURCES = ./main.c gfx.c input.c pmd.c all: asm ${OUTPUT} diff --git a/PC9801/WAVs/DIALOGUE1.wav b/PC9801/WAVs/DIALOGUE1.wav new file mode 100644 index 0000000..3027504 Binary files /dev/null and b/PC9801/WAVs/DIALOGUE1.wav differ diff --git a/PC9801/WAVs/DIALOGUE2.wav b/PC9801/WAVs/DIALOGUE2.wav new file mode 100644 index 0000000..4dc8475 Binary files /dev/null and b/PC9801/WAVs/DIALOGUE2.wav differ diff --git a/PC9801/WAVs/DIALOGUE3.wav b/PC9801/WAVs/DIALOGUE3.wav new file mode 100644 index 0000000..b81a312 Binary files /dev/null and b/PC9801/WAVs/DIALOGUE3.wav differ diff --git a/PC9801/WAVs/DIALOGUE4.wav b/PC9801/WAVs/DIALOGUE4.wav new file mode 100644 index 0000000..6a8b27d Binary files /dev/null and b/PC9801/WAVs/DIALOGUE4.wav differ diff --git a/PC9801/WAVs/DIALOGUE5.wav b/PC9801/WAVs/DIALOGUE5.wav new file mode 100644 index 0000000..7f5909f Binary files /dev/null and b/PC9801/WAVs/DIALOGUE5.wav differ diff --git a/PC9801/WAVs/FUCK.WAV b/PC9801/WAVs/FUCK.WAV new file mode 100644 index 0000000..6dd59da Binary files /dev/null and b/PC9801/WAVs/FUCK.WAV differ diff --git a/PC9801/WAVs/FUCK2.WAV b/PC9801/WAVs/FUCK2.WAV new file mode 100644 index 0000000..a0560e1 Binary files /dev/null and b/PC9801/WAVs/FUCK2.WAV differ diff --git a/PC9801/WAVs/FUCK3.WAV b/PC9801/WAVs/FUCK3.WAV new file mode 100644 index 0000000..5f91504 Binary files /dev/null and b/PC9801/WAVs/FUCK3.WAV differ diff --git a/PC9801/WAVs/GAME.P86 b/PC9801/WAVs/GAME.P86 new file mode 100644 index 0000000..3a0dfdf Binary files /dev/null and b/PC9801/WAVs/GAME.P86 differ diff --git a/PC9801/WAVs/GAME.PPC b/PC9801/WAVs/GAME.PPC new file mode 100644 index 0000000..5f4d8fb Binary files /dev/null and b/PC9801/WAVs/GAME.PPC differ diff --git a/PC9801/WAVs/MYFILE.WAV b/PC9801/WAVs/MYFILE.WAV new file mode 100644 index 0000000..3027504 Binary files /dev/null and b/PC9801/WAVs/MYFILE.WAV differ diff --git a/PC9801/gfx.c b/PC9801/gfx.c index 03b2d25..43ce824 100644 --- a/PC9801/gfx.c +++ b/PC9801/gfx.c @@ -56,8 +56,6 @@ void gfx_init() union REGS in, out; union REGS regs; - gfx_store_palette(old_palette, 16); - in.h.ah = VGA_MODE; in.h.ch = (3) << 6; int86(INTERRUPT_VGA, &in, &out); @@ -79,6 +77,8 @@ void gfx_init() int86(INTERRUPT_VGA, &in, &out); /* Start graphical co-GPU. */ outp(GDC_GFX_COMMAND, GDC_CMD_START); + + gfx_store_palette(old_palette, 16); #if 0 /* Disable text. */ @@ -109,6 +109,23 @@ void gfx_init() { mov DX,'5h' + mov AL,27 ; ESC + int 29h + mov AL,'[' ; '[' + int 29h + mov AL,'>' ; '>' + int 29h + mov AL,DH + int 29h + mov AL,DL + + int 29h + } + // Hide system line + __asm + { + mov DX,'1l' + mov AL,27 ; ESC int 29h mov AL,'[' ; '[' @@ -126,6 +143,8 @@ void gfx_end() { union REGS in, out; + CLEAR_TEXT_VRAM(); + gfx_fill_palette(old_palette, 16); /* Clock both GPUs back to 2.5MHz. */ @@ -150,12 +169,12 @@ void gfx_end() outp(GDC_TEXT_COMMAND, GDC_CMD_VSYNC_MASTER); outp(GDC_GFX_COMMAND, GDC_CMD_VSYNC_SLAVE); - CLEAR_TEXT_VRAM(); + CLEAR_TXT(); // Show cursor __asm { - mov DX,'1l' + mov DX,'5l' mov AL,27 ; ESC int 29h @@ -169,7 +188,30 @@ void gfx_end() int 29h } - gfx_fill_palette(old_palette, 16); + // Show system line + __asm + { + mov DX,'1h' + + mov AL,27 ; ESC + int 29h + mov AL,'[' ; '[' + int 29h + mov AL,'>' ; '>' + int 29h + mov AL,DH + int 29h + mov AL,DL + int 29h + } + + // KEY BEEP + __asm + { + xor AX,AX + mov ES,AX + and byte ptr ES:[500H],NOT 20h + } } void gfx_wait_vsync() diff --git a/PC9801/input.c b/PC9801/input.c index ff0d90b..2005975 100644 --- a/PC9801/input.c +++ b/PC9801/input.c @@ -22,7 +22,7 @@ #include "input.h" #include "keys.h" -uint8_t inputs[8] = {0}; +uint8_t inputs[18] = {0}; static union REGS out, in; @@ -39,19 +39,38 @@ static void keygroup_sense(char group_id) { void Get_Input() { - keygroup_sense(3); - input_update_bool(inputs[CONFIRM_KEY], (out.h.ah & K3_RETURN)); keygroup_sense(0); input_update_bool(inputs[ESC_KEY], (out.h.ah & K0_ESC)); + input_update_bool(inputs[KEY1_GAME], (out.h.ah & K0_1)); + input_update_bool(inputs[KEY2_GAME], (out.h.ah & K0_2)); + input_update_bool(inputs[KEY3_GAME], (out.h.ah & K0_3)); + + keygroup_sense(1); + input_update_bool(inputs[KEY0_GAME], (out.h.ah & K1_0)); + keygroup_sense(2); + input_update_bool(inputs[KEY_W], (out.h.ah & K2_W)); + + + keygroup_sense(3); + input_update_bool(inputs[CONFIRM_KEY], (out.h.ah & K3_RETURN)); + input_update_bool(inputs[KEY_S], (out.h.ah & K3_S)); + input_update_bool(inputs[KEY_A], (out.h.ah & K3_A)); + input_update_bool(inputs[KEY_D], (out.h.ah & K3_D)); + + keygroup_sense(6); input_update_bool(inputs[SPACE_KEY], (out.h.ah & K6_SPACE)); - keygroup_sense(9); + keygroup_sense(7); input_update_bool(inputs[DOWN_KEY], (out.h.ah & K7_ARROW_DOWN)); input_update_bool(inputs[UP_KEY], (out.h.ah & K7_ARROW_UP)); input_update_bool(inputs[LEFT_KEY], (out.h.ah & K7_ARROW_LEFT)); input_update_bool(inputs[RIGHT_KEY], (out.h.ah & K7_ARROW_RIGT)); + keygroup_sense(9); + input_update_bool(inputs[NUMPAD0_KEY], (out.h.ah & K9_NUM_0)); + input_update_bool(inputs[NUMPAD1_KEY], (out.h.ah & K9_NUM_1)); + input_update_bool(inputs[NUMPAD2_KEY], (out.h.ah & K9_NUM_2)); } diff --git a/PC9801/input.h b/PC9801/input.h index e70eba9..c447c2e 100644 --- a/PC9801/input.h +++ b/PC9801/input.h @@ -27,8 +27,22 @@ #define SPACE_KEY 5 #define ESC_KEY 6 +#define KEY0_GAME 7 +#define KEY1_GAME 8 +#define KEY2_GAME 9 +#define KEY3_GAME 10 + +#define NUMPAD0_KEY 11 +#define NUMPAD1_KEY 12 +#define NUMPAD2_KEY 13 + +#define KEY_W 14 +#define KEY_S 15 +#define KEY_A 16 +#define KEY_D 17 + // Function prototypes -extern uint8_t inputs[8]; +extern uint8_t inputs[18]; extern void Get_Input(); #endif diff --git a/PC9801/main.c b/PC9801/main.c index 46e5519..d34b6c5 100644 --- a/PC9801/main.c +++ b/PC9801/main.c @@ -11,12 +11,17 @@ #include #include #include +#include // For size_t + #include "gdc.h" #include "bios.h" + #include "gfx.h" #include "input.h" +#include "pmd.h" + const unsigned char bakura_palette[] = { 0x00, 0x00, 0x00, @@ -59,6 +64,7 @@ const unsigned char porn_palette[] = { 0x0F, 0x0E, 0x0D, }; +/* unsigned char title_palette[] = { 0x02, 0x02, 0x02, 0x02, 0x04, 0x03, @@ -77,13 +83,16 @@ unsigned char title_palette[] = { 0x06, 0x0D, 0x0D, 0x06, 0x0E, 0x09, }; +*/ + +#define INTENSITY_FRAME 1 // Looks nasty if disabled (this was a test) +#define PREALLOCATE 1 // This exists as to prevent memory issues (fragmentation ???) unsigned short offset_frames[4][4]; extern void zx0_decompress(); extern void lzsa1_decompress(); -#define SIZE 32000 unsigned char* hold_graph[4]; unsigned char font_graph, index_t, dst; @@ -98,18 +107,21 @@ void Load_Bitmap_Part(const char* filename, unsigned char* hold_graph[], unsigne size_t totalsize; _dos_open (filename, O_RDONLY, &fd); - + +#if !defined(PREALLOCATE) if (!hold_graph[index]) { free(hold_graph[index]); hold_graph[index] = NULL; } hold_graph[index] = (unsigned char*) malloc(size); +#endif _dos_read (fd, (char*)hold_graph[index], size, &totalsize); _dos_close (fd); } +/* void Load_Bitmap(const char* filename, unsigned char* hold_graph[], unsigned long size, unsigned char num_graphs) { int fd; @@ -128,10 +140,10 @@ void Load_Bitmap(const char* filename, unsigned char* hold_graph[], unsigned lon } _dos_close (fd); } - +*/ void Clear_Bitmap(unsigned char *hold_graph[]) { - unsigned short i; + unsigned char i; for (i = 0; i < 4; i++) { if (hold_graph[i]) @@ -142,6 +154,7 @@ void Clear_Bitmap(unsigned char *hold_graph[]) } } + static void CAL_Zx0Expand (uint8_t *source, uint8_t *dest) { unsigned sourceseg,sourceoff,destseg,destoff; @@ -242,6 +255,7 @@ const unsigned char jump[5] = static unsigned char bcd[4]; static unsigned char hibcd[4]; unsigned short delay_game; +unsigned char toggle_sound_status; void DrawString(const char* str, unsigned char x, unsigned char y) { @@ -279,18 +293,96 @@ void Refresh_screen() gfx_wait_vsync(); } -static inline Draw_Frame() +static void Draw_Frame() { CAL_LZSAExpand(hold_graph[FRAME_CURRENT], GDC_PLANE_1); CAL_LZSAExpand(hold_graph[FRAME_CURRENT] + offset_frames[FRAME_CURRENT][0], GDC_PLANE_2); CAL_LZSAExpand(hold_graph[FRAME_CURRENT] + (offset_frames[FRAME_CURRENT][0]+offset_frames[FRAME_CURRENT][1]), GDC_PLANE_3); +#ifdef INTENSITY_FRAME CAL_LZSAExpand(hold_graph[FRAME_CURRENT] + (offset_frames[FRAME_CURRENT][0]+offset_frames[FRAME_CURRENT][1]+offset_frames[FRAME_CURRENT][2]), GDC_PLANE_4); +#endif +} +/* +const char index_voices[6][10] = +{ + "DIAL1.P86", + "DIAL2.P86", + "DIAL3.P86", + "DIAL4.P86", + "DIAL5.P86", +}; +*/ + +unsigned char music, voices_enabled; +unsigned char fuck_status; + +void Check_Music_Driver() +{ + if (check_pmd() == 0) + { + // We found PCM signature + // Now check for PCM86's + if (check_pcm86() == 0) + { + // P86DRV's signature found, playing back music with this instead + if (initialize_p86() == 0) + { + // We will only load the voice lines on the fly + if (load_p86_file("GAME.P86") == 0) + { + voices_enabled = 2; + } + } + } + // Assume that driver being usesd is PMDB2 + else + { + voices_enabled = 1; + } + } + +} + +static void PMD_Play_Voice(unsigned char vc) +{ + if (voices_enabled == 2) + { + // 16540 hz, 0x2200 + pmd_play_pcm_sound_effect(vc, 0x2200, 0, 255); + } + else if (voices_enabled == 1) + { + // 16540 hz, 0x2200 + pmd_play_pcm_sound_effect(vc, 2540+16000, 2, 255); + } +} + +#define PMD_Stop() if (voices_enabled > 0) pmd_play_pcm_sound_effect(254, 0, 0, 0); + +/* +void __far *AllocHuge(size_t BlockSize) { + unsigned int segaddr; + + if (_dos_allocmem((unsigned short) ((BlockSize + 15) >> 4), &segaddr)) { + exit(1); + return NULL; + } else { + return MK_FP(segaddr, 0); + } } +*/ + int main() { unsigned char done; + + voices_enabled = 0; + music = 0; + Check_Music_Driver(); + gfx_init(); + hibcd[0] = 48; hibcd[1] = 48; @@ -300,8 +392,32 @@ int main() switch_gamemode(0); done = 0; +#if defined(PREALLOCATE) + hold_graph[0] = malloc(10259+12609+9495 +#ifdef INTENSITY_FRAME + +6455 +#endif + ); + hold_graph[1] = malloc(12517+14051+11218 +#ifdef INTENSITY_FRAME + +7352 +#endif + ); + hold_graph[2] = malloc(12755+13016+9861 +#ifdef INTENSITY_FRAME + +6648 +#endif + ); + hold_graph[3] = malloc(12051+12714+9422 +#ifdef INTENSITY_FRAME + +6386 +#endif + ); +#endif + while (!done) { + delay_game++; Get_Input(); if (inputs[ESC_KEY] == 1) @@ -312,7 +428,7 @@ int main() switch(game_mode) { default: - if (inputs[SPACE_KEY]) + if (inputs[SPACE_KEY] && delay_game > 60) { switch_gamemode(jump[game_mode]); } @@ -320,37 +436,56 @@ int main() case 1: time_game+=1; - if (FRAME_CURRENT > 0 && status_level1[status] != END_GAME_STATUS) + // If Character is fucking + if (fuck_status == 1) { - if (status_level1[status] == STOP_GAME_STATUS) + if (status_level1[status] != END_GAME_STATUS) { - if (!(bcd[2] == 48 && bcd[0] == 48 && bcd[1] == 48)) + if (status_level1[status] == STOP_GAME_STATUS) { - decrease_score(1); + if (!(bcd[2] == 48 && bcd[0] == 48 && bcd[1] == 48)) + { + decrease_score(1); + } } + else + { + add_score(1); + } + + Draw_Frame(); + + DrawString("SCORE", 0, 20); + DrawString(bcd, 0, 21); + Refresh_screen(); + + FRAME_CURRENT++; + if (FRAME_CURRENT > 3) + { + FRAME_CURRENT = 0; + fuck_status = 0; + } + + time_game += 2; } - else - { - add_score(1); - } - - Draw_Frame(); - - FRAME_CURRENT++; - if (FRAME_CURRENT > 3) FRAME_CURRENT = 0; - - DrawString("SCORE", 0, 20); - DrawString(bcd, 0, 21); - Refresh_screen(); - - time_game += 2; } - if (FRAME_CURRENT == 0) + // If Standby + if (fuck_status == 0) { if (inputs[SPACE_KEY] == 1) { - FRAME_CURRENT = 1; + PMD_Play_Voice(5); + + if (toggle_sound_status == 1) + { + if (status_level1[status] == KEEPITUP_GAME_STATUS) + { + PMD_Play_Voice(6); + toggle_sound_status = 0; + } + } + fuck_status = 1; } } @@ -366,6 +501,7 @@ int main() time_game = 0; status++; DrawString(ingame_quote[status_level1[status]], 0, 24); + toggle_sound_status = 1; } } @@ -373,7 +509,6 @@ int main() break; case 3: - delay_game++; if (inputs[SPACE_KEY] && delay_game > 25) { text_progress++; @@ -384,8 +519,8 @@ int main() } else { - CLEAR_TXT(); - + CLEAR_TEXT_VRAM(); + PMD_Play_Voice(text_progress); switch(text_progress) { case 1: @@ -393,13 +528,13 @@ int main() break; case 2: DrawString("I'm Rikuto, i offer you the chance to prove your worth in a trial.", 0, 22); - break; case 3: DrawString("Don't be scared, it'll be fun!", 0, 22); break; case 4: - DrawString("Your challenge will be this: you'll be on the other end and punish them !", 0, 22); + DrawString("Your first challenge is going to be this:", 0, 22); + DrawString("You'll be on the other end and punish them !", 0, 23); break; } } @@ -414,6 +549,8 @@ int main() } + Clear_Bitmap(hold_graph); + PMD_Stop(); gfx_end(); return 0; } @@ -427,6 +564,8 @@ void switch_gamemode(unsigned char mode) i = 0; delay_game = 0; FRAME_CURRENT = 0; + fuck_status = 0; + toggle_sound_status = 0; memset(GDC_PLANE_1, 0, 32000); memset(GDC_PLANE_2, 0, 32000); @@ -434,15 +573,16 @@ void switch_gamemode(unsigned char mode) memset(GDC_PLANE_4, 0, 32000); CLEAR_TEXT_VRAM(); + gfx_fill_palette(bakura_palette, sizeof(bakura_palette) / 3); switch(mode) { case 0: - Load_Bitmap_Part("TITLE.ZX0", hold_graph, 15182+13796+10395+6496, 0); + /* Load_Bitmap_Part("TITLE.ZX0", hold_graph, 15182+13796+10395+6496, 0); CAL_Zx0Expand(hold_graph[0], GDC_PLANE_1); CAL_Zx0Expand(hold_graph[0] + 15182, GDC_PLANE_2); CAL_Zx0Expand(hold_graph[0] + (15182+13796), GDC_PLANE_3); - CAL_Zx0Expand(hold_graph[0] + (15182+13796+10395), GDC_PLANE_4); + CAL_Zx0Expand(hold_graph[0] + (15182+13796+10395), GDC_PLANE_4);*/ DrawString("COPYRIGHT INFRINGEMENT", 30, 0); DrawString("BY GAMEBLABLA", 34, 1); @@ -452,8 +592,6 @@ void switch_gamemode(unsigned char mode) DrawString("PRESS KEY TO START", 31, 22); - gfx_fill_palette(title_palette, sizeof(title_palette) / 3); - Refresh_screen(); break; case 1: @@ -468,25 +606,41 @@ void switch_gamemode(unsigned char mode) offset_frames[0][1] = 11708; offset_frames[0][2] = 9179; offset_frames[0][3] = 6026; - Load_Bitmap_Part("FRAME1.BIN", hold_graph, 10259+12609+9495+6455, 0); + Load_Bitmap_Part("FRAME1.BIN", hold_graph, 10259+12609+9495 + #ifdef INTENSITY_FRAME + +6455 + #endif + , 0); offset_frames[1][0] = 11234; offset_frames[1][1] = 12305; offset_frames[1][2] = 9760; offset_frames[1][3] = 6322; - Load_Bitmap_Part("FRAME2.BIN", hold_graph, 12517+14051+11218+7352, 1); + Load_Bitmap_Part("FRAME2.BIN", hold_graph, 12517+14051+11218 + #ifdef INTENSITY_FRAME + +7352 + #endif + , 1); offset_frames[2][0] = 10940; offset_frames[2][1] = 12142; offset_frames[2][2] = 9252; offset_frames[2][3] = 6051; - Load_Bitmap_Part("FRAME3.BIN", hold_graph, 12755+13016+9861+6648, 2); + Load_Bitmap_Part("FRAME3.BIN", hold_graph, 12755+13016+9861 + #ifdef INTENSITY_FRAME + +6648 + #endif + , 2); offset_frames[3][0] = 10383; offset_frames[3][1] = 9778; offset_frames[3][2] = 8943; offset_frames[3][3] = 5968; - Load_Bitmap_Part("FRAME4.BIN", hold_graph, 12051+12714+9422+6386, 3); + Load_Bitmap_Part("FRAME4.BIN", hold_graph, 12051+12714+9422 + #ifdef INTENSITY_FRAME + +6386 + #endif + , 3); gfx_fill_palette(porn_palette, sizeof(porn_palette) / 3); @@ -505,8 +659,6 @@ void switch_gamemode(unsigned char mode) CAL_Zx0Expand(hold_graph[0] + (9966+9865), GDC_PLANE_3); CAL_Zx0Expand(hold_graph[0] + (9966+9865+9078), GDC_PLANE_4); - gfx_fill_palette(bakura_palette, sizeof(bakura_palette) / 3); - DrawString("Your SCORE was ", 0, 0); DrawString(bcd, 15, 0); @@ -547,7 +699,7 @@ void switch_gamemode(unsigned char mode) CAL_Zx0Expand(hold_graph[0] + (9966+9865), GDC_PLANE_3); CAL_Zx0Expand(hold_graph[0] + (9966+9865+9078), GDC_PLANE_4); - gfx_fill_palette(bakura_palette, sizeof(bakura_palette) / 3); + PMD_Play_Voice(0); DrawString("Oh my, what do we have here?", 0, 22); DrawString("You look so innocent", 0, 23); @@ -559,6 +711,7 @@ void switch_gamemode(unsigned char mode) DrawString("Penetrate him by pressing a key", 0, 2); DrawString("Good luck !", 0, 5); Refresh_screen(); + PMD_Stop(); break; } diff --git a/PC9801/pmd.c b/PC9801/pmd.c new file mode 100644 index 0000000..d4d1496 --- /dev/null +++ b/PC9801/pmd.c @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PMD_VECTOR 0x60 +#define PCM86_VECTOR 0x65 + +void call_pmd_vector(); +int check_pmd(); +int check_pcm86(); +void CallMusicDriver(unsigned char ah_value, unsigned int *segment, unsigned int *offset); +void pmd_mstart(const char *music_data, unsigned int music_data_size); +int initialize_p86(); +int load_p86_file(const char *filename); +void pmd_play_FM_sound_effect(unsigned char sound_effect_index); +void pmd_play_pcm_sound_effect(unsigned char sound_effect_index, unsigned short frequency, char pan, unsigned char volume); + +void call_pmd_vector() +{ + union REGS regs; + + regs.h.ah = 0x10; + int86(0x60, ®s, ®s); +} + +int check_pmd() +{ + uint32_t pmdvector; + uint16_t pmdvector_offset, pmdvector_segment; + char p, m, d; + + /* Get the PMD vector address */ + pmdvector = *((uint32_t *)(PMD_VECTOR * 4)); + pmdvector_offset = (uint16_t)(pmdvector & 0xFFFF); + pmdvector_segment = (uint16_t)(pmdvector >> 16); + + /* Read the characters at the PMD vector address */ + p = *((char *)MK_FP(pmdvector_segment, pmdvector_offset + 2)); + m = *((char *)MK_FP(pmdvector_segment, pmdvector_offset + 3)); + d = *((char *)MK_FP(pmdvector_segment, pmdvector_offset + 4)); + + /* Check if the characters match "PMD" */ + if (p == 'P' && m == 'M' && d == 'D') { + return 0; /* PMD signature found */ + } + return 1; /* PMD signature not found */ +} + +int check_pcm86() +{ + uint32_t pcm86vector; + uint16_t pcm86vector_offset, pcm86vector_segment; + char p, c, m; + + /* Get the PCM86 vector address */ + pcm86vector = *((uint32_t *)(PCM86_VECTOR * 4)); + pcm86vector_offset = (uint16_t)(pcm86vector & 0xFFFF); + pcm86vector_segment = (uint16_t)(pcm86vector >> 16); + + /* Read the characters at the PCM86 vector address */ + p = *((char *)MK_FP(pcm86vector_segment, pcm86vector_offset + 2)); + c = *((char *)MK_FP(pcm86vector_segment, pcm86vector_offset + 3)); + m = *((char *)MK_FP(pcm86vector_segment, pcm86vector_offset + 4)); + + /* Check if the characters match "P86" */ + if (p == 'P' && c == '8' && m == '6') { + return 0; /* PCM86 signature found */ + } + return 1; /* PCM86 signature not found */ +} + +void CallMusicDriver(unsigned char ah_value, unsigned int *segment, unsigned int *offset) +{ + union REGS inregs, outregs; + struct SREGS sregs; + + inregs.h.ah = ah_value; + int86x(0x60, &inregs, &outregs, &sregs); + + if (segment) { + *segment = sregs.ds; + } + if (offset) { + *offset = outregs.x.dx; + } +} + +void pmd_mstart(const char *music_data, unsigned int music_data_size) +{ + unsigned int segment, offset; + + // API call 01 - Stop Song + CallMusicDriver(0x01, NULL, NULL); + + // API call 06 - Get Song Buffer Address + CallMusicDriver(0x06, &segment, &offset); + + // Load music data into song buffer + _fmemcpy(MK_FP(segment, offset), music_data, music_data_size); + + // API call 00 - Play Song + CallMusicDriver(0x00, NULL, NULL); +} + + +int initialize_p86() +{ + union REGS inregs, outregs; + + inregs.h.ah = 0; // Set AH=0 to initialize P86 + + int86(0x65, &inregs, &outregs); // Call interrupt 0x65 + + if (outregs.h.al == 0) { + return 0; // Normal end + } else { + return -1; // Abnormal end + } +} + +int load_p86_file(const char *filename) +{ + union REGS inregs, outregs; + struct SREGS sregs; + + // Prepare input registers + inregs.h.ah = 6; // Set AH=6 to load a P86 file + + // Pass the filename to DS:DX + inregs.x.dx = FP_OFF(filename); + sregs.ds = FP_SEG(filename); + + // Set ES to the environment segment + sregs.es = _psp; // _psp is provided by dos.h and points to the PSP (Program Segment Prefix) + + // Call interrupt 0x65 with the prepared registers + int86x(0x65, &inregs, &outregs, &sregs); + + return outregs.h.al; // Return AL register value with the result of the operation +} + +void pmd_play_FM_sound_effect(unsigned char sound_effect_index) +{ + union REGS inregs; + + // Set AH to 0xC0 for FM sound effect pronunciation + inregs.h.ah = 0x0C; + + // Set AL to the sound effect index + inregs.h.al = sound_effect_index; + + // Call the music driver + int86(0x60, &inregs, NULL); +} + + +// Starts at sound index 1, not 0 +void pmd_play_pcm_sound_effect(unsigned char sound_effect_index, unsigned short frequency, char pan, unsigned char volume) +{ + union REGS inregs; + + // Set AH to 0x0F for PCM sound effect + inregs.h.ah = 0x0F; + + // Set AL to the sound effect index + inregs.h.al = sound_effect_index; + + // Set DX to the frequency + inregs.x.dx = frequency; + + // Set CH to the pan + inregs.h.ch = pan; + + // Set CL to the volume + inregs.h.cl = volume; + + // Call the music driver + int86(0x60, &inregs, NULL); +} diff --git a/PC9801/pmd.h b/PC9801/pmd.h new file mode 100644 index 0000000..3bf50bb --- /dev/null +++ b/PC9801/pmd.h @@ -0,0 +1,12 @@ +#define PMD_VECTOR 0x60 +#define PCM86_VECTOR 0x65 + +void call_pmd_vector(); +int check_pmd(); +int check_pcm86(); +void CallMusicDriver(unsigned char ah_value, unsigned int *segment, unsigned int *offset); +void pmd_mstart(const char *music_data, unsigned int music_data_size); +int initialize_p86(); +int load_p86_file(const char *filename); +void pmd_play_FM_sound_effect(unsigned char sound_effect_index); +void pmd_play_pcm_sound_effect(unsigned char sound_effect_index, unsigned short frequency, char pan, unsigned char volume);