DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

wessapi.c (30195B)


      1 
      2 /* WESS API INCLUDES */
      3 #include "wessapi.h"	// audio stuff...
      4 #include "seqload.h"
      5 #include "soundhw.h"
      6 #include "wessarc.h"
      7 #include "wessseq.h"
      8 
      9 #include "funqueue.h"
     10 
     11 #include "graph.h" // debug
     12 
     13 #ifndef NOUSEWESSCODE
     14 //./seqload.h
     15 //./wessapi.h
     16 //./wessseq.h
     17 //./funqueue.h
     18 
     19 #define _ALIGN4_ 1
     20 #define _ALIGN8_ 1
     21 
     22 extern void (**CmdFuncArr[10])(track_status *);
     23 
     24 module_data				tmp_moddata;		//0x800B4160
     25 patch_group_data		tmp_patgrpdata;		//0x800B4188
     26 pmasterstat tmp_mss;			//0x800B41A8
     27 pmasterstat *pm_stat;			//0x800B41CC
     28 
     29 Wess_File_IO_Struct *fp_wmd_file;//8005D8D0
     30 int sysinit;//8005D8D4
     31 int module_loaded;//8005D8D8
     32 int early_exit;//8005D8DC
     33 int wmd_mem_is_mine;//8005D8E0
     34 char *wmd_mem;//8005D8E4
     35 char *wmd_end;//8005D8E8
     36 int wmd_size;//8005D8EC
     37 static int(*Error_func)(int, int) = 0;//8005D8F0
     38 static int Error_module = 0;//8005D8F4
     39 
     40 static void err(int code) // 8002F400
     41 {
     42 	if (Error_func) {
     43 		Error_func(Error_module, code);
     44 	}
     45 }
     46 
     47 static void zeroset(char *pdest, unsigned long size) // 8002F438
     48 {
     49 	while (size--) *pdest++ = 0;
     50 }
     51 
     52 void wess_install_error_handler(int(*error_func)(int, int), int module) // 8002F460
     53 {
     54 	Error_func = error_func;
     55 	Error_module = module;
     56 }
     57 
     58 void * wess_get_master_status(void) // 8002F474
     59 {
     60 	return pm_stat;
     61 }
     62 
     63 int Is_System_Active(void) // 8002F484
     64 {
     65 	if (!sysinit)
     66 	{
     67 		return 0;
     68 	}
     69 	return 1;
     70 }
     71 
     72 int Is_Module_Loaded(void) // 8002F4A8
     73 {
     74 	if (!module_loaded)
     75 	{
     76 		return 0;
     77 	}
     78 	return 1;
     79 }
     80 
     81 int Is_Seq_Num_Valid(int seq_num) // 8002F4CC
     82 {
     83     if ((seq_num >= 0) && (seq_num < wess_seq_loader_count()))
     84     {
     85         if ((pm_stat->pmod_info->pseq_info + seq_num)->ptrk_info)
     86         {
     87             return 1;
     88         }
     89     }
     90 
     91     return 0;
     92 
     93 	/*if ((seq_num<0) || (seq_num >= wess_seq_loader_count()))
     94 	{
     95 		return 0;
     96 	}
     97 	else if ((pm_stat->pmod_info->pseq_info + seq_num)->ptrk_info == NULL) {
     98 		return 0;
     99 	}
    100 	return 1;*/
    101 }
    102 
    103 void Register_Early_Exit(void) // 8002F540
    104 {
    105 	if (!early_exit)
    106 	{
    107 		early_exit = 1;
    108 	}
    109 }
    110 
    111 void wess_install_handler(void) // 8002F564
    112 {
    113 	init_WessTimer();
    114 }
    115 
    116 void wess_restore_handler(void) // 8002F584
    117 {
    118 	exit_WessTimer();
    119 }
    120 
    121 /* used by wesssys_exit */
    122 enum RestoreFlag {NoRestore,YesRestore};
    123 
    124 int wesssys_init(void) // 8002F5A4
    125 {
    126 	int initok;
    127 
    128 	initok = 0;
    129 
    130 	if (!sysinit)
    131 	{
    132 		wess_engine_off(); /* make sure the SeqEngine is disabled */
    133 
    134 		if (!WessTimerActive)
    135 		{
    136 			wess_install_handler();
    137 		}
    138 
    139 		wess_low_level_init();
    140 		sysinit = 1;
    141 		initok = 1;
    142 	}
    143 	return (initok);
    144 }
    145 
    146 void wesssys_exit(enum RestoreFlag rflag) // 8002F608
    147 {
    148 	if (!Is_System_Active())
    149 	{
    150 		return;
    151 	}
    152 
    153 	if (sysinit)
    154 	{
    155 		if (module_loaded)
    156 		{
    157 			wess_unload_module();
    158 		}
    159 
    160 		wess_low_level_exit();
    161 		sysinit = 0;
    162 		if (rflag | WessTimerActive)
    163 		{
    164 			wess_restore_handler();
    165 		}
    166 	}
    167 }
    168 
    169 char *wess_get_wmd_start(void) // 8002F684
    170 {
    171 	return(wmd_mem);
    172 }
    173 
    174 char *wess_get_wmd_end(void) // 8002F694
    175 {
    176 	return(wmd_end);
    177 }
    178 
    179 static void free_mem_if_mine(void) // 8002F6A4
    180 {
    181 	if (wmd_mem_is_mine)
    182 	{
    183 		if (wmd_mem != NULL)
    184 		{
    185 			wess_free(wmd_mem);
    186 			wmd_mem = NULL;
    187 		}
    188 		wmd_mem_is_mine = 0;
    189 	}
    190 }
    191 
    192 void wess_unload_module(void) // 8002F6F4
    193 {
    194 	if (module_loaded)
    195 	{
    196 		wess_seq_stopall();
    197 		wess_engine_off();
    198 
    199 		/* shutdown the loaded drivers and SeqEngine */
    200 		CmdFuncArr[NoSound_ID][DriverExit]((track_status *)pm_stat);
    201 		CmdFuncArr[N64_ID][DriverExit]((track_status *)pm_stat);
    202 		free_mem_if_mine();
    203 
    204 		module_loaded = 0;
    205 	}
    206 }
    207 
    208 int wess_size_module(char *wmd_filename) // 8002F770
    209 {
    210 	int readrequest, readresult;
    211 	callback_status	*pcalltable;
    212 	int size, i;
    213 
    214 	if (!wmd_filename)
    215 		return 0;
    216 
    217 	if (!(fp_wmd_file = module_open(wmd_filename)))
    218 	{
    219 		err(wess_FOPEN);
    220 		return (module_loaded);
    221 	}
    222 
    223 	pm_stat = (master_status_structure *)&tmp_mss;
    224 	tmp_mss.voices_total = wess_driver_voices;
    225 	tmp_mss.pabstime = &millicount;
    226 	tmp_mss.pmod_info = (module_data *)&tmp_moddata;
    227 	tmp_mss.ppat_info = (patch_group_data *)&tmp_patgrpdata;
    228 
    229 	readrequest = sizeof(tmp_moddata.mod_hdr);
    230 	readresult = module_read(&tmp_moddata.mod_hdr, readrequest, fp_wmd_file);
    231 	if (readrequest != readresult)
    232 	{
    233 		err(wess_FREAD);
    234 		return(0);
    235 	}
    236 
    237 	if ((pm_stat->pmod_info->mod_hdr.module_id_text != WESS_SSSP_TEXT) ||
    238 		(pm_stat->pmod_info->mod_hdr.module_version != WESS_CORE_VERSION))
    239 	{
    240 		return(0);
    241 	}
    242 
    243 	readrequest = sizeof(tmp_patgrpdata.pat_grp_hdr);
    244 	readresult = module_read(&tmp_patgrpdata.pat_grp_hdr, readrequest, fp_wmd_file);
    245 	if (readrequest != readresult)
    246 	{
    247 		err(wess_FREAD);
    248 		return(0);
    249 	}
    250 
    251 	module_close(fp_wmd_file);
    252 
    253 	size = 8;//start Align 8
    254 	pm_stat->ppat_info->ppat_data = (char *)size;
    255 	size += pm_stat->pmod_info->mod_hdr.data_size;
    256 
    257 	pm_stat->pseqstattbl = (sequence_status *)size;
    258 	size += sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences;
    259 
    260 	pm_stat->ptrkstattbl = (track_status *)size;
    261 	size += sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks;
    262 
    263 	pm_stat->pvoicestattbl = (voice_status *)size;
    264 	size += sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total;
    265 
    266 	pm_stat->pcalltable = (callback_status *)size;
    267 	size += sizeof(*pm_stat->pcalltable) * wess_driver_callbacks;
    268 
    269 	pm_stat->max_trks_perseq = wess_driver_max_trks_per_seq;
    270 
    271 	for (i = 0; i < wess_driver_sequences; i++)
    272 	{
    273 		size += sizeof(char) * wess_driver_gates;
    274 #if _ALIGN4_ == 1
    275 		//force align to word boundary because previous size adjust
    276 		//may wind up with odd address
    277 		size += (unsigned int)size & 1;
    278 		size += (unsigned int)size & 2;
    279 #endif
    280 
    281 		size += sizeof(char) * wess_driver_iters;
    282 #if _ALIGN4_ == 1
    283 		//force align to word boundary because previous size adjust
    284 		//may wind up with odd address
    285 		size += (unsigned int)size & 1;
    286 		size += (unsigned int)size & 2;
    287 #endif
    288 
    289 		size += sizeof(char) * pm_stat->max_trks_perseq;
    290 #if _ALIGN4_ == 1
    291 		//force align to word boundary because previous size adjust
    292 		//may wind up with odd address
    293 		size += (unsigned int)size & 1;
    294 		size += (unsigned int)size & 2;
    295 #endif
    296 	}
    297 
    298 	pm_stat->max_substack_pertrk = wess_driver_max_subs_per_trk;
    299 
    300 	for (i = 0; i < wess_driver_tracks; i++)
    301 	{
    302 		size += sizeof(long) * pm_stat->max_substack_pertrk;
    303 	}
    304 
    305 #if _ALIGN4_ == 1
    306 	//force align to word boundary because previous size adjust
    307 	//may wind up with odd address
    308 	size += (unsigned int)size & 1;
    309 	size += (unsigned int)size & 2;
    310 #endif
    311 
    312 	return size;
    313 }
    314 
    315 int wess_load_module(char *wmd_filename,
    316 	char *memory_pointer,
    317 	int   memory_allowance/*,
    318 	int **settings_tag_lists*/) // 8002FA3C
    319 {
    320 	int i, j, k, n, z, types, num, indx, loadit;
    321 	int tracks_toload;
    322 	int readrequest, readresult;
    323 	char max_tracks_inseq, max_voices_intrk, max_substack_intrk;
    324 	char *pdest;
    325 	char *pmem;
    326 	unsigned long patfpos, trkinfosize;
    327 	char *tempwmd;
    328 	int setting, flag, flag2;
    329 	int decomp_type;
    330 
    331 	//PRINTF_D(WHITE, "WMD::module_loaded %d", module_loaded);
    332 
    333 	if (module_loaded)
    334 	{
    335 		wess_unload_module();
    336 	}
    337 
    338 	//num_sd = get_num_Wess_Sound_Drivers(settings_tag_lists);
    339 	//printf("num_sd %d\n", num_sd);
    340 
    341 	//PRINTF_D(WHITE, "WMD::memory_pointer %x", &memory_pointer);
    342 
    343 	if (memory_pointer == NULL)
    344 	{
    345 		wmd_mem_is_mine = 1;
    346 		wmd_mem = wess_malloc((char *)memory_allowance);
    347 		if (wmd_mem == NULL)
    348 		{
    349 			return(module_loaded);
    350 		}
    351 	}
    352 	else
    353     {
    354 		wmd_mem_is_mine = 0;
    355 		wmd_mem = memory_pointer;
    356 	}
    357 
    358 	wmd_size = memory_allowance;
    359 
    360 	//PRINTF_D(WHITE, "WMD::wmd_mem %x", &wmd_mem);
    361 	//PRINTF_D(WHITE, "WMD::wmd_size %d", wmd_size);
    362 
    363 	zeroset(wmd_mem, wmd_size);
    364 
    365 	if (!Is_System_Active())
    366 	{
    367 	    //PRINTF_D(WHITE, "WMD::Is_System_Active no activo");
    368 		free_mem_if_mine();
    369 		return (module_loaded);
    370 	}
    371 
    372 	if (wmd_filename == NULL)
    373 	{
    374 		free_mem_if_mine();
    375 		return (module_loaded);
    376 	}
    377 
    378 	if (!(fp_wmd_file = module_open(wmd_filename)))
    379 	{
    380 	    //PRINTF_D(WHITE, "WMD::fp_wmd_file %s Error al abrir", fp_wmd_file);
    381 		err(wess_FOPEN);
    382 		free_mem_if_mine();
    383 		return (module_loaded);
    384 	}
    385 
    386 	//PRINTF_D(WHITE, "WMD::fp_wmd_file %s", fp_wmd_file);
    387 
    388 
    389 
    390 	/* loads a related group of patches and sequences */
    391 	/* a module has the information necessary to set up sequencer work
    392 	areas and data areas */
    393 	/*
    394 	The module loading sequence works as follows :
    395 	*/
    396 
    397 	pmem = wmd_mem;
    398 
    399 	/*
    400 	- allocate space for a master_status_structure
    401 	- update the pmasterstat pointer
    402 	*/
    403 
    404 	pm_stat = (master_status_structure *)&tmp_mss;
    405 	tmp_mss.voices_total = wess_driver_voices;
    406 	tmp_mss.pabstime = &millicount;
    407 
    408 	/*
    409 	- allocate for the module_data structure
    410 	- update the pmod_info pointer
    411 	*/
    412 
    413 	tmp_mss.pmod_info = (module_data *)&tmp_moddata;
    414 
    415 	/*
    416 	- allocate for the patch_group_data structure
    417 	- update the ppat_info pointer
    418 	*/
    419 	tmp_mss.ppat_info = (patch_group_data *)&tmp_patgrpdata;
    420 
    421 	/*
    422 	- read in sizeof(pm_stat->pmod_info->mod_hdr)
    423 	bytes from the .lmd file into the pm_stat->pmod_info->mod_hdr
    424 	structure.
    425 	*/
    426 
    427 	readrequest = sizeof(tmp_moddata.mod_hdr);
    428 	readresult = module_read(&tmp_moddata.mod_hdr, readrequest, fp_wmd_file);
    429 	if (readrequest != readresult)
    430 	{
    431 		err(wess_FREAD);
    432 		free_mem_if_mine();
    433 		return(0);
    434 	}
    435 
    436 	//PRINTF_D(WHITE, "WMD::mod_hdr");
    437 	//PRINTF_D(WHITE, "WMD::module_id_text %x",pm_stat->pmod_info->mod_hdr.module_id_text);
    438 	//PRINTF_D(WHITE, "WMD::module_version %d",pm_stat->pmod_info->mod_hdr.module_version);
    439 	//PRINTF_D(WHITE, "WMD::sequences %d",pm_stat->pmod_info->mod_hdr.sequences);
    440 	//PRINTF_D(WHITE, "WMD::decomp_type %d",pm_stat->pmod_info->mod_hdr.decomp_type);
    441 	//PRINTF_D(WHITE, "WMD::compress_size %d",pm_stat->pmod_info->mod_hdr.compress_size);
    442 	//PRINTF_D(WHITE, "WMD::data_size %d",pm_stat->pmod_info->mod_hdr.data_size);
    443 
    444 	if ((pm_stat->pmod_info->mod_hdr.module_id_text != WESS_SSSP_TEXT) ||
    445 		(pm_stat->pmod_info->mod_hdr.module_version != WESS_CORE_VERSION))
    446 	{
    447 		free_mem_if_mine();
    448 		return(0);
    449 	}
    450 
    451 	readrequest = sizeof(tmp_patgrpdata.pat_grp_hdr);
    452 	readresult = module_read(&tmp_patgrpdata.pat_grp_hdr, readrequest, fp_wmd_file);
    453 	if (readrequest != readresult)
    454 	{
    455 		err(wess_FREAD);
    456 		free_mem_if_mine();
    457 		return(0);
    458 	}
    459 
    460 	//PRINTF_D(WHITE, "WMD::pat_grp_hdr");
    461 	//PRINTF_D(WHITE, "WMD::load_flags %d",pm_stat->ppat_info->pat_grp_hdr.load_flags);
    462 	//PRINTF_D(WHITE, "WMD::patches %d",pm_stat->ppat_info->pat_grp_hdr.patches);
    463 	//PRINTF_D(WHITE, "WMD::patch_size %d",pm_stat->ppat_info->pat_grp_hdr.patch_size);
    464 	//PRINTF_D(WHITE, "WMD::patchmaps %d",pm_stat->ppat_info->pat_grp_hdr.patchmaps);
    465 	//PRINTF_D(WHITE, "WMD::patchmap_size %d",pm_stat->ppat_info->pat_grp_hdr.patchmap_size);
    466 	//PRINTF_D(WHITE, "WMD::patchinfo %d",pm_stat->ppat_info->pat_grp_hdr.patchinfo);
    467 	//PRINTF_D(WHITE, "WMD::patchinfo_size %d",pm_stat->ppat_info->pat_grp_hdr.patchinfo_size);
    468 	//PRINTF_D(WHITE, "WMD::drummaps %d",pm_stat->ppat_info->pat_grp_hdr.drummaps);
    469 	//PRINTF_D(WHITE, "WMD::drummap_size %d",pm_stat->ppat_info->pat_grp_hdr.drummap_size);
    470 	//PRINTF_D(WHITE, "WMD::extra_data_size %d",pm_stat->ppat_info->pat_grp_hdr.extra_data_size);
    471 
    472 #if _ALIGN8_ == 1
    473 	//force align to word boundary because previous size adjust
    474 	//may wind up with odd address
    475 	pmem += (unsigned int)pmem & 1;
    476 	pmem += (unsigned int)pmem & 2;
    477 	pmem += (unsigned int)pmem & 4;
    478 #endif
    479 
    480 	/*
    481 	- allocate and initialize space for
    482 	pm_stat->patch_types patch_group_data structures
    483 	and update the pm_stat->ppat_info pointer.
    484 	*/
    485 
    486 	pm_stat->ppat_info->ppat_data = (char*)(patch_group_data *)pmem;
    487 	pmem += pm_stat->pmod_info->mod_hdr.data_size;
    488 
    489 	if (pm_stat->pmod_info->mod_hdr.decomp_type)
    490 	{
    491 		module_close(fp_wmd_file);
    492 
    493 		decomp_type = pm_stat->pmod_info->mod_hdr.decomp_type;
    494 		readrequest = pm_stat->pmod_info->mod_hdr.data_size;//uncompressed_size
    495 		if (wess_decomp(decomp_type, wmd_filename, 56, pm_stat->ppat_info->ppat_data, readrequest) < 0)
    496 			return(0);
    497 	}
    498 	else
    499 	{
    500 		readrequest = pm_stat->pmod_info->mod_hdr.data_size;
    501 		readresult = module_read(pm_stat->ppat_info->ppat_data, readrequest, fp_wmd_file);
    502 
    503 		//printf("WMD::readrequest %d\n",readrequest);
    504 		//printf("WMD::readrequest %d\n",readresult);
    505 		if (readrequest != readresult)
    506 		{
    507 			err(wess_FREAD);
    508 			free_mem_if_mine();
    509 			return(0);
    510 		}
    511 
    512 		module_close(fp_wmd_file);
    513 	}
    514 
    515 	/*
    516 	--init work structures --------------------------------------------
    517 	- allocate and initialize space for
    518 	pmod_info->mod_hdr.seq_work_areas sequence_status structures
    519 	and update the pmseqstattbl pointer and zero seqs_active.
    520 	*/
    521 
    522 	pm_stat->pseqstattbl = (sequence_status *)pmem;
    523 	pmem += sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences;
    524 
    525 	//PRINTF_D(WHITE, "WMD::pseqstattbl %d",sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences);
    526 
    527 	/*
    528 	- allocate and initialize space for
    529 	pmod_info->mod_hdr.trk_work_areas track_status structures
    530 	and update the pmtrkstattbl pointer and zero trks_active.
    531 	*/
    532 
    533 	pm_stat->ptrkstattbl = (track_status *)pmem;
    534 	pmem += sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks;
    535 
    536 	//PRINTF_D(WHITE, "WMD::ptrkstattbl %d",sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks);
    537 
    538 	/*
    539 	- allocate and initialize space for
    540 	voice_total voice_status structures
    541 	and update the pmvoicestattbl pointer and zero voices_active.
    542 	*/
    543 
    544 	pm_stat->pvoicestattbl = (voice_status *)pmem;
    545 	pmem += sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total;
    546 
    547 	//PRINTF_D(WHITE, "WMD::pvoicestattbl %d",sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total);
    548 
    549 	/*
    550 	- initialize patch_type parameter for each voice work area.
    551 	only the amount of hardware voices possible for each
    552 	patch_type loaded will have voice work areas!!!
    553 	you will run out of voice work areas for a given patch type
    554 	at the same time you have run out of hardware polyphony!!!
    555 	eh,eh,this is cool!,eh,eh
    556 	*/
    557 
    558 	for (i = 0; i < pm_stat->voices_total; i++)
    559 	{
    560 		(pm_stat->pvoicestattbl + i)->patchtype = 1;
    561 		(pm_stat->pvoicestattbl + i)->refindx = i;
    562 	}
    563 
    564 	/*
    565 	- allocate pm_stat->max_tracks_inseq chars for the ptrk_indxs
    566 	pointers in each sequence_status structure.
    567 	update each pointer to each area.
    568 	initialize indexes to 0xFF.
    569 	*/
    570 
    571 	pm_stat->pcalltable = (callback_status *)pmem;
    572 	pmem += sizeof(*pm_stat->pcalltable) * wess_driver_callbacks;
    573 
    574 	//PRINTF_D(WHITE, "WMD::pcalltable %d",sizeof(*pm_stat->pcalltable) * wess_driver_callbacks);
    575 
    576 	pm_stat->max_trks_perseq = wess_driver_max_trks_per_seq;
    577 
    578 	//PRINTF_D(WHITE, "WMD::max_trks_perseq %d",pm_stat->max_trks_perseq);
    579 
    580 	for (i = 0; i < wess_driver_sequences; i++)
    581 	{
    582 		(pm_stat->pseqstattbl + i)->pgates = (char *)pmem;
    583 
    584 		pmem += sizeof(char) * wess_driver_gates;
    585 #if _ALIGN4_ == 1
    586 		//force align to word boundary because previous pmem adjust
    587 		//may wind up with odd address
    588 		pmem += (unsigned int)pmem & 1;
    589 		pmem += (unsigned int)pmem & 2;
    590 #endif
    591 
    592 		(pm_stat->pseqstattbl + i)->piters = (char *)pmem;
    593 		pmem += sizeof(char) * wess_driver_iters;
    594 #if _ALIGN4_ == 1
    595 		//force align to word boundary because previous pmem adjust
    596 		//may wind up with odd address
    597 		pmem += (unsigned int)pmem & 1;
    598 		pmem += (unsigned int)pmem & 2;
    599 #endif
    600 
    601 		j = pm_stat->max_trks_perseq;
    602 		pdest = (pm_stat->pseqstattbl + i)->ptrk_indxs = (char *)pmem;
    603 		pmem += sizeof(char) * j;
    604 #if _ALIGN4_ == 1
    605 		//force align to word boundary because previous pmem adjust
    606 		//may wind up with odd address
    607 		pmem += (unsigned int)pmem & 1;
    608 		pmem += (unsigned int)pmem & 2;
    609 #endif
    610 
    611 		while (j--)
    612 		{
    613 			*pdest++ = 0xFF;
    614 		}
    615 	}
    616 
    617 	/*
    618 	- allocate pm_stat->max_voices_intrk chars for the pvoice_indxs
    619 	pointers in each track_status structure.
    620 	update each pointer to each area.
    621 	initialize indexes to 0xFF.
    622 	*/
    623 
    624 	pm_stat->max_substack_pertrk = wess_driver_max_subs_per_trk;
    625 
    626 	//PRINTF_D(WHITE, "WMD::max_substack_pertrk %d",wess_driver_max_subs_per_trk);
    627 
    628 	for (i = 0; i < wess_driver_tracks; i++)
    629 	{
    630 		(pm_stat->ptrkstattbl + i)->refindx = i;
    631 		(pm_stat->ptrkstattbl + i)->psubstack = (unsigned long *)pmem;
    632 		/* (pm_stat->ptrkstattbl+i)->psp is set when sequence is triggered */
    633 		pmem += sizeof(long) * pm_stat->max_substack_pertrk;
    634 		(pm_stat->ptrkstattbl + i)->pstackend = (unsigned long *)pmem;
    635 	}
    636 
    637 #if _ALIGN4_ == 1
    638 	//force align to word boundary because previous pmem adjust
    639 	//may wind up with odd address
    640 	pmem += (unsigned int)pmem & 1;
    641 	pmem += (unsigned int)pmem & 2;
    642 #endif
    643 
    644 	CmdFuncArr[NoSound_ID][DriverInit]((track_status *)pm_stat);
    645 	CmdFuncArr[N64_ID][DriverInit]((track_status *)pm_stat);
    646 
    647 	wmd_end = pmem;
    648 	module_loaded = 1;
    649 	wess_engine_on();
    650 
    651 	return (1);
    652 }
    653 
    654 void filltrackstat(track_status *ptk_stat, track_data *ptk_info, TriggerPlayAttr *attr) // 8003002C
    655 {
    656 	int tempmask;
    657 
    658 	ptk_stat->flags = (ptk_stat->flags | TRK_ACTIVE | TRK_OFF) & ~TRK_TIMED & ~TRK_LOOPED & ~TRK_SKIP;
    659 
    660 	ptk_stat->patchtype = 1;
    661 	ptk_stat->voices_active = 0;
    662 	ptk_stat->sndclass = ptk_info->trk_hdr->voices_type;//ptk_info->trk_hdr.voices_class;
    663 
    664 	ptk_stat->starppi = 0;
    665 	ptk_stat->accppi = 0;
    666 	ptk_stat->totppi = 0;
    667 	ptk_stat->psp = (unsigned char*)ptk_stat->psubstack;
    668 	ptk_stat->ppq = ptk_info->trk_hdr->initppq;
    669 	ptk_stat->labellist_count = ptk_info->trk_hdr->labellist_count;
    670 	ptk_stat->data_size = ptk_info->trk_hdr->data_size;
    671 
    672 	ptk_stat->mutemask = ptk_info->trk_hdr->mutebits;
    673 
    674 	if ((attr == NULL) || (!attr->mask))
    675 	{
    676 		tempmask = 0;
    677 	}
    678 	else {
    679 		tempmask = attr->mask;
    680 	}
    681 
    682 	if (tempmask & TRIGGER_VOLUME) //0x01
    683 	{
    684 		ptk_stat->volume_cntrl = attr->volume;
    685 	}
    686 	else {
    687 		ptk_stat->volume_cntrl = ptk_info->trk_hdr->initvolume_cntrl;
    688 	}
    689 
    690 	if (tempmask & TRIGGER_PAN) //0x02
    691 	{
    692 		ptk_stat->pan_cntrl = attr->pan;
    693 	}
    694 	else {
    695 		ptk_stat->pan_cntrl = ptk_info->trk_hdr->initpan_cntrl;
    696 	}
    697 
    698 	if (tempmask & TRIGGER_PATCH) //0x04
    699 	{
    700 		ptk_stat->patchnum = attr->patch;
    701 	}
    702 	else {
    703 		ptk_stat->patchnum = ptk_info->trk_hdr->initpatchnum;
    704 	}
    705 
    706 	if (tempmask & TRIGGER_PITCH) //0x08
    707 	{
    708 		ptk_stat->pitch_cntrl = attr->pitch;
    709 	}
    710 	else {
    711 		ptk_stat->pitch_cntrl = ptk_info->trk_hdr->initpitch_cntrl;
    712 	}
    713 
    714 	if (tempmask & TRIGGER_MUTEMODE) //0x10
    715 	{
    716 		if (ptk_stat->mutemask & (1 << attr->mutemode))
    717 		{
    718 			ptk_stat->flags |= TRK_MUTE;
    719 		}
    720 		else {
    721 			ptk_stat->flags &= ~TRK_MUTE;
    722 		}
    723 	}
    724 	else {
    725 		ptk_stat->flags &= ~TRK_MUTE;
    726 	}
    727 
    728 	if (tempmask & TRIGGER_TEMPO) //0x20
    729 	{
    730 		ptk_stat->qpm = attr->tempo;
    731 	}
    732 	else {
    733 		ptk_stat->qpm = ptk_info->trk_hdr->initqpm;
    734 	}
    735 
    736 	ptk_stat->ppi = CalcPartsPerInt(GetIntsPerSec(), ptk_stat->ppq, ptk_stat->qpm);
    737 
    738 	if (tempmask & TRIGGER_TIMED) //0x40
    739 	{
    740 		ptk_stat->endppi = ptk_stat->totppi + attr->timeppq;
    741 		ptk_stat->flags |= TRK_TIMED;
    742 	}
    743 	else {
    744 		ptk_stat->flags &= ~TRK_TIMED;
    745 	}
    746 
    747 	if (tempmask&TRIGGER_LOOPED) //0x80
    748 	{
    749 		ptk_stat->flags |= TRK_LOOPED;
    750 	}
    751 	else {
    752 		ptk_stat->flags &= ~TRK_LOOPED;
    753 	}
    754 
    755 	if (tempmask & TRIGGER_REVERB) //0x100
    756 	{
    757 		ptk_stat->reverb = attr->reverb;
    758 	}
    759 	else {
    760 		ptk_stat->reverb = ptk_info->trk_hdr->reverb;
    761 	}
    762 
    763 	/*printf("ptk_stat->ppq %d\n",ptk_stat->ppq);
    764 	printf("ptk_stat->ppq %d\n",ptk_stat->ppq);
    765 	printf("ptk_stat->labellist_count %d\n",ptk_stat->labellist_count);
    766 	printf("ptk_stat->data_size %d\n",ptk_stat->data_size);
    767 	printf("ptk_stat->mutemask %d\n",ptk_stat->mutemask);
    768 	printf("ptk_stat->volume_cntrl %d\n",ptk_stat->volume_cntrl);
    769 	printf("ptk_stat->pan_cntrl %d\n",ptk_stat->pan_cntrl);
    770 	printf("ptk_stat->patchnum %d\n",ptk_stat->patchnum);
    771 	printf("ptk_stat->pitch_cntrl %d\n",ptk_stat->pitch_cntrl);
    772 	printf("ptk_stat->qpm %d\n",ptk_stat->qpm);
    773 	printf("ptk_stat->ppi %d\n",ptk_stat->ppi);
    774 	printf("ptk_stat->flags %d\n",ptk_stat->flags);
    775 	printf("ptk_stat->reverb %d\n",ptk_stat->reverb);*/
    776 }
    777 
    778 void assigntrackstat(track_status *ptk_stat, track_data *ptk_info) // 800302F8
    779 {
    780 	ptk_stat->data_space = ptk_info->trk_hdr->data_size;
    781 	ptk_stat->labellist_max = ptk_info->trk_hdr->labellist_count;
    782 	ptk_stat->pstart = ptk_info->ptrk_data;
    783 	ptk_stat->ppos = Read_Vlq(ptk_stat->pstart, &ptk_stat->deltatime);
    784 	ptk_stat->plabellist = ptk_info->plabellist;
    785 }
    786 
    787 /* used by wess trigger functions */
    788 enum LoopedFlag { NoLooped, YesLooped };
    789 
    790 /* used by wess trigger functions */
    791 enum HandleFlag { NoHandle, YesHandle };
    792 
    793 int wess_seq_structrig(sequence_data *psq_info,
    794 	int seq_num,
    795 	int seq_type,
    796 	enum HandleFlag gethandle,
    797 	TriggerPlayAttr *attr) // 8003036C
    798 {
    799     char i, j, limit;
    800     short n;
    801 	char tracksfilled;
    802 	char *pdest;
    803 	sequence_status *psq_stat;
    804 	track_data *ptk_info;
    805 	track_status *ptk_stat;
    806 
    807 	//-------
    808 	sequence_data *_psq_info;
    809 	int _seq_num;
    810 	int _seq_type;
    811 	enum HandleFlag _gethandle;
    812 	TriggerPlayAttr *_attr;
    813 
    814 	_psq_info = psq_info;
    815 	_seq_num  = seq_num;
    816 	_seq_type = seq_type;
    817 	_gethandle = gethandle;
    818 	_attr = attr;
    819 
    820 	if (!Is_Seq_Num_Valid(_seq_num))
    821 	{
    822 		return (0);
    823 	}
    824 
    825 	//printf("wess_seq_structrig %d\n",_seq_num);
    826 
    827 	/* runs trigger function and update status structures for api */
    828 
    829 	/*
    830 	- save the sequencer information block pointer,
    831 	if a sequence status structure is free:
    832 	mark sequence as active,
    833 	flag to start what tracks can be started,
    834 	for each track started update psq_info->ptrk_indxs
    835 	*/
    836 
    837 	wess_disable();
    838 
    839 	/* find an open sequence structure */
    840 
    841 	limit = wess_driver_sequences;//pm_stat->pmod_info->mod_hdr.seq_work_areas;
    842 
    843 	for (i = 0; i<limit; i++)
    844 	{
    845 		if (!((pm_stat->pseqstattbl + i)->flags & SEQ_ACTIVE))
    846 		{
    847 			break;
    848 		}
    849 	}
    850 	if (i == limit)
    851 	{
    852 		wess_enable();
    853 		return (0); /* no sequence work area available */
    854 	}
    855 	else
    856 	{
    857 		tracksfilled = 0; /* used to check if any tracks are started */
    858 		/*
    859 		we found a sequence structure so fill it.
    860 		*/
    861 
    862 		psq_stat = pm_stat->pseqstattbl + i;          /* pointer math */
    863 
    864 		/*
    865 		for n tracks in the sequence find and open track structure
    866 		and initialize it.
    867 		*/
    868 		n = _psq_info->seq_hdr.tracks;
    869 		limit = wess_driver_tracks;//pm_stat->pmod_info->mod_hdr.trk_work_areas;
    870 		pdest = psq_stat->ptrk_indxs;
    871 
    872 		//printf("tracks %d\n",n);
    873 		//printf("limit %d\n",limit);
    874 
    875 		for (j = 0; j<limit; j++)
    876 		{
    877 			if (!((pm_stat->ptrkstattbl + j)->flags & TRK_ACTIVE))
    878 			{
    879 
    880 				ptk_stat = pm_stat->ptrkstattbl + j;  /* pointer math */
    881 				ptk_info = _psq_info->ptrk_info + tracksfilled;
    882 
    883 				/* refindx was filled at init time */
    884 				ptk_stat->seq_owner = i;
    885 
    886 				filltrackstat(ptk_stat, ptk_info, _attr);
    887 				assigntrackstat(ptk_stat, ptk_info);
    888 
    889 				if (_gethandle)
    890 				{
    891 					ptk_stat->flags |= (TRK_STOPPED | TRK_HANDLED);
    892 
    893 				}
    894 				else {
    895 					ptk_stat->flags &= ~(TRK_STOPPED | TRK_HANDLED);
    896 					psq_stat->tracks_playing++;
    897 				}
    898 
    899 				psq_stat->tracks_active++;
    900 				pm_stat->trks_active++;
    901 				*pdest++ = j; /* update ptrk_indxs for the sequence */
    902 				tracksfilled++;
    903 
    904 				if (!(((--n)<<16)>>16)) break;
    905 			}
    906 		}
    907 
    908 		/* if tracks were started, activate the sequence */
    909 		if (tracksfilled)
    910 		{
    911 			psq_stat->seq_num = _seq_num;
    912 			psq_stat->seq_type = _seq_type;
    913 			if (_gethandle)
    914 			{
    915 				psq_stat->flags |= SEQ_HANDLE;
    916 				psq_stat->playmode = SEQ_STATE_STOPPED;
    917 			}
    918 			else {
    919 				psq_stat->flags &= ~SEQ_HANDLE;
    920 				psq_stat->playmode = SEQ_STATE_PLAYING;
    921 			}
    922 			psq_stat->volume = 128;
    923 			psq_stat->pan = 64;
    924 			psq_stat->flags |= SEQ_ACTIVE;
    925 			pm_stat->seqs_active++;
    926 		}
    927 		wess_enable();
    928 
    929 		if (tracksfilled)
    930 		{
    931 			return (i + 1);
    932 		}
    933 		else {
    934 			return (0);
    935 		}
    936 	}
    937 }
    938 
    939 void wess_seq_trigger(int seq_num) // 80030650
    940 {
    941 	wess_seq_trigger_type(seq_num, 0);
    942 }
    943 
    944 void wess_seq_trigger_special(int seq_num, TriggerPlayAttr *attr) // 80030670
    945 {
    946 	sequence_data *psq_info;
    947 
    948 	psq_info = pm_stat->pmod_info->pseq_info + seq_num; /* pointer math */
    949 
    950 	wess_seq_structrig(psq_info, seq_num, 0, NoHandle, attr);
    951 }
    952 
    953 int wess_seq_status(int sequence_number) // 800306C0
    954 {
    955 	/* immediate stop of sequence */
    956 	char nt, na;
    957 	sequence_status *psq_stat;
    958 	int status;
    959 
    960 	int _sequence_number;
    961 
    962 	_sequence_number = sequence_number;
    963 
    964 	if (!Is_Seq_Num_Valid(_sequence_number))
    965 	{
    966 		return(SEQUENCE_INVALID);
    967 	}
    968 
    969 	status = SEQUENCE_INACTIVE;
    970 
    971 	wess_disable();
    972 
    973 	/* search for all sequences with this number and turn them off */
    974 	nt = wess_driver_sequences;//pm_stat->pmod_info->mod_hdr.seq_work_areas;
    975 	na = pm_stat->seqs_active;
    976 	psq_stat = pm_stat->pseqstattbl;
    977 
    978 	if (na)
    979 	{
    980 		while (nt--)
    981 		{
    982 			if (psq_stat->flags & SEQ_ACTIVE)
    983 			{
    984 				if (psq_stat->seq_num == _sequence_number)
    985 				{
    986 					if (psq_stat->playmode == SEQ_STATE_STOPPED)
    987 					{
    988 						status = SEQUENCE_STOPPED;
    989 					}
    990 					else if (psq_stat->playmode == SEQ_STATE_PLAYING) {
    991 						status = SEQUENCE_PLAYING;
    992 					}
    993 				}
    994 
    995 				if (!--na) break;
    996 			}
    997 			psq_stat++;
    998 		}
    999 	}
   1000 
   1001 	wess_enable();
   1002 
   1003 	return(status);
   1004 }
   1005 
   1006 /* used by wess_seq_stop and wess_seq_stop_and_voiceramp functions */
   1007 enum MuteRelease { NoMuteRelease, YesMuteRelease};
   1008 
   1009 void __wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec) // 800307AC
   1010 {
   1011 	/* immediate stop of sequence */
   1012 
   1013 	char nt, na;
   1014 	sequence_status *psq_stat;
   1015 	track_status *ptmp;
   1016 	int li, lj;
   1017 
   1018 	int _sequence_number;
   1019 	enum MuteRelease _mrelease;
   1020 	int _millisec;
   1021 
   1022 	_sequence_number = sequence_number;
   1023 	_mrelease = mrelease;
   1024 	_millisec = millisec;
   1025 
   1026 	if (!Is_Seq_Num_Valid(_sequence_number))
   1027 	{
   1028 		return;
   1029 	}
   1030 
   1031 	wess_disable();
   1032 
   1033 	/* search for all sequences with this number and turn them off */
   1034 	nt = wess_driver_sequences;
   1035 	na = pm_stat->seqs_active;
   1036 	psq_stat = pm_stat->pseqstattbl;
   1037 	if (na)
   1038 	{
   1039 		while (nt--)
   1040 		{
   1041 			if (psq_stat->flags & SEQ_ACTIVE)
   1042 			{
   1043 				if (psq_stat->seq_num == _sequence_number)
   1044 				{
   1045 					psq_stat->flags = (psq_stat->flags | SEQ_STOP) & ~SEQ_PAUSE & ~SEQ_RESTART;
   1046 				}
   1047 				if (!--na) break;
   1048 			}
   1049 			psq_stat++;
   1050 		}
   1051 	}
   1052 
   1053 	if (_mrelease)
   1054 	{
   1055 		queue_the_function(QUEUE_SEQ_STOP_AND_VOICERAMP);
   1056 		queue_the_data(&_millisec, sizeof(int));
   1057 	}
   1058 	else
   1059 	{
   1060 		queue_the_function(QUEUE_SEQ_STOP);
   1061 	}
   1062 	queue_the_data(&_sequence_number, sizeof(int));
   1063 	wess_enable();
   1064 }
   1065 
   1066 void wess_seq_stop(int sequence_number) // 800308BC
   1067 {
   1068 	__wess_seq_stop(sequence_number, NoMuteRelease, 0);
   1069 }
   1070 
   1071 void wess_seq_stop_and_voiceramp(int sequence_number, int millisec) // 800308E0
   1072 {
   1073 	__wess_seq_stop(sequence_number, YesMuteRelease, millisec);
   1074 }
   1075 
   1076 void queue_wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec);
   1077 
   1078 void run_queue_wess_seq_stop(void) // 80030904
   1079 {
   1080 	int sequence_number;
   1081 
   1082 	unqueue_the_data(&sequence_number, sizeof(int));
   1083 	queue_wess_seq_stop(sequence_number, NoMuteRelease, 0);
   1084 }
   1085 
   1086 void run_queue_wess_seq_stop_and_voiceramp(void) // 80030938
   1087 {
   1088 	int millisec;
   1089 	int sequence_number;
   1090 
   1091 	unqueue_the_data(&millisec, sizeof(int));
   1092 	unqueue_the_data(&sequence_number, sizeof(int));
   1093 	queue_wess_seq_stop(sequence_number, YesMuteRelease, millisec);
   1094 }
   1095 
   1096 void queue_wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec) // 80030978
   1097 {
   1098 	/* immediate stop of sequence */
   1099 
   1100 	char nt, na;
   1101 	sequence_status *psq_stat;
   1102 	track_status *ptmp;
   1103 	char *lpdest;
   1104 	int li, lj;
   1105 	int get_millisec;
   1106 
   1107 	int _sequence_number;
   1108 	enum MuteRelease _mrelease;
   1109 	int _millisec;
   1110 
   1111 	_sequence_number = sequence_number;
   1112 	_mrelease = mrelease;
   1113 	_millisec = millisec;
   1114 
   1115 	if (!Is_Seq_Num_Valid(_sequence_number))
   1116 	{
   1117 		return;
   1118 	}
   1119 
   1120 	wess_disable();
   1121 
   1122 	/* search for all sequences with this number and turn them off */
   1123 	nt = wess_driver_sequences;
   1124 	na = pm_stat->seqs_active;
   1125 	psq_stat = pm_stat->pseqstattbl;
   1126 	if (na)
   1127 	{
   1128 		if (_mrelease)
   1129 		{
   1130 			get_millisec = wess_get_mute_release();
   1131 			wess_set_mute_release(_millisec);
   1132 		}
   1133 
   1134 		while (nt--)
   1135 		{
   1136 			//if (psq_stat->active)
   1137 			if (psq_stat->flags & SEQ_ACTIVE)
   1138 			{
   1139 				if (psq_stat->seq_num == _sequence_number)
   1140 				{
   1141 					if (psq_stat->flags & SEQ_STOP)
   1142 					{
   1143 						psq_stat->flags &= ~SEQ_STOP;
   1144 
   1145 						li = psq_stat->tracks_active;
   1146 						lj = pm_stat->max_trks_perseq;
   1147 						/* *lpdest refers to an active track if not 0xFF */
   1148 						lpdest = psq_stat->ptrk_indxs;
   1149 						while (lj--)
   1150 						{
   1151 							if (*lpdest != 0xFF)
   1152 							{
   1153 								ptmp = (pm_stat->ptrkstattbl + (*lpdest));
   1154 								CmdFuncArr[ptmp->patchtype][TrkOff](ptmp);
   1155 								if (!--li) break;
   1156 							}
   1157 							lpdest++;
   1158 						}
   1159 					}
   1160 				}
   1161 				if (!--na) break;
   1162 			}
   1163 			psq_stat++;
   1164 		}
   1165 
   1166 		if (_mrelease)
   1167 		{
   1168 			wess_set_mute_release(get_millisec);
   1169 		}
   1170 	}
   1171 
   1172 	wess_enable();
   1173 }
   1174 
   1175 void __wess_seq_stopall(enum MuteRelease mrelease, int millisec) // 80030B78
   1176 {
   1177 	/* immediate stop of all sequences */
   1178 
   1179 	char nt, na;
   1180 	sequence_status *psq_stat;
   1181 	track_status *ptmp;
   1182 	int li, lj;
   1183 
   1184 	enum MuteRelease _mrelease;
   1185 	int _millisec;
   1186 
   1187 	_mrelease = mrelease;
   1188 	_millisec = millisec;
   1189 
   1190 	if (!Is_Module_Loaded())
   1191 	{
   1192 		return;
   1193 	}
   1194 
   1195 	wess_disable();
   1196 
   1197 	/* search for all sequences with this number and turn them off */
   1198 	nt = wess_driver_sequences;
   1199 	na = pm_stat->seqs_active;
   1200 	psq_stat = pm_stat->pseqstattbl;
   1201 	if (na)
   1202 	{
   1203 		while (nt--)
   1204 		{
   1205 			if (psq_stat->flags & SEQ_ACTIVE)
   1206 			{
   1207 				psq_stat->flags = (psq_stat->flags | SEQ_STOP) & ~SEQ_PAUSE & ~SEQ_RESTART;
   1208 				if (!--na) break;
   1209 			}
   1210 			psq_stat++;
   1211 		}
   1212 	}
   1213 
   1214 	if (_mrelease)
   1215 	{
   1216 		queue_the_function(QUEUE_SEQ_STOPALL_AND_VOICERAMP);
   1217 		queue_the_data(&_millisec, sizeof(int));
   1218 	}
   1219 	else
   1220 	{
   1221 		queue_the_function(QUEUE_SEQ_STOPALL);
   1222 	}
   1223 
   1224 	wess_enable();
   1225 }
   1226 
   1227 void wess_seq_stopall(void) // 80030C68
   1228 {
   1229 	__wess_seq_stopall(NoMuteRelease, 0);
   1230 }
   1231 
   1232 void wess_seq_stopall_and_voiceramp(int millisec) // 80030C8C
   1233 {
   1234 	__wess_seq_stopall(YesMuteRelease, millisec);
   1235 }
   1236 
   1237 void queue_wess_seq_stopall(enum MuteRelease mrelease, int millisec);
   1238 
   1239 void run_queue_wess_seq_stopall(void) // 80030CB0
   1240 {
   1241 	queue_wess_seq_stopall(NoMuteRelease, 0);
   1242 }
   1243 
   1244 void run_queue_wess_seq_stopall_and_voiceramp(void) // 80030CD4
   1245 {
   1246 	int millisec;
   1247 
   1248 	unqueue_the_data(&millisec, sizeof(int));
   1249 	queue_wess_seq_stopall(YesMuteRelease, millisec);
   1250 }
   1251 
   1252 void queue_wess_seq_stopall(enum MuteRelease mrelease, int millisec) // 80030D04
   1253 {
   1254 	char nt, na;
   1255 	sequence_status *psq_stat;
   1256 	track_status *ptmp;
   1257 	char *lpdest;
   1258 	int li, lj;
   1259 	int get_millisec;
   1260 
   1261 	enum MuteRelease _mrelease;
   1262 	int _millisec;
   1263 
   1264 	_mrelease = mrelease;
   1265 	_millisec = millisec;
   1266 
   1267 	if (!Is_Module_Loaded())
   1268 	{
   1269 		return;
   1270 	}
   1271 
   1272 	/* immediate stop of all sequences */
   1273 	wess_disable();
   1274 
   1275 	/* search for all sequences and turn them off */
   1276 	nt = wess_driver_sequences;
   1277 	na = pm_stat->seqs_active;
   1278 	psq_stat = pm_stat->pseqstattbl;
   1279 	if (na)
   1280 	{
   1281 		if (_mrelease)
   1282 		{
   1283 			get_millisec = wess_get_mute_release();
   1284 			wess_set_mute_release(_millisec);
   1285 		}
   1286 
   1287 		while (nt--)
   1288 		{
   1289 			if (psq_stat->flags & SEQ_ACTIVE)
   1290 			{
   1291 				if (psq_stat->flags & SEQ_STOP)
   1292 				{
   1293 					psq_stat->flags &= ~SEQ_STOP;
   1294 
   1295 					li = psq_stat->tracks_active;
   1296 					lj = pm_stat->max_trks_perseq;
   1297 					/* *lpdest refers to an active track if not 0xFF */
   1298 					lpdest = psq_stat->ptrk_indxs;
   1299 					while (lj--)
   1300 					{
   1301 						if (*lpdest != 0xFF)
   1302 						{
   1303 							ptmp = (pm_stat->ptrkstattbl + (*lpdest));
   1304 							CmdFuncArr[ptmp->patchtype][TrkOff](ptmp);
   1305 							if (!--li) break;
   1306 						}
   1307 						lpdest++;
   1308 					}
   1309 				}
   1310 				if (!--na) break;
   1311 			}
   1312 
   1313 			psq_stat++;
   1314 		}
   1315 
   1316 		if (_mrelease)
   1317 		{
   1318 			wess_set_mute_release(get_millisec);
   1319 		}
   1320 	}
   1321 
   1322 	wess_enable();
   1323 }
   1324 #endif // 0