/* ** Copyright (C) 1993 Forte. All rights reserved ** Written late one night 6/27/93. */ #include #include #include #include #include #include "midi.h" #include "totsr.h" #include "ultramid.h" extern int control_break; /* interrupt clock stuff */ static void interrupt (*orig_clock)(void) = 0L; static void interrupt clock(void); static unsigned long clock_interval = 8334L; /* microseconds */ #define CLOCK_DIVISOR 9944U #define ORIG_CLOCK_DIVISOR 0U /* the timer interrupt is on vector 0x08 */ #define TIMER 0x08 void (far *um_hook)(void) = 0L; int um_data_out( int byte ) { if (um_hook) { _AX = TSR_MIDI_OUT; _CX = byte; (*um_hook)(); } return(0); } void um_pitch_bend( int channel, int msb, int lsb ) { um_data_out( (pitch_wheel+channel) ); um_data_out( msb ); um_data_out( lsb ); } void um_program( int channel, int prog ) { um_data_out( (program_chng+channel) ); um_data_out( prog ); } void um_chanpressure( int channel, int pitch, int pressure ) { um_data_out( (channel_aftertouch+channel) ); um_data_out( pitch ); um_data_out( pressure ); } void um_pressure( int channel, int pitch, int pressure ) { um_data_out( (poly_aftertouch+channel) ); um_data_out( pitch ); um_data_out( pressure ); } void um_parameter( int channel, int control, int value ) { um_data_out( (control_change+channel) ); um_data_out( control ); um_data_out( value ); } int um_note_on( int channel, int note, int velocity ) { int error; error = um_data_out( (note_on+channel) ); error += um_data_out( note ); error += um_data_out( velocity ); return(error); } void um_note_off( int channel, int note, int velocity ) { um_data_out( (note_off+channel) ); um_data_out( note ); um_data_out( velocity ); } int reset_um( ) { int i; _AX = TSR_ALL_NOTES_OFF; if (um_hook) (*um_hook)(); for (i=0; i < 16; i++) { um_parameter(i, 0x78, 0); /* all sounds off */ um_parameter(i, 0x79, 0); /* reset all controllers */ um_parameter(i, 100, 0); /* RPN MSB 0 */ um_parameter(i, 101, 0); /* RPN LSB 0 */ um_parameter(i, 6, 2); /* Pitch Bend Sensitivity MSB */ um_parameter(i, 38, 0); /* Pitch Bend Sensitivity LSB */ } return(1); } static unsigned long us_timer = 0L; static unsigned long timer = 0L; static unsigned long tempo = 4800L; static void interrupt clock() { short t; us_timer += clock_interval; if (us_timer > tempo) { t = us_timer / tempo; us_timer -= (t * tempo); timer += t; } if (orig_clock) (*orig_clock)(); } void um_set_tempo(us, divisor) unsigned long us; short divisor; { /* ** the tempo and divisor values are described in the Standard Midi ** File specification 1.0 */ int smpte_format, smpte_resolution; if (divisor > 0) { tempo = us / divisor; } else { smpte_format = (-divisor >> 8) & 0x7f; smpte_resolution = divisor & 0x7f; tempo = 1000000 / (smpte_format * smpte_resolution); } if (tempo <= 0) tempo = 1; } void um_reset_tick_counter() { timer = 0L; us_timer = 0L; } int um_wait_for ( unsigned long some_time ) { if (kbhit() || control_break) return(1); while (some_time > timer) if (kbhit() || control_break) return(1); return(0); } #pragma warn -par int um_init_hardware(struct MIDILIB *ml) { int vector, i; char far *stamp; struct track *track; unsigned long length; for (vector=0x78; vector <= 0x7f; vector++) { um_hook = (void (far *)())getvect(vector); stamp = (char far *)MK_FP( FP_SEG(um_hook), 0x103 ); if (strncmp(stamp, "ULTRAMID", 8) == 0) break; } if (vector <= 0x7f) { midi_message("UltraMID is now loading instrument patches"); if (um_hook) { _AX = TSR_APP_START; (*um_hook)(); } reset_um(); if (um_hook) { for (track=ml->Mp_tracks; track; track = track->next_track) { _ES = FP_SEG(track->data); asm push es _DI = FP_OFF(track->data); asm push di length = track->length; asm mov bx, word ptr length+2 asm mov dx, word ptr length asm pop di asm pop es _AX = TSR_LOAD_MIDI_PATCHES; (*um_hook)(); } _AX = TSR_START_SEQUENCE; (*um_hook)(); } } else { um_hook = 0L; midi_error("Couldn't find UltraMID"); return(1); } return(0); } #pragma warn .par void um_cleanup( void ) { reset_um(); if (um_hook) { _AX = TSR_APP_END; (*um_hook)(); } } void um_init_timers(void) { orig_clock = getvect(TIMER); setvect(TIMER, clock); outportb(0x43, 0x36); outportb(0x40, CLOCK_DIVISOR & 0xff); outportb(0x40, (CLOCK_DIVISOR & 0xff00) >> 8); } void um_cleanup_timers(void) { outportb(0x43, 0x36); outportb(0x40, ORIG_CLOCK_DIVISOR & 0xff); outportb(0x40, (ORIG_CLOCK_DIVISOR & 0xff00) >> 8); if (orig_clock) setvect(TIMER, orig_clock); }