home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C++ Games Programming
/
CPPGAMES.ISO
/
mt
/
mtsc3.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-13
|
11KB
|
357 lines
/* mtsc3.c */
/* `MIDI Sequencing In C', Jim Conger, M&T Books, 1989 */
/* #define TURBOC 1 Define if using TURBOC, leave out for Microsoft */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#ifdef TURBOC
#include <alloc.h>
#else
#include <malloc.h>
#endif
#include "standard.h"
#include "screenf.h"
#include "mpu401.h"
#include "mt.h"
#include "video.h"
#include "mtsc.h"
#include "mtdeclar.h"
/* Erase one note in both note and event lists */
struct note_time far
*delete_note(struct note_time far *first_notep, int measure, int track)
{
struct note_time far *np;
struct note_pos *notepos;
int status;
writeword(
"To Delete: Move cross hair to a note, then hit return (ESC to exit).",
1, g_graph_char_v, g_norm_attrib);
notepos = select_note(measure, FALSE);
if (notepos == NULL){
clearline(g_graph_char_v, g_norm_attrib);
return(NULL);
}
else{
np = find_note(first_notep, notepos->note, notepos->measure,
notepos->tick);
if (np != NULL){
status = remove_event(np->on_event, track);
if (!status)
writerr("Memory pointer error in deleting note-on event.",
g_graph_char_v, g_norm_attrib, g_norm_attrib);
status = remove_event(np->off_event, track);
if (!status)
writerr("Memory pointer error in deleting note-off event.",
g_graph_char_v, g_norm_attrib, g_norm_attrib);
draw_note(np, g_back_color); /* erase note on screen */
clearline(g_graph_char_v, g_norm_attrib);
return(remove_note(first_notep, np));
}
else{
clearline(g_graph_char_v, g_norm_attrib);
writerr("You did not select an existing note.", g_graph_char_v,
g_norm_attrib, g_norm_attrib);
clearline(g_graph_char_v, g_norm_attrib);
return(first_notep);
}
}
}
/* Cursor movement to select note, option to leave cross hair at point */
struct note_pos
*select_note(int measure, int option)
{
int c, i, vert_sum, horz_sum;
static int oldx, oldy, newx, newy, note, tick, csr_measure;
char nbuf[10];
static struct note_pos on_ev;
struct note_pos *notepos;
notepos = &on_ev;
if (g_sc_refresh == 1){ /* fix cursor pos. unless screen is refreshed */
/* find measure, tick for center of screen */
csr_measure = measure;
newx = LEFT_BORDER - CROSS_HALF;
tick = g_first_tick;
for (i = LEFT_BORDER; i <= g_dots_h; i += MIN_SPACE * 2){
tick += g_scale;
newx += MIN_SPACE;
if (tick >= TICK_PER_BEAT * g_meter){
csr_measure++;
tick = 0;
}
}
note = (g_top_note + g_bot_note)/2;
}
else if (g_sc_refresh == 2){ /* only used for add_note, 2nd pass */
tick += g_scale;
newx += MIN_SPACE;
if (tick >= TICK_PER_BEAT * g_meter){
csr_measure++;
tick = 0;
}
}
oldx = newx;
g_sc_refresh = 0;
oldy = newy = find_note_line(note) - CROSS_HALF;
xsprite(cross, newx, newy, g_emph_color);
clear_select_lines();
write_int(tick, g_graph_char_h - 9, g_graph_char_v - 5, g_norm_attrib);
writeword(g_notes[note].name, g_graph_char_h - 9, g_graph_char_v - 4,
g_norm_attrib);
write_int(csr_measure + 1, g_graph_char_h - 9, g_graph_char_v - 3,
g_norm_attrib);
while(1){
vert_sum = horz_sum = 0;
while(!kbhit())
; /* wait for keypress */
while(kbhit()){ /* sum all pending cursor keystrokes */
c = getch();
while (!c)
c = getch(); /* pass over null chars */
switch (c){
case ESC: /* quit on ESC */
xsprite(cross, oldx, oldy, g_emph_color);
clear_select_lines();
return(NULL);
case BACKSP:
case KLEFT:
horz_sum--;
break;
case KUP:
vert_sum++;
break;
case KDOWN:
vert_sum--;
break;
case KRIGHT:
case ' ':
horz_sum++;
break;
case TAB:
case SKRIGHT:
horz_sum += 10;
break;
case BTAB:
case SKLEFT:
horz_sum -= 10;
break;
case KPGUP:
vert_sum += 12;
break;
case KPGDN:
vert_sum -= 12;
break;
case KHOME:
vert_sum += 48;
break;
case KEND:
vert_sum -= 48;
break;
default: /* hitting key/return to select a marked note */
if (!option) /* clear cross hairs if option == 0 */
xsprite(cross, oldx, oldy, g_emph_color);
clear_select_lines();
notepos->measure = csr_measure;
notepos->tick = tick;
notepos->note = note;
notepos->sprite_x = oldx;
notepos->sprite_y = oldy;
return(notepos);
}
}
if (abs(horz_sum) > 2) /* increase horz speedup */
horz_sum *= 2;
while (horz_sum < 0){ /* compute new cursor location */
if (newx > LEFT_BORDER - CROSS_HALF){
newx -= MIN_SPACE;
tick -= g_scale;
if (tick < 0){
tick = (TICK_PER_BEAT * g_meter) - g_scale;
csr_measure--;
}
}
horz_sum++;
}
while (horz_sum > 0){
if (newx < g_dots_h - 2 * CROSS_HALF){
newx += MIN_SPACE;
tick += g_scale;
if (tick > (TICK_PER_BEAT * g_meter) - 1){
tick = 0;
csr_measure++;
}
}
horz_sum--;
}
while (vert_sum > 0){
if (newy >= g_top_note_line - CROSS_HALF + HALF_NOTE_DOTS)
newy -= g_notes[note++].up_dots;
vert_sum--;
}
while (vert_sum < 0){
if (newy <= g_bot_note_line - HALF_NOTE_DOTS - CROSS_HALF)
newy += g_notes[note--].down_dots;
vert_sum++;
}
xsprite(cross, oldx, oldy, g_emph_color);
xsprite(cross, newx, newy, g_emph_color);
clear_select_lines();
write_int(tick, g_graph_char_h - 9, g_graph_char_v - 5, g_norm_attrib);
writeword(g_notes[note].name, g_graph_char_h - 9, g_graph_char_v - 4,
g_norm_attrib);
write_int(csr_measure + 1, g_graph_char_h - 9, g_graph_char_v - 3, g_norm_attrib);
oldx = newx;
oldy = newy;
}
return(NULL);
}
void
clear_select_lines(void) /* blank out the note name and tick areas */
{
writeword(" ", g_graph_char_h - 9, g_graph_char_v - 5, g_norm_attrib);
writeword(" ", g_graph_char_h - 9, g_graph_char_v - 4, g_norm_attrib);
writeword(" ", g_graph_char_h - 9, g_graph_char_v - 3, g_norm_attrib);
}
/* Locate a note within the note list, given that the cursor is on the */
/* specified measure and tick. Return pointer to it, or NULL if not found. */
struct note_time far
*find_note(struct note_time far *first_notep, int note, int measure, int tick)
{
float startn, endn, noten; /* decimal measure.xx fraction of measure */
noten = note_to_float(measure, tick);
while (first_notep->next != NULL){
if (first_notep->note_number == note){ /* if same note */
startn = note_to_float(first_notep->on_measure,
first_notep->on_tick);
endn = note_to_float(first_notep->off_measure,
first_notep->off_tick);
if (noten >= startn && noten <= endn)
return(first_notep);
}
first_notep = first_notep->next; /* no match, so try next note */
}
return(NULL);
}
/* Convert note timing as measure, tick to floating point value */
float
note_to_float(int measure, int tick)
{
float fm, ft, fn;
fm = measure;
ft = tick;
ft = ft/(TICK_PER_BEAT * g_meter);
fn = fm + ft;
return(fn);
}
/* Removes one event from the event list. Corrects timing bytes as needed */
int
remove_event(struct event far *eventp, int track)
{
int ticks;
struct event far *ep;
struct event far *lastep;
struct event far *nextep;
lastep = ep = g_trackarray[track].first;
while (ep != eventp && ep != NULL){
lastep = ep;
ep = ep->next;
}
if (ep == NULL)
return(0);
nextep = ep->next;
while (nextep->b[0] == TIME_OUT){ /* go past any linked TIME_OUT's */
nextep = nextep->next; /* nextep is first event with a */
} /* timing byte. */
ticks = ep->b[0] + nextep->b[0];
if (ticks < MAX_CLOCK){ /* adjust next clock byte, then */
nextep->b[0] = ticks; /* delete the marked event. */
lastep->next = ep->next;
#ifdef TURBOC
farfree(ep);
#else
_ffree(ep);
#endif
}
else{
nextep->b[0] -= MAX_CLOCK - ep->b[0]; /* if clock is too large, */
ep->nbytes = 1; /* use (not) deleted event */
ep->b[0] = TIME_OUT; /* to hold a new TIME_OUT. */
ep->b[1] = ep->b[2] = ep->b[3] = 0;
}
return(1);
}
/* Remove one note's data from note list. */
struct note_time far
*remove_note(struct note_time far *first_notep, struct note_time far *notep)
{
struct note_time far *np;
struct note_time far *lastnp;
if (notep == first_notep){ /* if deleting first note */
lastnp = notep;
first_notep = first_notep->next;
#ifdef TURBOC
farfree(lastnp);
#else
_ffree(lastnp);
#endif
return(first_notep);
}
else{
lastnp = np = first_notep;
while (np != notep && np != NULL){
lastnp = np;
np = np->next;
}
if (np == NULL)
return(0);
lastnp->next = np->next;
#ifdef TURBOC
farfree(np);
#else
_ffree(np);
#endif
return(first_notep);
}
}