diff options
Diffstat (limited to 'engines/sci')
42 files changed, 1 insertions, 13030 deletions
diff --git a/engines/sci/engine/kemu_old.c b/engines/sci/engine/kemu_old.c deleted file mode 100644 index 4ec6c0a106..0000000000 --- a/engines/sci/engine/kemu_old.c +++ /dev/null @@ -1,330 +0,0 @@ -/*************************************************************************** - kemu_old.c Copyright (C) 2002 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ -/* Emulation code for old kernel functions */ - -#include <engine.h> -#include "kernel_compat.h" -#include "kernel_types.h" -#include "heap.h" - -#define EMU_HEAP_START_ADDR 1000 - -#define EMU_TYPE_VERBATIM 0 /* Arithmetic values */ -#define EMU_TYPE_REGISTERS 1 /* Must re-interpret afterwards. Also used for objects. */ -#define EMU_TYPE_BLOCK 2 /* Bulk data; string or similar. May physically point to stack */ - -static int funct_nr; - -typedef struct { - heap_ptr start; /* Beginning of the block */ - reg_t pos; /* Needed for resolving conflicts */ - int length; /* Number of bytes occupied on the heap */ - object_t *obj; /* For object types: Pointer to the physical object */ - - /* Emulation data part */ - int emudat_type; /* EMU_TYPE_... */ - heap_ptr emudat_location; /* Only for 1 and 2 */ - union { - reg_t *regs; /* registers, for type 1 */ - byte *block; /* Bulk data location, for type 2 */ - } emu_data; - int emudat_size; /* Amount of bytes or number of entries */ -} emu_param_t; - -static inline emu_param_t -identify_value(state_t *s, reg_t reg, heap_ptr firstfree) -{ - emu_param_t retval; - int type = determine_reg_type(s, reg); - - retval.start = firstfree; - retval.pos = reg; - - retval.obj = NULL; - retval.length = 0; - retval.emudat_type = EMU_TYPE_VERBATIM; /* To allow error aborts */ - - if (type & KSIG_NULL) - type &= KSIG_ARITHMETIC; - - switch (type) { - - case KSIG_ARITHMETIC: /* trivial */ - retval.emudat_size = 0; - break; - - case KSIG_OBJECT: - retval.emudat_type = EMU_TYPE_REGISTERS; - retval.obj = obj_get(s, reg); - if (!retval.obj) { BREAKPOINT(); } - retval.length = -SCRIPT_OBJECT_MAGIC_OFFSET - + retval.obj->variables_nr * 4 /* values and selectors */ - + 2; /* Extra magic selector word (is this really needed?) */ - retval.emu_data.regs = retval.obj->variables; - retval.emudat_size = retval.obj->variables_nr; - retval.emudat_location = retval.start - SCRIPT_OBJECT_MAGIC_OFFSET; - break; - - case KSIG_REF: { - retval.emudat_type = EMU_TYPE_BLOCK; - - retval.emu_data.block = - s->seg_manager.dereference(&s->seg_manager, - reg, &retval.emudat_size); - - if (!retval.emu_data.block) { - SCIkdebug(SCIkERROR, "Cannot handle references into segment type %02x" - " (from "PREG") during emulation\n", - type, PRINT_REG(reg)); - retval.emudat_type = EMU_TYPE_VERBATIM; - retval.length = 0; - } - - retval.length = retval.emudat_size; - retval.emudat_location = retval.start; - - break; - } - - default: - SCIkdebug(SCIkERROR, "Cannot handle argument type %02x (from "PREG - ") during emulation\n", - type, PRINT_REG(reg)); - } - - return retval; -} - -static inline void -writeout_value(state_t *s, emu_param_t *p) -{ - if (p->obj) /* First copy object; don't need to read back this part later */ - memcpy(s->heap + p->start, p->obj->base_obj + SCRIPT_OBJECT_MAGIC_OFFSET, - p->length); - - switch (p->emudat_type) { - - case EMU_TYPE_VERBATIM: - SCIkdebug(SCIkEMU, "\tVerbatim/Arithmetic\n"); - return; - - case EMU_TYPE_REGISTERS: { - int i, max = p->emudat_size; - - SCIkdebug(SCIkEMU, "\tObject, %d selectors\n", max); - - for (i = 0; i < max; i++) { - byte *dest = s->heap + p->emudat_location + (i << 1); - - dest[0] = p->emu_data.regs[i].offset & 0xff; - dest[1] = (p->emu_data.regs[i].offset >> 8) & 0xff; - /* Assume they're all numeric values */ - } - return; - } - - case EMU_TYPE_BLOCK: - SCIkdebug(SCIkEMU, "\tBulk\n"); - memcpy(s->heap + p->emudat_location, p->emu_data.block, p->emudat_size); - return; - - default: - BREAKPOINT(); - } -} - -static inline void -recover_value(state_t *s, emu_param_t *p) -{ /* Writes back the value */ - switch (p->emudat_type) { - - case EMU_TYPE_VERBATIM: - return; - - case EMU_TYPE_REGISTERS: { - int i, max = p->emudat_size; - for (i = 0; i < max; i++) { - int val = GET_HEAP(p->emudat_location + (i << 1)); - if (p->emu_data.regs[i].offset != val) { - SCIkdebug(SCIkEMU, " Recovering property #%d from %04x: 0:%04x\n", - i, p->emudat_location + (i << 1), val); - p->emu_data.regs[i] = make_reg(0, val); - } else { - SCIkdebug(SCIkEMU, " Property #%d from %04x is unchanged (%04x vs "PREG")\n", - i, p->emudat_location + (i << 1), val, PRINT_REG(p->emu_data.regs[i])); - } - /* Don't overwrite unless something changed, to preserve pointers */ - } - return; - } - - case EMU_TYPE_BLOCK: - memcpy(p->emu_data.block, s->heap + p->emudat_location, p->emudat_size); - SCIkdebug(SCIkEMU, " Recovering %d raw bytes from %04x\n", - p->emudat_size, p->emudat_location); - return; - - default: - BREAKPOINT(); - } -} - -static void -_restrict_against(state_t *s, emu_param_t *self, emu_param_t *other) -{ - if (self->pos.segment != other->pos.segment) - return; - - if (self->pos.offset <= other->pos.offset - && self->pos.offset + self->emudat_size > other->pos.offset) { - mem_obj_t *mobj = GET_SEGMENT_ANY(s->seg_manager, self->pos.segment); - - self->emudat_size = other->pos.offset - self->pos.offset; - - if (mobj && mobj->type == MEM_OBJ_STACK) - self->emudat_size *= sizeof(reg_t); /* Accomodate for size differences */ - } -} - -static void -resolve_conflicts(state_t *s, emu_param_t *params, int count) -{ - int i, j; - for (i = 0; i < count; i++) - for (j = 0; j < count; j++) - if (i != j) - _restrict_against(s, params + i, params + j); -} - -reg_t -kFsciEmu(state_t *s, int _funct_nr, int argc, reg_t *argv) -{ - emu_param_t *shadow_args; - funct_nr = _funct_nr; - - if (!s->kfunct_emu_table[funct_nr]) { - SCIkwarn(SCIkERROR, "Attempt to emulate unknown kernel function %x\n", - funct_nr); - return NULL_REG; - } else { - heap_ptr argp = EMU_HEAP_START_ADDR; /* arguments go here */ - heap_ptr datap = argp + argc * 2; /* copied stuff goes here */ - int i; - - shadow_args = sci_malloc(sizeof(emu_param_t) * (argc + 1 - /* Prevents stupid warning */)); - memset(shadow_args, 0, sizeof(emu_param_t) * (argc + 1)); - - SCIkdebug(SCIkEMU, "Emulating kernel call %s[%x] w/ %d arguments at HP:%04x\n", - s->kernel_names[funct_nr], funct_nr, argc, argp); - - for (i = 0; i < argc; i++) { - int emu_value = argv[i].offset; /* Value we'll pass to the function */ - - SCIkdebug(SCIkEMU, " %3d : ["PREG"] ->\n", i, PRINT_REG(argv[i])); - - shadow_args[i] = identify_value(s, argv[i], datap); - - switch (shadow_args[i].emudat_type) { - - case EMU_TYPE_VERBATIM: - break; - - case EMU_TYPE_REGISTERS: - case EMU_TYPE_BLOCK: - emu_value = shadow_args[i].emudat_location; - break; - - default: - BREAKPOINT(); - - } - - SCIkdebug(SCIkEMU, "\t%04x [%d at %04x]\n", - emu_value, shadow_args[i].length, shadow_args[i].start); - - PUT_HEAP(argp, emu_value); - argp += 2; - - if (0xffff - shadow_args[i].length < datap) { - SCIkdebug(SCIkERROR, "Out of heap space while emulating!\n"); - return NULL_REG; - } - datap += shadow_args[i].length; /* Step over last block we wrote */ - } - - for (i = 0; i < argc; i++) - writeout_value(s, shadow_args + i); - - resolve_conflicts(s, shadow_args, argc); - - s->kfunct_emu_table[funct_nr](s, funct_nr, argc, EMU_HEAP_START_ADDR); - - for (i = 0; i < argc; i++) - recover_value(s, shadow_args + i); - free(shadow_args); - return make_reg(0, s->acc); - } -} - - -int -read_selector16(state_t *s, heap_ptr object, selector_t selector_id, const char *file, int line) -{ - int slc_count = GET_HEAP(object + SCRIPT_SELECTORCTR_OFFSET); - int i; - heap_ptr slc_names = object + slc_count * 2; - - for (i = 0; i < slc_count; i++) { - if (GET_HEAP(slc_names + (i<<1)) == selector_id) - return GET_HEAP(object + (i<<1)); - } - - SCIkdebug(SCIkWARNING, "[EMU] Could not read selector %d from HP:%04x (%s, L%d)\n", - selector_id, object, file, line); - return 0; -} - -void -write_selector16(state_t *s, heap_ptr object, selector_t selector_id, - int value, const char *fname, int line) -{ - int slc_count = GET_HEAP(object + SCRIPT_SELECTORCTR_OFFSET); - int i; - heap_ptr slc_names = object + slc_count * 2; - - for (i = 0; i < slc_count; i++) { - if (GET_HEAP(slc_names + (i<<1)) == selector_id) { - PUT_HEAP(object + (i<<1), value); - return; - } - } - - SCIkdebug(SCIkWARNING, "[EMU] Could not write selector %d from HP:%04x (%s, L%d)\n", - selector_id, object, fname, line); -} - diff --git a/engines/sci/engine/simplesaid.c b/engines/sci/engine/simplesaid.c deleted file mode 100644 index e74a3aec90..0000000000 --- a/engines/sci/engine/simplesaid.c +++ /dev/null @@ -1,312 +0,0 @@ -/*************************************************************************** - simplesaid.c Copyright (C) 2000 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - - -#ifdef SCI_SIMPLE_SAID_CODE - -#include <engine.h> -#include <kdebug.h> - -static int current_pword; -static int said_pos; -static int refstart_pos, parse_pos; -static parse_tree_node_t *words; -static int dontclaim; /* Whether the Parse() event should be claimed */ -static int reached_end; - -static state_t *state; -static heap_ptr addr; - -#define WORDP_MODE_STAY 0 -#define WORDP_MODE_NEXT 1 -#define WORDP_MODE_SEEK 2 - -/* hack */ -#define s state - -static inline int /* Returns whether the specified word matches */ -word_p(int mode, int word) -{ - int oldpp = parse_pos; - do { - if (mode) - ++parse_pos; - - current_pword = words[parse_pos << 1].content.value; - /* SDEBUG("Word at %d = %03x\n", parse_pos, current_pword); */ - if (current_pword == word) { - /* ++matches; */ - SCIkdebug(SCIkSAID, "wordp(%d, %03x) from %d -> 1\n", mode, word, oldpp); - - reached_end |= (words[(parse_pos + 1) << 1].type == -1); - - return 1; - } - - } while ((mode == WORDP_MODE_SEEK) && (words[parse_pos <<1].type != -1)); - - if (words[parse_pos << 1].type == -1) - --parse_pos; - - SCIkdebug(SCIkSAID, "wordp(%d, %03x) from %d -> 0\n", mode, word, oldpp); - - return 0; -} - - - -static inline int /* End of input? */ -end_p() -{ - int val = (words[(parse_pos + 1) << 1 ].type == -1) || reached_end; - - SCIkdebug(SCIkSAID, "endp(pp=%d) = %d\n", parse_pos, val); - - return val; -} - - - -static inline int /* Returns whether the current_word references that specified word */ -reference_p(int referenced_word_index, int word) -{ - int val = 0; - int seeker = (refstart_pos << 1) + 2; - - while (words[seeker].type != -1) { - - if (words[seeker].content.value == word) - if (((words[seeker + 1].content.branches[0] > -1) - && (words[seeker + 1].content.branches[0] == referenced_word_index)) - || ((words[seeker + 1].content.branches[1] > -1) - && (words[seeker + 1].content.branches[1] == referenced_word_index))) { - val = 1; - reached_end |= (words[seeker + 2].type == -1); - break; - } - - seeker += 2; - } - - SCIkdebug(SCIkSAID, "%03x > pos[%d] = %d (start at %d)\n", word, referenced_word_index, val, refstart_pos); - - return val; -} - - -static inline int /* Checks whether the current word has trailing references */ -follows_p(void) -{ - /* int val = (words[(parse_pos << 1) + 1].content.branches[1] > (parse_pos << 1)); - - SDEBUG("follows-p(pp=%d) = %d\n", parse_pos, val);*/ - - dontclaim = 1; - return 1; /* appears to work best */ -} - - -static inline int -next_parse_token(int *token_is_op) -{ - int item = state->heap[addr++]; - - if (item < 0xf0) { - item = item << 8 | state->heap[addr++]; - *token_is_op = 0; - } else - *token_is_op = 1; - - return item; -} - -#define STATE_INITIAL 0 -#define STATE_OR 1 -#define STATE_SEEK 2 -#define STATE_REF 3 - -static int -simplesaid(int minor_state, int terminator) -{ - int major_state = STATE_INITIAL; - int refword = parse_pos; /* The word references apply to */ - int aspiring_refword = -1; /* in "a < b < c", c refers to b, and aspiring_refword will be b. */ - int truth = 1; - int token_is_op; - SCIkdebug(SCIkSAID, "simplesaid(%02x)\n", terminator); - - while (42) { - - int token = next_parse_token(&token_is_op); - SCIkdebug(SCIkSAID, "Got token %03x on truth %d\n", token, truth); - - if (token_is_op && (token == terminator)) { - if (terminator == SAID_TERM) - truth = truth && end_p(); - SCIkdebug(SCIkSAID, "Terminator; returning %d\n", truth); - return truth; - } - - if (token_is_op) /* operator? */ - switch (token) { - - case SAID_COMMA: - minor_state = STATE_OR; - break; - - case SAID_SLASH: - if (!truth) { - while (((token = next_parse_token(&token_is_op)) != terminator) - && (token != SAID_TERM)); /* Proceed to end of block */ - if (token != terminator) - SCIkwarn(SCIkERROR, "Syntax error: Unexpected end of spec"); - return 0; - } - - major_state = STATE_SEEK; - minor_state = STATE_INITIAL; - break; - - case SAID_PARENC: - SCIkwarn(SCIkERROR, "')' without matching '('\n"); - return 0; - - case SAID_PARENO: - switch (minor_state) { - - case STATE_OR: - truth |= simplesaid(minor_state, SAID_PARENC); - break; - - case STATE_INITIAL: - truth = truth && simplesaid(minor_state, SAID_PARENC); - break; - - default: - SCIkwarn(SCIkERROR, "'(' in minor state %d\n", minor_state); - } - break; - - case SAID_BRACKC: - SCIkwarn(SCIkERROR, "']' without matching '['\n"); - return 0; - - case SAID_BRACKO: { - int parse_pos_old = parse_pos; - int recurse = simplesaid(minor_state, SAID_BRACKC); - if (!recurse) - parse_pos = parse_pos_old; - break; - } - - case SAID_LT: - if (aspiring_refword > -1) /* "a < b < c" */ - refword = aspiring_refword; /* refword = 'b' (in the case above) */ - major_state = STATE_REF; - break; - - case SAID_GT: - return truth && follows_p(); - - case SAID_TERM: - SCIkwarn(SCIkERROR, "Unexpected end of spec\n"); - return 0; - - default: - SCIkwarn(SCIkERROR, "Syntax error: Unexpected token 0x%02x\n", token); - return 0; - } else { - int tempresult; - - /* ++word_tokens_nr; /* Normal word token */ - - switch(major_state) { - - case STATE_INITIAL: - tempresult = word_p(((minor_state == STATE_OR)? WORDP_MODE_STAY : WORDP_MODE_NEXT), token); - refword = parse_pos; - break; - - case STATE_SEEK: - tempresult = word_p(WORDP_MODE_SEEK, token); - major_state = STATE_INITIAL; - refword = parse_pos; - break; - - case STATE_REF: - tempresult = reference_p(refword, token); - aspiring_refword = parse_pos; - break; - - default: - SCIkwarn(SCIkERROR, "Invalid major state!\n"); - return 0; - } - - SCIkdebug(SCIkSAID, "state=(%d,%d), truth = %d * %d\n", major_state, minor_state, truth, tempresult); - - if (minor_state == STATE_OR) - truth |= tempresult; - else - truth = truth && tempresult; - - minor_state = STATE_INITIAL; - } - } -} - -#undef s - -int -vocab_simple_said_test(state_t *s, heap_ptr address) -{ - int matched; - current_pword = reached_end = 0; - dontclaim = 0; - said_pos = 0; - if (s->parser_lastmatch_word == SAID_NO_MATCH) - SCIkdebug(SCIkSAID, "lastmatch_word: none\n"); - else - SCIkdebug(SCIkSAID, "lastmatch_word=%d\n", s->parser_lastmatch_word); - parse_pos = (s->parser_lastmatch_word == SAID_NO_MATCH)? -1 : s->parser_lastmatch_word; - refstart_pos = parse_pos; - state = s; - addr = address; - words = s->parser_nodes; - matched = simplesaid(STATE_INITIAL, SAID_TERM); - SCIkdebug(SCIkSAID, "Result: (matched,dontclaim)=(%d,%d)\n", matched, dontclaim); - - if (!matched) - return SAID_NO_MATCH; - - if (dontclaim) /* partial match */ - return parse_pos; /* Return lastmatch word */ - - return SAID_FULL_MATCH; -} - -#endif /* SCI_SIMPLE_SAID_CODE */ diff --git a/engines/sci/gfx/gfx_console.c b/engines/sci/gfx/gfx_console.c deleted file mode 100644 index 0cde8092f3..0000000000 --- a/engines/sci/gfx/gfx_console.c +++ /dev/null @@ -1,1450 +0,0 @@ -/*************************************************************************** - gfx_console.c Copyright (C) 2002 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ -/* Graphical on-screen console */ - - -#include <console.h> -#include <ctype.h> - -#ifdef WANT_CONSOLE -# define CON_MAX_CLUSTERS 16 - -#define CON_CLUSTER_SIZE 64 - -/* Number of console entries stored = CON_MAX_CLUSTERS * CON_CLUSTER_SIZE */ - -#define CON_ENTRY_USED(e) ((e).height > 0) - -#define CON_INPUT_HISTORY_SIZE 64 -#define CON_BUILTIN_CHARS_NR 256 -#define CON_BUILTIN_CHARS_HEIGHT 8 -#define CON_BUILTIN_CHARS_WIDTH 8 - -#define CON_OVERWRAP_SYMBOL 0x10 - -#define CON_GFX_PROMPT "$ " - -extern byte con_builtin_font_data[]; - -typedef struct { - int height; /* Number of pixels occupied by this entry, or 0 if unused */ - int pixmaps_nr; - gfx_pixmap_t **pixmaps; - char *text; /* Dynamically allocated */ -} con_entry_t; - - -typedef struct _con_buffer { - con_entry_t entries[CON_CLUSTER_SIZE]; - struct _con_buffer *next; - struct _con_buffer *prev; -} con_buffer_t; - -typedef struct { - con_buffer_t *buf; - int entry; - int offset; /* pixel offset relative to the bottom */ -} con_pos_t; - -typedef struct { - int locked_to_end; - con_pos_t pos; - gfx_pixmap_t *background; - gfx_color_t color_bg, color_transparent, color_cursor, color_text, color_input; - gfx_pixmap_t *input_prompt; - gfx_pixmap_t *input_precursor; - gfx_pixmap_t *input_oncursor; - gfx_pixmap_t *input_postcursor; - int cursor_position; - int input_window; /* First character to display, may be up to -2 to include prompt */ - char *input_text; - int input_bufsize; - int input_prompt_pos; /* -strlen(input prompt) */ - int input_history_pos; - int partial_write; - char *input_history[CON_INPUT_HISTORY_SIZE]; -} con_t; - - -/* Visual options for the con */ -static int con_bg_red = 0; -static int con_bg_green = 0; -static int con_bg_blue = 64; -static int con_bg_alpha = 64; -static int con_displayed_lines = 180; -static int con_border_width = 3; - -static int con_top_buffer_entry_nr = 0; -static int con_buffer_clusters = 0; -static con_buffer_t *con_buffer = NULL; -static con_buffer_t *con_buffer_tail = NULL; -static con_t con; /* The global con */ -static gfx_bitmap_font_t con_font; -static int con_font_initialized = 0; -static gfx_state_t *con_last_gfx_state = NULL; - -/*-- Forwards --*/ -static void -_con_free_entry_pixmaps(gfx_state_t *state, con_entry_t *entry); -/* Free all pixmaps from the specified entry -** Parameters: (gfx_state_t *) state: The state to free from -** (con_entry_t *) entry: The entry to liberate from its pixmaps -*/ - -static gfx_pixmap_t * -_con_render_text(gfx_state_t *state, char *text, int len, - gfx_color_t *color, gfx_color_t *bgcolor); -/* Renders the specified text in the specified fg color -** Parameters: (gfx_state_t *) state: The state to render in -** (char *) text: The text to render -** (int) len: Length of the text to render, or -1 for strlen -** (gfx_color_t *) color: The fg color to choose -** (gfx_color_t *) bgcolor: The bg color to choose -** Returns : (gfx_pixmap_t *) An appropriate pixmap -*/ - - -void -con_jump_to_end(gfx_state_t *gfx); -/* Makes the console jump to the logical end of its buffer and redraws -** Parameters: (gfx_stat_t *) gfx: The graphics state to use fo rdrawing -*/ - -static void -_con_redraw(gfx_state_t *state, int update_display_field, int update_input_field); -/* Performs a (partial) redraw -** Parameters: (gfx_state_t *) state: The graphical state to draw with -** (int) update_display_field: Whether the upper part of the -** console, used to display test, should be updated -** (int) update_input_field: Whether the lower part of the -** console, used to display the user input, should be -** updated -*/ - -static void -free_con_buffer(con_buffer_t *buf); -/* Frees the specified con buffer and all of its predecessors -** Parameters: (con_buffer_t *) buf: The buffer to free -** Pixmaps are freed if neccessary, using the last used gfx state for con_gfx_show(). -*/ - -void -con_gfx_hide(gfx_state_t *state); -/* Removes the console, restoring the background graphics -** Parameters: (gfx_state_t *state: The graphics state to draw with -*/ - -static gfx_pixmap_t ** -_con_render_text_multiline(gfx_state_t *state, char *text, int maxchars, int *nr); -/*-- code --*/ - -static rect_t -con_box() -{ - return gfx_rect(0, 0, 320, - con_displayed_lines - + con_border_width); -} - -void -con_gfx_show(gfx_state_t *state) -{ - gfxop_set_clip_zone(state, gfx_rect(0, 0, 320, 200)); - con_last_gfx_state = state; - - con.locked_to_end = 1; - con.background = gfxop_grab_pixmap(state, con_box()); - - gfxop_set_color(state, &con.color_bg, con_bg_red, con_bg_green, - con_bg_blue, con_bg_alpha, -1, -1); - gfxop_set_color(state, &con.color_transparent, 0, 0, 0, 255, -1, -1); - gfxop_set_color(state, &con.color_text, 255, 255, 255, 0, -1, -1); - gfxop_set_color(state, &con.color_input, 255, 255, 0, 0, -1, -1); - gfxop_set_color(state, &con.color_cursor, 255, 0, 0, 0, -1, -1); - - if (!con.input_prompt) { - con.input_prompt = _con_render_text(state, CON_GFX_PROMPT, -1, - &con.color_input, NULL); - con.input_text = (char*)sci_malloc(con.input_bufsize = 64); - con.input_text[0] = 0; - con.input_history_pos = 0; - con.partial_write = 0; - memset(con.input_history, 0, sizeof(char *) * CON_INPUT_HISTORY_SIZE); - } - - con_jump_to_end(state); - _con_redraw(state, 0, 1); -} - -static void -_con_draw_bg_pic(gfx_state_t *state, rect_t zone) -{ - gfxop_draw_pixmap(state, con.background, zone, gfx_point(zone.x,zone.y)); -} - -void -con_jump_to_end(gfx_state_t *state) -{ - con.locked_to_end = 1; - _con_redraw(state, 1, 0); -} - - -void -con_fold_text(gfx_state_t *state) -{ - con_buffer_t *seeker = con_buffer; - - /* Fold all text pixmaps */ - while (seeker) { - int i; - for (i = 0; i < CON_CLUSTER_SIZE; i++) - if (CON_ENTRY_USED(seeker->entries[i]) - && seeker->entries[i].text && seeker->entries[i].pixmaps_nr) - _con_free_entry_pixmaps(state, &seeker->entries[i]); - - seeker = seeker->next; - } -} - -void -con_gfx_hide(gfx_state_t *state) -{ - /* Restore background */ - _con_draw_bg_pic(state, con_box()); - - if (con.background) - gfxop_free_pixmap(state, con.background); - con.background = NULL; - - con_fold_text(state); - gfxop_update(state); -} - -static inline con_buffer_t * -_create_con_buffer(con_buffer_t *prev) -{ - con_buffer_t *buf = (con_buffer_t *)sci_malloc(sizeof (con_buffer_t)); - int i; - - for (i = 0; i < CON_CLUSTER_SIZE; i++) - buf->entries[i].height = 0; - - buf->prev = prev; - buf->next = NULL; - if (prev) - prev->next = buf; - - con_buffer_clusters++; - - return buf; -} - - -static inline void -_add_into_con_buffer(gfx_pixmap_t *pixmap, char *text) -{ - con_entry_t *target; - - if (!con_buffer) { - con_buffer = con_buffer_tail = _create_con_buffer(NULL); - con_top_buffer_entry_nr = 0; - } - - if (con_top_buffer_entry_nr == CON_CLUSTER_SIZE) { - /* Out of entries in this cluster */ - con_buffer = _create_con_buffer(con_buffer); - con_top_buffer_entry_nr = 0; - } - - target = con_buffer->entries + con_top_buffer_entry_nr; - - if (con.partial_write && text) { - int real_entry = con_top_buffer_entry_nr - 1; - int needlen = strlen(text); - char *oldtext; - - if (real_entry < 0) - target = con_buffer->prev->entries + CON_CLUSTER_SIZE - 1; - else - target = con_buffer->entries + real_entry; - - if (target->pixmaps) - _con_free_entry_pixmaps(con_last_gfx_state, target); - - needlen += strlen(target->text); - oldtext = target->text; - target->text = (char *)sci_malloc(needlen+1); - strcpy(target->text, oldtext); - strcat(target->text, text); - free(oldtext); - free(text); - - con.partial_write = (target->text && *(target->text) && - target->text[strlen(target->text) - 1] != '\n'); - - return; - } - else ++con_top_buffer_entry_nr; - - - con.partial_write = (text && *(text) && - text[strlen(text) - 1] != '\n'); - - if (pixmap) - target->height = pixmap->index_yl; - else - target->height = 1; /* Will be calculated on demand */ - - if (!pixmap) { - target->pixmaps = NULL; - target->pixmaps_nr = 0; - } else { - target->pixmaps = (gfx_pixmap_t **)sci_malloc(sizeof(gfx_pixmap_t *)); - target->pixmaps[0] = pixmap; - target->pixmaps_nr = 1; - } - target->text = text; - - while (con_buffer_clusters > CON_MAX_CLUSTERS - && con_buffer_tail) { - if (con_buffer_tail->next) { - con_buffer_tail = con_buffer_tail->next; - free_con_buffer(con_buffer_tail->prev); - } else { - fprintf(stderr,"WARNING: During cleanup, con_buffer_tail ran out!\n"); - free_con_buffer(con_buffer_tail->prev); - con_buffer_tail = con_buffer = NULL; - } - } -} - - -void -con_gfx_insert_string(char *string) -{ - if (string) - _add_into_con_buffer(NULL, string); -} - -void -con_gfx_insert_pixmap(gfx_pixmap_t *pixmap) -{ - if (pixmap) - _add_into_con_buffer(pixmap, NULL); -} - -static int -_unfold_graphics(gfx_state_t *state, con_entry_t *drawme, int nr_chars) - /* Returns whether unfolding was neccessary */ -{ - if (drawme->text && !drawme->pixmaps_nr) { - int i; - drawme->pixmaps = _con_render_text_multiline(state, drawme->text, - nr_chars, - &drawme->pixmaps_nr); - - drawme->height = 0; - for (i = 0; i < drawme->pixmaps_nr; i++) - drawme->height += - (drawme->pixmaps[i]->yl + state->driver->mode->yfact - 1) - / state->driver->mode->yfact; - /* Divide by scaler, round up */ - return 1; - } - - return 0; -} - -void -con_scroll(gfx_state_t *state, int offset, int maxchars) -{ - con_entry_t *next_entry; - /* Scrolls within the display by the specified amount */ - - if (con.locked_to_end) { - con.pos.buf = con_buffer; - con.pos.offset = 0; - con.pos.entry = con_top_buffer_entry_nr - 1; - } - - if (!con.pos.buf) - return; - - con.locked_to_end = 0; - - con.pos.offset += offset; /* offset exceeds size -> Use PREVIOUS entry */ - - while (con.pos.offset < 0 || con.pos.offset > con.pos.buf->entries[con.pos.entry].height) { - - if (con.pos.offset < 0) { - if (++con.pos.entry == CON_CLUSTER_SIZE - || ((con.pos.buf == con_buffer) - && (con.pos.entry >= con_top_buffer_entry_nr))) { - if (con.pos.buf->next) { - con.pos.entry = 0; - con.pos.buf = con.pos.buf->next; - } else { - con_jump_to_end(state); - return; - } - } - - next_entry = con.pos.buf->entries + con.pos.entry; - - _unfold_graphics(state, next_entry, maxchars); - con.pos.offset += next_entry->height; - } else { /* offset too great ? */ - - if (con.pos.entry == 0) { - if (con.pos.buf->prev) { - con.pos.entry = CON_CLUSTER_SIZE; - con.pos.buf = con.pos.buf->prev; - } else { - con.pos.offset = con.pos.buf->entries[0].height - 1; - return; - } - } - --con.pos.entry; - - next_entry = con.pos.buf->entries + con.pos.entry; - - _unfold_graphics(state, next_entry, maxchars); - con.pos.offset -= next_entry->height; - - if (con.pos.offset < 0) - con.pos.offset = -con.pos.offset; - } - } -} - -void -con_gfx_init() -{ - con_set_string_callback(con_gfx_insert_string); - con_set_pixmap_callback(con_gfx_insert_pixmap); - con.input_prompt = NULL; - con.input_text = NULL; - con.input_window = con.input_prompt_pos = -(int)strlen(CON_GFX_PROMPT); - con.cursor_position = 0; - con.input_precursor = NULL; - con.input_postcursor = NULL; - con.input_oncursor = NULL; -} - - -static void -_init_con_font() -{ - int i; - - con_font.ID = 0; - con_font.chars_nr = CON_BUILTIN_CHARS_NR; - con_font.widths = (int *)sci_malloc(sizeof(int) * CON_BUILTIN_CHARS_NR); - for (i = 0; i < CON_BUILTIN_CHARS_NR; i++) - con_font.widths[i] = CON_BUILTIN_CHARS_WIDTH; - con_font.row_size = (CON_BUILTIN_CHARS_WIDTH + 7) >> 3; - con_font.height = con_font.line_height = CON_BUILTIN_CHARS_HEIGHT; - con_font.char_size = ((CON_BUILTIN_CHARS_WIDTH + 7) >> 3) * CON_BUILTIN_CHARS_HEIGHT; - con_font.data = con_builtin_font_data; - - con_font_initialized = 1; -} - -static gfx_pixmap_t ** -_con_render_text_multiline(gfx_state_t *state, char *text, int maxchars, int *nr) -{ - int pixmaps_allocd = 1; - gfx_pixmap_t **retval = (gfx_pixmap_t **)sci_malloc(sizeof(gfx_pixmap_t *) * pixmaps_allocd); - char *printbuf = (char *)sci_malloc(maxchars + 8); - int index = 0; - int overwrap = 0; - - while (*text) { - int len = 0; - - if (overwrap) { - len = 2; - printbuf[0] = ' '; - printbuf[1] = CON_OVERWRAP_SYMBOL; - overwrap = 0; - } - - while (*text && - *text != '\n' && len < maxchars) { - if (*text != '\t') - printbuf[len++] = *text; - else { - int tabwidth = 8 - (len & 7); - memset(printbuf + len, ' ', tabwidth); - len += tabwidth; - } - text++; - } - - if (*text && (*text != '\n')) - overwrap = 1; - - if (index == pixmaps_allocd) - retval = (gfx_pixmap_t **)sci_realloc(retval, sizeof(gfx_pixmap_t *) * (pixmaps_allocd+= 4)); - - retval[index++] = _con_render_text(state, printbuf, len, - &con.color_text, NULL); - if (*text) text += (1 - overwrap); - } - - *nr = index; - sci_free(printbuf); - return retval; -} - -static gfx_pixmap_t * -_con_render_text(gfx_state_t *state, char *text, int len, - gfx_color_t *color, gfx_color_t *bgcolor) -{ - gfx_pixmap_t *pxm; - - if (len < 0) - len = strlen(text); - - if (!con_font_initialized) - _init_con_font(); - - pxm = gfxr_draw_font(&con_font, text, len, - &color->visual, - &color->visual, - (bgcolor) ? &bgcolor->visual : NULL); - - pxm->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX; - - gfx_xlate_pixmap(gfx_pixmap_alloc_data(pxm, state->driver->mode), - state->driver->mode, GFX_XLATE_FILTER_NONE); - return pxm; -} - -static inline int -_str_move_blank(char *data, int data_length, int initial_offset, int direction) - /* Finds the next beginning or end of a word */ -{ - int offset = initial_offset; - int abort = (direction < 0)? 0 : data_length; - int lookahead = (direction < 0)? -1 : 0; - - if (offset != abort) - offset += direction; - - while (offset != abort && isspace(data[offset])) - offset += direction; - - while (offset != abort && !isspace(data[offset + lookahead])) - offset += direction; - - return offset; -} - -char * -con_history_get_prev(int *handle) /* Should be -1 if not initialized yet */ -{ - int nexthandle; - - if (*handle == con.input_history_pos) - return NULL; - - if (*handle == -1) - *handle = con.input_history_pos; - - nexthandle = (*handle) - 1; - if (nexthandle == -1) - nexthandle = CON_INPUT_HISTORY_SIZE - 1; - - if (con.input_history[nexthandle]) - *handle = nexthandle; - - return con.input_history[nexthandle]; -} - -char * -con_history_get_next(int *handle) -{ - int last = (con.input_history_pos + CON_INPUT_HISTORY_SIZE - 1) % CON_INPUT_HISTORY_SIZE; - int nexthandle; - - if (*handle < 0 || *handle > CON_INPUT_HISTORY_SIZE) - return NULL; - - if (*handle == last) { - *handle = -1; - return NULL; /* End of history */ - } - - nexthandle = *handle + 1; - if (nexthandle == CON_INPUT_HISTORY_SIZE) - nexthandle = 0; - - if (con.input_history[nexthandle]) - *handle = nexthandle; - - return con.input_history[nexthandle]; -} - -void -con_history_archive(char *msg) -{ - char **writepos = &(con.input_history[con.input_history_pos]); - - if (*writepos) - sci_free(*writepos); - - *writepos = msg; - - if (++con.input_history_pos >= CON_INPUT_HISTORY_SIZE) - con.input_history_pos = 0; -} - -char * -con_gfx_read(gfx_state_t *state) -{ - int chwidth = CON_BUILTIN_CHARS_WIDTH / state->driver->mode->xfact; - int maxchars = 320 / chwidth; - sci_event_t evt; - char *retval; - int done = 0; - int slen = strlen(con.input_text); - int history_handle = -1; - - do { - int old_pos = con.cursor_position; - int must_resize = 0; /* Have to re-calculate the strlen */ - int must_redraw = 0; /* Redraw input field */ - int must_rewin = 0; /* Re-calculate window */ - int must_redraw_text = 0; /* Redraw display field */ - if (slen+1 >= con.input_bufsize) - con.input_text = (char *)sci_realloc(con.input_text, con.input_bufsize += 64); - - evt.type = 0; - while (!evt.type) - evt = gfxop_get_event(state, SCI_EVT_ANY); - - if (evt.type == SCI_EVT_KEYBOARD) { - - if (evt.buckybits & SCI_EVM_CTRL) { - switch(evt.data) { - case 'p': - case 'P': { - char *hist = con_history_get_prev(&history_handle); - - if (hist) { - sci_free(con.input_text); - con.input_text = sci_strdup(hist); - } - must_resize = must_redraw = must_rewin = 1; - } - break; - - case 'n': - case 'N': { - char *hist = con_history_get_next(&history_handle); - - if (hist) { - sci_free(con.input_text); - con.input_text = sci_strdup(hist); - } - must_resize = must_redraw = must_rewin = 1; - } - break; - - case 'a': - case 'A': /* C-a */ - con.cursor_position = 0; - break; - - case 'b': - case 'B': /* C-b */ - if (con.cursor_position) - --con.cursor_position; - break; - - case 'e': - case 'E': /* C-e */ - con.cursor_position = slen; - break; - - case 'f': - case 'F': /* C-f */ - if (con.cursor_position < slen) - ++con.cursor_position; - break; - - case 'd': - case 'D': - memmove(con.input_text + con.cursor_position, - con.input_text + con.cursor_position + 1, - slen - con.cursor_position); - must_resize = must_redraw = 1; - break; - - case 'h': - case 'H': - if (!con.cursor_position) - break; - - memmove(con.input_text + con.cursor_position - 1, - con.input_text + con.cursor_position, - slen - con.cursor_position + 1); - must_resize = must_redraw = 1; - --con.cursor_position; - break; - - case 'k': - case 'K': - con.input_text[con.cursor_position] = 0; - must_resize = must_redraw = 1; - break; - - case '`': return "go"; - - default: - break; - } - } else if (evt.buckybits & SCI_EVM_ALT) { - switch(evt.data) { - case 'b': - case 'B': - con.cursor_position = _str_move_blank(con.input_text, - slen, - con.cursor_position, - -1); - break; - - case 'f': - case 'F': - con.cursor_position = _str_move_blank(con.input_text, - slen, - con.cursor_position, - 1); - break; - - case 'd': - case 'D': { - int delpos = _str_move_blank(con.input_text, slen, - con.cursor_position, 1); - - must_resize = must_redraw = 1; - memmove(con.input_text + con.cursor_position, - con.input_text + delpos, - slen - delpos + 1); - } - - default: - break; - } - } else switch (evt.data) { - - case SCI_K_UP: { - char *hist = con_history_get_prev(&history_handle); - - if (hist) { - sci_free(con.input_text); - con.input_text = sci_strdup(hist); - } - must_resize = must_redraw = must_rewin = 1; - } - break; - - case SCI_K_DOWN: { - char *hist = con_history_get_next(&history_handle); - - if (hist) { - sci_free(con.input_text); - con.input_text = sci_strdup(hist); - } - must_resize = must_redraw = must_rewin = 1; - } - break; - - - case SCI_K_LEFT: - if (con.cursor_position) - --con.cursor_position; - break; - - case SCI_K_RIGHT: - if (con.cursor_position < slen) - ++con.cursor_position; - break; - - - case SCI_K_PGDOWN: - must_redraw_text = 1; - con_scroll(state, -75, maxchars); - break; - - case SCI_K_PGUP: - must_redraw_text = 1; - con_scroll(state, 75, maxchars); - break; - - case SCI_K_END: - con_jump_to_end(state); - must_redraw_text = 1; - break; - - case SCI_K_DELETE: - memmove(con.input_text + con.cursor_position, - con.input_text + con.cursor_position + 1, - slen - con.cursor_position); - must_resize = must_redraw = 1; - break; - - case SCI_K_BACKSPACE: - if (!con.cursor_position) - break; - - memmove(con.input_text + con.cursor_position - 1, - con.input_text + con.cursor_position, - slen - con.cursor_position + 1); - must_resize = must_redraw = 1; - --con.cursor_position; - break; - - - case SCI_K_ENTER: - done = 1; - break; - - default: - if ((evt.character >= 32) && (evt.character <= 255)) { - memmove(con.input_text + con.cursor_position + 1, - con.input_text + con.cursor_position, - slen - con.cursor_position + 1); - - con.input_text[con.cursor_position] = evt.character; - ++con.cursor_position; - ++slen; - must_redraw = 1; - } - } - } - - if (must_resize) - slen = strlen(con.input_text); - - if (old_pos != con.cursor_position) - must_redraw = 1; - - if (must_rewin) { - int chwidth = CON_BUILTIN_CHARS_WIDTH / state->driver->mode->xfact; - int nr_chars = 320 / chwidth; - - con.cursor_position = slen; - con.input_window = slen - nr_chars + (nr_chars >> 3); - } - - if (must_redraw || must_redraw_text) { - _con_redraw(state, must_redraw_text, must_redraw); - gfxop_update(state); - } - } while (!done); - - retval = con.input_text; - con.input_text = (char *)sci_malloc(64); - con.input_text[0] = 0; - con.input_window = con.input_prompt_pos; - con.cursor_position = 0; - - if (!*retval) { - int hist = -1; - sci_free(retval); - return con_history_get_prev(&hist); - } - /* else */ - con_history_archive(retval); - return retval; -} - -static void -_con_redraw(gfx_state_t *state, int update_display_field, int update_input_field) -{ - int chwidth = CON_BUILTIN_CHARS_WIDTH / state->driver->mode->xfact; - int nr_chars = 320 / chwidth; - int offset = con_displayed_lines; - int pixmap_index = -42; - int must_recompute_pixmap_index = 1; - int max_offset; - con_pos_t pos = con.pos; - rect_t fullbox = con_box(); - int yscale = state->driver->mode->yfact; - int input_field_height = con.input_prompt ? - (con.input_prompt->index_yl + yscale - 1) / yscale : 0; - /* This delta is in "virtual" SCI pixels */ - int input_field_size = con_border_width + input_field_height; - /* Let's consider the bottom padding to be part of the input field */ - - - if (!update_input_field && !update_display_field) - return; - if (!update_input_field) - fullbox.yl -= input_field_size; - - if (!update_display_field) { - fullbox.y = fullbox.yl - input_field_size; - fullbox.yl = input_field_size; - } - - if (con.color_bg.alpha) - _con_draw_bg_pic(state, fullbox); - - /* Draw overlay box */ - gfxop_draw_box(state, fullbox, con.color_bg, con.color_bg, - GFX_BOX_SHADE_FLAT); - - if (update_input_field) { - - if (con_border_width >= 2) { - int y = con_displayed_lines + con_border_width - 2; - - gfxop_draw_line(state, gfx_point(0, y), gfx_point(319, y), - con.color_input, GFX_LINE_MODE_FINE, - GFX_LINE_STYLE_NORMAL); - } - - if (con.input_prompt) { - int promptlen = strlen(CON_GFX_PROMPT); - - if (con.cursor_position - con.input_window < (nr_chars >> 3)) - con.input_window -= (nr_chars >> 1); - else if (con.cursor_position - con.input_window > (nr_chars - (nr_chars >> 3))) - con.input_window += (nr_chars >> 1); - - if (con.input_window < con.input_prompt_pos) - con.input_window = con.input_prompt_pos; - - offset -= input_field_height; - - if (con.input_oncursor) { - gfxop_free_pixmap(state, con.input_oncursor); - con.input_oncursor = NULL; - } - - if (con.input_text) { - char oncursorbuf[2]; - char *postcursor_text = con.input_text + con.cursor_position + 1; - char temp_sep; - - oncursorbuf[1] = 0; - oncursorbuf[0] = temp_sep = con.input_text[con.cursor_position]; - - if (!temp_sep) - oncursorbuf[0] = ' '; /* Draw at least a blank cursor */ - - if (con.input_precursor) { - gfxop_free_pixmap(state, con.input_precursor); - con.input_precursor = NULL; - } - if (con.input_postcursor) { - gfxop_free_pixmap(state, con.input_postcursor); - con.input_postcursor = NULL; - } - - con.input_oncursor = _con_render_text(state, oncursorbuf, -1, - &con.color_input, - &con.color_cursor); - if (con.input_text[0]) - con.input_precursor = _con_render_text(state, - con.input_text, -1, - &con.color_input, - NULL); - if (postcursor_text[-1]) - con.input_postcursor = _con_render_text(state, - postcursor_text, - -1, - &con.color_input, - NULL); - - con.input_text[con.cursor_position] = temp_sep; - } else { - con.input_oncursor = _con_render_text(state, " ", -1, - &con.color_input, - &con.color_cursor); - } - - - if (con.input_window < 0) { - con.input_prompt->xoffset = 0; - con.input_prompt->yoffset = 0; - gfxop_draw_pixmap(state, con.input_prompt, - gfx_rect(0, 0, - con.input_prompt->index_xl, - con.input_prompt->index_yl), - gfx_point(chwidth * (strlen(CON_GFX_PROMPT) - + con.input_window), - offset)); - } - - if (con.input_precursor && con.input_window < con.cursor_position) - gfxop_draw_pixmap(state, con.input_precursor, - gfx_rect(0, 0, - con.input_precursor->index_xl, - con.input_precursor->index_yl), - gfx_point(chwidth * -con.input_window, - offset)); - - if (con.input_postcursor && con.input_window + nr_chars - 1 > - con.cursor_position) { - gfxop_draw_pixmap(state, con.input_postcursor, - gfx_rect(0, 0, - con.input_postcursor->index_xl, - con.input_postcursor->index_yl), - gfx_point(chwidth * (con.cursor_position + 1 - - con.input_window), - offset)); - } - - if (con.input_oncursor) - gfxop_draw_pixmap(state, con.input_oncursor, - gfx_rect(0, 0, - con.input_oncursor->index_xl, - con.input_oncursor->index_yl), - gfx_point(chwidth * (con.cursor_position - - con.input_window), - offset)); - - - } - } else - offset -= input_field_height; - - if (!update_display_field) { - gfxop_update_box(state, fullbox); - return; - } - - max_offset = offset; - - if (con.locked_to_end) { - pos.buf = con_buffer; - pos.offset = 0; - pos.entry = con_top_buffer_entry_nr - 1; - } - - while (pos.buf && offset >= 0) { - con_entry_t *drawme; - int depth = pos.offset; - int line_yl; - - pos.offset = 0; - - if (pos.entry < 0) { - pos.entry = CON_CLUSTER_SIZE - 1; - if (pos.buf) - pos.buf = pos.buf->prev; - - if (!pos.buf) - break; - } - - drawme = &(pos.buf->entries[pos.entry]); - - if (_unfold_graphics(state, drawme, nr_chars)) - must_recompute_pixmap_index = 1; - - if (must_recompute_pixmap_index) { - pixmap_index = drawme->pixmaps_nr - 1; - must_recompute_pixmap_index = 0; - } - - if (pixmap_index < 0) { - pos.entry--; - continue; - } - - while (pixmap_index >= 0 - && depth > (drawme->pixmaps[pixmap_index]->yl + yscale - 1) / yscale) - depth -= (drawme->pixmaps[pixmap_index--]->yl + yscale -1) / yscale; - - if (pixmap_index == -1) { - fprintf(stderr, "ERROR: Offset too great! It was %d in a block of height %d\n", - con.pos.offset, drawme->height); - exit(1); - continue; - } - - line_yl = (drawme->pixmaps[pixmap_index]->yl + yscale - 1) / yscale; - - offset -= line_yl - depth; - depth = line_yl; - - if (offset + depth > max_offset) - depth = max_offset - offset; - - gfxop_draw_pixmap(state, drawme->pixmaps[pixmap_index], - gfx_rect(0, 0, - drawme->pixmaps[pixmap_index]->index_xl, depth), - gfx_point(0, offset)); - /* - ** TODO: Insert stuff into overwrapped lines ** - if (pixmap_index) - gfxop_draw_line(state, gfx_rect(chwidth - 2, offset, - chwidth - 2, offset + depth), - con.color_text, GFX_LINE_MODE_FINE, GFX_LINE_STYLE_NORMAL); - */ - - if (!pixmap_index) { - pos.entry--; - must_recompute_pixmap_index = 1; - } else - --pixmap_index; - } - - gfxop_update_box(state, fullbox); -} - -static void -_con_free_entry_pixmaps(gfx_state_t *state, con_entry_t *entry) -{ - int j; - - if (entry->pixmaps) { - for (j = 0; j < entry->pixmaps_nr; j++) - gfxop_free_pixmap(state, entry->pixmaps[j]); - sci_free(entry->pixmaps); - entry->pixmaps_nr = 0; - entry->pixmaps = NULL; - } -} - - -static void -_free_con_buffer(con_buffer_t *buf); - -static void -free_con_buffer(con_buffer_t *buf) -/* Frees a con buffer and all of its predecessors */ -{ - /* First, make sure we're not destroying the current display */ - if (!con.locked_to_end) { - con_buffer_t *seeker = con.pos.buf; - while (seeker && seeker != buf) - seeker = seeker->prev; - - if (seeker) { - if (seeker->prev) - con.pos.buf = seeker->next; - else - con.locked_to_end = 1; - } - } - _free_con_buffer(buf); -} - -static void -_free_con_buffer(con_buffer_t *buf) -{ - int i; - - if (buf) { - con_buffer_t *prev = buf->prev; - - if (buf->next) - buf->next->prev = NULL; - for (i = 0; i < CON_CLUSTER_SIZE; i++) - if (CON_ENTRY_USED(buf->entries[i])) { - if (buf->entries[i].text) - sci_free(buf->entries[i].text); - _con_free_entry_pixmaps(con_last_gfx_state, &buf->entries[i]); - - buf->entries[i].height = -1; - } - sci_free(buf); - --con_buffer_clusters; - - if (prev) - _free_con_buffer(prev); - } -} - - -byte con_builtin_font_data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, - 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, - 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, - 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0xd6, 0x10, 0x38, - 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x7c, 0x10, 0x38, - 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, - 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, - 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, - 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, - 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, - 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, - 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, - 0x18, 0xdb, 0x3c, 0xe7, 0xe7, 0x3c, 0xdb, 0x18, - 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, - 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, - 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, - 0x3e, 0x61, 0x3c, 0x66, 0x66, 0x3c, 0x86, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, - 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, - 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, - 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, - 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, - 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, - 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, - 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, - 0x18, 0x3e, 0x60, 0x3c, 0x06, 0x7c, 0x18, 0x00, - 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, - 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, - 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, - 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, - 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, - 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, - 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, - 0x7c, 0xc6, 0x06, 0x1c, 0x30, 0x66, 0xfe, 0x00, - 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, - 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, - 0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0xc6, 0x7c, 0x00, - 0x38, 0x60, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, - 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, - 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, - 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, - 0x06, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x06, 0x00, - 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, - 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, - 0x7c, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x00, - 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, - 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, - 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, - 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, - 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3a, 0x00, - 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, - 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, - 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, - 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, - 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, - 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, - 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0x7c, 0x0e, - 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, - 0x3c, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x3c, 0x00, - 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, - 0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00, - 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00, - 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, - 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, - 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, - 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, - 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0xe0, 0x60, 0x7c, 0x66, 0x66, 0x66, 0xdc, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00, - 0x1c, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, - 0x3c, 0x66, 0x60, 0xf8, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, - 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, - 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x06, 0x00, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, - 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, - 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0x00, - 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, - 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, - 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, - 0x00, 0x00, 0xdc, 0x76, 0x60, 0x60, 0xf0, 0x00, - 0x00, 0x00, 0x7e, 0xc0, 0x7c, 0x06, 0xfc, 0x00, - 0x30, 0x30, 0xfc, 0x30, 0x30, 0x36, 0x1c, 0x00, - 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, - 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, - 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0xfc, - 0x00, 0x00, 0x7e, 0x4c, 0x18, 0x32, 0x7e, 0x00, - 0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, - 0x70, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x70, 0x00, - 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00, - 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, - 0x38, 0x6c, 0x64, 0xf0, 0x60, 0x66, 0xfc, 0x00, - 0x00, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0x00, - 0x66, 0x66, 0x3c, 0x7e, 0x18, 0x7e, 0x18, 0x18, - 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, - 0x3e, 0x61, 0x3c, 0x66, 0x66, 0x3c, 0x86, 0x7c, - 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0x9d, 0xa1, 0xa1, 0x9d, 0x81, 0x7e, - 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, - 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x81, 0xb9, 0xa5, 0xb9, 0xa5, 0x81, 0x7e, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, - 0x78, 0x0c, 0x18, 0x30, 0x7c, 0x00, 0x00, 0x00, - 0x78, 0x0c, 0x38, 0x0c, 0x78, 0x00, 0x00, 0x00, - 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0xc0, - 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x38, - 0x18, 0x38, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, - 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, - 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, - 0x63, 0xe6, 0x6c, 0x7a, 0x36, 0x6a, 0xdf, 0x06, - 0x63, 0xe6, 0x6c, 0x7e, 0x33, 0x66, 0xcc, 0x0f, - 0xe1, 0x32, 0xe4, 0x3a, 0xf6, 0x2a, 0x5f, 0x86, - 0x18, 0x00, 0x18, 0x18, 0x30, 0x63, 0x3e, 0x00, - 0x18, 0x0c, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00, - 0x30, 0x60, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00, - 0x7c, 0x82, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00, - 0x76, 0xdc, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x00, - 0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x38, 0x6c, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, - 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, - 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x0c, 0x78, - 0x30, 0x18, 0xfe, 0xc0, 0xfc, 0xc0, 0xfe, 0x00, - 0x18, 0x30, 0xfe, 0xc0, 0xf8, 0xc0, 0xfe, 0x00, - 0x7c, 0x82, 0xfe, 0xc0, 0xfc, 0xc0, 0xfe, 0x00, - 0xc6, 0x00, 0xfe, 0xc0, 0xfc, 0xc0, 0xfe, 0x00, - 0x30, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x0c, 0x18, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x3c, 0x42, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x66, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0xf8, 0x6c, 0x66, 0xf6, 0x66, 0x6c, 0xf8, 0x00, - 0x76, 0xdc, 0x00, 0xe6, 0xf6, 0xde, 0xce, 0x00, - 0x0c, 0x06, 0x38, 0x6c, 0xc6, 0x6c, 0x38, 0x00, - 0x30, 0x60, 0x38, 0x6c, 0xc6, 0x6c, 0x38, 0x00, - 0x7c, 0x82, 0x38, 0x6c, 0xc6, 0x6c, 0x38, 0x00, - 0x76, 0xdc, 0x38, 0x6c, 0xc6, 0x6c, 0x38, 0x00, - 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x00, - 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, - 0x3a, 0x6c, 0xce, 0xd6, 0xe6, 0x6c, 0xb8, 0x00, - 0x60, 0x30, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x18, 0x30, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x7c, 0x82, 0x00, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x0c, 0x18, 0x66, 0x66, 0x3c, 0x18, 0x3c, 0x00, - 0xf0, 0x60, 0x7c, 0x66, 0x7c, 0x60, 0xf0, 0x00, - 0x78, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xcc, 0x00, - 0x30, 0x18, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0x18, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0x7c, 0x82, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0x76, 0xdc, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00, - 0xc6, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, - 0x00, 0x00, 0x7e, 0x12, 0xfe, 0x90, 0xfe, 0x00, - 0x00, 0x00, 0x7e, 0xc0, 0xc0, 0x7e, 0x0c, 0x38, - 0x30, 0x18, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, - 0x0c, 0x18, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, - 0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, - 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, - 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, - 0x0c, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3c, 0x00, - 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, - 0x30, 0x7e, 0x0c, 0x7c, 0xcc, 0xcc, 0x78, 0x00, - 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x00, - 0x30, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x0c, 0x18, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x76, 0xdc, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, - 0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, - 0x00, 0x02, 0x7c, 0xce, 0xd6, 0xe6, 0x7c, 0x80, - 0x60, 0x30, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x18, 0x30, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x78, 0x84, 0x00, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, - 0x18, 0x30, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0xfc, - 0xe0, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x60, 0xf0, - 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0xfc -}; - -#endif /* !WANT_CONSOLE */ diff --git a/engines/sci/include/conf_summary.h b/engines/sci/include/conf_summary.h deleted file mode 100644 index c2a1f8e16e..0000000000 --- a/engines/sci/include/conf_summary.h +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************** - conf_summary.h Copyright (C) 2007 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - -#ifndef CONF_SUMMARY_H_ -#define CONF_SUMMARY_H_ - -#include<conf_parse.h> -#include<conf_driver.h> - -typedef struct { - conf_option_t *option; /* NULL if this is a terminator */ - conf_parse_t *parse; /* Source location we got this information from, - ** or NULL for command-line or default */ - union { char *str; - int nr } choice; - int origin; - int flags; -} conf_option_choice_t; - -#define CONF_CHOICE_ORIGIN_DEFAULT 0 /* Built-in default */ -#define CONF_CHOICE_ORIGIN_CONFDEFAULT 1 /* Config file option */ -#define CONF_CHOICE_ORIGIN_CONFGAME 2 /* Game-specific option */ -#define CONF_CHOICE_ORIGIN_COMMANDLINE 3 - -#define CONF_CHOICE_FLAG_WRITEABLE (1<<0) /* 'parse' can be written to */ -#define CONF_CHOICE_FLAG_DISABLED (1<<1) /* Option isn't set, only listed for completeness */ - -typedef struct { - conf_option_choice_t *options; /* Driver-specific */ - conf_driver_t *driver; -} conf_driver_choice_t; - -typedef struct { - conf_option_choice_t *options; /* Subsystem-specific */ - int driver_origin; /* CONF_CHOICE_ORIGIN_* */ - conf_driver_choice_t *driver; /* The particular driver selected */ - conf_driver_choice_t *drivers; /* All available drivers, with their options */ -} conf_subsystem_choice_t; - -typedef struct { - char *game_id; /* NULL for default */ - conf_option_choice_t *options; /* Global */ - int flags; - conf_parse_t **append_location; /* Into here we can add new configuration options to override */ - - conf_subsystem_choice_t[CONF_SUBSYSTEMS_NR] subsystems; -} conf_game_choice_t; - -#define CONF_GAME_CHOICE_FLAG_OVERRIDE_IN_SECTION (1<<0) /* Override section already exists, need not be re-created */ - -typedef struct { - conf_game_choice_t *default; - - int game_choices_nr; - conf_game_choice_t *game_choices; -} conf_summary_t; - - -conf_summary_t * -conf_summary(conf_parse_t *raw_config); -/* Summarises a config parse in a conf_summary_t -** Parameters: (conf_parse_t *) raw_config: The parse to summarise -** Returns : (conf_summary_t *) A summarised configuration -** The summary includes (default) values for all driver/subsystem options -*/ - -void -conf_free_summary(conf_summary_t *summary); -/* Deallocates a configuration summary -** Parameters: (conf_summary_t *) summary: The summary to deallocate -** This only affects the summary, not the underlying parse. -*/ - -conf_game_choice_t * -conf_find_choice(conf_summary_t *choices, char *game_id); -/* Finds the correct game choice by game ID -** Parameters: (conf_summary_t *) summary: The summary to peruse -** (char *) game_id: Identified game ID. -** We search by exact match or otherwise default. -*/ - -#endif /* !defined (CONF_SUMMARY_H_) */ diff --git a/engines/sci/include/modules.h b/engines/sci/include/modules.h deleted file mode 100644 index 9a64956326..0000000000 --- a/engines/sci/include/modules.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************** - modules.h Copyright (C) 2001 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CR) <jameson@linuxgames.com> - -***************************************************************************/ - -#ifndef _FREESCI_MODULES_H_ -#define _FREESCI_MODULES_H_ - -#include <sciresource.h> - -#ifdef _WIN32 -# define MODULE_NAME_SUFFIX ".dll" -#else -# define MODULE_NAME_SUFFIX ".so" -#endif - - -/* Modules must sub-type this structure. Oh, wait, C doesn't do sub-typing. -** Well, they have to start the same, anyway... */ -typedef struct { - char *module_name; /* Module name */ - char *module_version; /* Module version */ - int class_magic; /* Magic ID to identify drivers of certain types */ - int class_version; /* Version of that particular driver class */ - - /* More entries might be added later, but won't be checked if magic or - ** version don't match. */ - -} sci_module_t; - - -void * -sci_find_module(char *path, char *name, char *type, char *struct_prefix, - char *file_suffix, int magic, int version, void **handle); -/* Attempts to open a module with the specified parameters in the path -** Parameters: (char *) path: The path to look in; supports several directories -** (char *) name: Module name -** (char *) type: Module type string (see below) -** (char *) struct_prefix: see below -** (char *) file_suffix: see below -** (int) magic: Magic number to identify the module type -** (int) version: The only version to support -** (void **) handle: Pointer to a void * which a handle is written -** to (for use with sci_close_module()). -** Returns : (void *) NULL if no module was found, a pointer to the structure -** otherwise -** This function looks for the structure 'struct_prefix + name' in a file called -** 'name + file_suffix + MODULE_NAME_SUFFIX' in the 'type' subdirectory. -** It only success if both the magic and the version number match. -*/ - -void -sci_close_module(void *module, char *type, char *name); -/* Closes a previously found module -** Parameters: (void *) module: Reference to the module to close -** (char *) type: Type of the module (for debugging) -** (char *) name: Module name (for debugging) -** Returns : (void) -*/ - - -#endif /* !_FREESCI_MODULES_H_ */ diff --git a/engines/sci/include/sci_conf.h b/engines/sci/include/sci_conf.h deleted file mode 100644 index da411226ed..0000000000 --- a/engines/sci/include/sci_conf.h +++ /dev/null @@ -1,187 +0,0 @@ -/*************************************************************************** - sci_conf.h Copyright (C) 1999,2000,01 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CJR) [jameson@linuxgames.com] - -***************************************************************************/ -/* Configuration and setup stuff for FreeSCI */ - -#ifndef _SCI_CONFIG_H_ -#define _SCI_CONFIG_H_ - -#include <versions.h> -#include <gfx_options.h> - -#define FREESCI_DRIVER_SUBSYSTEMS_NR 1 - -#define FREESCI_DRIVER_SUBSYSTEM_GFX 0 -#define FREESCI_DRIVER_SUBSYSTEM_PCM 1 -#define FREESCI_DRIVER_SUBSYSTEM_MIDIOUT 2 - -#ifdef _WIN32 -# define SCI_DEFAULT_MODULE_PATH "." -#else -# define SCI_DEFAULT_MODULE_PATH "/usr/local/lib/freesci/:/usr/lib/freesci/" -#endif - -typedef struct _driver_option { - char *option; - char *value; - struct _driver_option *next; -} driver_option_t; - -typedef struct _subsystem_options { - char *name; /* Driver name */ - driver_option_t *options; - struct _subsystem_options *next; /* next driver */ -} subsystem_options_t; - -typedef struct { - /* IMPORTANT: these values correspond directly to what's specified in - ** config.l. Where an option is of type OPTION_TYPE_NVP or - ** OPTION_TYPE_INVERSE_NVP, it is cast as an _integer_. Therefore it - ** should not be any other type except for int here. - */ - - char *name; /* Game identifier */ - sci_version_t version; /* The version to emulate */ - - gfx_options_t gfx_options; - - subsystem_options_t *driver_options[FREESCI_DRIVER_SUBSYSTEMS_NR]; - - int x_scale, y_scale, scale, color_depth; /* GFX subsystem initialization values */ - - int animation_delay; /* Number of microseconds to wait between each pic transition animation cycle */ - int animation_granularity; /* Granularity for pic transition animations */ - int alpha_threshold; /* Crossblitting alpha threshold */ - int unknown_count; /* The number of "unknown" kernel functions */ - char *resource_dir; /* Resource directory */ - char *gfx_driver_name; /* The graphics driver to use */ - char *console_log; /* The file to which console output should be echoed */ - char *menu_dir; /* Directory where the game menu searches for games */ - char debug_mode [80]; /* Characters specifying areas for which debug output should be enabled */ - int mouse; /* Whether the mouse should be active */ - int reverse_stereo; - int res_version; - -#ifdef __GNUC__ -# warning "Re-enable sound stuff" -#endif -#if 0 - midiout_driver_t *midiout_driver; /* the midiout method to use */ - midi_device_t *midi_device; /* the midi device to use */ - - pcmout_driver_t *pcmout_driver; /* the pcm driver to use */ - sound_server_t *sound_server; /* The sound server */ -#endif - guint16 pcmout_rate; /* Sample rate */ - guint8 pcmout_stereo; /* Stereo? */ - - char *module_path; /* path to directories modules are loaded from */ - void *dummy; /* This is sad... */ -} config_entry_t; - -int -config_init(config_entry_t **conf, char *conffil); -/* Initializes the config entry structurre based on information found in the config file. -** Parameters: (config_entry_t **) conf: See below -** (char *) conffile: Filename of the config file, or NULL to use the default name -** Returns : (int) The number of config file entries found -** This function reads the ~/.freesci/config file, parses it, and inserts the appropriate -** data into *conf. *conf will be malloc'd to be an array containing default information in [0] -** and game-specific data in each of the subsequent record entries. -** Not threadsafe. Uses flex-generated code. -*/ - -void -config_free(config_entry_t **conf, int entries); -/* Frees a config entry structure -** Parameters: (config_entry_t **) conf: Pointer to the pointer to the first entry of the list -** (int) entries: Number of entries to free -** Returns : (void) -*/ - - -void * -parse_gfx_driver(char *driver_name); -/* Parses a string and looks up an appropriate driver structure -** Parameters: (char *) driver_name: Name of the driver to look up -** Returns : (void *) A matching driver, or NULL on failure -*/ - -void * -parse_midiout_driver(char *driver_name); -/* Parses a string and looks up an appropriate driver structure -** Parameters: (char *) driver_name: Name of the driver to look up -** Returns : (void *) A matching driver, or NULL on failure -*/ - -void * -parse_midi_device(char *driver_name); -/* Parses a string and looks up an appropriate driver structure -** Parameters: (char *) driver_name: Name of the driver to look up -** Returns : (void *) A matching driver, or NULL on failure -*/ - -void * -parse_pcmout_driver(char *driver_name); -/* Parses a string and looks up an appropriate driver structure -** Parameters: (char *) driver_name: Name of the driver to look up -** Returns : (void *) A matching driver, or NULL on failure -*/ - -void * -parse_sound_server(char *driver_name); -/* Parses a string and looks up an appropriate driver structure -** Parameters: (char *) driver_name: Name of the driver to look up -** Returns : (void *) A matching sound server, or NULL on failure -*/ - -driver_option_t * -get_driver_options(config_entry_t *config, int subsystem, const char *name); -/* Retreives the driver options for one specific driver in a subsystem -** Parameters: (config_entry_t *) config: The config entry to search in -** (int) subsystem: Any of the FREESCI_DRIVER_SUBSYSTEMs -** (const char *) name: Name of the driver to look for -** Returns : (driver_option_t *) A pointer to the first option in -** a singly-linked list of options, or NULL if none was -** found -*/ - -#if 0 -void * -find_module(char *path, char *module_name, char *module_suffix); -/* Tries to find a module in the specified path -** Parameters: (char *) path: The path to search in (specified in config) -** (char *) module_name: Name of the module to look for -** (char *) module_suffix: Module structure to look for -** More precisely, the module "module_name" + MODULE_NAME_SUFFIX is -** looked for in all members of the path. If it is found, - -** FIXME: First need to add generic module architecture - -*/ -#endif - -#endif /* !_SCI_CONFIG_H */ diff --git a/engines/sci/main.c b/engines/sci/main.c deleted file mode 100644 index 2da6a550be..0000000000 --- a/engines/sci/main.c +++ /dev/null @@ -1,1840 +0,0 @@ -/*************************************************************************** - main.c Copyright (C) 1999,2000,01,02 Christoph Reichenbach - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Christoph Reichenbach (CJR) [jameson@linuxgames.com] - -***************************************************************************/ - -#include <sciresource.h> -#include <engine.h> -#include <uinput.h> -#include <console.h> -#include <gfx_operations.h> -#include <sci_conf.h> -#include <kdebug.h> -#include <sys/types.h> -#include <game_select.h> -#include "list.h" -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef HAVE_FORK -# include <sys/wait.h> -#endif - -#if defined(HAVE_SDL) && defined(MACOSX) -# include <SDL.h> -/* On OS X, SDL must #define main to something else in order to function */ -#endif - -#ifdef _MSC_VER -#define extern __declspec(dllimport) extern -#include <win32/getopt.h> -#endif - -#ifdef HAVE_READLINE_READLINE_H -#include <readline/readline.h> -#ifdef HAVE_READLINE_HISTORY_H -#include <readline/history.h> -#endif /* HAVE_READLINE_HISTORY_H */ -#endif /* HAVE_READLINE_READLINE_H */ - -#ifdef HAVE_GETOPT_H -# ifndef _MSC_VER -# include <getopt.h> -# else -# include <win32\getopt.h> -# endif -#endif /* HAVE_GETOPT_H */ - -#ifdef HAVE_GETOPT_LONG -#define EXPLAIN_OPTION(longopt, shortopt, description) " " longopt "\t" shortopt "\t" description "\n" -#else /* !HAVE_GETOPT_H */ -#define EXPLAIN_OPTION(longopt, shortopt, description) " " shortopt "\t" description "\n" -#endif /* !HAVE_GETOPT_H */ - - -#ifdef _WIN32 -# ifdef _MSC_VER -# include <direct.h> -# define PATH_MAX 255 -# endif -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -#endif - -#ifdef _DREAMCAST -# include <selectgame.h> -#endif - -#ifdef _MSC_VER -# define MSVC_FUNCTYPECAST_KLUDGE (void *) -#else -# define MSVC_FUNCTYPECAST_KLUDGE -#endif - -#define ACTION_PLAY 0 -#define ACTION_LIST_SAVEGAMES 1 - -static int sciv_action = ACTION_PLAY; - -/*** HW/OS-dependant features ***/ - -static void -check_features() -{ -#ifdef HAVE_ALPHA_EV6_SUPPORT - int helper; - printf("Checking for MVI instruction-set extension: "); - - helper = 0x100; -#ifdef __DECC - axp_have_mvi = asm("amask %0, %v0", helper); -#else - __asm__ ("amask %1, %0" - : "=r"(axp_have_mvi) - : "r"(helper)); -#endif - - axp_have_mvi = !axp_have_mvi; - - if (axp_have_mvi) - printf("found\n"); - else - printf("not present\n"); -#endif -} - - -static gfx_state_t static_gfx_state; /* see below */ -static gfx_options_t static_gfx_options; /* see below */ - -static state_t *gamestate; /* The main game state */ -static gfx_state_t *gfx_state = &static_gfx_state; /* The graphics state */ -static gfx_options_t *gfx_options = &static_gfx_options; /* Graphics options */ -static char *commandline_config_file = NULL; - -int -c_quit(state_t *s) -{ - script_abort_flag = 1; /* Terminate VM */ - _debugstate_valid = 0; - _debug_seeking = 0; - _debug_step_running = 0; - return 0; -} - -int -c_die(state_t *s) -{ - exit(0); /* Die */ - return 0; /* ;-P (fixes warning) */ -} - - -char *old_input = NULL; - -#ifdef HAVE_READLINE_READLINE_H -const char * -get_readline_input(void) -{ - char *input; - - fflush(NULL); - input = readline("> "); - - if (!input) { /* ^D */ - c_quit(NULL); - return ""; - } - - if (strlen(input) == 0) { - free (input); - } else { - -#ifdef HAVE_READLINE_HISTORY_H - add_history(input); -#endif /* HAVE_READLINE_HISTORY_H */ - - if (old_input) { - free(old_input); - } - old_input = input; - } - - return old_input? old_input : ""; -} -#endif /* HAVE_READLINE_READLINE_H */ - - -int -init_directories(char *work_dir, char *game_id) -{ - char *homedir = sci_get_homedir(); - - printf("Initializing directories...\n"); - if (!homedir) { /* We're probably not under UNIX if this happens */ - - if (!getcwd(work_dir, PATH_MAX)) { - fprintf(stderr,"Cannot get the working directory!\n"); - return 1; - } - - return 0; - } - - /* So we've got a home directory */ - - if (chdir(homedir)) { - -#ifdef _WIN32 - if (!getcwd(work_dir, PATH_MAX)) { - fprintf(stderr,"Cannot get the working directory: %s\n", work_dir); - return 1; - } -#else /* Assume UNIX-ish environment */ - fprintf(stderr,"Error: Could not enter home directory %s.\n", homedir); - perror("Reason"); - return 1; /* If we get here, something really bad is happening */ -#endif - } - - if (strlen(homedir) > MAX_HOMEDIR_SIZE) { - fprintf(stderr, "Your home directory path is too long. Re-compile FreeSCI with " - "MAX_HOMEDIR_SIZE set to at least %i and try again.\n", (int)(strlen(homedir))); - return 1; - } - - if (chdir(FREESCI_GAMEDIR)) { - if (scimkdir(FREESCI_GAMEDIR, 0700)) { - - fprintf(stderr, "Warning: Could not enter ~/"FREESCI_GAMEDIR"; save files" - " will be written to ~/\n"); - - getcwd(work_dir, PATH_MAX); - return 0; - - } - else /* mkdir() succeeded */ - chdir(FREESCI_GAMEDIR); - } - - if (chdir(game_id)) { - if (scimkdir(game_id, 0700)) { - - fprintf(stderr,"Warning: Could not enter ~/"FREESCI_GAMEDIR"/%s; " - "save files will be written to ~/"FREESCI_GAMEDIR"\n", game_id); - - getcwd(work_dir, PATH_MAX); - return 0; - } - else /* mkdir() succeeded */ - chdir(game_id); - } - - getcwd(work_dir, PATH_MAX); - - return 0; -} - - -const char * -get_gets_input(void) -{ - static char input[1024] = ""; - - putchar('>'); - - fflush(NULL); - while (!strchr(input, '\n')) - fgets(input, 1024, stdin); - - if (!input) { - c_quit(NULL); - return ""; - } - - if (strlen(input)) - if (input[strlen(input)-1] == '\n'); - input[strlen(input)-1] = 0; /* Remove trailing '\n' */ - - if (strlen(input) == 0) { - return old_input? old_input : ""; - } - - if (old_input) - free(old_input); - - old_input = (char *) sci_malloc(1024); - strcpy(old_input, input); - return input; -} - - - - -static void -list_graphics_drivers() -{ - int i = 0; - while (gfx_get_driver_name(i)) { - if (i != 0) - printf(", "); - - printf(gfx_get_driver_name(i)); - - i++; - } - printf("\n"); -} - -#ifdef __GNUC__ -#warning "Re-enable sound stuff" -#endif -#if 0 -static void -list_pcmout_drivers() -{ - int i = 0; - while (pcmout_drivers[i]) { - if (i != 0) - printf(", "); - printf(pcmout_drivers[i]->name); - i++; - } - printf("\n"); -} - -static void -list_midiout_drivers() -{ - int i = 0; - while (midiout_drivers[i]) { - if (i != 0) - printf(", "); - printf(midiout_drivers[i]->name); - i++; - } - printf("\n"); -} - - -static void -list_midi_devices() -{ - int i = 0; - while (midi_devices[i]) { - if (i != 0) - printf(", "); - printf(midi_devices[i]->name); - i++; - } - printf("\n"); -} - -static void -list_sound_servers() -{ - int i = 0; - while (sound_servers[i]) { - if (i != 0) - printf(", "); - printf(sound_servers[i]->name); - i++; - } - printf("\n"); -} -#endif - - -/**********************************************************/ -/* Startup and config management */ -/**********************************************************/ - -typedef struct { - int script_debug_flag; - int scale_x, scale_y, color_depth; - int mouse; - int master_sound; /* on or off */ - int show_rooms; - sci_version_t version; - int res_version; - char *gfx_driver_name; - char *gamedir; - char *gamemenu; - char *midiout_driver_name; - char *midi_device_name; - char *sound_server_name; - char *pcmout_driver_name; -} cl_options_t; - -#define ON 1 -#define OFF 0 -#define DONTCARE -1 - -static int game_select(cl_options_t cl_options, config_entry_t *confs, int conf_entries, const char* freesci_dir, const char *games_dir); -static int game_select_resource_found(); - -static char * -parse_arguments(int argc, char **argv, cl_options_t *cl_options, char **savegame_name) -{ - int c; -#ifdef HAVE_GETOPT_LONG - int optindex; - - struct option options[] = { - {"run", no_argument, NULL, 0 }, - {"debug", no_argument, NULL, 1 }, - {"gamedir", required_argument, 0, 'd'}, - {"menudir", required_argument, 0, 'G'}, - {"no-sound", required_argument, 0, 'q'}, - {"sci-version", required_argument, 0, 'V'}, - {"graphics", required_argument, 0, 'g'}, - {"midiout", required_argument, 0, 'O'}, - {"pcmout", required_argument, 0, 'P'}, - {"sound-server", required_argument, 0, 'S'}, - {"mididevice", required_argument, 0, 'M'}, - {"version", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"scale-x", required_argument, 0, 'x'}, - {"scale-y", required_argument, 0, 'y'}, - {"color-depth", required_argument, 0, 'c'}, - {"disable-mouse", no_argument, 0, 'm'}, - {"list-savegames", no_argument, 0, 'l'}, - {"show-rooms", no_argument, 0, 's'}, - {"config-file", required_argument, 0, 'f'}, - {0,0,0,0} - }; - - options[0].flag = &(cl_options->script_debug_flag); - options[1].flag = &(cl_options->script_debug_flag); -#endif /* HAVE_GETOPT_H */ - - cl_options->scale_x = cl_options->scale_y = cl_options->color_depth = 0; - cl_options->version = 0; - cl_options->script_debug_flag = 0; - cl_options->gfx_driver_name = NULL; - cl_options->gamedir = NULL; - cl_options->gamemenu = NULL; - cl_options->midiout_driver_name = NULL; - cl_options->pcmout_driver_name = NULL; - cl_options->midi_device_name = NULL; - cl_options->sound_server_name = NULL; - cl_options->mouse = ON; - cl_options->master_sound = ON; - cl_options->res_version = SCI_VERSION_AUTODETECT; - cl_options->show_rooms = 0; - -#ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "qlvhmsDr:d:G:V:g:x:y:c:M:O:S:P:f:", options, &optindex)) > -1) { -#else /* !HAVE_GETOPT_LONG */ - while ((c = getopt(argc, argv, "qlvhmsDr:d:G:V:g:x:y:c:M:O:S:P:f:")) > -1) { -#endif /* !HAVE_GETOPT_LONG */ - switch (c) { - - case 'r': - cl_options->res_version = atoi(optarg); - break; - - case 's': - cl_options->show_rooms = 1; - break; - - case 'D': - cl_options->script_debug_flag = 1; - break; - - case 'd': - if (cl_options->gamedir) - free(cl_options->gamedir); - - cl_options->gamedir = sci_strdup(optarg); - break; - - case 'G': - if (cl_options->gamemenu) - free(cl_options->gamemenu); - - cl_options->gamemenu = sci_strdup(optarg); - break; - - case 'f': - commandline_config_file = sci_strdup(optarg); - break; - - case 'V': { - int major = *optarg - '0'; /* One version digit */ - int minor = atoi(optarg + 2); - int patchlevel = atoi(optarg + 6); - - cl_options->version = SCI_VERSION(major, minor, patchlevel); - } - break; - - case 'g': - if (cl_options->gfx_driver_name) - free(cl_options->gfx_driver_name); - cl_options->gfx_driver_name = sci_strdup(optarg); - break; - case 'O': - if (cl_options->midiout_driver_name) - free(cl_options->midiout_driver_name); - cl_options->midiout_driver_name = sci_strdup(optarg); - break; - case 'P': - if (cl_options->pcmout_driver_name) - free(cl_options->pcmout_driver_name); - cl_options->pcmout_driver_name = sci_strdup(optarg); - break; - case 'M': - if (cl_options->midi_device_name) - free(cl_options->midi_device_name); - cl_options->midi_device_name = sci_strdup(optarg); - break; - case 'S': - if (cl_options->sound_server_name) - free(cl_options->sound_server_name); - cl_options->sound_server_name = sci_strdup(optarg); - break; - case '?': - /* getopt_long already printed an error message. */ - exit(1); - - case 'x': - cl_options->scale_x = atoi(optarg); - break; - - case 'y': - cl_options->scale_y = atoi(optarg); - break; - - case 'c': - cl_options->color_depth = (atoi(optarg) +7) >> 3; - break; - - case 'm': - cl_options->mouse = OFF; - break; - - case 'q': - cl_options->master_sound = OFF; - break; - - case 0: /* getopt_long already did this for us */ - break; - - case 'v': - printf("This is FreeSCI, version %s\n", VERSION); - - printf("Supported graphics drivers: "); - list_graphics_drivers(); - -#ifdef __GNUC__ -#warning "Re-enable sound stuff" -#endif -#if 0 - printf("Supported sound servers: "); - list_sound_servers(); - - printf("Supported midiout drivers: "); - list_midiout_drivers(); - - printf("Supported midi 'devices': "); - list_midi_devices(); - - printf("Supported pcmout drivers: "); - list_pcmout_drivers(); -#endif - - printf("\n"); - exit(0); - - case 'h': - printf("Usage: freesci [options] [game name] [savegame ID]\n" - "Runs a Sierra SCI game.\n" - "\n" - EXPLAIN_OPTION("--gamedir dir\t", "-ddir", "read game resources from dir") - EXPLAIN_OPTION("--menudir dir\t", "-Gdir", "display menu for all games under dir") - EXPLAIN_OPTION("--run\t\t", "-r", "do not start the debugger") - EXPLAIN_OPTION("--sci-version ver", "-Vver", "set the version for freesci to emulate") - EXPLAIN_OPTION("--version\t", "-v", "display version number and exit") - EXPLAIN_OPTION("--debug\t", "-D", "start up in debug mode") - EXPLAIN_OPTION("--help\t", "-h", "display this help text and exit") - EXPLAIN_OPTION("--graphics gfx", "-ggfx", "use the 'gfx' graphics driver") - EXPLAIN_OPTION("--scale-x\t", "-x", "Set horizontal scale factor") - EXPLAIN_OPTION("--scale-y\t", "-y", "Set vertical scale factor") - EXPLAIN_OPTION("--color-depth\t", "-c", "Specify color depth in bpp") - EXPLAIN_OPTION("--disable-mouse", "-m", "Disable support for pointing device") - EXPLAIN_OPTION("--midiout drv\t", "-Odrv", "use the 'drv' midiout driver") - EXPLAIN_OPTION("--mididevice drv", "-Mdrv", "use the 'drv' midi device (eg mt32 or adlib)") - EXPLAIN_OPTION("--pcmout drv\t", "-Pdrv", "use the 'drv' pcmout driver") - EXPLAIN_OPTION("--sound-server srv", "-Ssrv", "Specifies the asynchronous sound server to use") - EXPLAIN_OPTION("--no-sound\t", "-q", "disable sound output") - EXPLAIN_OPTION("--list-savegames", "-l", "Lists all savegame IDs") - EXPLAIN_OPTION("--show-rooms\t", "-s","Displays room numbers on the game console") - "\n" - "The game name, if provided, must be equal to a game name as specified in the\n" - "FreeSCI config file.\n" - "It is overridden by --gamedir.\n" - "\n" - ); - exit(0); - - case 'l': - sciv_action = ACTION_LIST_SAVEGAMES; - break; - - default: - exit(1); - } - } -#if 0 - } /* Work around EMACS paren matching bug */ -#endif - - if (optind+1 >= argc) - *savegame_name = NULL; - else - *savegame_name = argv[optind + 1]; - - if (optind == argc) - return NULL; - - return - argv[optind]; -} - -static int -find_config(char *game_name, config_entry_t *conf, int conf_entries, - sci_version_t *version) -{ - int i, conf_nr = 0; - - for (i = 1; i < conf_entries; i++) - if (!strcasecmp(conf[i].name, game_name)) { - conf_nr = i; - if (version) - *version = conf[i].version; - } - - return conf_nr; -} - -static void -init_console() -{ -#ifdef WANT_CONSOLE - con_gfx_init(); -#endif - con_hook_command(&c_quit, "quit", "", "console: Quits gracefully"); - con_hook_command(&c_die, "die", "", "console: Quits ungracefully"); - - con_hook_int(&(gfx_options->buffer_pics_nr), "buffer_pics_nr", - "Number of pics to buffer in LRU storage\n"); - con_hook_int(&(gfx_options->pic0_dither_mode), "pic0_dither_mode", - "Mode to use for pic0 dithering\n"); - con_hook_int(&(gfx_options->pic0_dither_pattern), "pic0_dither_pattern", - "Pattern to use for pic0 dithering\n"); - con_hook_int(&(gfx_options->pic0_unscaled), "pic0_unscaled", - "Whether pic0 should be drawn unscaled\n"); - con_hook_int(&(gfx_options->dirty_frames), "dirty_frames", - "Dirty frames management\n"); - con_hook_int(&gfx_crossblit_alpha_threshold, "alpha_threshold", - "Alpha threshold for crossblitting\n"); - con_hook_int(&sci0_palette, "sci0_palette", - "SCI0 palette- 0: EGA, 1:AGI/Amiga, 2:Grayscale\n"); - con_hook_int(&sci01_priority_table_flags, "sci01_priority_table_flags", - "SCI01 priority table debugging flags: 1:Disable, 2:Print on change\n"); - - con_passthrough = 1; /* enables all sciprintf data to be sent to stdout */ - -#ifdef HAVE_READLINE_HISTORY_H - using_history(); /* Activate history for readline */ -#endif /* HAVE_READLINE_HISTORY_H */ - -#ifdef HAVE_READLINE_READLINE_H - _debug_get_input = get_readline_input; /* Use readline for debugging input */ -#else /* !HAVE_READLINE_READLINE_H */ - _debug_get_input = get_gets_input; /* Use gets for debug input */ -#endif /* !HAVE_READLINE_READLINE_H */ -} - - -static int -init_gamestate(state_t *gamestate, resource_mgr_t *resmgr, sci_version_t version) -{ - int errc; - gamestate->resmgr = resmgr; - - if ((errc = script_init_engine(gamestate, version))) { /* Initialize game state */ - int recovered = 0; - - if (errc == SCI_ERROR_INVALID_SCRIPT_VERSION) { - int tversion = SCI_VERSION_FTU_NEW_SCRIPT_HEADER - ((version < SCI_VERSION_FTU_NEW_SCRIPT_HEADER)? 0 : 1); - - while (!recovered && tversion) { - printf("Trying version %d.%03x.%03d instead\n", SCI_VERSION_MAJOR(tversion), - SCI_VERSION_MINOR(tversion), SCI_VERSION_PATCHLEVEL(tversion)); - - errc = script_init_engine(gamestate, tversion); - - if ((recovered = !errc)) - version = tversion; - - if (errc != SCI_ERROR_INVALID_SCRIPT_VERSION) - break; - - switch (tversion) { - - case SCI_VERSION_FTU_NEW_SCRIPT_HEADER - 1: - if (version >= SCI_VERSION_FTU_NEW_SCRIPT_HEADER) - tversion = 0; - else - tversion = SCI_VERSION_FTU_NEW_SCRIPT_HEADER; - break; - - case SCI_VERSION_FTU_NEW_SCRIPT_HEADER: - tversion = 0; - break; - } - } - if (recovered) - printf("Success.\n"); - } - - if (!recovered) { - fprintf(stderr,"Script initialization failed. Aborting...\n"); - return 1; - } - } - return 0; -} - -static int -init_gfx(config_entry_t *conf, cl_options_t *cl_options, gfx_driver_t *driver, resource_mgr_t *resmgr) -{ - int scale_x = 0, scale_y = 0, color_depth = 0; - - if (conf) { - if (conf->scale) - scale_x = scale_y = conf->scale; - - if (conf->x_scale) - scale_x = conf->x_scale; - - if (conf->y_scale) - scale_y = conf->y_scale; - - if (conf->color_depth) - color_depth = conf->color_depth >> 3; /* In there it's bpp */ - } - - gfx_state->driver = driver; - gamestate->gfx_state = gfx_state; - gfx_state->version = resmgr->sci_version; - - if (cl_options->scale_x > 0) { - scale_x = cl_options->scale_x; - - if (!scale_y) - scale_y = cl_options->scale_x; - } - - if (cl_options->scale_y > 0) { - scale_y = cl_options->scale_y; - - if (!scale_x) - scale_x = cl_options->scale_y; - } - - if (cl_options->color_depth > 0) - color_depth = cl_options->color_depth; - - if (cl_options->color_depth > 0 && scale_x == 0) - scale_x = scale_y = 2; /* Some default setting */ - - if (scale_x > 0) { - - if (color_depth > 0) { - if (gfxop_init(gfx_state, scale_x, - scale_y, (gfx_color_mode_t) color_depth, - gfx_options, resmgr)) { - fprintf(stderr,"Graphics initialization failed. Aborting...\n"); - return 1; - } - } else { - color_depth = 4; - while (gfxop_init(gfx_state, scale_x, - scale_y, (gfx_color_mode_t) color_depth, - gfx_options, resmgr) && --color_depth); - - if (!color_depth) { - fprintf(stderr,"Could not find a matching color depth. Aborting...\n"); - return 1; - } - } - - } else if (gfxop_init_default(gfx_state, gfx_options, resmgr)) { - fprintf(stderr,"Graphics initialization failed. Aborting...\n"); - return 1; - } - - return 0; -} - - -typedef void *old_lookup_funct_t(char *name); - -typedef void *lookup_funct_t(const char *path, const char *name); - - -static void * -lookup_driver(lookup_funct_t lookup_func, void explain_func(void), - const char *driver_class, const char *driver_name, const char *path) -{ - void *retval = lookup_func(path, driver_name); - - if (!retval) { - if (!driver_name) - sciprintf("The default %s is not available; please choose" - " one explicitly.\n", driver_class); - else - sciprintf("The %s you requested, '%s', is not available.\n" -/* "Please choose one among the following: " */ - , - driver_class, driver_name); -/* explain_func(); */ - exit(1); - } - - return retval; -} - - -/*static void * -old_lookup_driver(old_lookup_funct_t lookup_func, void explain_func(void), - char *driver_class, char *driver_name) -{ - void *retval = lookup_func(driver_name); - - if (!retval) { - sciprintf("The %s you requested, '%s', is not available.\n" - "Please choose one among the following: ", - driver_class, driver_name); - explain_func(); - exit(1); - } - - return retval; -}*/ - -#define NAMEBUF_LEN 30 -static void -list_savegames(state_t *s) -{ - sci_dir_t dir; - char *filename = NULL; - - sci_init_dir(&dir); - - filename = sci_find_first(&dir, "*"); - - sciprintf("\nSavegame listing:\n" - "-----------------\n"); - while (filename) { - char namebuf[NAMEBUF_LEN + 1]; - if (test_savegame(s, filename, namebuf, NAMEBUF_LEN)) { - if (namebuf[0]) - sciprintf("%s:\t\"%s\"\n", filename, namebuf); - else - sciprintf("%s\n", filename); - } - filename = sci_find_next(&dir); - } - sciprintf("-----------------\n"); -} - -void -get_file_directory(char* directory, const char* file) -{ - char* end; - - strcpy(directory, file); - - end = directory + strlen(directory) - 1; - while ((end >= directory) && (end != 0)) - { - if (*end == G_DIR_SEPARATOR) - { - *end = 0; - break; - } - else - { - end--; - } - } -} - -static void -detect_versions(sci_version_t *version, int *res_version, cl_options_t *options, config_entry_t *conf) -{ - sci_version_t exe_version; - sci_version_t hash_version; - int hash_res_version; - guint32 code; - int got_exe_version; - const char *game_name; - - sciprintf("Detecting interpreter and resource versions...\n"); - - got_exe_version = !version_detect_from_executable(&exe_version); - - if (got_exe_version) { - sciprintf("Interpreter version: %d.%03d.%03d (by executable scan)\n", - SCI_VERSION_MAJOR(exe_version), - SCI_VERSION_MINOR(exe_version), - SCI_VERSION_PATCHLEVEL(exe_version)); - - if (SCI_VERSION_MAJOR(exe_version) >= 1) { - sciprintf("FIXME: Implement version mapping (results of executable scan ignored)\n"); - got_exe_version = 0; - } - - } - - game_name = version_guess_from_hashcode(&hash_version, &hash_res_version, &code); - - if (game_name) { - sciprintf("Interpreter version: %d.%03d.%03d (by hash code %08X)\n", - SCI_VERSION_MAJOR(hash_version), - SCI_VERSION_MINOR(hash_version), - SCI_VERSION_PATCHLEVEL(hash_version), code); - if (got_exe_version && exe_version != hash_version) - sciprintf("UNEXPECTED INCONSISTENCY: Hash code %08X indicates interpreter version\n" - " %d.%03d.%03d, but analysis of the executable yields %d.%03d.%03d (for game\n" - " '%s'). Please report this!\n", - code, - SCI_VERSION_MAJOR(hash_version), - SCI_VERSION_MINOR(hash_version), - SCI_VERSION_PATCHLEVEL(hash_version), - SCI_VERSION_MAJOR(exe_version), - SCI_VERSION_MINOR(exe_version), - SCI_VERSION_PATCHLEVEL(exe_version), game_name); - - if (hash_res_version != SCI_VERSION_AUTODETECT) - sciprintf("Resource version: %d (by hash code)\n", hash_res_version); - - sciprintf("Game identified as '%s'\n", game_name); - } else { - sciprintf("Could not identify game by hash code: %08X\n", code); - - if (got_exe_version) - sciprintf("Please report the preceding two lines and the name of the game you were trying\n" - "to run to the FreeSCI development team to help other users!\n", - code); - } - - if (options->version) - *version = options->version; - else if (conf && conf->version) - *version = conf->version; - else if (game_name) - *version = hash_version; - else if (got_exe_version) - *version = exe_version; - else - *version = 0; - - if (options->res_version != SCI_VERSION_AUTODETECT) - *res_version = options->res_version; - else if (conf && conf->res_version != SCI_VERSION_AUTODETECT) - *res_version = conf->res_version; - else if (game_name) - *res_version = hash_res_version; - else - *res_version = SCI_VERSION_AUTODETECT; - - if (*version) - sciprintf("Using interpreter version %d.%03d.%03d\n", - SCI_VERSION_MAJOR(*version), - SCI_VERSION_MINOR(*version), - SCI_VERSION_PATCHLEVEL(*version)); - - if (*res_version != SCI_VERSION_AUTODETECT) - sciprintf("Using resource version %d\n", *res_version); -} - -int -main(int argc, char** argv) -{ - config_entry_t *active_conf = NULL; /* Active configuration used */ - config_entry_t *confs = {0}; /* Configuration read from config file (if it exists) */ - cl_options_t cl_options; /* Command line options */ - int conf_entries = -1; /* Number of config entries */ - int conf_nr = -1; /* Element of conf to use */ -/* FILE *console_logfile = NULL; */ - char freesci_dir[PATH_MAX+1] = ""; - char startdir[PATH_MAX+1] = ""; - char resource_dir[PATH_MAX+1] = ""; - char work_dir[PATH_MAX+1] = ""; - char *cwd; - char *gfx_driver_name = NULL; -/* char *midiout_driver_name = NULL; - char *midi_device_name = NULL; - char *pcm_driver_name = NULL; */ - char *game_name = NULL; - char *savegame_name = NULL; - sci_version_t version; - int res_version; - gfx_driver_t *gfx_driver = NULL; -#if 0 - sound_server_t *sound_server = NULL; -#endif - const char *module_path = SCI_DEFAULT_MODULE_PATH; - resource_mgr_t *resmgr; -#ifdef _DREAMCAST - /* Fake command line arguments. */ - char *args[] = {"/cd/freesci.bin", "-f/ram/config", NULL}; - argv = args; - argc = 2; - chdir("/ram"); -#endif - - init_console(); /* So we can get any output */ - - game_name = parse_arguments(argc, argv, &cl_options, &savegame_name); - - /* remember where freesci executable is located */ - get_file_directory(freesci_dir, argv[0]); - - getcwd(startdir, PATH_MAX); - script_debug_flag = cl_options.script_debug_flag; - - printf("FreeSCI %s Copyright (C) 1999-2007\n", VERSION); - printf(" Dmitry Jemerov, Christopher T. Lansdown, Sergey Lapin, Rickard Lind,\n" - " Carl Muckenhoupt, Christoph Reichenbach, Magnus Reftel, Lars Skovlund,\n" - " Rink Springer, Petr Vyhnak, Solomon Peachy, Matt Hargett, Alex Angas\n" - " Walter van Niftrik, Rainer Canavan, Ruediger Hanke, Hugues Valois\n" - "This program is free software. You can copy and/or modify it freely\n" - "according to the terms of the GNU general public license, v2.0\n" - "or any later version, at your option.\n" - "It comes with ABSOLUTELY NO WARRANTY.\n"); - -#ifdef _DREAMCAST - choose_game(); - game_name = "game"; -#endif - - conf_entries = config_init(&confs, commandline_config_file); - - /* working directory was changed by config_init so restore it */ - chdir(startdir); - - if (game_name) { - - conf_nr = find_config(game_name, confs, conf_entries, &version); - active_conf = confs + conf_nr; - - if (!cl_options.gamedir) - if (chdir(active_conf->resource_dir)) { - if (conf_nr) - fprintf(stderr,"Error entering '%s' to load resource data\n", active_conf->resource_dir); - else - fprintf(stderr,"Game '%s' isn't registered in your config file.\n", game_name); - exit(1); - } - } - - if (cl_options.gamedir) - { - if (chdir(cl_options.gamedir)) { - printf ("Error changing to game directory '%s'\n", cl_options.gamedir); - exit(1); - } - free(cl_options.gamedir); - } - - /* by now, if the user specified a game name or a game directory, the working dir has been changed */ - /* so if no resource are found in the working dir, invoke the game selection screen */ - if (!game_name && !game_select_resource_found()) - { - char *menu_dir; - - if (cl_options.gamemenu) - menu_dir = cl_options.gamemenu; - else - menu_dir = confs->menu_dir; - - chdir(startdir); - conf_nr = game_select(cl_options, confs, conf_entries, freesci_dir, menu_dir); - if (conf_nr < 0) - return 1; - if (conf_nr > 0) - /* A game from the config file was chosen */ - active_conf = confs + conf_nr; - } - - detect_versions(&version, &res_version, &cl_options, active_conf); - - getcwd(resource_dir, PATH_MAX); /* Store resource directory */ - - sciprintf("Loading resources...\n"); - - resmgr = scir_new_resource_manager(resource_dir, res_version, 1, 256*1024); - - if (!resmgr) { - printf("No resources found in '%s'.\nAborting...\n", - resource_dir); - exit(1); - } - - script_adjust_opcode_formats(resmgr->sci_version); - - check_features(); - - chdir(startdir); - -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - printf("Mapping instruments to General Midi\n"); - - map_MIDI_instruments(resmgr); -#endif - - sciprintf("FreeSCI, version "VERSION"\n"); - - gamestate = (state_t *) sci_calloc(sizeof(state_t), 1); - - if (init_gamestate(gamestate, resmgr, version)) - return 1; - - gamestate->gfx_state = NULL; - if (game_init(gamestate)) { /* Initialize */ - fprintf(stderr,"Game initialization failed: Aborting...\n"); - return 1; - } - - if (init_directories(work_dir, (char *) gamestate->game_name)) { - fprintf(stderr,"Error resolving the working directory\n"); - exit(1); - } - - /* Set the CWD as the savegame dir */ - cwd = sci_getcwd(); - script_set_gamestate_save_dir(gamestate, cwd); - sci_free(cwd); - - if (sciv_action == ACTION_LIST_SAVEGAMES) { - list_savegames(gamestate); - exit(0); - } - gamestate->resource_dir = resource_dir; - gamestate->work_dir = work_dir; - gamestate->port_serial = 0; - - if (!game_name) - game_name = (char *) gamestate->game_name; - - /* If no game-specific configuration has been read, then read the non-specific config from file */ - if (!active_conf) { - conf_nr = find_config(game_name, confs, conf_entries, &version); - active_conf = confs + conf_nr; - } - - /* gcc doesn't warn about (void *)s being typecast. If your compiler doesn't like these - ** implicit casts, don't hesitate to typecast appropriately. */ - if (cl_options.gfx_driver_name) { - gfx_driver_name = sci_strdup(cl_options.gfx_driver_name); - free(cl_options.gfx_driver_name); - } /* else it's still NULL */ - -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - if (cl_options.pcmout_driver_name) - pcmout_driver = old_lookup_driver((old_lookup_funct_t *)pcmout_find_driver, - MSVC_FUNCTYPECAST_KLUDGE list_pcmout_drivers, - "pcmout driver", cl_options.pcmout_driver_name); - - if (cl_options.midiout_driver_name) - { - midiout_driver = old_lookup_driver((old_lookup_funct_t *)midiout_find_driver, - MSVC_FUNCTYPECAST_KLUDGE list_midiout_drivers, - "midiout driver", cl_options.midiout_driver_name); - free(cl_options.midiout_driver_name); - } - - if (cl_options.midi_device_name) - { - midi_device = old_lookup_driver((old_lookup_funct_t *)midi_find_device, - MSVC_FUNCTYPECAST_KLUDGE list_midi_devices, - "MIDI device", cl_options.midi_device_name); - free(cl_options.midi_device_name); - } - - if (cl_options.sound_server_name) - { - sound_server = old_lookup_driver((old_lookup_funct_t *)sound_server_find_driver, - MSVC_FUNCTYPECAST_KLUDGE list_sound_servers, - "sound server", cl_options.sound_server_name); - free(cl_options.sound_server_name); - } -#endif - - if (confs) { - memcpy(gfx_options, &(active_conf->gfx_options), sizeof(gfx_options_t)); /* memcpy so that console works */ - if (!gfx_driver_name) - gfx_driver_name = active_conf->gfx_driver_name; -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - if (!sound_server) - sound_server = active_conf->sound_server; - - /* make sure we have sound drivers */ - if (!midiout_driver) - midiout_driver = active_conf->midiout_driver; - if (!midi_device) - midi_device = active_conf->midi_device; - if (!pcmout_driver) - pcmout_driver = active_conf->pcmout_driver; -#endif - } - - if (confs) { - module_path = active_conf->module_path; - - if (!gfx_driver_name) - gfx_driver_name = active_conf->gfx_driver_name; - } - - gfx_driver = (gfx_driver_t *) - lookup_driver((lookup_funct_t *)gfx_find_driver, - MSVC_FUNCTYPECAST_KLUDGE list_graphics_drivers, - "graphics driver", gfx_driver_name, module_path); - - if (!gfx_driver) { - if (gfx_driver_name) - fprintf(stderr,"Failed to find graphics driver \"%s\"\n" - "Please run 'freesci -v' to get a list of all " - "available drivers.\n", gfx_driver_name); - else - fprintf(stderr,"No default gfx driver available.\n"); - - return 1; - } - - if (!gamestate->version_lock_flag) - if (active_conf->version) - gamestate->version = active_conf->version; - - if (strlen (active_conf->debug_mode)) - set_debug_mode (gamestate, 1, active_conf->debug_mode); - - -#if 0 - { - int j; - for (j =0; j < conf_entries; j++) { - int i; - config_entry_t *c = conf + j; - fprintf(stderr, "[%s]\n", c->name); - for (i = 0; i < 2; i++) { - subsystem_options_t *subsys = c->driver_options[i]; - fprintf(stderr, " <%s>\n", i? "midiout" : "gfx"); - - while (subsys) { - driver_option_t *opt; - fprintf(stderr, " {%p,%s}\n", subsys->name,subsys->name); - opt = subsys->options; - while (opt) { - fprintf(stderr, "\t%p'%s' = %p'%s'\n", opt->option, opt->option, opt->value,opt->value); - opt = opt->next; - } - subsys = subsys->next; - } - } - } - } -#endif /* 0 */ - - /* Now configure the graphics driver with the specified options */ - { - driver_option_t *option = get_driver_options(active_conf, FREESCI_DRIVER_SUBSYSTEM_GFX, gfx_driver->name); - while (option) { - if ((gfx_driver->set_parameter)(gfx_driver, option->option, option->value)) { - fprintf(stderr, "Fatal error occured in graphics driver while processing \"%s = %s\"\n", - option->option, option->value); - exit(1); - } - - option = option->next; - } - } - -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - /* Configure the pcmout driver */ - { - pcmout_sample_rate = active_conf->pcmout_rate; - pcmout_stereo = active_conf->pcmout_stereo; - } - - /* Configure the midiout driver */ - { - driver_option_t *option = get_driver_options(active_conf, FREESCI_DRIVER_SUBSYSTEM_MIDIOUT, midiout_driver->name); - while (option) { - if ((midiout_driver->set_parameter)(midiout_driver, option->option, option->value)) { - fprintf(stderr, "Fatal error occured in midiout driver while processing \"%s = %s\"\n", - option->option, option->value); - exit(1); - } - - option = option->next; - } - } -#endif - - /* Allows drivers to access files in the resource directory. */ - if (chdir(gamestate->resource_dir)) { - fprintf(stderr,"Error entering resource directory '%s'\n", - gamestate->resource_dir); - exit(1); - } - - if (init_gfx(active_conf, &cl_options, gfx_driver, resmgr)) - return 1; - - - if (game_init_graphics(gamestate)) { /* Init interpreter graphics */ - fprintf(stderr,"Game initialization failed: Error in GFX subsystem. Aborting...\n"); - return 1; - } - - if (game_init_sound(gamestate, (cl_options.master_sound == OFF)? SFX_STATE_FLAG_NOSOUND : 0)) { - fprintf(stderr,"Game initialization failed: Error in sound subsystem. Aborting...\n"); - return 1; - } - - if (chdir(gamestate->work_dir)) { - fprintf(stderr,"Error entering working directory '%s'\n", - gamestate->work_dir); - exit(1); - } - -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - if (!sound_server) - sound_server = sound_server_find_driver(NULL); -#endif - - if (cl_options.show_rooms) - set_debug_mode(gamestate, 1, "r"); - -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - gamestate->sound_server = sound_server; - - if (gamestate->sound_server) { - int poly; - if (gamestate->sound_server->init( - gamestate, - ((active_conf->reverse_stereo) ? SOUNDSERVER_INIT_FLAG_REVERSE_STEREO : 0))) - { - - fprintf(stderr,"Sound server initialization failed- aborting.\n"); - return 1; - } - sci_sched_yield(); - - if (!soundserver_dead) { - poly = gamestate->sound_server->command(gamestate, get_msg_value("SOUND_COMMAND_TEST"), 0, 0); - - printf("Sound server reports polyphony %d\n", poly); - - gamestate->sound_server->command(gamestate, get_msg_value("SOUND_COMMAND_SET_VOLUME"), 0, 0xc); - - } - - gamestate->sound_server->get_event(gamestate); /* Get init message */ - /* FIXME: memory allocated that is not freed */ - } -#endif - - if (active_conf && active_conf->console_log) - open_console_file (active_conf->console_log); - gamestate->animation_delay = active_conf->animation_delay; - gamestate->animation_granularity = active_conf->animation_granularity; - gfx_crossblit_alpha_threshold = active_conf->alpha_threshold; - - printf("Emulating SCI version %d.%03d.%03d\n", - SCI_VERSION_MAJOR(gamestate->version), - SCI_VERSION_MINOR(gamestate->version), - SCI_VERSION_PATCHLEVEL(gamestate->version)); - - printf("Graphics: Using the %s driver %s\n", - gfx_driver->name, gfx_driver->version); -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - printf("MIDI-out: Using the %s driver %s\n", - midiout_driver->name, midiout_driver->version); - printf("MIDI-device: Using the %s driver %s\n", - midi_device->name, midi_device->version); - printf("PCM-out: Using the %s driver %s\n", - pcmout_driver->name, pcmout_driver->version); - - if (sound_server) - printf("Sound server: Using the %s sound server %s\n", - sound_server->name, sound_server->version); - else - printf("Sound server: Disabled.\n"); -#endif - - gamestate->have_mouse_flag = (cl_options.mouse == DONTCARE)? - active_conf->mouse : cl_options.mouse; - - if (savegame_name) - game_restore(&gamestate, savegame_name); - else - game_run(&gamestate); /* Run the game */ -#ifdef __GNUC__ -#warning "sound" -#endif -#if 0 - if (gamestate->sound_server) - gamestate->sound_server->exit(gamestate); /* Shutdown sound daemon first */ -#endif - - game_exit(gamestate); - script_free_engine(gamestate); /* Uninitialize game state */ - script_free_breakpoints(gamestate); - - scir_free_resource_manager(resmgr); - - if (conf_entries >= 0) - config_free(&confs, conf_entries); - - close_console_file(); - - chdir (startdir); /* ? */ - -#ifdef HAVE_FORK - printf("Waiting for sound server to die..."); - wait(NULL); /* Wait for sound server process to die, if neccessary */ - printf(" OK.\n"); -#endif - - gfxop_exit(gfx_state); - - sci_free(gamestate); - - if (commandline_config_file) - sci_free(commandline_config_file); - -#ifdef WITH_DMALLOC - fprintf(stderr,"--- Everything but the two console buffers should have been freed now ---\n"); - dmalloc_log_unfreed(); -/* BREAKPOINT(); */ - ((*(int *)NULL) = 42); -#endif - return 0; -} - - -static int -game_select_resource_found() -{ - int fd; - - fd = sci_open("resource.map", O_RDONLY | O_BINARY); - if (IS_VALID_FD(fd)) - { - close(fd); - return 1; - } - - return 0; -} - -static int -game_select_init_gfx(config_entry_t *conf, cl_options_t *cl_options, gfx_driver_t *driver, sci_version_t sci_version) -{ - int scale_x = 0, scale_y = 0; - int color_depth = 0; - - if (conf) { - if (conf->scale) - scale_x = scale_y = conf->scale; - - if (conf->x_scale) - scale_x = conf->x_scale; - - if (conf->y_scale) - scale_y = conf->y_scale; - - if (conf->color_depth) - color_depth = conf->color_depth >> 3; /* In there it's bpp */ - } - - gfx_state->driver = driver; - gfx_state->version = sci_version; - - if (cl_options->scale_x > 0) { - scale_x = cl_options->scale_x; - - if (!scale_y) - scale_y = cl_options->scale_x; - } - - if (cl_options->scale_y > 0) { - scale_y = cl_options->scale_y; - - if (!scale_x) - scale_x = cl_options->scale_y; - } - - if (cl_options->color_depth > 0) - color_depth = cl_options->color_depth; - - if (color_depth > 0 && scale_x == 0) - scale_x = scale_y = 2; /* Some default setting */ - -/* fprintf(stderr, "cd-conf=%d, cd-cl=%d, cd=%d\n", - conf->color_depth, cl_options->color_depth, color_depth); */ - - fprintf(stderr, "Checking byte depth %d\n", color_depth); - - if (scale_x > 0) { - - if (color_depth > 0) { - if (game_select_gfxop_init(gfx_state, scale_x, - scale_y, (gfx_color_mode_t) color_depth, - gfx_options, 0)) { - fprintf(stderr,"Graphics initialization failed. Aborting...\n"); - return 1; - } - } else { - color_depth = 4; - while (game_select_gfxop_init(gfx_state, scale_x, - scale_y, (gfx_color_mode_t) color_depth, - gfx_options, 0) && --color_depth); - - if (!color_depth) { - fprintf(stderr,"Could not find a matching color depth. Aborting...\n"); - return 1; - } - } - - } else if (game_select_gfxop_init_default(gfx_state, gfx_options, 0)) { - fprintf(stderr,"Graphics initialization failed. Aborting...\n"); - return 1; - } - - return 0; -} - -static int compare_games(const void* arg1, const void* arg2) -{ - game_t* game1 = (game_t *)arg1; - game_t* game2 = (game_t *)arg2; - - return strcmp(game1->name, game2->name); -} - -static gfx_bitmap_font_t* load_font(const char* font_dir, const char* filename) -{ - gfx_bitmap_font_t* font = NULL; - int fh; - int fsize; - byte* buffer; - char work_dir[256]; - - getcwd(work_dir, 256); - - /* change to the font directory */ - chdir(font_dir); - - fh = sci_open(filename, O_RDONLY|O_BINARY); - - if (!IS_VALID_FD(fh)) - return NULL; - - fsize = sci_fd_size(fh); - - buffer = (byte *) sci_malloc(fsize); - - /* skip the header information, is present by default when using sciunpack */ - read(fh, buffer, 2); - - /* read the font data */ - read(fh, buffer, fsize); - - font = gfxr_read_font(0, buffer, fsize); - - sci_free(buffer); - - close(fh); - - chdir(work_dir); - - return font; -} - -#define FONT_DEFAULT "default.fnt" -#define FONT_SMALL "small.fnt" - -static void -add_games(const char *dir_name, games_list_head_t *head, int *games, gfx_driver_t *driver, - gfx_bitmap_font_t* font_default, gfx_bitmap_font_t* font_small) -{ - sci_dir_t dir; - char *filename; - int fd; - - if (chdir(dir_name)) - return; - - fd = sci_open("resource.map", O_RDONLY); - - if (IS_VALID_FD(fd)) { - games_list_t *list; - sci_version_t result; - int res_version; - const char *game_name; - guint32 code; - - close(fd); - - list = (games_list_t*)sci_malloc(sizeof(games_list_t)); - getcwd(list->game.dir, PATH_MAX); - game_name = version_guess_from_hashcode(&result, &res_version, &code); - - if (game_name) - list->game.name = sci_strdup(game_name); - else - list->game.name = sci_strdup(dir_name); - - list->game.conf_nr = 0; - LIST_INSERT_HEAD(head, list, entries); - (*games)++; - - game_select_scan_info(driver, font_default, font_small, list->game.name, *games); - } - - sci_init_dir(&dir); - - filename = sci_find_first(&dir, "*"); - - while (filename) { - add_games(filename, head, games, driver, font_default, font_small); - filename = sci_find_next(&dir); - } - - sci_finish_find(&dir); - chdir(".."); - - return; -} - -static int -find_games(const char* dir, game_t **games, gfx_driver_t *driver, gfx_bitmap_font_t* font_default, gfx_bitmap_font_t* font_small) -{ - games_list_head_t head; - int games_nr = 0; - games_list_t *list; - int i; - - game_select_scan_info(driver, font_default, font_small, NULL, 0); - - LIST_INIT(&head); - add_games(dir, &head, &games_nr, driver, font_default, font_small); - - if (!games_nr) - return 0; - - *games = (game_t*)sci_malloc(sizeof(game_t) * games_nr); - - i = 0; - while ((list = LIST_FIRST(&head))) { - (*games)[i++] = list->game; - LIST_REMOVE(list, entries); - sci_free(list); - } - - return games_nr; -} - -static int game_select(cl_options_t cl_options, config_entry_t *confs, int conf_entries, const char* freesci_dir, const char *games_dir) { - char start_dir[PATH_MAX+1] = ""; - char *gfx_driver_name = NULL; - gfx_driver_t *gfx_driver = NULL; - const char *module_path = SCI_DEFAULT_MODULE_PATH; - int selected_game = -1; - gfx_bitmap_font_t* font_default; - gfx_bitmap_font_t* font_small; - int font_default_allocated = 0; - int font_small_allocated = 0; - game_t *games = NULL; - int games_nr; - int i; - - getcwd(start_dir, PATH_MAX); - script_debug_flag = cl_options.script_debug_flag; - - /* gcc doesn't warn about (void *)s being typecast. If your compiler doesn't like these - ** implicit casts, don't hesitate to typecast appropriately. */ - if (cl_options.gfx_driver_name) { - gfx_driver_name = sci_strdup(cl_options.gfx_driver_name); - /* free(cl_options.gfx_driver_name); */ - } /* else it's still NULL */ - - if (confs) { - memcpy(gfx_options, &(confs->gfx_options), sizeof(gfx_options_t)); /* memcpy so that console works */ - if (!gfx_driver_name) - gfx_driver_name = confs->gfx_driver_name; - } - - if (confs) { - module_path = confs->module_path; - - if (!gfx_driver_name) - gfx_driver_name = confs->gfx_driver_name; - } - - gfx_driver = (gfx_driver_t *) - lookup_driver((lookup_funct_t *)gfx_find_driver, - MSVC_FUNCTYPECAST_KLUDGE list_graphics_drivers, - "graphics driver", gfx_driver_name, module_path); - - if (!gfx_driver) { - if (gfx_driver_name) - fprintf(stderr,"Failed to find graphics driver \"%s\"\n" - "Please run 'freesci -v' to get a list of all " - "available drivers.\n", gfx_driver_name); - else - fprintf(stderr,"No default gfx driver available.\n"); - - return -2; - } - - - /* Now configure the graphics driver with the specified options */ - { - driver_option_t *option = get_driver_options(confs, FREESCI_DRIVER_SUBSYSTEM_GFX, gfx_driver->name); - while (option) { - if ((gfx_driver->set_parameter)(gfx_driver, option->option, option->value)) { - fprintf(stderr, "Fatal error occured in graphics driver while processing \"%s = %s\"\n", - option->option, option->value); - exit(1); - } - - option = option->next; - } - } - - if (game_select_init_gfx(confs, &cl_options, gfx_driver, 0)) - return -2; - - /* load user supplied font from disk, if not found then use built-in font */ - font_default = load_font(freesci_dir, FONT_DEFAULT); - if (!font_default) - font_default = gfxr_get_font(NULL, GFX_FONT_BUILTIN_6x10, 0); - else - font_default_allocated = 1; - - /* load user supplied font from disk, if not found then use built-in font */ - font_small = load_font(freesci_dir, FONT_SMALL); - if (!font_small) - font_small = gfxr_get_font(NULL, GFX_FONT_BUILTIN_5x8, 0); - else - font_small_allocated = 1; - - chdir(start_dir); - - if (games_dir) - games_nr = find_games(games_dir, &games, gfx_driver, font_default, font_small); - else - games_nr = 0; - - games = (game_t*)sci_realloc(games, sizeof(game_t) * (games_nr + conf_entries)); - - for (i = 0; i < conf_entries; i++) { - if (confs[i].name) { - char *c; - - games[games_nr].name = sci_strdup(confs[i].name); - games[games_nr].conf_nr = i; - /* Replace all '_'with ' ' */ - - c = games[games_nr].name; - while (*c != 0) - { - if (*c == '_') - *c = ' '; - c++; - } - strncpy(games[games_nr].dir, confs[i].resource_dir, PATH_MAX - 1); - games[games_nr++].dir[PATH_MAX - 1] = 0; - } - } - - /* Sort game list */ - qsort(games, games_nr, sizeof(game_t), compare_games); - - /* Index of game selected is returned - -1 means no selection (quit) */ - selected_game = game_select_display(gfx_driver, games, games_nr, font_default, font_small); - if (selected_game >= 0) - { - chdir(games[selected_game].dir); - } - - if (font_default_allocated == 1) - gfxr_free_font(font_default); - - if (font_small_allocated == 1) - gfxr_free_font(font_small); - - if (selected_game >= 0) - selected_game = games[selected_game].conf_nr; - - for (i = 0; i < games_nr; i++) - sci_free(games[i].name); - sci_free(games); - - gfx_driver->exit(gfx_driver); - - return selected_game; -} diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 18fa897aaa..3b58b0b053 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -16,6 +16,7 @@ MODULE_OBJS = \ engine/kscripts.o \ engine/ksound.o \ engine/kstring.o \ + engine/message.o \ engine/said.o \ engine/savegame.o \ engine/scriptconsole.o \ @@ -83,7 +84,6 @@ MODULE_OBJS = \ sfx/player/realtime.o \ sfx/seq/sequencers.o \ sfx/softseq/amiga.o \ - sfx/softseq/fmopl.o \ sfx/softseq/opl2.o \ sfx/softseq/pcspeaker.o \ sfx/softseq/SN76496.o \ diff --git a/engines/sci/scicore/sci_dos.c b/engines/sci/scicore/sci_dos.c deleted file mode 100644 index 0435afa32b..0000000000 --- a/engines/sci/scicore/sci_dos.c +++ /dev/null @@ -1,219 +0,0 @@ -/*************************************************************************** - sci_dos.c Copyright (C) 1999 Rink Springer - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - - Please contact the maintainer for bug reports or inquiries. - - Current Maintainer: - - Rink Springer [rink@springer.cx] - -***************************************************************************/ - -#include <stdlib.h> -#include <sci_dos.h> -#include <string.h> - -#define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) - -gpointer -malloc0(guint32 size) { - char* ptr; - - /* allocate the buffer, return NULL if no buffer */ - if((ptr= sci_malloc(size))==NULL) return NULL; - - /* clear it to zeros */ - memset(ptr,0,size); - - /* return the pointer */ - return ptr; -} - -guint -g_printf_string_upper_bound (const gchar* format, - va_list args) -{ - guint len = 1; - - while (*format) - { - gboolean long_int = FALSE; - gboolean extra_long = FALSE; - gchar c; - - c = *format++; - - if (c == '%') - { - gboolean done = FALSE; - - while (*format && !done) - { - switch (*format++) - { - gchar *string_arg; - - case '*': - len += va_arg (args, int); - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - /* add specified format length, since it might exceed the - * size we assume it to have. - */ - format -= 1; - len += strtol (format, (char**) &format, 10); - break; - case 'h': - /* ignore short int flag, since all args have at least the - * same size as an int - */ - break; - case 'l': - if (long_int) - extra_long = TRUE; /* linux specific */ - else - long_int = TRUE; - break; - case 'q': - case 'L': - long_int = TRUE; - extra_long = TRUE; - break; - case 's': - string_arg = va_arg (args, char *); - if (string_arg) - len += strlen (string_arg); - else - { - /* add enough padding to hold "(null)" identifier */ - len += 16; - } - done = TRUE; - break; - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - case 'X': - { - if (long_int) - (void) va_arg (args, long); - else - (void) va_arg (args, int); - } - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'D': - case 'O': - case 'U': - (void) va_arg (args, long); - len += 32; - done = TRUE; - break; - case 'e': - case 'E': - case 'f': - case 'g': - (void) va_arg (args, double); - len += extra_long ? 64 : 32; - done = TRUE; - break; - case 'c': - (void) va_arg (args, int); - len += 1; - done = TRUE; - break; - case 'p': - case 'n': - (void) va_arg (args, void*); - len += 32; - done = TRUE; - break; - case '%': - len += 1; - done = TRUE; - break; - default: - /* ignore unknow/invalid flags */ - break; - } - } - } - else - len += 1; - } - -return len; -} - -gchar* -g_strdup_vprintf (const gchar *format, - va_list args1) { - gchar *buffer; - va_list args2; - - G_VA_COPY (args2, args1); - - buffer = g_new (gchar, g_printf_string_upper_bound (format, args1)); - - vsprintf (buffer, format, args2); - va_end (args2); - - return buffer; -} - -gint -g_vsnprintf (gchar *str, - gulong n, - gchar const *fmt, - va_list args) { - gchar* printed; - - - printed = g_strdup_vprintf (fmt, args); - strncpy (str, printed, n); - str[n-1] = '\0'; - - free (printed); - - return strlen (str); -} - -gpointer -g_memdup (gpointer mem, guint byte_size) { - gpointer new_mem; - - if (mem) { - new_mem = sci_malloc (byte_size); - memcpy (new_mem, mem, byte_size); - } else { - new_mem = NULL; - } - - return new_mem; -} diff --git a/engines/sci/sfx/old/Makefile b/engines/sci/sfx/old/Makefile deleted file mode 100644 index f7235d945b..0000000000 --- a/engines/sci/sfx/old/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -CC = gcc -CFLAGS = -O2 -Wall -LIBS = -L/usr/lib -lasound -objects = main.o midi_mt32.o midiout.o midiout_unixraw.o midiout_alsaraw.o - -sciplaymidi: $(objects) - $(CC) $(LIBS) -o sciplaymidi $(objects) - -main.o: main.c - $(CC) $(CFLAGS) -c main.c -midi_mt32.o: midi_mt32.c midi_mt32.h midiout.h - $(CC) $(CFLAGS) -c midi_mt32.c -midiout.o: midiout.c midiout.h midiout_unixraw.h midiout_alsaraw.h - $(CC) $(CFLAGS) -c midiout.c -midiout_unixraw.o: midiout_unixraw.c midiout_unixraw.h - $(CC) $(CFLAGS) -c midiout_unixraw.c -midiout_alsaraw.o: midiout_alsaraw.c midiout_alsaraw.h - $(CC) $(CFLAGS) -c midiout_alsaraw.c - -.PHONY: clean distclean -clean: - rm -f sciplaymidi $(objects) -distclean: - rm -f sciplaymidi $(objects) *~ diff --git a/engines/sci/sfx/old/README b/engines/sci/sfx/old/README deleted file mode 100644 index c652175761..0000000000 --- a/engines/sci/sfx/old/README +++ /dev/null @@ -1,6 +0,0 @@ -type 'make' and './sciplaymidi' to program your MT-32 with the file -'patch.001' in the current directory - -Only tested with Linux and ALSA... - -Rickard Lind <rpl@dd.chalmers.se> diff --git a/engines/sci/sfx/old/ROADMAP b/engines/sci/sfx/old/ROADMAP deleted file mode 100644 index 9a6ec1b4da..0000000000 --- a/engines/sci/sfx/old/ROADMAP +++ /dev/null @@ -1,72 +0,0 @@ -The way I would have made things if I had the time to do it -Rickard Lind <rpl@dd.chalmers.se>, 2000-12-30 -------------------------------------------------------------------------------- - -Step 1: - -D rename "src/sound/midi.c" in freesci to "oldmidi.c" and still use it -D move my "midi*" and "midiout*" to "src/sound" -D change all "glib.h" to the real thing - -Step 2: - -D implement all note-playing, volume changing, reverb etc in "midi_mt32.*" - use disassembled sierra SCI1.1 driver as the main source of inspiration -D change "soundserver_null.c" to use the new device driver for MT-32 -* use "~/.freesci/config" to set ALSA/OSS and other options - -Step 3: - -* Implement a GM translation driver "midi_gm.*" using a parsed textfile - for instrument mapping -* Improve instrument mappings using new features such as keyshift, - volume adjust and velocity remap - -Step 4: - -* Reimplement a SCI0 soundserver using the new sound sub sytem -* PCM support (samples) with ALSA and possibly DirectX -* MPU-401 UART midiout driver for DOS/Windows - -Step 5: - -* SCI01, SCI1, SCI32 soundserver -* Adlib support "midi_opl2.*", "oplout_alsaraw.*", "oplout_pcmemu.*" -* PCM support Sound Blaster DOS - -Step 6: - -* Make it possible to play samples and use opl2 emulation (found in MAME - I think) at the same time through the same sound device - -Step 7: - -* All those other little nifty things... - -------------------------------------------------------------------------------- - -My idea concerning naming of the files: - -src/sound/midi.* wrapper for MIDI device drivers -src/sound/midiout.* wrapper for different methods to output - MIDI data -src/sound/pcm.* wrapper for PCM device drivers -src/sound/pcmout.* wrapper for different methods to output - PCM data -src/sound/midi_mt32.* Roland MT-32 device driver -src/sound/midi_opl2.* Adlib/OPL2 device driver -src/sound/midiout_alsaraw.* rawmidi output using alsalib -src/sound/midiout_unixraw.* rawmidi output using unix filesystem -src/sound/oplout_alsaraw.* opl output using alsa - -------------------------------------------------------------------------------- - -Use Linux and ALSA 0.5.x (or later) and Roland MT-32 while developing. -Don't implement supremely stupid abstract frameworks without consulting -experienced people on the mailinglist first. There are infinite ways to -implement the sound subsystem the VERY VERY WRONG way. Don't make -everything too much of a hack either. - -Use the files is in "lists/" when doing text output for debugging purposes. - -Good luck! diff --git a/engines/sci/sfx/old/main.c b/engines/sci/sfx/old/main.c deleted file mode 100644 index 73daebd1bb..0000000000 --- a/engines/sci/sfx/old/main.c +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************** - main.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include "midi_mt32.h" - -int main() -{ - int fd; - unsigned char *patch; - unsigned int length; - - patch = (unsigned char *)sci_malloc(65536); - - fd = open("patch.001", O_RDONLY); - length = read(fd, patch, 65536); - close(fd); - - if (patch[0] == 0x89 && patch[1] == 0x00) - midi_mt32_open(patch + 2, length - 2); - else - midi_mt32_open(patch, length); - - midi_mt32_close(); - - free(patch); - return 0; -} diff --git a/engines/sci/sfx/old/midi.c b/engines/sci/sfx/old/midi.c deleted file mode 100644 index 1be951befb..0000000000 --- a/engines/sci/sfx/old/midi.c +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************** - midi.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDI_MT32_H_ -#define _MIDI_MT32_H_ - -int midi_mt32_open(guint8 *data_ptr, unsigned int data_length); -int midi_mt32_close(); - -int midi_mt32_noteoff(guint8 channel, guint8 note); -int midi_mt32_noteon(guint8 channel, guint8 note, guint8 velocity); - -#endif /* _MIDI_MT32_H_ */ diff --git a/engines/sci/sfx/old/midi.h b/engines/sci/sfx/old/midi.h deleted file mode 100644 index 9a816781d3..0000000000 --- a/engines/sci/sfx/old/midi.h +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************** - midi.h Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDI_H_ -#define _MIDI_H_ - -int midi_open(guint8 *data_ptr, unsigned int data_length); -int midi_close(); - -int midi_noteoff(guint8 channel, guint8 note); -int midi_noteon(guint8 channel, guint8 note, guint8 velocity); - -#endif /* _MIDI_H_ */ diff --git a/engines/sci/sfx/old/midi_mt32.c b/engines/sci/sfx/old/midi_mt32.c deleted file mode 100644 index be5550bd93..0000000000 --- a/engines/sci/sfx/old/midi_mt32.c +++ /dev/null @@ -1,341 +0,0 @@ -/*************************************************************************** - midi_mt32.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include "glib.h" -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include "midi_mt32.h" -#include "midiout.h" - -#define RHYTHM_CHANNEL 9 - -int midi_mt32_poke(guint32 address, guint8 *data, unsigned int n); -int midi_mt32_poke_gather(guint32 address, guint8 *data1, unsigned int count1, - guint8 *data2, unsigned int count2); -int midi_mt32_write_block(guint8 *data, unsigned int count); -int midi_mt32_patch001_type(guint8 *data, unsigned int length); -int midi_mt32_patch001_type0_length(guint8 *data, unsigned int length); -int midi_mt32_patch001_type1_length(guint8 *data, unsigned int length); -int midi_mt32_sysex_delay(); - -static guint8 *data; -static unsigned int length; -static int type; -static guint8 sysex_buffer[266] = {0xF0, 0x41, 0x10, 0x16, 0x12}; - -static gint8 patch_map[128] = { - 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, - 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, - 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, - 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, - 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, - 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}; -static gint8 keyshift[128] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static gint8 volume_adjust[128] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static guint8 velocity_map_index[128] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; -static guint8 velocity_map[4][128] = { - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, - 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, - 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, - 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, - 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, - 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}, - {0,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39, - 39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47, - 47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55, - 55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63, - 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79, - 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95, - 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111, - 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127}, - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, - 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31, - 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47, - 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, - 64,65,66,66,67,67,68,68,69,69,70,70,71,71,72,72, - 73,73,74,74,75,75,76,76,77,77,78,78,79,79,80,80, - 81,81,82,82,83,83,84,84,85,85,86,86,87,87,88,88, - 89,89,90,90,91,91,92,92,93,93,94,94,95,95,96,96}, - {0,32,32,33,33,34,34,35,35,36,36,37,37,38,38,39, - 39,40,40,41,41,42,42,43,43,44,44,45,45,46,46,47, - 47,48,48,49,49,50,50,51,51,52,52,53,53,54,54,55, - 55,56,56,57,57,58,58,59,59,60,60,61,61,62,62,63, - 64,65,66,66,67,67,68,68,69,69,70,70,71,71,72,72, - 73,73,74,74,75,75,76,76,77,77,78,78,79,79,80,80, - 81,81,82,82,83,83,84,84,85,85,86,86,87,87,88,88, - 89,89,90,90,91,91,92,92,93,93,94,94,95,95,96,96}}; -static gint8 rhythmkey_map[128] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,35,36,37,38,39,40,41,42,43,44,45,46,47, - 48,49,50,51,-1,-1,54,-1,56,-1,-1,-1,60,61,62,63, - 64,65,66,67,68,69,70,71,72,73,-1,75,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; -/* static struct { - gint8 sci_patch; - gint8 sci_volume; - gint8 sci_pitchwheel; - gint8 patch; - gint8 keyshift; - gint8 volume_adjust; - guint8 velocity_map_index; - guint8 -} channel[16]; */ -static guint8 master_volume; - -int midi_mt32_open(guint8 *data_ptr, unsigned int data_length) -{ - guint8 unknown_sysex[6] = {0x16, 0x16, 0x16, 0x16, 0x16, 0x16}; - guint8 i, memtimbres; - unsigned int block2, block3; - - if (midiout_open() < 0) - return -1; - - data = data_ptr; - length = data_length; - - type = midi_mt32_patch001_type(data, length); - printf("MT-32: Programming Roland MT-32 with patch.001 (v%i)\n", type); - - if (type == 0) { - /* Display MT-32 initialization message */ - printf("MT-32: Displaying Text: \"%.20s\"\n", data + 20); - midi_mt32_poke(0x200000, data + 20, 20); - midi_mt32_sysex_delay(); - - /* Write Patches (48 or 96) */ - memtimbres = data[491]; - block2 = (memtimbres * 246) + 492; - printf("MT-32: Writing Patches #01 - #32\n"); - midi_mt32_poke(0x050000, data + 107, 256); - midi_mt32_sysex_delay(); - if ((length > block2) && - data[block2] == 0xAB && - data[block2 + 1] == 0xCD) { - printf("MT-32: Writing Patches #33 - #64\n"); - midi_mt32_poke_gather(0x050200, data + 363, 128, data + block2 + 2, 128); - midi_mt32_sysex_delay(); - printf("MT-32: Writing Patches #65 - #96\n"); - midi_mt32_poke(0x050400, data + block2 + 130, 256); - midi_mt32_sysex_delay(); - block3 = block2 + 386; - } else { - printf("MT-32: Writing Patches #33 - #48\n"); - midi_mt32_poke(0x050200, data + 363, 128); - midi_mt32_sysex_delay(); - block3 = block2; - } - /* Write Memory Timbres */ - for (i = 0; i < memtimbres; i++) { - printf("MT-32: Writing Memory Timbre #%02d: \"%.10s\"\n", - i + 1, data + 492 + i * 246); - midi_mt32_poke(0x080000 + (i << 9), data + 492 + i * 246, 246); - midi_mt32_sysex_delay(); - } - /* Write Rhythm key map and Partial Reserve */ - if ((length > block3) && - data[block3] == 0xDC && - data[block3 + 1] == 0xBA) { - printf("MT-32: Writing Rhythm key map\n"); - midi_mt32_poke(0x030110, data + block3 + 2, 256); - midi_mt32_sysex_delay(); - printf("MT-32: Writing Partial Reserve\n"); - midi_mt32_poke(0x100004, data + block3 + 258, 9); - midi_mt32_sysex_delay(); - } - /* Display MT-32 initialization done message */ - printf("MT-32: Displaying Text: \"%.20s\"\n", data); - midi_mt32_poke(0x200000, data, 20); - midi_mt32_sysex_delay(); - /* Write undocumented MT-32(?) SysEx */ - printf("MT-32: Writing {F0 41 10 16 12 52 00 0A 16 16 16 16 16 16 20 F7}\n"); - midi_mt32_poke(0x52000A, unknown_sysex, 6); - midi_mt32_sysex_delay(); - return 0; - } else if (type == 1) { - midi_mt32_write_block(data + 1155, (data[1154] << 8) + data[1153]); - memcpy(patch_map, data, 128); - memcpy(keyshift, data + 128, 128); - memcpy(volume_adjust, data + 256, 128); - memcpy(velocity_map_index, data + 513, 128); - for (i = 0; i < 4; i++) - memcpy(velocity_map[i], data + 641 + i * 128, 128); - memcpy(rhythmkey_map, data + 384, 128); - return 0; - } - return -1; -} - -int midi_mt32_close() -{ -if (type == 0) { - printf("MT-32: Displaying Text: \"%.20s\"\n", data + 40); - midi_mt32_poke(0x200000, data + 40, 20); - midi_mt32_sysex_delay(); -} -return midiout_close(); -} - -int midi_mt32_noteoff(guint8 channel, guint8 note) -{ - return 0; -} - -int midi_mt32_noteon(guint8 channel, guint8 note, guint8 velocity) -{ -/* guint8 buffer[3] = {0x90}; - if (channel == RHYTHM_CHANNEL) - if (rhythmkey_map[note] == -1) - return 0; - else { - buffer[0] |= channel - buffer[1] = rhythmkey_map[note]; - buffer[2] = velo - midi_write_event(buffer, 3); - }; */ - return 0; -} - -int midi_mt32_poke(guint32 address, guint8 *data, unsigned int count) -{ - guint8 checksum = 0; - unsigned int i; - - if (count > 256) return -1; - - checksum -= (sysex_buffer[5] = (char)((address >> 16) & 0x7F)); - checksum -= (sysex_buffer[6] = (char)((address >> 8) & 0x7F)); - checksum -= (sysex_buffer[7] = (char)(address & 0x7F)); - - for (i = 0; i < count; i++) - checksum -= (sysex_buffer[i + 8] = data[i]); - - sysex_buffer[count + 8] = checksum & 0x7F; - sysex_buffer[count + 9] = 0xF7; - - return midiout_write_block(sysex_buffer, count + 10); -} - -int midi_mt32_poke_gather(guint32 address, guint8 *data1, unsigned int count1, - guint8 *data2, unsigned int count2) -{ - guint8 checksum = 0; - unsigned int i; - - if ((count1 + count2) > 256) return -1; - - checksum -= (sysex_buffer[5] = (char)((address >> 16) & 0x7F)); - checksum -= (sysex_buffer[6] = (char)((address >> 8) & 0x7F)); - checksum -= (sysex_buffer[7] = (char)(address & 0x7F)); - - for (i = 0; i < count1; i++) - checksum -= (sysex_buffer[i + 8] = data1[i]); - for (i = 0; i < count2; i++) - checksum -= (sysex_buffer[i + 8 + count1] = data2[i]); - - sysex_buffer[count1 + count2 + 8] = checksum & 0x7F; - sysex_buffer[count1 + count2 + 9] = 0xF7; - - return midiout_write_block(sysex_buffer, count1 + count2 + 10); -} - -int midi_mt32_write_block(guint8 *data, unsigned int count) -{ - unsigned int block_start = 0; - unsigned int i = 0; - - while (i < count) { - if ((data[i] == 0xF0) && (i != block_start)) { - midiout_write_block(data + block_start, i - block_start); - block_start = i; - } - if (data[i] == 0xF7) { - midiout_write_block(data + block_start, i - block_start + 1); - midi_mt32_sysex_delay(); - block_start = i + 1; - } - i++; - } - if (count >= block_start) - midiout_write_block(data + block_start, count - block_start); - return 0; -} - -int midi_mt32_patch001_type(guint8 *data, unsigned int length) -{ - /* length test */ - if (length < 1155) - return 0; - if (length > 16889) - return 1; - if (midi_mt32_patch001_type0_length(data, length) && - !midi_mt32_patch001_type1_length(data, length)) - return 0; - if (midi_mt32_patch001_type1_length(data, length) && - !midi_mt32_patch001_type0_length(data, length)) - return 1; - return -1; -} - -int midi_mt32_patch001_type0_length(guint8 *data, unsigned int length) -{ - unsigned int pos = 492 + 246 * data[491]; - - if ((length >= (pos + 386)) && (data[pos] == 0xAB) && (data[pos + 1] == 0xCD)) - pos += 386; - if ((length >= (pos + 267)) && (data[pos] == 0xDC) && (data[pos + 1] == 0xBA)) - pos += 267; - if (pos == length) - return 1; - return 0; -} - -int midi_mt32_patch001_type1_length(guint8 *data, unsigned int length) -{ - if ((length >= 1155) && (((data[1154] << 8) + data[1153] + 1155) == length)) - return 1; - return 0; -} - -int midi_mt32_sysex_delay() -{ - usleep(320 * 63); /* One MIDI byte is 320us, 320us * 63 > 20ms */ - return 0; -} diff --git a/engines/sci/sfx/old/midi_mt32.h b/engines/sci/sfx/old/midi_mt32.h deleted file mode 100644 index 0e14efd41d..0000000000 --- a/engines/sci/sfx/old/midi_mt32.h +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - midi_mt32.h Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDI_MT32_H_ -#define _MIDI_MT32_H_ - -#include "glib.h" - -int midi_mt32_open(guint8 *data_ptr, unsigned int data_length); -int midi_mt32_close(); - -#endif /* _MIDI_MT32_H_ */ diff --git a/engines/sci/sfx/old/midiout.c b/engines/sci/sfx/old/midiout.c deleted file mode 100644 index 262836baba..0000000000 --- a/engines/sci/sfx/old/midiout.c +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - midiout.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include "glib.h" -#include "midiout.h" -#include "midiout_alsaraw.h" -#include "midiout_unixraw.h" - -static int (*midiout_ptr_close)(); -static int (*midiout_ptr_write)(guint8 *, unsigned int); - -static unsigned char running_status = 0; - -int midiout_open() -{ - midiout_ptr_close = midiout_alsaraw_close; - midiout_ptr_write = midiout_alsaraw_write; - return midiout_alsaraw_open(0, 0); - - /* - midiout_ptr_close = midiout_unixraw_close; - midiout_ptr_write = midiout_unixraw_write; - return midiout_unixraw_open("/dev/midi00"); - */ -} - -int midiout_close() -{ - return midiout_ptr_close(); -} - -int midiout_write_event(guint8 *buffer, unsigned int count) -{ - if (buffer[0] == running_status) - return midiout_ptr_write(buffer + 1, count - 1); - else { - running_status = buffer[0]; - return midiout_ptr_write(buffer, count); - } -} - -int midiout_write_block(guint8 *buffer, unsigned int count) -{ - running_status = 0; - return midiout_ptr_write(buffer, count); -} diff --git a/engines/sci/sfx/old/midiout.h b/engines/sci/sfx/old/midiout.h deleted file mode 100644 index e0ce3915ae..0000000000 --- a/engines/sci/sfx/old/midiout.h +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - midiout.h Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDIOUT_H_ -#define _MIDIOUT_H_ - -int midiout_open(); -int midiout_close(); -int midiout_write_event(guint8 *buffer, unsigned int count); -int midiout_write_block(guint8 *buffer, unsigned int count); - -#endif /* _MIDIOUT_H_ */ diff --git a/engines/sci/sfx/old/midiout_alsaraw.c b/engines/sci/sfx/old/midiout_alsaraw.c deleted file mode 100644 index e95aa28425..0000000000 --- a/engines/sci/sfx/old/midiout_alsaraw.c +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - midiout_alsaraw.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include "glib.h" -#include <stdio.h> -#include <sys/asoundlib.h> -#include "midiout_alsaraw.h" - -static snd_rawmidi_t *handle; - -int midiout_alsaraw_open(int card, int device) -{ - int err; - - if ((err = snd_rawmidi_open(&handle, card, device, SND_RAWMIDI_OPEN_OUTPUT)) < 0) { - fprintf(stderr, "Open failed (%i): /dev/snd/midiC%iD%i\n", err, card, device); - return -1; - } - return 0; -} - -int midiout_alsaraw_close() -{ - if (snd_rawmidi_close(handle) < 0) - return -1; - return 0; -} - -int midiout_alsaraw_write(guint8 *buffer, unsigned int count) -{ - if (snd_rawmidi_write(handle, buffer, count) != count) - return -1; - return 0; -} diff --git a/engines/sci/sfx/old/midiout_alsaraw.h b/engines/sci/sfx/old/midiout_alsaraw.h deleted file mode 100644 index cbf9da44c1..0000000000 --- a/engines/sci/sfx/old/midiout_alsaraw.h +++ /dev/null @@ -1,28 +0,0 @@ -/*************************************************************************** - midiout_alsaraw.h Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDIOUT_ALSARAW_H_ -#define _MIDIOUT_ALSARAW_H_ - -int midiout_alsaraw_open(int card, int device); -int midiout_alsaraw_close(); -int midiout_alsaraw_write(guint8 *buffer, unsigned int count); - -#endif /* _MIDIOUT_ALSARAW_H_ */ diff --git a/engines/sci/sfx/old/midiout_unixraw.c b/engines/sci/sfx/old/midiout_unixraw.c deleted file mode 100644 index a0dc85955f..0000000000 --- a/engines/sci/sfx/old/midiout_unixraw.c +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** - midiout_unixraw.c Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#include "glib.h" -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include "midiout_unixraw.h" - -static int fd; - -int midiout_unixraw_open(char *devicename) -{ - if (!IS_VALID_FD(fd = open(devicename, O_WRONLY|O_SYNC))) { - fprintf(stderr, "Open failed (%i): %s\n", fd, devicename); - return -1; - } - return 0; -} - -int midiout_unixraw_close() -{ - if (close(fd) < 0) - return -1; - return 0; -} - -int midiout_unixraw_write(guint8 *buffer, unsigned int count) -{ - if (write(fd, buffer, count) != count) - return -1; - return 0; -} diff --git a/engines/sci/sfx/old/midiout_unixraw.h b/engines/sci/sfx/old/midiout_unixraw.h deleted file mode 100644 index c5980696e9..0000000000 --- a/engines/sci/sfx/old/midiout_unixraw.h +++ /dev/null @@ -1,28 +0,0 @@ -/*************************************************************************** - midiout_unixraw.h Copyright (C) 2000 Rickard Lind - - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - -***************************************************************************/ - -#ifndef _MIDIOUT_UNIXRAW_H_ -#define _MIDIOUT_UNIXRAW_H_ - -int midiout_unixraw_open(char *devicename); -int midiout_unixraw_close(); -int midiout_unixraw_write(guint8 *buffer, unsigned int count); - -#endif /* _MIDIOUT_UNIXRAW_H_ */ diff --git a/engines/sci/sfx/softseq/fmopl.c b/engines/sci/sfx/softseq/fmopl.c deleted file mode 100644 index 6ea777c667..0000000000 --- a/engines/sci/sfx/softseq/fmopl.c +++ /dev/null @@ -1,1144 +0,0 @@ -/*************************************************************************** - fmopl.c Copyright (C) 1999-2000 Tatsuyuki Satoh - 2001-2004 The ScummVM project - 2002 Solomon Peachy - 2004 Walter van Niftrik - - This program may be modified and copied freely according to the terms of - the GNU general public license (GPL), as long as the above copyright - notice and the licensing information contained herein are preserved. - - Please refer to www.gnu.org for licensing details. - - This work is provided AS IS, without warranty of any kind, expressed or - implied, including but not limited to the warranties of merchantibility, - noninfringement, and fitness for a specific purpose. The author will not - be held liable for any damage caused by this work or derivatives of it. - - By using this source code, you agree to the licensing terms as stated - above. - - LGPL licensed version of MAMEs fmopl (V0.37a modified) by - Tatsuyuki Satoh. Included from LGPL'ed AdPlug. - -***************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - -#ifndef INLINE -# ifdef _MSC_VER -# define INLINE __inline -# else -# define INLINE inline -# endif -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <math.h> - -#include "fmopl.h" - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -/* -------------------- preliminary define section --------------------- */ -/* attack/decay rate time rate */ -#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */ -#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */ - -#define FREQ_BITS 24 /* frequency turn */ - -/* counter bits = 20 , octerve 7 */ -#define FREQ_RATE (1<<(FREQ_BITS-20)) -#define TL_BITS (FREQ_BITS+2) - -/* final output shift , limit minimum and maximum */ -#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ -#define OPL_MAXOUT (0x7fff<<OPL_OUTSB) -#define OPL_MINOUT (-0x8000<<OPL_OUTSB) - -/* -------------------- quality selection --------------------- */ - -/* sinwave entries */ -/* used static memory = SIN_ENT * 4 (byte) */ -#define SIN_ENT 2048 - -/* output level entries (envelope,sinwave) */ -/* envelope counter lower bits */ -int ENV_BITS; -/* envelope output entries */ -int EG_ENT; - -/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */ -/* used static memory = EG_ENT*4 (byte) */ -int EG_OFF; /* OFF */ -int EG_DED; -int EG_DST; /* DECAY START */ -int EG_AED; -#define EG_AST 0 /* ATTACK START */ - -#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */ - -/* LFO table entries */ -#define VIB_ENT 512 -#define VIB_SHIFT (32-9) -#define AMS_ENT 512 -#define AMS_SHIFT (32-9) - -#define VIB_RATE 256 - -/* -------------------- local defines , macros --------------------- */ - -/* register number to channel number , slot offset */ -#define SLOT1 0 -#define SLOT2 1 - -/* envelope phase */ -#define ENV_MOD_RR 0x00 -#define ENV_MOD_DR 0x01 -#define ENV_MOD_AR 0x02 - -/* -------------------- tables --------------------- */ -static const int slot_array[32]= -{ - 0, 2, 4, 1, 3, 5,-1,-1, - 6, 8,10, 7, 9,11,-1,-1, - 12,14,16,13,15,17,-1,-1, -#ifdef TWELVE_VOICE - 18,20,22,19,21,23,-1,-1 -#else - -1,-1,-1,-1,-1,-1,-1,-1 -#endif -}; - -static guint32 KSL_TABLE[8 * 16]; - -static const double KSL_TABLE_SEED[8 * 16] = { - /* OCT 0 */ - 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, - /* OCT 1 */ - 0.000, 0.000, 0.000, 0.000, - 0.000, 0.000, 0.000, 0.000, - 0.000, 0.750, 1.125, 1.500, - 1.875, 2.250, 2.625, 3.000, - /* OCT 2 */ - 0.000, 0.000, 0.000, 0.000, - 0.000, 1.125, 1.875, 2.625, - 3.000, 3.750, 4.125, 4.500, - 4.875, 5.250, 5.625, 6.000, - /* OCT 3 */ - 0.000, 0.000, 0.000, 1.875, - 3.000, 4.125, 4.875, 5.625, - 6.000, 6.750, 7.125, 7.500, - 7.875, 8.250, 8.625, 9.000, - /* OCT 4 */ - 0.000, 0.000, 3.000, 4.875, - 6.000, 7.125, 7.875, 8.625, - 9.000, 9.750, 10.125, 10.500, - 10.875, 11.250, 11.625, 12.000, - /* OCT 5 */ - 0.000, 3.000, 6.000, 7.875, - 9.000, 10.125, 10.875, 11.625, - 12.000, 12.750, 13.125, 13.500, - 13.875, 14.250, 14.625, 15.000, - /* OCT 6 */ - 0.000, 6.000, 9.000, 10.875, - 12.000, 13.125, 13.875, 14.625, - 15.000, 15.750, 16.125, 16.500, - 16.875, 17.250, 17.625, 18.000, - /* OCT 7 */ - 0.000, 9.000, 12.000, 13.875, - 15.000, 16.125, 16.875, 17.625, - 18.000, 18.750, 19.125, 19.500, - 19.875, 20.250, 20.625, 21.000 -}; - -/* sustain lebel table (3db per step) */ -/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ - -static int SL_TABLE[16]; - -static const guint32 SL_TABLE_SEED[16] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31 -}; - -#define TL_MAX (EG_ENT * 2) /* limit(tl + ksr + envelope) + sinwave */ -/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */ -/* TL_TABLE[ 0 to TL_MAX ] : plus section */ -/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */ -static int *TL_TABLE; - -/* pointers to TL_TABLE with sinwave output offset */ -static int **SIN_TABLE; - -/* LFO table */ -static int *AMS_TABLE; -static int *VIB_TABLE; - -/* envelope output curve table */ -/* attack + decay + OFF */ -//static int ENV_CURVE[2*EG_ENT+1]; -static int ENV_CURVE[2 * 4096 + 1]; // to keep it static ... - -/* multiple table */ -#define ML(a) (int)(a * 2) -static const guint32 MUL_TABLE[16]= { -/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */ - ML(0.50), ML(1.00), ML(2.00), ML(3.00), ML(4.00), ML(5.00), ML(6.00), ML(7.00), - ML(8.00), ML(9.00), ML(10.00), ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00) -}; -#undef ML - -/* dummy attack / decay rate ( when rate == 0 ) */ -static int RATE_0[16]= -{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - -/* -------------------- static state --------------------- */ - -/* lock level of common table */ -static int num_lock = 0; - -/* work table */ -static void *cur_chip = NULL; /* current chip point */ -/* currenct chip state */ -/* static OPLSAMPLE *bufL,*bufR; */ -static OPL_CH *S_CH; -static OPL_CH *E_CH; -OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2; - -static int outd[1]; -static int ams; -static int vib; -int *ams_table; -int *vib_table; -static int amsIncr; -static int vibIncr; -static int feedback2; /* connect for SLOT 2 */ - -/* --------------------- rebuild tables ------------------- */ - -#define SC_KSL(mydb) ((guint32) (mydb / (EG_STEP / 2))) -#define SC_SL(db) (int)(db * ((3 / EG_STEP) * (1 << ENV_BITS))) + EG_DST - -void OPLBuildTables(int ENV_BITS_PARAM, int EG_ENT_PARAM) { - int i; - - ENV_BITS = ENV_BITS_PARAM; - EG_ENT = EG_ENT_PARAM; - EG_OFF = ((2 * EG_ENT)<<ENV_BITS); /* OFF */ - EG_DED = EG_OFF; - EG_DST = (EG_ENT << ENV_BITS); /* DECAY START */ - EG_AED = EG_DST; - //EG_STEP = (96.0/EG_ENT); - - for (i = 0; i < (int)(sizeof(KSL_TABLE_SEED) / sizeof(double)); i++) - KSL_TABLE[i] = SC_KSL(KSL_TABLE_SEED[i]); - - for (i = 0; i < (int)(sizeof(SL_TABLE_SEED) / sizeof(guint32)); i++) - SL_TABLE[i] = SC_SL(SL_TABLE_SEED[i]); -} - -#undef SC_KSL -#undef SC_SL - -/* --------------------- subroutines --------------------- */ - -INLINE int Limit(int val, int max, int min) { - if ( val > max ) - val = max; - else if ( val < min ) - val = min; - - return val; -} - -/* status set and IRQ handling */ -INLINE void OPL_STATUS_SET(FM_OPL *OPL, int flag) { - /* set status flag */ - OPL->status |= flag; - if(!(OPL->status & 0x80)) { - if(OPL->status & OPL->statusmask) { /* IRQ on */ - OPL->status |= 0x80; - /* callback user interrupt handler (IRQ is OFF to ON) */ - if(OPL->IRQHandler) - (OPL->IRQHandler)(OPL->IRQParam,1); - } - } -} - -/* status reset and IRQ handling */ -INLINE void OPL_STATUS_RESET(FM_OPL *OPL, int flag) { - /* reset status flag */ - OPL->status &= ~flag; - if((OPL->status & 0x80)) { - if (!(OPL->status & OPL->statusmask)) { - OPL->status &= 0x7f; - /* callback user interrupt handler (IRQ is ON to OFF) */ - if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); - } - } -} - -/* IRQ mask set */ -INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL, int flag) { - OPL->statusmask = flag; - /* IRQ handling check */ - OPL_STATUS_SET(OPL,0); - OPL_STATUS_RESET(OPL,0); -} - -/* ----- key on ----- */ -INLINE void OPL_KEYON(OPL_SLOT *SLOT) { - /* sin wave restart */ - SLOT->Cnt = 0; - /* set attack */ - SLOT->evm = ENV_MOD_AR; - SLOT->evs = SLOT->evsa; - SLOT->evc = EG_AST; - SLOT->eve = EG_AED; -} -/* ----- key off ----- */ -INLINE void OPL_KEYOFF(OPL_SLOT *SLOT) { - if( SLOT->evm > ENV_MOD_RR) { - /* set envelope counter from envleope output */ - SLOT->evm = ENV_MOD_RR; - if( !(SLOT->evc & EG_DST) ) - //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST; - SLOT->evc = EG_DST; - SLOT->eve = EG_DED; - SLOT->evs = SLOT->evsr; - } -} - -/* ---------- calcrate Envelope Generator & Phase Generator ---------- */ -/* return : envelope output */ -INLINE guint32 OPL_CALC_SLOT(OPL_SLOT *SLOT) { - /* calcrate envelope generator */ - if((SLOT->evc += SLOT->evs) >= SLOT->eve) { - switch( SLOT->evm ){ - case ENV_MOD_AR: /* ATTACK -> DECAY1 */ - /* next DR */ - SLOT->evm = ENV_MOD_DR; - SLOT->evc = EG_DST; - SLOT->eve = SLOT->SL; - SLOT->evs = SLOT->evsd; - break; - case ENV_MOD_DR: /* DECAY -> SL or RR */ - SLOT->evc = SLOT->SL; - SLOT->eve = EG_DED; - if(SLOT->eg_typ) { - SLOT->evs = 0; - } else { - SLOT->evm = ENV_MOD_RR; - SLOT->evs = SLOT->evsr; - } - break; - case ENV_MOD_RR: /* RR -> OFF */ - SLOT->evc = EG_OFF; - SLOT->eve = EG_OFF + 1; - SLOT->evs = 0; - break; - } - } - /* calcrate envelope */ - return SLOT->TLL + ENV_CURVE[SLOT->evc>>ENV_BITS] + (SLOT->ams ? ams : 0); -} - -/* set algorythm connection */ -static void set_algorythm(OPL_CH *CH) { - int *carrier = &outd[0]; - CH->connect1 = CH->CON ? carrier : &feedback2; - CH->connect2 = carrier; -} - -/* ---------- frequency counter for operater update ---------- */ -INLINE void CALC_FCSLOT(OPL_CH *CH, OPL_SLOT *SLOT) { - int ksr; - - /* frequency step counter */ - SLOT->Incr = CH->fc * SLOT->mul; - ksr = CH->kcode >> SLOT->KSR; - - if( SLOT->ksr != ksr ) - { - SLOT->ksr = ksr; - /* attack , decay rate recalcration */ - SLOT->evsa = SLOT->AR[ksr]; - SLOT->evsd = SLOT->DR[ksr]; - SLOT->evsr = SLOT->RR[ksr]; - } - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); -} - -/* set multi,am,vib,EG-TYP,KSR,mul */ -INLINE void set_mul(FM_OPL *OPL, int slot, int v) { - OPL_CH *CH = &OPL->P_CH[slot / 2]; - OPL_SLOT *SLOT = &CH->SLOT[slot & 1]; - - SLOT->mul = MUL_TABLE[v & 0x0f]; - SLOT->KSR = (v & 0x10) ? 0 : 2; - SLOT->eg_typ = (v & 0x20) >> 5; - SLOT->vib = (v & 0x40); - SLOT->ams = (v & 0x80); - CALC_FCSLOT(CH, SLOT); -} - -/* set ksl & tl */ -INLINE void set_ksl_tl(FM_OPL *OPL, int slot, int v) { - OPL_CH *CH = &OPL->P_CH[slot / 2]; - OPL_SLOT *SLOT = &CH->SLOT[slot & 1]; - int ksl = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */ - - SLOT->ksl = ksl ? 3-ksl : 31; - SLOT->TL = (int)((v & 0x3f) * (0.75 / EG_STEP)); /* 0.75db step */ - - if(!(OPL->mode & 0x80)) { /* not CSM latch total level */ - SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl); - } -} - -/* set attack rate & decay rate */ -INLINE void set_ar_dr(FM_OPL *OPL, int slot, int v) { - OPL_CH *CH = &OPL->P_CH[slot / 2]; - OPL_SLOT *SLOT = &CH->SLOT[slot & 1]; - int ar = v >> 4; - int dr = v & 0x0f; - - SLOT->AR = ar ? &OPL->AR_TABLE[ar << 2] : RATE_0; - SLOT->evsa = SLOT->AR[SLOT->ksr]; - if(SLOT->evm == ENV_MOD_AR) - SLOT->evs = SLOT->evsa; - - SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; - SLOT->evsd = SLOT->DR[SLOT->ksr]; - if(SLOT->evm == ENV_MOD_DR) - SLOT->evs = SLOT->evsd; -} - -/* set sustain level & release rate */ -INLINE void set_sl_rr(FM_OPL *OPL, int slot, int v) { - OPL_CH *CH = &OPL->P_CH[slot / 2]; - OPL_SLOT *SLOT = &CH->SLOT[slot & 1]; - int sl = v >> 4; - int rr = v & 0x0f; - - SLOT->SL = SL_TABLE[sl]; - if(SLOT->evm == ENV_MOD_DR) - SLOT->eve = SLOT->SL; - SLOT->RR = &OPL->DR_TABLE[rr<<2]; - SLOT->evsr = SLOT->RR[SLOT->ksr]; - if(SLOT->evm == ENV_MOD_RR) - SLOT->evs = SLOT->evsr; -} - -/* operator output calcrator */ -#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt + con) / (0x1000000 / SIN_ENT)) & (SIN_ENT-1)][env] -/* ---------- calcrate one of channel ---------- */ -INLINE void OPL_CALC_CH(OPL_CH *CH) { - guint32 env_out; - OPL_SLOT *SLOT; - - feedback2 = 0; - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env_out=OPL_CALC_SLOT(SLOT); - if(env_out < (guint32)(EG_ENT - 1)) { - /* PG */ - if(SLOT->vib) - SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE); - else - SLOT->Cnt += SLOT->Incr; - /* connectoion */ - if(CH->FB) { - int feedback1 = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB; - CH->op1_out[1] = CH->op1_out[0]; - *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT, env_out, feedback1); - } - else { - *CH->connect1 += OP_OUT(SLOT, env_out, 0); - } - }else { - CH->op1_out[1] = CH->op1_out[0]; - CH->op1_out[0] = 0; - } - /* SLOT 2 */ - SLOT = &CH->SLOT[SLOT2]; - env_out=OPL_CALC_SLOT(SLOT); - if(env_out < (guint32)(EG_ENT - 1)) { - /* PG */ - if(SLOT->vib) - SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE); - else - SLOT->Cnt += SLOT->Incr; - /* connectoion */ - outd[0] += OP_OUT(SLOT, env_out, feedback2); - } -} - -/* ---------- calcrate rythm block ---------- */ -#define WHITE_NOISE_db 6.0 -INLINE void OPL_CALC_RH(OPL_CH *CH) { - guint32 env_tam, env_sd, env_top, env_hh; - int whitenoise = (int)((rand()&1) * (WHITE_NOISE_db / EG_STEP)); - int tone8; - - OPL_SLOT *SLOT; - int env_out; - - /* BD : same as FM serial mode and output level is large */ - feedback2 = 0; - /* SLOT 1 */ - SLOT = &CH[6].SLOT[SLOT1]; - env_out = OPL_CALC_SLOT(SLOT); - if(env_out < EG_ENT-1) { - /* PG */ - if(SLOT->vib) - SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE); - else - SLOT->Cnt += SLOT->Incr; - /* connectoion */ - if(CH[6].FB) { - int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB; - CH[6].op1_out[1] = CH[6].op1_out[0]; - feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1); - } - else { - feedback2 = OP_OUT(SLOT, env_out, 0); - } - }else { - feedback2 = 0; - CH[6].op1_out[1] = CH[6].op1_out[0]; - CH[6].op1_out[0] = 0; - } - /* SLOT 2 */ - SLOT = &CH[6].SLOT[SLOT2]; - env_out = OPL_CALC_SLOT(SLOT); - if(env_out < EG_ENT-1) { - /* PG */ - if(SLOT->vib) - SLOT->Cnt += (SLOT->Incr * vib / VIB_RATE); - else - SLOT->Cnt += SLOT->Incr; - /* connectoion */ - outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2; - } - - // SD (17) = mul14[fnum7] + white noise - // TAM (15) = mul15[fnum8] - // TOP (18) = fnum6(mul18[fnum8]+whitenoise) - // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise - env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise; - env_tam =OPL_CALC_SLOT(SLOT8_1); - env_top = OPL_CALC_SLOT(SLOT8_2); - env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise; - - /* PG */ - if(SLOT7_1->vib) - SLOT7_1->Cnt += (2 * SLOT7_1->Incr * vib / VIB_RATE); - else - SLOT7_1->Cnt += 2 * SLOT7_1->Incr; - if(SLOT7_2->vib) - SLOT7_2->Cnt += ((CH[7].fc * 8) * vib / VIB_RATE); - else - SLOT7_2->Cnt += (CH[7].fc * 8); - if(SLOT8_1->vib) - SLOT8_1->Cnt += (SLOT8_1->Incr * vib / VIB_RATE); - else - SLOT8_1->Cnt += SLOT8_1->Incr; - if(SLOT8_2->vib) - SLOT8_2->Cnt += ((CH[8].fc * 48) * vib / VIB_RATE); - else - SLOT8_2->Cnt += (CH[8].fc * 48); - - tone8 = OP_OUT(SLOT8_2,whitenoise,0 ); - - /* SD */ - if(env_sd < (guint32)(EG_ENT - 1)) - outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8; - /* TAM */ - if(env_tam < (guint32)(EG_ENT - 1)) - outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2; - /* TOP-CY */ - if(env_top < (guint32)(EG_ENT - 1)) - outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2; - /* HH */ - if(env_hh < (guint32)(EG_ENT-1)) - outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2; -} - -/* ----------- initialize time tabls ----------- */ -static void init_timetables(FM_OPL *OPL, int ARRATE, int DRRATE) { - int i; - double rate; - - /* make attack rate & decay rate tables */ - for (i = 0; i < 4; i++) - OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; - for (i = 4; i <= 60; i++){ - rate = OPL->freqbase; /* frequency rate */ - if(i < 60) - rate *= 1.0 + (i & 3) * 0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ - rate *= 1 << ((i >> 2) - 1); /* b2-5 : shift bit */ - rate *= (double)(EG_ENT << ENV_BITS); - OPL->AR_TABLE[i] = (int)(rate / ARRATE); - OPL->DR_TABLE[i] = (int)(rate / DRRATE); - } - for (i = 60; i < 75; i++) { - OPL->AR_TABLE[i] = EG_AED-1; - OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; - } -} - -/* ---------- generic table initialize ---------- */ -static int OPLOpenTable(void) { - int s,t; - double rate; - int i,j; - double pom; - - /* allocate dynamic tables */ - if((TL_TABLE = (int *)malloc(TL_MAX * 2 * sizeof(int))) == NULL) - return 0; - if((SIN_TABLE = (int **)malloc(SIN_ENT * 4 * sizeof(int *))) == NULL) { - free(TL_TABLE); - return 0; - } - if((AMS_TABLE = (int *)malloc(AMS_ENT * 2 * sizeof(int))) == NULL) { - free(TL_TABLE); - free(SIN_TABLE); - return 0; - } - if((VIB_TABLE = (int *)malloc(VIB_ENT * 2 * sizeof(int))) == NULL) { - free(TL_TABLE); - free(SIN_TABLE); - free(AMS_TABLE); - return 0; - } - /* make total level table */ - for (t = 0; t < EG_ENT - 1 ; t++){ - rate = ((1 << TL_BITS) - 1) / pow(10.0, EG_STEP * t / 20); /* dB -> voltage */ - TL_TABLE[ t] = (int)rate; - TL_TABLE[TL_MAX + t] = -TL_TABLE[t]; - } - /* fill volume off area */ - for (t = EG_ENT - 1; t < TL_MAX; t++){ - TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0; - } - - /* make sinwave table (total level offet) */ - /* degree 0 = degree 180 = off */ - SIN_TABLE[0] = SIN_TABLE[SIN_ENT /2 ] = &TL_TABLE[EG_ENT - 1]; - for (s = 1;s <= SIN_ENT / 4; s++){ - pom = sin(2 * PI * s / SIN_ENT); /* sin */ - pom = 20 * log10(1 / pom); /* decibel */ - j = (int)(pom / EG_STEP); /* TL_TABLE steps */ - - /* degree 0 - 90 , degree 180 - 90 : plus section */ - SIN_TABLE[ s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j]; - /* degree 180 - 270 , degree 360 - 270 : minus section */ - SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j]; - } - for (s = 0;s < SIN_ENT; s++) { - SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; - SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)]; - SIN_TABLE[SIN_ENT * 3 + s] = (s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 + s]; - } - - /* envelope counter -> envelope output table */ - for (i=0; i < EG_ENT; i++) { - /* ATTACK curve */ - pom = pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT; - /* if( pom >= EG_ENT ) pom = EG_ENT-1; */ - ENV_CURVE[i] = (int)pom; - /* DECAY ,RELEASE curve */ - ENV_CURVE[(EG_DST >> ENV_BITS) + i]= i; - } - /* off */ - ENV_CURVE[EG_OFF >> ENV_BITS]= EG_ENT - 1; - /* make LFO ams table */ - for (i=0; i < AMS_ENT; i++) { - pom = (1.0 + sin(2 * PI * i / AMS_ENT)) / 2; /* sin */ - AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */ - AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */ - } - /* make LFO vibrate table */ - for (i=0; i < VIB_ENT; i++) { - /* 100cent = 1seminote = 6% ?? */ - pom = (double)VIB_RATE * 0.06 * sin(2 * PI * i / VIB_ENT); /* +-100sect step */ - VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */ - VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */ - } - return 1; -} - -static void OPLCloseTable(void) { - free(TL_TABLE); - free(SIN_TABLE); - free(AMS_TABLE); - free(VIB_TABLE); -} - -/* CSM Key Controll */ -INLINE void CSMKeyControll(OPL_CH *CH) { - OPL_SLOT *slot1 = &CH->SLOT[SLOT1]; - OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; - /* all key off */ - OPL_KEYOFF(slot1); - OPL_KEYOFF(slot2); - /* total level latch */ - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - /* key on */ - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(slot1); - OPL_KEYON(slot2); -} - -/* ---------- opl initialize ---------- */ -static void OPL_initalize(FM_OPL *OPL) { - int fn; - - /* frequency base */ - OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; - /* Timer base time */ - OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 ); - /* make time tables */ - init_timetables(OPL, OPL_ARRATE, OPL_DRRATE); - /* make fnumber -> increment counter table */ - for( fn=0; fn < 1024; fn++) { - OPL->FN_TABLE[fn] = (guint32)(OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2); - } - /* LFO freq.table */ - OPL->amsIncr = (int)(OPL->rate ? (double)AMS_ENT * (1 << AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0); - OPL->vibIncr = (int)(OPL->rate ? (double)VIB_ENT * (1 << VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0); -} - -/* ---------- write a OPL registers ---------- */ -void OPLWriteReg(FM_OPL *OPL, int r, int v) { - OPL_CH *CH; - int slot; - guint32 block_fnum; - - switch(r & 0xe0) { - case 0x00: /* 00-1f:controll */ - switch(r & 0x1f) { - case 0x01: - /* wave selector enable */ - if(OPL->type&OPL_TYPE_WAVESEL) { - OPL->wavesel = v & 0x20; - if(!OPL->wavesel) { - /* preset compatible mode */ - int c; - for(c=0; c<OPL->max_ch; c++) { - OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; - OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; - } - } - } - return; - case 0x02: /* Timer 1 */ - OPL->T[0] = (256-v) * 4; - break; - case 0x03: /* Timer 2 */ - OPL->T[1] = (256-v) * 16; - return; - case 0x04: /* IRQ clear / mask and Timer enable */ - if(v & 0x80) { /* IRQ flag clear */ - OPL_STATUS_RESET(OPL, 0x7f); - } - else { /* set IRQ mask ,timer enable*/ - guint8 st1 = v & 1; - guint8 st2 = (v >> 1) & 1; - /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ - OPL_STATUS_RESET(OPL, v & 0x78); - OPL_STATUSMASK_SET(OPL,((~v) & 0x78) | 0x01); - /* timer 2 */ - if(OPL->st[1] != st2) { - double interval = st2 ? (double)OPL->T[1] * OPL->TimerBase : 0.0; - OPL->st[1] = st2; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 1, interval); - } - /* timer 1 */ - if(OPL->st[0] != st1) { - double interval = st1 ? (double)OPL->T[0] * OPL->TimerBase : 0.0; - OPL->st[0] = st1; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam + 0, interval); - } - } - return; - } - break; - case 0x20: /* am,vib,ksr,eg type,mul */ - slot = slot_array[r&0x1f]; - if(slot == -1) - return; - set_mul(OPL,slot,v); - return; - case 0x40: - slot = slot_array[r&0x1f]; - if(slot == -1) - return; - set_ksl_tl(OPL,slot,v); - return; - case 0x60: - slot = slot_array[r&0x1f]; - if(slot == -1) - return; - set_ar_dr(OPL,slot,v); - return; - case 0x80: - slot = slot_array[r&0x1f]; - if(slot == -1) - return; - set_sl_rr(OPL,slot,v); - return; - case 0xa0: - switch(r) { - case 0xbd: - /* amsep,vibdep,r,bd,sd,tom,tc,hh */ - { - guint8 rkey = OPL->rythm ^ v; - OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0]; - OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0]; - OPL->rythm = v & 0x3f; - if(OPL->rythm & 0x20) { - /* BD key on/off */ - if(rkey & 0x10) { - if(v & 0x10) { - OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0; - OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]); - OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]); - } - else { - OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]); - OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]); - } - } - /* SD key on/off */ - if(rkey & 0x08) { - if(v & 0x08) - OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]); - else - OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]); - }/* TAM key on/off */ - if(rkey & 0x04) { - if(v & 0x04) - OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]); - else - OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]); - } - /* TOP-CY key on/off */ - if(rkey & 0x02) { - if(v & 0x02) - OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]); - else - OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]); - } - /* HH key on/off */ - if(rkey & 0x01) { - if(v & 0x01) - OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]); - else - OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]); - } - } - } - return; - } - /* keyon,block,fnum */ - if((r & 0x0f) >= ADLIB_VOICES) - return; - CH = &OPL->P_CH[r & 0x0f]; - if(!(r&0x10)) { /* a0-a8 */ - block_fnum = (CH->block_fnum & 0x1f00) | v; - } - else { /* b0-b8 */ - int keyon = (v >> 5) & 1; - block_fnum = ((v & 0x1f) << 8) | (CH->block_fnum & 0xff); - if(CH->keyon != keyon) { - if((CH->keyon=keyon)) { - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(&CH->SLOT[SLOT1]); - OPL_KEYON(&CH->SLOT[SLOT2]); - } - else { - OPL_KEYOFF(&CH->SLOT[SLOT1]); - OPL_KEYOFF(&CH->SLOT[SLOT2]); - } - } - } - /* update */ - if(CH->block_fnum != block_fnum) { - int blockRv = 7 - (block_fnum >> 10); - int fnum = block_fnum & 0x3ff; - CH->block_fnum = block_fnum; - CH->ksl_base = KSL_TABLE[block_fnum >> 6]; - CH->fc = OPL->FN_TABLE[fnum] >> blockRv; - CH->kcode = CH->block_fnum >> 9; - if((OPL->mode & 0x40) && CH->block_fnum & 0x100) - CH->kcode |=1; - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - return; - case 0xc0: - /* FB,C */ - if((r & 0x0f) >= ADLIB_VOICES) - return; - CH = &OPL->P_CH[r&0x0f]; - { - int feedback = (v >> 1) & 7; - CH->FB = feedback ? (8 + 1) - feedback : 0; - CH->CON = v & 1; - set_algorythm(CH); - } - return; - case 0xe0: /* wave type */ - slot = slot_array[r & 0x1f]; - if(slot == -1) - return; - CH = &OPL->P_CH[slot / 2]; - if(OPL->wavesel) { - CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT]; - } - return; - } -} - -/* lock/unlock for common table */ -static int OPL_LockTable(void) -{ - num_lock++; - if(num_lock>1) - return 0; - /* first time */ - cur_chip = NULL; - /* allocate total level table (128kb space) */ - if(!OPLOpenTable()) { - num_lock--; - return -1; - } - return 0; -} - -static void OPL_UnLockTable(void) { - if(num_lock) - num_lock--; - if(num_lock) - return; - /* last time */ - cur_chip = NULL; - OPLCloseTable(); -} - -/*******************************************************************************/ -/* YM3812 local section */ -/*******************************************************************************/ - -/* ---------- update one of chip ----------- */ -void YM3812UpdateOne(FM_OPL *OPL, gint16 *buffer, int length, int interleave) { - int i; - int data; - gint16 *buf = buffer; - guint32 amsCnt = OPL->amsCnt; - guint32 vibCnt = OPL->vibCnt; - guint8 rythm = OPL->rythm & 0x20; - OPL_CH *CH, *R_CH; - - if((void *)OPL != cur_chip){ - cur_chip = (void *)OPL; - /* channel pointers */ - S_CH = OPL->P_CH; - E_CH = &S_CH[9]; - /* rythm slot */ - SLOT7_1 = &S_CH[7].SLOT[SLOT1]; - SLOT7_2 = &S_CH[7].SLOT[SLOT2]; - SLOT8_1 = &S_CH[8].SLOT[SLOT1]; - SLOT8_2 = &S_CH[8].SLOT[SLOT2]; - /* LFO state */ - amsIncr = OPL->amsIncr; - vibIncr = OPL->vibIncr; - ams_table = OPL->ams_table; - vib_table = OPL->vib_table; - } - R_CH = rythm ? &S_CH[6] : E_CH; - for(i = 0; i < length; i++) { - /* channel A channel B channel C */ - /* LFO */ - ams = ams_table[(amsCnt += amsIncr) >> AMS_SHIFT]; - vib = vib_table[(vibCnt += vibIncr) >> VIB_SHIFT]; - outd[0] = 0; - /* FM part */ - for(CH=S_CH; CH < R_CH; CH++) - OPL_CALC_CH(CH); - /* Rythn part */ - if(rythm) - OPL_CALC_RH(S_CH); -#ifdef TWELVE_VOICE - for(CH=&S_CH[9]; CH < &S_CH[ADLIB_VOICES]; CH++) - OPL_CALC_CH(CH); -#endif - /* limit check */ - data = Limit(outd[0], OPL_MAXOUT, OPL_MINOUT); - /* store to sound buffer */ - buf[i << interleave] = data >> OPL_OUTSB; - } - - OPL->amsCnt = amsCnt; - OPL->vibCnt = vibCnt; -} - -/* ---------- reset a chip ---------- */ -void OPLResetChip(FM_OPL *OPL) { - int c,s; - int i; - - /* reset chip */ - OPL->mode = 0; /* normal mode */ - OPL_STATUS_RESET(OPL, 0x7f); - /* reset with register write */ - OPLWriteReg(OPL, 0x01,0); /* wabesel disable */ - OPLWriteReg(OPL, 0x02,0); /* Timer1 */ - OPLWriteReg(OPL, 0x03,0); /* Timer2 */ - OPLWriteReg(OPL, 0x04,0); /* IRQ mask clear */ - for(i = 0xff; i >= 0x20; i--) - OPLWriteReg(OPL,i,0); - /* reset OPerator parameter */ - for(c = 0; c < OPL->max_ch ;c++ ) { - OPL_CH *CH = &OPL->P_CH[c]; - /* OPL->P_CH[c].PAN = OPN_CENTER; */ - for(s = 0; s < 2; s++ ) { - /* wave table */ - CH->SLOT[s].wavetable = &SIN_TABLE[0]; - /* CH->SLOT[s].evm = ENV_MOD_RR; */ - CH->SLOT[s].evc = EG_OFF; - CH->SLOT[s].eve = EG_OFF + 1; - CH->SLOT[s].evs = 0; - } - } -} - -/* ---------- Create a virtual YM3812 ---------- */ -/* 'rate' is sampling rate and 'bufsiz' is the size of the */ -FM_OPL *OPLCreate(int type, int clock, int rate) { - char *ptr; - FM_OPL *OPL; - int state_size; -#ifdef TWELVE_VOICE - int max_ch = 12; -#else - int max_ch = 9; /* normaly 9 channels */ -#endif - - if( OPL_LockTable() == -1) - return NULL; - /* allocate OPL state space */ - state_size = sizeof(FM_OPL); - state_size += sizeof(OPL_CH) * max_ch; - - /* allocate memory block */ - ptr = (char *)calloc(state_size, 1); - if(ptr == NULL) - return NULL; - - /* clear */ - memset(ptr, 0, state_size); - OPL = (FM_OPL *)ptr; ptr += sizeof(FM_OPL); - OPL->P_CH = (OPL_CH *)ptr; ptr += sizeof(OPL_CH) * max_ch; - - /* set channel state pointer */ - OPL->type = type; - OPL->clock = clock; - OPL->rate = rate; - OPL->max_ch = max_ch; - - /* init grobal tables */ - OPL_initalize(OPL); - - /* reset chip */ - OPLResetChip(OPL); - return OPL; -} - -/* ---------- Destroy one of vietual YM3812 ---------- */ -void OPLDestroy(FM_OPL *OPL) { - OPL_UnLockTable(); - free(OPL); -} - -/* ---------- Option handlers ---------- */ - -void OPLSetTimerHandler(FM_OPL *OPL, OPL_TIMERHANDLER TimerHandler,int channelOffset) { - OPL->TimerHandler = TimerHandler; - OPL->TimerParam = channelOffset; -} - -void OPLSetIRQHandler(FM_OPL *OPL, OPL_IRQHANDLER IRQHandler, int param) { - OPL->IRQHandler = IRQHandler; - OPL->IRQParam = param; -} -void OPLSetUpdateHandler(FM_OPL *OPL, OPL_UPDATEHANDLER UpdateHandler,int param) { - OPL->UpdateHandler = UpdateHandler; - OPL->UpdateParam = param; -} - -/* ---------- YM3812 I/O interface ---------- */ -int OPLWrite(FM_OPL *OPL,int a,int v) { - if(!(a & 1)) { /* address port */ - OPL->address = v & 0xff; - } - else { /* data port */ - if(OPL->UpdateHandler) - OPL->UpdateHandler(OPL->UpdateParam,0); - OPLWriteReg(OPL, OPL->address,v); - } - return OPL->status >> 7; -} - -unsigned char OPLRead(FM_OPL *OPL,int a) { - if(!(a & 1)) { /* status port */ - return OPL->status & (OPL->statusmask | 0x80); - } - /* data port */ - switch(OPL->address) { - case 0x05: /* KeyBoard IN */ - fprintf(stderr, "OPL:read unmapped KEYBOARD port\n"); - return 0; - case 0x19: /* I/O DATA */ - fprintf(stderr, "OPL:read unmapped I/O port\n"); - return 0; - case 0x1a: /* PCM-DATA */ - return 0; - } - return 0; -} - -int OPLTimerOver(FM_OPL *OPL, int c) { - if(c) { /* Timer B */ - OPL_STATUS_SET(OPL, 0x20); - } - else { /* Timer A */ - OPL_STATUS_SET(OPL, 0x40); - /* CSM mode key,TL controll */ - if(OPL->mode & 0x80) { /* CSM mode total level latch and auto key on */ - int ch; - if(OPL->UpdateHandler) - OPL->UpdateHandler(OPL->UpdateParam,0); - for(ch = 0; ch < 9; ch++) - CSMKeyControll(&OPL->P_CH[ch]); - } - } - /* reload timer */ - if (OPL->TimerHandler) - (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase); - return OPL->status >> 7; -} diff --git a/engines/sci/sfx/softseq/mt32/freeverb.cpp b/engines/sci/sfx/softseq/mt32/freeverb.cpp deleted file mode 100644 index 1c3aab0494..0000000000 --- a/engines/sci/sfx/softseq/mt32/freeverb.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -// Comb filter implementation -// -// Written by -// http://www.dreampoint.co.uk -// This code is public domain - -#include "freeverb.h" - -comb::comb() { - filterstore = 0; - bufidx = 0; -} - -void comb::setbuffer(float *buf, int size) { - buffer = buf; - bufsize = size; -} - -void comb::mute() { - for (int i = 0; i < bufsize; i++) - buffer[i] = 0; -} - -void comb::setdamp(float val) { - damp1 = val; - damp2 = 1 - val; -} - -float comb::getdamp() { - return damp1; -} - -void comb::setfeedback(float val) { - feedback = val; -} - -float comb::getfeedback() { - return feedback; -} - -// Allpass filter implementation - -allpass::allpass() { - bufidx = 0; -} - -void allpass::setbuffer(float *buf, int size) { - buffer = buf; - bufsize = size; -} - -void allpass::mute() { - for (int i = 0; i < bufsize; i++) - buffer[i] = 0; -} - -void allpass::setfeedback(float val) { - feedback = val; -} - -float allpass::getfeedback() { - return feedback; -} - -// Reverb model implementation - -revmodel::revmodel() { - // Tie the components to their buffers - combL[0].setbuffer(bufcombL1,combtuningL1); - combR[0].setbuffer(bufcombR1,combtuningR1); - combL[1].setbuffer(bufcombL2,combtuningL2); - combR[1].setbuffer(bufcombR2,combtuningR2); - combL[2].setbuffer(bufcombL3,combtuningL3); - combR[2].setbuffer(bufcombR3,combtuningR3); - combL[3].setbuffer(bufcombL4,combtuningL4); - combR[3].setbuffer(bufcombR4,combtuningR4); - combL[4].setbuffer(bufcombL5,combtuningL5); - combR[4].setbuffer(bufcombR5,combtuningR5); - combL[5].setbuffer(bufcombL6,combtuningL6); - combR[5].setbuffer(bufcombR6,combtuningR6); - combL[6].setbuffer(bufcombL7,combtuningL7); - combR[6].setbuffer(bufcombR7,combtuningR7); - combL[7].setbuffer(bufcombL8,combtuningL8); - combR[7].setbuffer(bufcombR8,combtuningR8); - allpassL[0].setbuffer(bufallpassL1,allpasstuningL1); - allpassR[0].setbuffer(bufallpassR1,allpasstuningR1); - allpassL[1].setbuffer(bufallpassL2,allpasstuningL2); - allpassR[1].setbuffer(bufallpassR2,allpasstuningR2); - allpassL[2].setbuffer(bufallpassL3,allpasstuningL3); - allpassR[2].setbuffer(bufallpassR3,allpasstuningR3); - allpassL[3].setbuffer(bufallpassL4,allpasstuningL4); - allpassR[3].setbuffer(bufallpassR4,allpasstuningR4); - - // Set default values - allpassL[0].setfeedback(0.5f); - allpassR[0].setfeedback(0.5f); - allpassL[1].setfeedback(0.5f); - allpassR[1].setfeedback(0.5f); - allpassL[2].setfeedback(0.5f); - allpassR[2].setfeedback(0.5f); - allpassL[3].setfeedback(0.5f); - allpassR[3].setfeedback(0.5f); - setwet(initialwet); - setroomsize(initialroom); - setdry(initialdry); - setdamp(initialdamp); - setwidth(initialwidth); - setmode(initialmode); - - // Buffer will be full of rubbish - so we MUST mute them - mute(); -} - -void revmodel::mute() { - int i; - - if (getmode() >= freezemode) - return; - - for (i = 0; i < numcombs; i++) { - combL[i].mute(); - combR[i].mute(); - } - - for (i = 0; i < numallpasses; i++) { - allpassL[i].mute(); - allpassR[i].mute(); - } -} - -void revmodel::processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) { - float outL, outR, input; - - while (numsamples-- > 0) { - int i; - - outL = outR = 0; - input = (*inputL + *inputR) * gain; - - // Accumulate comb filters in parallel - for (i = 0; i < numcombs; i++) { - outL += combL[i].process(input); - outR += combR[i].process(input); - } - - // Feed through allpasses in series - for (i = 0; i < numallpasses; i++) { - outL = allpassL[i].process(outL); - outR = allpassR[i].process(outR); - } - - // Calculate output REPLACING anything already there - *outputL = outL * wet1 + outR * wet2 + *inputL * dry; - *outputR = outR * wet1 + outL * wet2 + *inputR * dry; - - // Increment sample pointers, allowing for interleave (if any) - inputL += skip; - inputR += skip; - outputL += skip; - outputR += skip; - } -} - -void revmodel::processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip) { - float outL, outR, input; - - while (numsamples-- > 0) { - int i; - - outL = outR = 0; - input = (*inputL + *inputR) * gain; - - // Accumulate comb filters in parallel - for (i = 0; i < numcombs; i++) { - outL += combL[i].process(input); - outR += combR[i].process(input); - } - - // Feed through allpasses in series - for (i = 0; i < numallpasses; i++) { - outL = allpassL[i].process(outL); - outR = allpassR[i].process(outR); - } - - // Calculate output MIXING with anything already there - *outputL += outL * wet1 + outR * wet2 + *inputL * dry; - *outputR += outR * wet1 + outL * wet2 + *inputR * dry; - - // Increment sample pointers, allowing for interleave (if any) - inputL += skip; - inputR += skip; - outputL += skip; - outputR += skip; - } -} - -void revmodel::update() { - // Recalculate internal values after parameter change - - int i; - - wet1 = wet * (width / 2 + 0.5f); - wet2 = wet * ((1 - width) / 2); - - if (mode >= freezemode) { - roomsize1 = 1; - damp1 = 0; - gain = muted; - } else { - roomsize1 = roomsize; - damp1 = damp; - gain = fixedgain; - } - - for (i = 0; i < numcombs; i++) { - combL[i].setfeedback(roomsize1); - combR[i].setfeedback(roomsize1); - } - - for (i = 0; i < numcombs; i++) { - combL[i].setdamp(damp1); - combR[i].setdamp(damp1); - } -} - -// The following get/set functions are not inlined, because -// speed is never an issue when calling them, and also -// because as you develop the reverb model, you may -// wish to take dynamic action when they are called. - -void revmodel::setroomsize(float value) { - roomsize = (value * scaleroom) + offsetroom; - update(); -} - -float revmodel::getroomsize() { - return (roomsize - offsetroom) / scaleroom; -} - -void revmodel::setdamp(float value) { - damp = value * scaledamp; - update(); -} - -float revmodel::getdamp() { - return damp / scaledamp; -} - -void revmodel::setwet(float value) { - wet = value * scalewet; - update(); -} - -float revmodel::getwet() { - return wet / scalewet; -} - -void revmodel::setdry(float value) { - dry = value * scaledry; -} - -float revmodel::getdry() { - return dry / scaledry; -} - -void revmodel::setwidth(float value) { - width = value; - update(); -} - -float revmodel::getwidth() { - return width; -} - -void revmodel::setmode(float value) { - mode = value; - update(); -} - -float revmodel::getmode() { - if (mode >= freezemode) - return 1; - else - return 0; -} diff --git a/engines/sci/sfx/softseq/mt32/freeverb.h b/engines/sci/sfx/softseq/mt32/freeverb.h deleted file mode 100644 index 53c5307c5a..0000000000 --- a/engines/sci/sfx/softseq/mt32/freeverb.h +++ /dev/null @@ -1,239 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -// Macro for killing denormalled numbers -// -// Written by Jezar at Dreampoint, June 2000 -// http://www.dreampoint.co.uk -// Based on IS_DENORMAL macro by Jon Watte -// This code is public domain - -#ifndef FREEVERB_H -#define FREEVERB_H - -#define undenormalise(sample) if (((*(unsigned int*)&sample) & 0x7f800000) == 0) sample = 0.0f - -// Comb filter class declaration - -class comb { -public: - comb(); - void setbuffer(float *buf, int size); - inline float process(float inp); - void mute(); - void setdamp(float val); - float getdamp(); - void setfeedback(float val); - float getfeedback(); -private: - float feedback; - float filterstore; - float damp1; - float damp2; - float *buffer; - int bufsize; - int bufidx; -}; - - -// Big to inline - but crucial for speed - -inline float comb::process(float input) { - float output; - - output = buffer[bufidx]; - undenormalise(output); - - filterstore = (output * damp2) + (filterstore * damp1); - undenormalise(filterstore); - - buffer[bufidx] = input + (filterstore * feedback); - - if (++bufidx >= bufsize) - bufidx = 0; - - return output; -} - -// Allpass filter declaration - -class allpass { -public: - allpass(); - void setbuffer(float *buf, int size); - inline float process(float inp); - void mute(); - void setfeedback(float val); - float getfeedback(); -private: - float feedback; - float *buffer; - int bufsize; - int bufidx; -}; - - -// Big to inline - but crucial for speed - -inline float allpass::process(float input) { - float output; - float bufout; - - bufout = buffer[bufidx]; - undenormalise(bufout); - - output = -input + bufout; - buffer[bufidx] = input + (bufout * feedback); - - if (++bufidx >= bufsize) - bufidx = 0; - - return output; -} - - -// Reverb model tuning values - -const int numcombs = 8; -const int numallpasses = 4; -const float muted = 0; -const float fixedgain = 0.015f; -const float scalewet = 3; -const float scaledry = 2; -const float scaledamp = 0.4f; -const float scaleroom = 0.28f; -const float offsetroom = 0.7f; -const float initialroom = 0.5f; -const float initialdamp = 0.5f; -const float initialwet = 1 / scalewet; -const float initialdry = 0; -const float initialwidth = 1; -const float initialmode = 0; -const float freezemode = 0.5f; -const int stereospread = 23; - -// These values assume 44.1KHz sample rate -// they will probably be OK for 48KHz sample rate -// but would need scaling for 96KHz (or other) sample rates. -// The values were obtained by listening tests. -const int combtuningL1 = 1116; -const int combtuningR1 = 1116 + stereospread; -const int combtuningL2 = 1188; -const int combtuningR2 = 1188 + stereospread; -const int combtuningL3 = 1277; -const int combtuningR3 = 1277 + stereospread; -const int combtuningL4 = 1356; -const int combtuningR4 = 1356 + stereospread; -const int combtuningL5 = 1422; -const int combtuningR5 = 1422 + stereospread; -const int combtuningL6 = 1491; -const int combtuningR6 = 1491 + stereospread; -const int combtuningL7 = 1557; -const int combtuningR7 = 1557 + stereospread; -const int combtuningL8 = 1617; -const int combtuningR8 = 1617 + stereospread; -const int allpasstuningL1 = 556; -const int allpasstuningR1 = 556 + stereospread; -const int allpasstuningL2 = 441; -const int allpasstuningR2 = 441 + stereospread; -const int allpasstuningL3 = 341; -const int allpasstuningR3 = 341 + stereospread; -const int allpasstuningL4 = 225; -const int allpasstuningR4 = 225 + stereospread; - - -// Reverb model declaration - -class revmodel { -public: - revmodel(); - void mute(); - void processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip); - void processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip); - void setroomsize(float value); - float getroomsize(); - void setdamp(float value); - float getdamp(); - void setwet(float value); - float getwet(); - void setdry(float value); - float getdry(); - void setwidth(float value); - float getwidth(); - void setmode(float value); - float getmode(); -private: - void update(); - - float gain; - float roomsize, roomsize1; - float damp, damp1; - float wet, wet1, wet2; - float dry; - float width; - float mode; - - // The following are all declared inline - // to remove the need for dynamic allocation - // with its subsequent error-checking messiness - - // Comb filters - comb combL[numcombs]; - comb combR[numcombs]; - - // Allpass filters - allpass allpassL[numallpasses]; - allpass allpassR[numallpasses]; - - // Buffers for the combs - float bufcombL1[combtuningL1]; - float bufcombR1[combtuningR1]; - float bufcombL2[combtuningL2]; - float bufcombR2[combtuningR2]; - float bufcombL3[combtuningL3]; - float bufcombR3[combtuningR3]; - float bufcombL4[combtuningL4]; - float bufcombR4[combtuningR4]; - float bufcombL5[combtuningL5]; - float bufcombR5[combtuningR5]; - float bufcombL6[combtuningL6]; - float bufcombR6[combtuningR6]; - float bufcombL7[combtuningL7]; - float bufcombR7[combtuningR7]; - float bufcombL8[combtuningL8]; - float bufcombR8[combtuningR8]; - - // Buffers for the allpasses - float bufallpassL1[allpasstuningL1]; - float bufallpassR1[allpasstuningR1]; - float bufallpassL2[allpasstuningL2]; - float bufallpassR2[allpasstuningR2]; - float bufallpassL3[allpasstuningL3]; - float bufallpassR3[allpasstuningR3]; - float bufallpassL4[allpasstuningL4]; - float bufallpassR4[allpasstuningR4]; -}; - -#endif diff --git a/engines/sci/sfx/softseq/mt32/i386.cpp b/engines/sci/sfx/softseq/mt32/i386.cpp deleted file mode 100644 index f092189d76..0000000000 --- a/engines/sci/sfx/softseq/mt32/i386.cpp +++ /dev/null @@ -1,849 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include "mt32emu.h" - -#ifdef MT32EMU_HAVE_X86 - -namespace MT32Emu { - -#ifndef _MSC_VER - -#define eflag(value) __asm__ __volatile__("pushfl \n popfl \n" : : "a"(value)) -#define cpuid_flag (1 << 21) - -static inline bool atti386_DetectCPUID() { - unsigned int result; - - // Is there a cpuid? - result = cpuid_flag; // set test - eflag(result); - if (!(result & cpuid_flag)) - return false; - - result = 0; // clear test - eflag(result); - if (result & cpuid_flag) - return false; - - return true; -} - -static inline bool atti386_DetectSIMD() { - unsigned int result; - - if (atti386_DetectCPUID() == false) - return false; - - /* check cpuid */ - __asm__ __volatile__( - "pushl %%ebx \n" \ - "movl $1, %%eax \n" \ - "cpuid \n" \ - "movl %%edx, %0 \n" \ - "popl %%ebx \n" \ - : "=r"(result) : : "eax", "ecx", "edx"); - - if (result & (1 << 25)) - return true; - - return false; -} - -static inline bool atti386_Detect3DNow() { - unsigned int result; - - if (atti386_DetectCPUID() == false) - return false; - - // get cpuid - __asm__ __volatile__( - "pushl %%ebx \n" \ - "movl $0x80000001, %%eax \n" \ - "cpuid \n" \ - "movl %%edx, %0 \n" \ - "popl %%ebx \n" \ - : "=r"(result) : : "eax", "ecx", "edx"); - - if (result & 0x80000000) - return true; - - return false; -} - - -static inline float atti386_iir_filter_sse(float *output, float *hist1_ptr, float *coef_ptr) { - __asm__ __volatile__ ( - "pushl %1 \n" \ - "pushl %2 \n" \ - "movss 0(%0), %%xmm1 \n" \ - "movups 0(%1), %%xmm2 \n" \ - "movlps 0(%2), %%xmm3 \n" \ - " \n" \ - "shufps $0x44, %%xmm3, %%xmm3 \n" \ - " \n" \ - "mulps %%xmm3, %%xmm2 \n" \ - " \n" \ - "subss %%xmm2, %%xmm1 \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "subss %%xmm2, %%xmm1 \n" \ - " \n" \ - "movss %%xmm1, 0(%2) \n" \ - " \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "addss %%xmm2, %%xmm1 \n" \ - " \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "addss %%xmm2, %%xmm1 \n" \ - " \n" \ - "movss %%xmm3, 4(%2) \n" \ - " \n" \ - "addl $16, %1 \n" \ - "addl $8, %2 \n" \ - " \n" \ - "movups 0(%1), %%xmm2 \n" \ - " \n" \ - "movlps 0(%2), %%xmm3 \n" \ - "shufps $0x44, %%xmm3, %%xmm3 \n" \ - " \n" \ - "mulps %%xmm3, %%xmm2 \n" \ - " \n" \ - "subss %%xmm2, %%xmm1 \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "subss %%xmm2, %%xmm1 \n" \ - " \n" \ - "movss %%xmm1, 0(%2) \n" \ - " \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "addss %%xmm2, %%xmm1 \n" \ - " \n" \ - "shufps $0x39, %%xmm2, %%xmm2 \n" \ - "addss %%xmm2, %%xmm1 \n" \ - " \n" \ - "movss %%xmm3, 4(%2) \n" \ - "movss %%xmm1, 0(%0) \n" \ - "popl %2 \n" \ - "popl %1 \n" \ - : : "r"(output), "r"(coef_ptr), "r"(hist1_ptr) - : "memory" -#ifdef __SSE__ - , "xmm1", "xmm2", "xmm3" -#endif - ); - - return *output; -} - -static inline float atti386_iir_filter_3DNow(float output, float *hist1_ptr, float *coef_ptr) { - float tmp; - - __asm__ __volatile__ ( - "movq %0, %%mm1 \n" \ - " \n" \ - "movl %1, %%edi \n" \ - "movq 0(%%edi), %%mm2 \n" \ - " \n" \ - "movl %2, %%eax; \n" \ - "movq 0(%%eax), %%mm3 \n" \ - " \n" \ - "pfmul %%mm3, %%mm2 \n" \ - "pfsub %%mm2, %%mm1 \n" \ - " \n" \ - "psrlq $32, %%mm2 \n" \ - "pfsub %%mm2, %%mm1 \n" \ - " \n" \ - "movd %%mm1, %3 \n" \ - " \n" \ - "addl $8, %%edi \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "movq 0(%%eax), %%mm3 \n" \ - " \n" \ - "pfmul %%mm3, %%mm2 \n" \ - "pfadd %%mm2, %%mm1 \n" \ - " \n" \ - "psrlq $32, %%mm2 \n" \ - "pfadd %%mm2, %%mm1 \n" \ - " \n" \ - "pushl %3 \n" \ - "popl 0(%%eax) \n" \ - " \n" \ - "movd %%mm3, 4(%%eax) \n" \ - " \n" \ - "addl $8, %%edi \n" \ - "addl $8, %%eax \n" \ - " \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "movq 0(%%eax), %%mm3 \n" \ - " \n" \ - "pfmul %%mm3, %%mm2 \n" \ - "pfsub %%mm2, %%mm1 \n" \ - " \n" \ - "psrlq $32, %%mm2 \n" \ - "pfsub %%mm2, %%mm1 \n" \ - " \n" \ - "movd %%mm1, %3 \n" \ - " \n" \ - "addl $8, %%edi \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "movq 0(%%eax), %%mm3 \n" \ - " \n" \ - "pfmul %%mm3, %%mm2 \n" \ - "pfadd %%mm2, %%mm1 \n" \ - " \n" \ - "psrlq $32, %%mm2 \n" \ - "pfadd %%mm2, %%mm1 \n" \ - " \n" \ - "pushl %3 \n" \ - "popl 0(%%eax) \n" \ - "movd %%mm3, 4(%%eax) \n" \ - " \n" \ - "movd %%mm1, %0 \n" \ - "femms \n" \ - : "=m"(output) : "g"(coef_ptr), "g"(hist1_ptr), "m"(tmp) - : "eax", "edi", "memory" -#ifdef __MMX__ - , "mm1", "mm2", "mm3" -#endif - ); - - return output; -} - -static inline void atti386_produceOutput1(int tmplen, Bit16s myvolume, Bit16s *useBuf, Bit16s *snd) { - __asm__ __volatile__( - "movl %0, %%ecx \n" \ - "movw %1, %%ax \n" \ - "shll $16, %%eax \n" \ - "movw %1, %%ax \n" \ - "movd %%eax, %%mm3 \n" \ - "movd %%eax, %%mm2 \n" \ - "psllq $32, %%mm3 \n" \ - "por %%mm2, %%mm3 \n" \ - "movl %2, %%esi \n" \ - "movl %3, %%edi \n" \ - "1: \n" \ - "movq 0(%%esi), %%mm1 \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "pmulhw %%mm3, %%mm1 \n" \ - "paddw %%mm2, %%mm1 \n" \ - "movq %%mm1, 0(%%edi) \n" \ - " \n" \ - "addl $8, %%esi \n" \ - "addl $8, %%edi \n" \ - " \n" \ - "decl %%ecx \n" \ - "cmpl $0, %%ecx \n" \ - "jg 1b \n" \ - "emms \n" \ - : : "g"(tmplen), "g"(myvolume), "g"(useBuf), "g"(snd) - : "eax", "ecx", "edi", "esi", "memory" -#ifdef __MMX__ - , "mm1", "mm2", "mm3" -#endif - ); -} - -static inline void atti386_produceOutput2(Bit32u len, Bit16s *snd, float *sndbufl, float *sndbufr, float *multFactor) { - __asm__ __volatile__( - "movl %4, %%ecx \n" \ - "shrl $1, %%ecx \n" \ - "addl $4, %%ecx \n" \ - "pushl %%ecx \n" \ - " \n" \ - "movl %0, %%esi \n" \ - "movups 0(%%esi), %%xmm1 \n" \ - " \n" \ - "movl %1, %%esi \n" \ - "movl %2, %%edi \n" \ - "1: \n" \ - "xorl %%eax, %%eax \n" \ - "movw 0(%1), %%ax \n" \ - "cwde \n" \ - "incl %1 \n" \ - "incl %1 \n" \ - "movd %%eax, %%mm1 \n" \ - "psrlq $32, %%mm1 \n" \ - "movw 0(%1), %%ax \n" \ - "incl %1 \n" \ - "incl %1 \n" \ - "movd %%eax, %%mm2 \n" \ - "por %%mm2, %%mm1 \n" \ - " \n" \ - "decl %%ecx \n" \ - "jnz 1b \n" \ - " \n" \ - "popl %%ecx \n" \ - "movl %1, %%esi \n" \ - "movl %3, %%edi \n" \ - "incl %%esi \n" \ - "2: \n" \ - "decl %%ecx \n" \ - "jnz 2b \n" \ - : : "g"(multFactor), "r"(snd), "g"(sndbufl), "g"(sndbufr), "g"(len) - : "eax", "ecx", "edi", "esi", "mm1", "mm2", "xmm1", "memory"); -} - -static inline void atti386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) { - __asm__ __volatile__( - "movl %0, %%ecx \n" \ - "movl %1, %%esi \n" \ - "movl %2, %%edi \n" \ - "1: \n" \ - "movq 0(%%edi), %%mm1 \n" \ - "movq 0(%%esi), %%mm2 \n" \ - "paddw %%mm2, %%mm1 \n" \ - "movq %%mm1, 0(%%esi) \n" \ - "addl $8, %%edi \n" \ - "addl $8, %%esi \n" \ - "decl %%ecx \n" \ - "cmpl $0, %%ecx \n" \ - "jg 1b \n" \ - "emms \n" \ - : : "g"(len), "g"(buf1), "g"(buf2) - : "ecx", "edi", "esi", "memory" -#ifdef __MMX__ - , "mm1", "mm2" -#endif - ); -} - -static inline void atti386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) { - __asm__ __volatile__( - "movl %0, %%ecx \n" \ - "movl %1, %%esi \n" \ - "movl %2, %%edi \n" \ - "1: \n" \ - "movq 0(%%esi), %%mm1 \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "movq %%mm1, %%mm3 \n" \ - "pmulhw %%mm2, %%mm1 \n" \ - "paddw %%mm3, %%mm1 \n" \ - "movq %%mm1, 0(%%esi) \n" \ - "addl $8, %%edi \n" \ - "addl $8, %%esi \n" \ - "decl %%ecx \n" \ - "cmpl $0, %%ecx \n" \ - "jg 1b \n" \ - "emms \n" \ - : : "g"(len), "g"(buf1), "g"(buf2) - : "ecx", "edi", "esi", "memory" -#ifdef __MMX__ - , "mm1", "mm2", "mm3" -#endif - ); -} - -static inline void atti386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) { - __asm__ __volatile__( - "movl %0, %%ecx \n" \ - "movl %1, %%esi \n" \ - "movl %2, %%edi \n" \ - "1: \n" \ - "movq 0(%%esi), %%mm1 \n" \ - "movq 0(%%edi), %%mm2 \n" \ - "pmulhw %%mm2, %%mm1 \n" \ - "movq %%mm1, 0(%%esi) \n" \ - "addl $8, %%edi \n" \ - "addl $8, %%esi \n" \ - "decl %%ecx \n" \ - "cmpl $0, %%ecx \n" \ - "jg 1b \n" \ - "emms \n" \ - : : "g"(len), "g"(buf1), "g"(buf2) - : "ecx", "edi", "esi", "memory" -#ifdef __MMX__ - , "mm1", "mm2" -#endif - ); -} - -static inline void atti386_partialProductOutput(int quadlen, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *p1buf) { - __asm__ __volatile__( - "movl %0, %%ecx \n" \ - "movw %1, %%ax \n" \ - "shll $16, %%eax \n" \ - "movw %2, %%ax \n" \ - "movd %%eax, %%mm1 \n" \ - "movd %%eax, %%mm2 \n" \ - "psllq $32, %%mm1 \n" \ - "por %%mm2, %%mm1 \n" \ - "movl %3, %%edi \n" \ - "movl %4, %%esi \n" \ - "pushl %%ebx \n" \ - "1: \n" \ - "movw 0(%%esi), %%bx \n" \ - "addl $2, %%esi \n" \ - "movw 0(%%esi), %%dx \n" \ - "addl $2, %%esi \n" \ - "" \ - "movw %%dx, %%ax \n" \ - "shll $16, %%eax \n" \ - "movw %%dx, %%ax \n" \ - "movd %%eax, %%mm2 \n" \ - "psllq $32, %%mm2 \n" \ - "movw %%bx, %%ax \n" \ - "shll $16, %%eax \n" \ - "movw %%bx, %%ax \n" \ - "movd %%eax, %%mm3 \n" \ - "por %%mm3, %%mm2 \n" \ - "" \ - "pmulhw %%mm1, %%mm2 \n" \ - "movq %%mm2, 0(%%edi) \n" \ - "addl $8, %%edi \n" \ - "" \ - "decl %%ecx \n" \ - "cmpl $0, %%ecx \n" \ - "jg 1b \n" \ - "emms \n" \ - "popl %%ebx \n" \ - : : "g"(quadlen), "g"(leftvol), "g"(rightvol), "g"(partialBuf), "g"(p1buf) - : "eax", "ecx", "edx", "edi", "esi", "memory" -#ifdef __MMX__ - , "mm1", "mm2", "mm3" -#endif - ); -} - -#endif - -bool DetectSIMD() { -#ifdef _MSC_VER - bool found_simd; - __asm { - pushfd - pop eax // get EFLAGS into eax - mov ebx,eax // keep a copy - xor eax,0x200000 - // toggle CPUID bit - - push eax - popfd // set new EFLAGS - pushfd - pop eax // EFLAGS back into eax - - xor eax,ebx - // have we changed the ID bit? - - je NO_SIMD - // No, no CPUID instruction - - // we could toggle the - // ID bit so CPUID is present - mov eax,1 - - cpuid // get processor features - test edx,1<<25 // check the SIMD bit - jz NO_SIMD - mov found_simd,1 - jmp DONE - NO_SIMD: - mov found_simd,0 - DONE: - } - return found_simd; -#else - return atti386_DetectSIMD(); -#endif -} - -bool Detect3DNow() { -#ifdef _MSC_VER - bool found3D = false; - __asm { - pushfd - pop eax - mov edx, eax - xor eax, 00200000h - push eax - popfd - pushfd - pop eax - xor eax, edx - jz NO_3DNOW - - mov eax, 80000000h - cpuid - - cmp eax, 80000000h - jbe NO_3DNOW - - mov eax, 80000001h - cpuid - test edx, 80000000h - jz NO_3DNOW - mov found3D, 1 -NO_3DNOW: - - } - return found3D; -#else - return atti386_Detect3DNow(); -#endif -} - -float iir_filter_sse(float input,float *hist1_ptr, float *coef_ptr) { - float output; - - // 1st number of coefficients array is overall input scale factor, or filter gain - output = input * (*coef_ptr++); - -#ifdef _MSC_VER - __asm { - - movss xmm1, output - - mov eax, coef_ptr - movups xmm2, [eax] - - mov eax, hist1_ptr - movlps xmm3, [eax] - shufps xmm3, xmm3, 44h - // hist1_ptr+1, hist1_ptr, hist1_ptr+1, hist1_ptr - - mulps xmm2, xmm3 - - subss xmm1, xmm2 - // Rotate elements right - shufps xmm2, xmm2, 39h - subss xmm1, xmm2 - - // Store new_hist - movss DWORD PTR [eax], xmm1 - - // Rotate elements right - shufps xmm2, xmm2, 39h - addss xmm1, xmm2 - - // Rotate elements right - shufps xmm2, xmm2, 39h - addss xmm1, xmm2 - - // Store previous hist - movss DWORD PTR [eax+4], xmm3 - - add coef_ptr, 16 - add hist1_ptr, 8 - - mov eax, coef_ptr - movups xmm2, [eax] - - mov eax, hist1_ptr - movlps xmm3, [eax] - shufps xmm3, xmm3, 44h - // hist1_ptr+1, hist1_ptr, hist1_ptr+1, hist1_ptr - - mulps xmm2, xmm3 - - subss xmm1, xmm2 - // Rotate elements right - shufps xmm2, xmm2, 39h - subss xmm1, xmm2 - - // Store new_hist - movss DWORD PTR [eax], xmm1 - - // Rotate elements right - shufps xmm2, xmm2, 39h - addss xmm1, xmm2 - - // Rotate elements right - shufps xmm2, xmm2, 39h - addss xmm1, xmm2 - - // Store previous hist - movss DWORD PTR [eax+4], xmm3 - - movss output, xmm1 - } -#else - output = atti386_iir_filter_sse(&output, hist1_ptr, coef_ptr); -#endif - return output; -} - -float iir_filter_3dnow(float input,float *hist1_ptr, float *coef_ptr) { - float output; - - // 1st number of coefficients array is overall input scale factor, or filter gain - output = input * (*coef_ptr++); - - // I find it very sad that 3DNow requires twice as many instructions as Intel's SSE - // Intel does have the upper hand here. -#ifdef _MSC_VER - float tmp; - __asm { - movq mm1, output - mov ebx, coef_ptr - movq mm2, [ebx] - - mov eax, hist1_ptr; - movq mm3, [eax] - - pfmul mm2, mm3 - pfsub mm1, mm2 - - psrlq mm2, 32 - pfsub mm1, mm2 - - // Store new hist - movd tmp, mm1 - - add ebx, 8 - movq mm2, [ebx] - movq mm3, [eax] - - pfmul mm2, mm3 - pfadd mm1, mm2 - - psrlq mm2, 32 - pfadd mm1, mm2 - - push tmp - pop DWORD PTR [eax] - - movd DWORD PTR [eax+4], mm3 - - add ebx, 8 - add eax, 8 - - movq mm2, [ebx] - movq mm3, [eax] - - pfmul mm2, mm3 - pfsub mm1, mm2 - - psrlq mm2, 32 - pfsub mm1, mm2 - - // Store new hist - movd tmp, mm1 - - add ebx, 8 - movq mm2, [ebx] - movq mm3, [eax] - - pfmul mm2, mm3 - pfadd mm1, mm2 - - psrlq mm2, 32 - pfadd mm1, mm2 - - push tmp - pop DWORD PTR [eax] - movd DWORD PTR [eax+4], mm3 - - movd output, mm1 - - femms - } -#else - output = atti386_iir_filter_3DNow(output, hist1_ptr, coef_ptr); -#endif - return output; -} - -#if MT32EMU_USE_MMX > 0 - -int i386_partialProductOutput(int len, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *mixedBuf) { - int tmplen = len >> 1; - if (tmplen == 0) { - return 0; - } -#ifdef _MSC_VER - __asm { - mov ecx,tmplen - mov ax, leftvol - shl eax,16 - mov ax, rightvol - movd mm1, eax - movd mm2, eax - psllq mm1, 32 - por mm1, mm2 - mov edi, partialBuf - mov esi, mixedBuf -mmxloop1: - mov bx, [esi] - add esi,2 - mov dx, [esi] - add esi,2 - - mov ax, dx - shl eax, 16 - mov ax, dx - movd mm2,eax - psllq mm2, 32 - mov ax, bx - shl eax, 16 - mov ax, bx - movd mm3,eax - por mm2,mm3 - - pmulhw mm2, mm1 - movq [edi], mm2 - add edi, 8 - - dec ecx - cmp ecx,0 - jg mmxloop1 - emms - } -#else - atti386_partialProductOutput(tmplen, leftvol, rightvol, partialBuf, mixedBuf); -#endif - return tmplen << 1; -} - -int i386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) { - int tmplen = len >> 2; - if (tmplen == 0) { - return 0; - } -#ifdef _MSC_VER - __asm { - mov ecx, tmplen - mov esi, buf1 - mov edi, buf2 - -mixloop1: - movq mm1, [edi] - movq mm2, [esi] - paddw mm1,mm2 - movq [esi],mm1 - add edi,8 - add esi,8 - - dec ecx - cmp ecx,0 - jg mixloop1 - emms - } -#else - atti386_mixBuffers(buf1, buf2, tmplen); -#endif - return tmplen << 2; -} - - -int i386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) { - int tmplen = len >> 2; - if (tmplen == 0) { - return 0; - } -#ifdef _MSC_VER - __asm { - mov ecx, tmplen - mov esi, buf1 - mov edi, buf2 - -mixloop2: - movq mm1, [esi] - movq mm2, [edi] - movq mm3, mm1 - pmulhw mm1, mm2 - paddw mm1,mm3 - movq [esi],mm1 - add edi,8 - add esi,8 - - dec ecx - cmp ecx,0 - jg mixloop2 - emms - } -#else - atti386_mixBuffersRingMix(buf1, buf2, tmplen); -#endif - return tmplen << 2; -} - -int i386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) { - int tmplen = len >> 2; - if (tmplen == 0) { - return 0; - } -#ifdef _MSC_VER - __asm { - mov ecx, tmplen - mov esi, buf1 - mov edi, buf2 - -mixloop3: - movq mm1, [esi] - movq mm2, [edi] - pmulhw mm1, mm2 - movq [esi],mm1 - add edi,8 - add esi,8 - - dec ecx - cmp ecx,0 - jg mixloop3 - emms - } -#else - atti386_mixBuffersRing(buf1, buf2, tmplen); -#endif - return tmplen << 2; -} - -int i386_produceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume) { - int tmplen = (len >> 1); - if (tmplen == 0) { - return 0; - } -#ifdef _MSC_VER - __asm { - mov ecx, tmplen - mov ax,volume - shl eax,16 - mov ax,volume - movd mm3,eax - movd mm2,eax - psllq mm3, 32 - por mm3,mm2 - mov esi, useBuf - mov edi, stream -mixloop4: - movq mm1, [esi] - movq mm2, [edi] - pmulhw mm1, mm3 - paddw mm1,mm2 - movq [edi], mm1 - - add esi,8 - add edi,8 - - dec ecx - cmp ecx,0 - jg mixloop4 - emms - } -#else - atti386_produceOutput1(tmplen, volume, useBuf, stream); -#endif - return tmplen << 1; -} - -#endif - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/i386.h b/engines/sci/sfx/softseq/mt32/i386.h deleted file mode 100644 index e8644411cd..0000000000 --- a/engines/sci/sfx/softseq/mt32/i386.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_I386_H -#define MT32EMU_I386_H - -namespace MT32Emu { -#ifdef MT32EMU_HAVE_X86 - -// Function that detects the availablity of SSE SIMD instructions -bool DetectSIMD(); -// Function that detects the availablity of 3DNow instructions -bool Detect3DNow(); - -float iir_filter_sse(float input,float *hist1_ptr, float *coef_ptr); -float iir_filter_3dnow(float input,float *hist1_ptr, float *coef_ptr); -float iir_filter_normal(float input,float *hist1_ptr, float *coef_ptr); - -#if MT32EMU_USE_MMX > 0 -int i386_partialProductOutput(int len, Bit16s leftvol, Bit16s rightvol, Bit16s *partialBuf, Bit16s *mixedBuf); -int i386_mixBuffers(Bit16s * buf1, Bit16s *buf2, int len); -int i386_mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len); -int i386_mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len); -int i386_produceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume); -#endif - -#endif - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/mt32_file.cpp b/engines/sci/sfx/softseq/mt32/mt32_file.cpp deleted file mode 100644 index 86cb29fd49..0000000000 --- a/engines/sci/sfx/softseq/mt32/mt32_file.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <stdio.h> - -#include "mt32emu.h" - -namespace MT32Emu { - - bool ANSIFile::open(const char *filename, OpenMode mode) { - const char *fmode; - if (mode == OpenMode_read) { - fmode = "rb"; - } else { - fmode = "wb"; - } - fp = fopen(filename, fmode); - return (fp != NULL); - } - - void ANSIFile::close() { - fclose(fp); - } - - size_t ANSIFile::read(void *in, size_t size) { - return fread(in, 1, size, fp); - } - - bool ANSIFile::readLine(char *in, size_t size) { - return fgets(in, (int)size, fp) != NULL; - } - - bool ANSIFile::readBit8u(Bit8u *in) { - int c = fgetc(fp); - if (c == EOF) - return false; - *in = (Bit8u)c; - return true; - } - - bool File::readBit16u(Bit16u *in) { - Bit8u b[2]; - if (read(&b[0], 2) != 2) - return false; - *in = ((b[0] << 8) | b[1]); - return true; - } - - bool File::readBit32u(Bit32u *in) { - Bit8u b[4]; - if (read(&b[0], 4) != 4) - return false; - *in = ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]); - return true; - } - - size_t ANSIFile::write(const void *out, size_t size) { - return fwrite(out, 1, size, fp); - } - - bool ANSIFile::writeBit8u(Bit8u out) { - return fputc(out, fp) != EOF; - } - - bool File::writeBit16u(Bit16u out) { - if (!writeBit8u((Bit8u)((out & 0xFF00) >> 8))) { - return false; - } - if (!writeBit8u((Bit8u)(out & 0x00FF))) { - return false; - } - return true; - } - - bool File::writeBit32u(Bit32u out) { - if (!writeBit8u((Bit8u)((out & 0xFF000000) >> 24))) { - return false; - } - if (!writeBit8u((Bit8u)((out & 0x00FF0000) >> 16))) { - return false; - } - if (!writeBit8u((Bit8u)((out & 0x0000FF00) >> 8))) { - return false; - } - if (!writeBit8u((Bit8u)(out & 0x000000FF))) { - return false; - } - return true; - } - - bool ANSIFile::isEOF() { - return feof(fp) != 0; - } -} diff --git a/engines/sci/sfx/softseq/mt32/mt32_file.h b/engines/sci/sfx/softseq/mt32/mt32_file.h deleted file mode 100644 index 5f05c9e9ae..0000000000 --- a/engines/sci/sfx/softseq/mt32/mt32_file.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_FILE_H -#define MT32EMU_FILE_H - -#include <stdio.h> - -namespace MT32Emu { - -class File { -public: - enum OpenMode { - OpenMode_read = 0, - OpenMode_write = 1 - }; - virtual ~File() {} - virtual void close() = 0; - virtual size_t read(void *in, size_t size) = 0; - virtual bool readLine(char *in, size_t size) = 0; - virtual bool readBit8u(Bit8u *in) = 0; - virtual bool readBit16u(Bit16u *in); - virtual bool readBit32u(Bit32u *in); - virtual size_t write(const void *out, size_t size) = 0; - virtual bool writeBit8u(Bit8u out) = 0; - // Note: May write a single byte to the file before failing - virtual bool writeBit16u(Bit16u out); - // Note: May write some (<4) bytes to the file before failing - virtual bool writeBit32u(Bit32u out); - virtual bool isEOF() = 0; -}; - -class ANSIFile: public File { -private: - FILE *fp; -public: - bool open(const char *filename, OpenMode mode); - void close(); - size_t read(void *in, size_t size); - bool readLine(char *in, size_t size); - bool readBit8u(Bit8u *in); - size_t write(const void *out, size_t size); - bool writeBit8u(Bit8u out); - bool isEOF(); -}; - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/mt32emu.h b/engines/sci/sfx/softseq/mt32/mt32emu.h deleted file mode 100644 index 0aa4df7488..0000000000 --- a/engines/sci/sfx/softseq/mt32/mt32emu.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_MT32EMU_H -#define MT32EMU_MT32EMU_H - -// Debugging -// Show the instruments played -#define MT32EMU_MONITOR_INSTRUMENTS 1 -// Shows number of partials MT-32 is playing, and on which parts -#define MT32EMU_MONITOR_PARTIALS 0 -// Determines how the waveform cache file is handled (must be regenerated after sampling rate change) -#define MT32EMU_WAVECACHEMODE 0 // Load existing cache if possible, otherwise generate and save cache -//#define MT32EMU_WAVECACHEMODE 1 // Load existing cache if possible, otherwise generage but don't save cache -//#define MT32EMU_WAVECACHEMODE 2 // Ignore existing cache, generate and save cache -//#define MT32EMU_WAVECACHEMODE 3 // Ignore existing cache, generate but don't save cache - -// Configuration -// The maximum number of partials playing simultaneously -#define MT32EMU_MAX_PARTIALS 32 -// The maximum number of notes playing simultaneously per part. -// No point making it more than MT32EMU_MAX_PARTIALS, since each note needs at least one partial. -#define MT32EMU_MAX_POLY 32 -// This calculates the exact frequencies of notes as they are played, instead of offsetting from pre-cached semitones. Potentially very slow. -#define MT32EMU_ACCURATENOTES 0 - -#if (defined (_MSC_VER) && defined(_M_IX86)) -#define MT32EMU_HAVE_X86 -#elif defined(__GNUC__) -#if __GNUC__ >= 3 && defined(__i386__) -#define MT32EMU_HAVE_X86 -#endif -#endif - -#ifdef MT32EMU_HAVE_X86 -#define MT32EMU_USE_MMX 1 -#else -#define MT32EMU_USE_MMX 0 -#endif - -#include "freeverb.h" - -#include "structures.h" -#include "i386.h" -#include "mt32_file.h" -#include "tables.h" -#include "partial.h" -#include "partialManager.h" -#include "part.h" -#include "synth.h" - -#endif diff --git a/engines/sci/sfx/softseq/mt32/part.cpp b/engines/sci/sfx/softseq/mt32/part.cpp deleted file mode 100644 index b3d71bccca..0000000000 --- a/engines/sci/sfx/softseq/mt32/part.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <string.h> -#include <math.h> - -#include "mt32emu.h" - -namespace MT32Emu { - -static const Bit8u PartialStruct[13] = { - 0, 0, 2, 2, 1, 3, - 3, 0, 3, 0, 2, 1, 3 }; - -static const Bit8u PartialMixStruct[13] = { - 0, 1, 0, 1, 1, 0, - 1, 3, 3, 2, 2, 2, 2 }; - -static const float floatKeyfollow[17] = { - -1.0f, -1.0f/2.0f, -1.0f/4.0f, 0.0f, - 1.0f/8.0f, 1.0f/4.0f, 3.0f/8.0f, 1.0f/2.0f, 5.0f/8.0f, 3.0f/4.0f, 7.0f/8.0f, 1.0f, - 5.0f/4.0f, 3.0f/2.0f, 2.0f, - 1.0009765625f, 1.0048828125f -}; - -//FIXME:KG: Put this dpoly stuff somewhere better -bool dpoly::isActive() const { - return partials[0] != NULL || partials[1] != NULL || partials[2] != NULL || partials[3] != NULL; -} - -Bit32u dpoly::getAge() const { - for (int i = 0; i < 4; i++) { - if (partials[i] != NULL) { - return partials[i]->age; - } - } - return 0; -} - -RhythmPart::RhythmPart(Synth *useSynth, unsigned int usePartNum): Part(useSynth, usePartNum) { - strcpy(name, "Rhythm"); - rhythmTemp = &synth->mt32ram.rhythmSettings[0]; - refresh(); -} - -Part::Part(Synth *useSynth, unsigned int usePartNum) { - this->synth = useSynth; - this->partNum = usePartNum; - patchCache[0].dirty = true; - holdpedal = false; - patchTemp = &synth->mt32ram.patchSettings[partNum]; - if (usePartNum == 8) { - // Nasty hack for rhythm - timbreTemp = NULL; - } else { - sprintf(name, "Part %d", partNum + 1); - timbreTemp = &synth->mt32ram.timbreSettings[partNum]; - } - currentInstr[0] = 0; - currentInstr[10] = 0; - expression = 127; - volumeMult = 0; - volumesetting.leftvol = 32767; - volumesetting.rightvol = 32767; - bend = 0.0f; - memset(polyTable,0,sizeof(polyTable)); - memset(patchCache, 0, sizeof(patchCache)); -} - -void Part::setHoldPedal(bool pedalval) { - if (holdpedal && !pedalval) { - holdpedal = false; - stopPedalHold(); - } else { - holdpedal = pedalval; - } -} - -void RhythmPart::setBend(unsigned int midiBend) { - synth->printDebug("%s: Setting bend (%d) not supported on rhythm", name, midiBend); - return; -} - -void Part::setBend(unsigned int midiBend) { - // FIXME:KG: Slightly unbalanced increments, but I wanted min -1.0, centre 0.0 and max 1.0 - if (midiBend <= 0x2000) { - bend = ((signed int)midiBend - 0x2000) / (float)0x2000; - } else { - bend = ((signed int)midiBend - 0x2000) / (float)0x1FFF; - } - // Loop through all partials to update their bend - for (int i = 0; i < MT32EMU_MAX_POLY; i++) { - for (int j = 0; j < 4; j++) { - if (polyTable[i].partials[j] != NULL) { - polyTable[i].partials[j]->setBend(bend); - } - } - } -} - -void RhythmPart::setModulation(unsigned int midiModulation) { - synth->printDebug("%s: Setting modulation (%d) not supported on rhythm", name, midiModulation); -} - -void Part::setModulation(unsigned int midiModulation) { - // Just a bloody guess, as always, before I get things figured out - for (int t = 0; t < 4; t++) { - if (patchCache[t].playPartial) { - int newrate = (patchCache[t].modsense * midiModulation) >> 7; - //patchCache[t].lfoperiod = lfotable[newrate]; - patchCache[t].lfodepth = newrate; - //FIXME:KG: timbreTemp->partial[t].lfo.depth = - } - } -} - -void RhythmPart::refresh() { - updateVolume(); - // (Re-)cache all the mapped timbres ahead of time - for (unsigned int drumNum = 0; drumNum < synth->controlROMMap->rhythmSettingsCount; drumNum++) { - int drumTimbreNum = rhythmTemp[drumNum].timbre; - if (drumTimbreNum >= 127) // 94 on MT-32 - continue; - Bit16s pan = rhythmTemp[drumNum].panpot; // They use R-L 0-14... - // FIXME:KG: Panning cache should be backed up to partials using it, too - if (pan < 7) { - drumPan[drumNum].leftvol = pan * 4681; - drumPan[drumNum].rightvol = 32767; - } else { - drumPan[drumNum].rightvol = (14 - pan) * 4681; - drumPan[drumNum].leftvol = 32767; - } - PatchCache *cache = drumCache[drumNum]; - backupCacheToPartials(cache); - for (int t = 0; t < 4; t++) { - // Common parameters, stored redundantly - cache[t].dirty = true; - cache[t].pitchShift = 0.0f; - cache[t].benderRange = 0.0f; - cache[t].pansetptr = &drumPan[drumNum]; - cache[t].reverb = rhythmTemp[drumNum].reverbSwitch > 0; - } - } -} - -void Part::refresh() { - updateVolume(); - backupCacheToPartials(patchCache); - for (int t = 0; t < 4; t++) { - // Common parameters, stored redundantly - patchCache[t].dirty = true; - patchCache[t].pitchShift = (patchTemp->patch.keyShift - 24) + (patchTemp->patch.fineTune - 50) / 100.0f; - patchCache[t].benderRange = patchTemp->patch.benderRange; - patchCache[t].pansetptr = &volumesetting; - patchCache[t].reverb = patchTemp->patch.reverbSwitch > 0; - } - memcpy(currentInstr, timbreTemp->common.name, 10); -} - -const char *Part::getCurrentInstr() const { - return ¤tInstr[0]; -} - -void RhythmPart::refreshTimbre(unsigned int absTimbreNum) { - for (int m = 0; m < 85; m++) { - if (rhythmTemp[m].timbre == absTimbreNum - 128) - drumCache[m][0].dirty = true; - } -} - -void Part::refreshTimbre(unsigned int absTimbreNum) { - if (getAbsTimbreNum() == absTimbreNum) { - memcpy(currentInstr, timbreTemp->common.name, 10); - patchCache[0].dirty = true; - } -} - -int Part::fixBiaslevel(int srcpnt, int *dir) { - int noteat = srcpnt & 0x3F; - int outnote; - if (srcpnt < 64) - *dir = 0; - else - *dir = 1; - outnote = 33 + noteat; - //synth->printDebug("Bias note %d, dir %d", outnote, *dir); - - return outnote; -} - -int Part::fixKeyfollow(int srckey) { - if (srckey>=0 && srckey<=16) { - int keyfix[17] = { -256*16, -128*16, -64*16, 0, 32*16, 64*16, 96*16, 128*16, (128+32)*16, 192*16, (192+32)*16, 256*16, (256+64)*16, (256+128)*16, (512)*16, 4100, 4116}; - return keyfix[srckey]; - } else { - //LOG(LOG_ERROR|LOG_MISC,"Missed key: %d", srckey); - return 256; - } -} - -void Part::abortPoly(dpoly *poly) { - if (!poly->isPlaying) { - return; - } - for (int i = 0; i < 4; i++) { - Partial *partial = poly->partials[i]; - if (partial != NULL) { - partial->deactivate(); - } - } - poly->isPlaying = false; -} - -void Part::setPatch(const PatchParam *patch) { - patchTemp->patch = *patch; -} - -void RhythmPart::setTimbre(TimbreParam * /*timbre*/) { - synth->printDebug("%s: Attempted to call setTimbre() - doesn't make sense for rhythm", name); -} - -void Part::setTimbre(TimbreParam *timbre) { - *timbreTemp = *timbre; -} - -unsigned int RhythmPart::getAbsTimbreNum() const { - synth->printDebug("%s: Attempted to call getAbsTimbreNum() - doesn't make sense for rhythm", name); - return 0; -} - -unsigned int Part::getAbsTimbreNum() const { - return (patchTemp->patch.timbreGroup * 64) + patchTemp->patch.timbreNum; -} - -void RhythmPart::setProgram(unsigned int patchNum) { - synth->printDebug("%s: Attempt to set program (%d) on rhythm is invalid", name, patchNum); -} - -void Part::setProgram(unsigned int patchNum) { - setPatch(&synth->mt32ram.patches[patchNum]); - setTimbre(&synth->mt32ram.timbres[getAbsTimbreNum()].timbre); - - refresh(); - - allSoundOff(); //FIXME:KG: Is this correct? -} - -void Part::backupCacheToPartials(PatchCache cache[4]) { - // check if any partials are still playing with the old patch cache - // if so then duplicate the cached data from the part to the partial so that - // we can change the part's cache without affecting the partial. - // We delay this until now to avoid a copy operation with every note played - for (int m = 0; m < MT32EMU_MAX_POLY; m++) { - for (int i = 0; i < 4; i++) { - Partial *partial = polyTable[m].partials[i]; - if (partial != NULL && partial->patchCache == &cache[i]) { - partial->cachebackup = cache[i]; - partial->patchCache = &partial->cachebackup; - } - } - } -} - -void Part::cacheTimbre(PatchCache cache[4], const TimbreParam *timbre) { - backupCacheToPartials(cache); - int partialCount = 0; - for (int t = 0; t < 4; t++) { - if (((timbre->common.pmute >> t) & 0x1) == 1) { - cache[t].playPartial = true; - partialCount++; - } else { - cache[t].playPartial = false; - continue; - } - - // Calculate and cache common parameters - - cache[t].pcm = timbre->partial[t].wg.pcmwave; - cache[t].useBender = (timbre->partial[t].wg.bender == 1); - - switch (t) { - case 0: - cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct12] & 0x2) ? true : false; - cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct12]; - cache[t].structurePosition = 0; - cache[t].structurePair = 1; - break; - case 1: - cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct12] & 0x1) ? true : false; - cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct12]; - cache[t].structurePosition = 1; - cache[t].structurePair = 0; - break; - case 2: - cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct34] & 0x2) ? true : false; - cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct34]; - cache[t].structurePosition = 0; - cache[t].structurePair = 3; - break; - case 3: - cache[t].PCMPartial = (PartialStruct[(int)timbre->common.pstruct34] & 0x1) ? true : false; - cache[t].structureMix = PartialMixStruct[(int)timbre->common.pstruct34]; - cache[t].structurePosition = 1; - cache[t].structurePair = 2; - break; - default: - break; - } - - cache[t].waveform = timbre->partial[t].wg.waveform; - cache[t].pulsewidth = timbre->partial[t].wg.pulsewid; - cache[t].pwsens = timbre->partial[t].wg.pwvelo; - if (timbre->partial[t].wg.keyfollow > 16) { - synth->printDebug("Bad keyfollow value in timbre!"); - cache[t].pitchKeyfollow = 1.0f; - } else { - cache[t].pitchKeyfollow = floatKeyfollow[timbre->partial[t].wg.keyfollow]; - } - - cache[t].pitch = timbre->partial[t].wg.coarse + (timbre->partial[t].wg.fine - 50) / 100.0f + 24.0f; - cache[t].pitchEnv = timbre->partial[t].env; - cache[t].pitchEnv.sensitivity = (char)((float)cache[t].pitchEnv.sensitivity * 1.27f); - cache[t].pitchsustain = cache[t].pitchEnv.level[3]; - - // Calculate and cache TVA envelope stuff - cache[t].ampEnv = timbre->partial[t].tva; - cache[t].ampEnv.level = (char)((float)cache[t].ampEnv.level * 1.27f); - - cache[t].ampbias[0] = fixBiaslevel(cache[t].ampEnv.biaspoint1, &cache[t].ampdir[0]); - cache[t].ampblevel[0] = 12 - cache[t].ampEnv.biaslevel1; - cache[t].ampbias[1] = fixBiaslevel(cache[t].ampEnv.biaspoint2, &cache[t].ampdir[1]); - cache[t].ampblevel[1] = 12 - cache[t].ampEnv.biaslevel2; - cache[t].ampdepth = cache[t].ampEnv.envvkf * cache[t].ampEnv.envvkf; - - // Calculate and cache filter stuff - cache[t].filtEnv = timbre->partial[t].tvf; - cache[t].filtkeyfollow = fixKeyfollow(cache[t].filtEnv.keyfollow); - cache[t].filtEnv.envdepth = (char)((float)cache[t].filtEnv.envdepth * 1.27); - cache[t].tvfbias = fixBiaslevel(cache[t].filtEnv.biaspoint, &cache[t].tvfdir); - cache[t].tvfblevel = cache[t].filtEnv.biaslevel; - cache[t].filtsustain = cache[t].filtEnv.envlevel[3]; - - // Calculate and cache LFO stuff - cache[t].lfodepth = timbre->partial[t].lfo.depth; - cache[t].lfoperiod = synth->tables.lfoPeriod[(int)timbre->partial[t].lfo.rate]; - cache[t].lforate = timbre->partial[t].lfo.rate; - cache[t].modsense = timbre->partial[t].lfo.modsense; - } - for (int t = 0; t < 4; t++) { - // Common parameters, stored redundantly - cache[t].dirty = false; - cache[t].partialCount = partialCount; - cache[t].sustain = (timbre->common.nosustain == 0); - } - //synth->printDebug("Res 1: %d 2: %d 3: %d 4: %d", cache[0].waveform, cache[1].waveform, cache[2].waveform, cache[3].waveform); - -#if MT32EMU_MONITOR_INSTRUMENTS == 1 - synth->printDebug("%s (%s): Recached timbre", name, currentInstr); - for (int i = 0; i < 4; i++) { - synth->printDebug(" %d: play=%s, pcm=%s (%d), wave=%d", i, cache[i].playPartial ? "YES" : "NO", cache[i].PCMPartial ? "YES" : "NO", timbre->partial[i].wg.pcmwave, timbre->partial[i].wg.waveform); - } -#endif -} - -const char *Part::getName() const { - return name; -} - -void Part::updateVolume() { - volumeMult = synth->tables.volumeMult[patchTemp->outlevel * expression / 127]; -} - -int Part::getVolume() const { - // FIXME: Use the mappings for this in the control ROM - return patchTemp->outlevel * 127 / 100; -} - -void Part::setVolume(int midiVolume) { - // FIXME: Use the mappings for this in the control ROM - patchTemp->outlevel = (Bit8u)(midiVolume * 100 / 127); - updateVolume(); - synth->printDebug("%s (%s): Set volume to %d", name, currentInstr, midiVolume); -} - -void Part::setExpression(int midiExpression) { - expression = midiExpression; - updateVolume(); -} - -void RhythmPart::setPan(unsigned int midiPan) -{ - // FIXME:KG: This is unchangeable for drums (they always use drumPan), is that correct? - synth->printDebug("%s: Setting pan (%d) not supported on rhythm", name, midiPan); -} - -void Part::setPan(unsigned int midiPan) { - // FIXME:KG: Tweaked this a bit so that we have a left 100%, centre and right 100% - // (But this makes the range somewhat skewed) - // Check against the real thing - // NOTE: Panning is inverted compared to GM. - if (midiPan < 64) { - volumesetting.leftvol = (Bit16s)(midiPan * 512); - volumesetting.rightvol = 32767; - } else if (midiPan == 64) { - volumesetting.leftvol = 32767; - volumesetting.rightvol = 32767; - } else { - volumesetting.rightvol = (Bit16s)((127 - midiPan) * 520); - volumesetting.leftvol = 32767; - } - patchTemp->panpot = (Bit8u)(midiPan * 14 / 127); - //synth->printDebug("%s (%s): Set pan to %d", name, currentInstr, panpot); -} - -void RhythmPart::playNote(unsigned int key, int vel) { - if (key < 24 || key > 108)/*> 87 on MT-32)*/ { - synth->printDebug("%s: Attempted to play invalid key %d", name, key); - return; - } - int drumNum = key - 24; - int drumTimbreNum = rhythmTemp[drumNum].timbre; - if (drumTimbreNum >= 127) { // 94 on MT-32 - synth->printDebug("%s: Attempted to play unmapped key %d", name, key); - return; - } - int absTimbreNum = drumTimbreNum + 128; - TimbreParam *timbre = &synth->mt32ram.timbres[absTimbreNum].timbre; - memcpy(currentInstr, timbre->common.name, 10); -#if MT32EMU_MONITOR_INSTRUMENTS == 1 - synth->printDebug("%s (%s): starting poly (drum %d, timbre %d) - Vel %d Key %d", name, currentInstr, drumNum, absTimbreNum, vel, key); -#endif - if (drumCache[drumNum][0].dirty) { - cacheTimbre(drumCache[drumNum], timbre); - } - playPoly(drumCache[drumNum], key, MIDDLEC, vel); -} - -void Part::playNote(unsigned int key, int vel) { - int freqNum = key; - if (freqNum < 12) { - synth->printDebug("%s (%s): Attempted to play invalid key %d < 12; moving up by octave", name, currentInstr, key); - freqNum += 12; - } else if (freqNum > 108) { - synth->printDebug("%s (%s): Attempted to play invalid key %d > 108; moving down by octave", name, currentInstr, key); - while (freqNum > 108) { - freqNum -= 12; - } - } - // POLY1 mode, Single Assign - // Haven't found any software that uses any of the other poly modes - // FIXME:KG: Should this also apply to rhythm? - for (unsigned int i = 0; i < MT32EMU_MAX_POLY; i++) { - if (polyTable[i].isActive() && (polyTable[i].key == key)) { - //AbortPoly(&polyTable[i]); - stopNote(key); - break; - } - } -#if MT32EMU_MONITOR_INSTRUMENTS == 1 - synth->printDebug("%s (%s): starting poly - Vel %d Key %d", name, currentInstr, vel, key); -#endif - if (patchCache[0].dirty) { - cacheTimbre(patchCache, timbreTemp); - } - playPoly(patchCache, key, freqNum, vel); -} - -void Part::playPoly(const PatchCache cache[4], unsigned int key, int freqNum, int vel) { - unsigned int needPartials = cache[0].partialCount; - unsigned int freePartials = synth->partialManager->getFreePartialCount(); - - if (freePartials < needPartials) { - if (!synth->partialManager->freePartials(needPartials - freePartials, partNum)) { - synth->printDebug("%s (%s): Insufficient free partials to play key %d (vel=%d); needed=%d, free=%d", name, currentInstr, key, vel, needPartials, synth->partialManager->getFreePartialCount()); - return; - } - } - // Find free poly - int m; - for (m = 0; m < MT32EMU_MAX_POLY; m++) { - if (!polyTable[m].isActive()) { - break; - } - } - if (m == MT32EMU_MAX_POLY) { - synth->printDebug("%s (%s): No free poly to play key %d (vel %d)", name, currentInstr, key, vel); - return; - } - - dpoly *tpoly = &polyTable[m]; - - tpoly->isPlaying = true; - tpoly->key = key; - tpoly->isDecay = false; - tpoly->freqnum = freqNum; - tpoly->vel = vel; - tpoly->pedalhold = false; - - bool allnull = true; - for (int x = 0; x < 4; x++) { - if (cache[x].playPartial) { - tpoly->partials[x] = synth->partialManager->allocPartial(partNum); - allnull = false; - } else { - tpoly->partials[x] = NULL; - } - } - - if (allnull) - synth->printDebug("%s (%s): No partials to play for this instrument", name, this->currentInstr); - - tpoly->sustain = cache[0].sustain; - tpoly->volumeptr = &volumeMult; - - for (int x = 0; x < 4; x++) { - if (tpoly->partials[x] != NULL) { - tpoly->partials[x]->startPartial(tpoly, &cache[x], tpoly->partials[cache[x].structurePair]); - tpoly->partials[x]->setBend(bend); - } - } -} - -static void startDecayPoly(dpoly *tpoly) { - if (tpoly->isDecay) { - return; - } - tpoly->isDecay = true; - - for (int t = 0; t < 4; t++) { - Partial *partial = tpoly->partials[t]; - if (partial == NULL) - continue; - partial->startDecayAll(); - } - tpoly->isPlaying = false; -} - -void Part::allNotesOff() { - // Note: Unchecked on real MT-32, but the MIDI specification states that all notes off (0x7B) - // should treat the hold pedal as usual. - // All *sound* off (0x78) should stop notes immediately regardless of the hold pedal. - // The latter controller is not implemented on the MT-32 (according to the docs). - for (int q = 0; q < MT32EMU_MAX_POLY; q++) { - dpoly *tpoly = &polyTable[q]; - if (tpoly->isPlaying) { - if (holdpedal) - tpoly->pedalhold = true; - else if (tpoly->sustain) - startDecayPoly(tpoly); - } - } -} - -void Part::allSoundOff() { - for (int q = 0; q < MT32EMU_MAX_POLY; q++) { - dpoly *tpoly = &polyTable[q]; - if (tpoly->isPlaying) { - startDecayPoly(tpoly); - } - } -} - -void Part::stopPedalHold() { - for (int q = 0; q < MT32EMU_MAX_POLY; q++) { - dpoly *tpoly; - tpoly = &polyTable[q]; - if (tpoly->isActive() && tpoly->pedalhold) - stopNote(tpoly->key); - } -} - -void Part::stopNote(unsigned int key) { - // Non-sustaining instruments ignore stop commands. - // They die away eventually anyway - -#if MT32EMU_MONITOR_INSTRUMENTS == 1 - synth->printDebug("%s (%s): stopping key %d", name, currentInstr, key); -#endif - - if (key != 255) { - for (int q = 0; q < MT32EMU_MAX_POLY; q++) { - dpoly *tpoly = &polyTable[q]; - if (tpoly->isPlaying && tpoly->key == key) { - if (holdpedal) - tpoly->pedalhold = true; - else if (tpoly->sustain) - startDecayPoly(tpoly); - } - } - return; - } - - // Find oldest poly... yes, the MT-32 can be reconfigured to kill different poly first - // This is simplest - int oldest = -1; - Bit32u oldage = 0; - - for (int q = 0; q < MT32EMU_MAX_POLY; q++) { - dpoly *tpoly = &polyTable[q]; - - if (tpoly->isPlaying && !tpoly->isDecay) { - if (tpoly->getAge() >= oldage) { - oldage = tpoly->getAge(); - oldest = q; - } - } - } - - if (oldest != -1) { - startDecayPoly(&polyTable[oldest]); - } -} - -} diff --git a/engines/sci/sfx/softseq/mt32/part.h b/engines/sci/sfx/softseq/mt32/part.h deleted file mode 100644 index 54c4999653..0000000000 --- a/engines/sci/sfx/softseq/mt32/part.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_PART_H -#define MT32EMU_PART_H - -namespace MT32Emu { - -class PartialManager; -class Synth; - -class Part { -private: - // Pointers to the areas of the MT-32's memory dedicated to this part (for parts 1-8) - MemParams::PatchTemp *patchTemp; - TimbreParam *timbreTemp; - - // 0=Part 1, .. 7=Part 8, 8=Rhythm - unsigned int partNum; - - bool holdpedal; - - StereoVolume volumesetting; - - PatchCache patchCache[4]; - - float bend; // -1.0 .. +1.0 - - dpoly polyTable[MT32EMU_MAX_POLY]; - - void abortPoly(dpoly *poly); - - static int fixKeyfollow(int srckey); - static int fixBiaslevel(int srcpnt, int *dir); - - void setPatch(const PatchParam *patch); - -protected: - Synth *synth; - char name[8]; // "Part 1".."Part 8", "Rhythm" - char currentInstr[11]; - int expression; - Bit32u volumeMult; - - void updateVolume(); - void backupCacheToPartials(PatchCache cache[4]); - void cacheTimbre(PatchCache cache[4], const TimbreParam *timbre); - void playPoly(const PatchCache cache[4], unsigned int key, int freqNum, int vel); - const char *getName() const; - -public: - Part(Synth *synth, unsigned int usePartNum); - virtual ~Part() {} - virtual void playNote(unsigned int key, int vel); - void stopNote(unsigned int key); - void allNotesOff(); - void allSoundOff(); - int getVolume() const; - void setVolume(int midiVolume); - void setExpression(int midiExpression); - virtual void setPan(unsigned int midiPan); - virtual void setBend(unsigned int midiBend); - virtual void setModulation(unsigned int midiModulation); - virtual void setProgram(unsigned int midiProgram); - void setHoldPedal(bool pedalval); - void stopPedalHold(); - virtual void refresh(); - virtual void refreshTimbre(unsigned int absTimbreNum); - virtual void setTimbre(TimbreParam *timbre); - virtual unsigned int getAbsTimbreNum() const; - const char *getCurrentInstr() const; -}; - -class RhythmPart: public Part { - // Pointer to the area of the MT-32's memory dedicated to rhythm - const MemParams::RhythmTemp *rhythmTemp; - - // This caches the timbres/settings in use by the rhythm part - PatchCache drumCache[85][4]; - StereoVolume drumPan[85]; -public: - RhythmPart(Synth *synth, unsigned int usePartNum); - void refresh(); - void refreshTimbre(unsigned int timbreNum); - void setTimbre(TimbreParam *timbre); - void playNote(unsigned int key, int vel); - unsigned int getAbsTimbreNum() const; - void setPan(unsigned int midiPan); - void setBend(unsigned int midiBend); - void setModulation(unsigned int midiModulation); - void setProgram(unsigned int patchNum); -}; - -} -#endif diff --git a/engines/sci/sfx/softseq/mt32/partial.cpp b/engines/sci/sfx/softseq/mt32/partial.cpp deleted file mode 100644 index 9d32282a82..0000000000 --- a/engines/sci/sfx/softseq/mt32/partial.cpp +++ /dev/null @@ -1,960 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <stdlib.h> -#include <math.h> -#include <string.h> - -#include "mt32emu.h" - -#ifdef MACOSX -// Older versions of Mac OS X didn't supply a powf function. To ensure -// binary compatibility, we force using pow instead of powf (the only -// potential drawback is that it might be a little bit slower). -#define powf pow -#endif - -#define FIXEDPOINT_UDIV(x, y, point) (((x) << (point)) / ((y))) -#define FIXEDPOINT_SDIV(x, y, point) (((x) * (1 << point)) / ((y))) -#define FIXEDPOINT_UMULT(x, y, point) (((x) * (y)) >> point) -#define FIXEDPOINT_SMULT(x, y, point) (((x) * (y)) / (1 << point)) - -using namespace MT32Emu; - -Partial::Partial(Synth *useSynth) { - this->synth = useSynth; - ownerPart = -1; - poly = NULL; - pair = NULL; -#if MT32EMU_ACCURATENOTES == 1 - for (int i = 0; i < 3; i++) { - noteLookupStorage.waveforms[i] = new Bit16s[65536]; - } - noteLookup = ¬eLookupStorage; -#endif -} - -Partial::~Partial() { -#if MT32EMU_ACCURATENOTES == 1 - for (int i = 0; i < 3; i++) { - delete[] noteLookupStorage.waveforms[i]; - } - delete[] noteLookupStorage.wavTable; -#endif -} - -int Partial::getOwnerPart() const { - return ownerPart; -} - -bool Partial::isActive() { - return ownerPart > -1; -} - -const dpoly *Partial::getDpoly() const { - return this->poly; -} - -void Partial::activate(int part) { - // This just marks the partial as being assigned to a part - ownerPart = part; -} - -void Partial::deactivate() { - ownerPart = -1; - if (poly != NULL) { - for (int i = 0; i < 4; i++) { - if (poly->partials[i] == this) { - poly->partials[i] = NULL; - break; - } - } - if (pair != NULL) { - pair->pair = NULL; - } - } -} - -void Partial::initKeyFollow(int key) { - // Setup partial keyfollow - // Note follow relative to middle C - - // Calculate keyfollow for pitch -#if 1 - float rel = key == -1 ? 0.0f : (key - MIDDLEC); - float newPitch = rel * patchCache->pitchKeyfollow + patchCache->pitch + patchCache->pitchShift; - //FIXME:KG: Does it truncate the keyfollowed pitch to a semitone (towards MIDDLEC)? - //int newKey = (int)(rel * patchCache->pitchKeyfollow); - //float newPitch = newKey + patchCache->pitch + patchCache->pitchShift; -#else - float rel = key == -1 ? 0.0f : (key + patchCache->pitchShift - MIDDLEC); - float newPitch = rel * patchCache->pitchKeyfollow + patchCache->pitch; -#endif -#if MT32EMU_ACCURATENOTES == 1 - noteVal = newPitch; - synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f", key, patchCache->pitch, patchCache->pitchKeyfollow, patchCache->pitchShift, newPitch); -#else - float newPitchInt; - float newPitchFract = modff(newPitch, &newPitchInt); - if (newPitchFract > 0.5f) { - newPitchInt += 1.0f; - newPitchFract -= 1.0f; - } - noteVal = (int)newPitchInt; - fineShift = (int)(powf(2.0f, newPitchFract / 12.0f) * 4096.0f); - synth->printDebug("key=%d, pitch=%f, pitchKeyfollow=%f, pitchShift=%f, newPitch=%f, noteVal=%d, fineShift=%d", key, patchCache->pitch, patchCache->pitchKeyfollow, patchCache->pitchShift, newPitch, noteVal, fineShift); -#endif - // FIXME:KG: Raise/lower by octaves until in the supported range. - while (noteVal > HIGHEST_NOTE) // FIXME:KG: see tables.cpp: >108? - noteVal -= 12; - while (noteVal < LOWEST_NOTE) // FIXME:KG: see tables.cpp: <12? - noteVal += 12; - // Calculate keyfollow for filter - int keyfollow = ((key - MIDDLEC) * patchCache->filtkeyfollow) / 4096; - if (keyfollow > 108) - keyfollow = 108; - else if (keyfollow < -108) - keyfollow = -108; - filtVal = synth->tables.tvfKeyfollowMult[keyfollow + 108]; - realVal = synth->tables.tvfKeyfollowMult[(noteVal - MIDDLEC) + 108]; -} - -int Partial::getKey() const { - if (poly == NULL) { - return -1; - } else { - return poly->key; - } -} - -void Partial::startPartial(dpoly *usePoly, const PatchCache *useCache, Partial *pairPartial) { - if (usePoly == NULL || useCache == NULL) { - synth->printDebug("*** Error: Starting partial for owner %d, usePoly=%s, useCache=%s", ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", useCache == NULL ? "*** NULL ***" : "OK"); - return; - } - patchCache = useCache; - poly = usePoly; - mixType = patchCache->structureMix; - structurePosition = patchCache->structurePosition; - - play = true; - initKeyFollow(poly->freqnum); // Initialises noteVal, filtVal and realVal -#if MT32EMU_ACCURATENOTES == 0 - noteLookup = &synth->tables.noteLookups[noteVal - LOWEST_NOTE]; -#else - Tables::initNote(synth, ¬eLookupStorage, noteVal, (float)synth->myProp.sampleRate, synth->masterTune, synth->pcmWaves, NULL); -#endif - keyLookup = &synth->tables.keyLookups[poly->freqnum - 12]; - - if (patchCache->PCMPartial) { - pcmNum = patchCache->pcm; - if (synth->controlROMMap->pcmCount > 128) { - // CM-32L, etc. support two "banks" of PCMs, selectable by waveform type parameter. - if (patchCache->waveform > 1) { - pcmNum += 128; - } - } - pcmWave = &synth->pcmWaves[pcmNum]; - } else { - pcmWave = NULL; - } - - lfoPos = 0; - pulsewidth = patchCache->pulsewidth + synth->tables.pwVelfollowAdd[patchCache->pwsens][poly->vel]; - if (pulsewidth > 100) { - pulsewidth = 100; - } else if (pulsewidth < 0) { - pulsewidth = 0; - } - - for (int e = 0; e < 3; e++) { - envs[e].envpos = 0; - envs[e].envstat = -1; - envs[e].envbase = 0; - envs[e].envdist = 0; - envs[e].envsize = 0; - envs[e].sustaining = false; - envs[e].decaying = false; - envs[e].prevlevel = 0; - envs[e].counter = 0; - envs[e].count = 0; - } - ampEnvVal = 0; - pitchEnvVal = 0; - pitchSustain = false; - loopPos = 0; - partialOff.pcmoffset = partialOff.pcmplace = 0; - pair = pairPartial; - useNoisePair = pairPartial == NULL && (mixType == 1 || mixType == 2); - age = 0; - alreadyOutputed = false; - memset(history,0,sizeof(history)); -} - -Bit16s *Partial::generateSamples(long length) { - if (!isActive() || alreadyOutputed) { - return NULL; - } - if (poly == NULL) { - synth->printDebug("*** ERROR: poly is NULL at Partial::generateSamples()!"); - return NULL; - } - - alreadyOutputed = true; - - // Generate samples - - Bit16s *partialBuf = &myBuffer[0]; - Bit32u volume = *poly->volumeptr; - while (length--) { - Bit32s envval; - Bit32s sample = 0; - if (!envs[EnvelopeType_amp].sustaining) { - if (envs[EnvelopeType_amp].count <= 0) { - Bit32u ampval = getAmpEnvelope(); - if (!play) { - deactivate(); - break; - } - if (ampval > 100) { - ampval = 100; - } - - ampval = synth->tables.volumeMult[ampval]; - ampval = FIXEDPOINT_UMULT(ampval, synth->tables.tvaVelfollowMult[poly->vel][(int)patchCache->ampEnv.velosens], 8); - //if (envs[EnvelopeType_amp].sustaining) - ampEnvVal = ampval; - } - --envs[EnvelopeType_amp].count; - } - - unsigned int lfoShift = 0x1000; - if (pitchSustain) { - // Calculate LFO position - // LFO does not kick in completely until pitch envelope sustains - if (patchCache->lfodepth > 0) { - lfoPos++; - if (lfoPos >= patchCache->lfoperiod) - lfoPos = 0; - int lfoatm = FIXEDPOINT_UDIV(lfoPos, patchCache->lfoperiod, 16); - int lfoatr = synth->tables.sintable[lfoatm]; - lfoShift = synth->tables.lfoShift[patchCache->lfodepth][lfoatr]; - } - } else { - // Calculate Pitch envelope - envval = getPitchEnvelope(); - int pd = patchCache->pitchEnv.depth; - pitchEnvVal = synth->tables.pitchEnvVal[pd][envval]; - } - - int delta; - - // Wrap positions or end if necessary - if (patchCache->PCMPartial) { - // PCM partial - - delta = noteLookup->wavTable[pcmNum]; - int len = pcmWave->len; - if (partialOff.pcmplace >= len) { - if (pcmWave->loop) { - //partialOff.pcmplace = partialOff.pcmoffset = 0; - partialOff.pcmplace %= len; - } else { - play = false; - deactivate(); - break; - } - } - } else { - // Synthesis partial - delta = 0x10000; - partialOff.pcmplace %= (Bit16u)noteLookup->div2; - } - - // Build delta for position of next sample - // Fix delta code - Bit32u tdelta = delta; -#if MT32EMU_ACCURATENOTES == 0 - tdelta = FIXEDPOINT_UMULT(tdelta, fineShift, 12); -#endif - tdelta = FIXEDPOINT_UMULT(tdelta, pitchEnvVal, 12); - tdelta = FIXEDPOINT_UMULT(tdelta, lfoShift, 12); - tdelta = FIXEDPOINT_UMULT(tdelta, bendShift, 12); - delta = (int)tdelta; - - // Get waveform - either PCM or synthesized sawtooth or square - if (ampEnvVal > 0) { - if (patchCache->PCMPartial) { - // Render PCM sample - int ra, rb, dist; - Bit32u taddr; - Bit32u pcmAddr = pcmWave->addr; - if (delta < 0x10000) { - // Linear sound interpolation - taddr = pcmAddr + partialOff.pcmplace; - ra = synth->pcmROMData[taddr]; - taddr++; - if (taddr == pcmAddr + pcmWave->len) { - // Past end of PCM - if (pcmWave->loop) { - rb = synth->pcmROMData[pcmAddr]; - } else { - rb = 0; - } - } else { - rb = synth->pcmROMData[taddr]; - } - dist = rb - ra; - sample = (ra + ((dist * (Bit32s)(partialOff.pcmoffset >> 8)) >> 8)); - } else { - // Sound decimation - // The right way to do it is to use a lowpass filter on the waveform before selecting - // a point. This is too slow. The following approximates this as fast as possible - int idelta = delta >> 16; - taddr = pcmAddr + partialOff.pcmplace; - ra = synth->pcmROMData[taddr++]; - for (int ix = 0; ix < idelta - 1; ix++) { - if (taddr == pcmAddr + pcmWave->len) { - // Past end of PCM - if (pcmWave->loop) { - taddr = pcmAddr; - } else { - // Behave as if all subsequent samples were 0 - break; - } - } - ra += synth->pcmROMData[taddr++]; - } - sample = ra / idelta; - } - } else { - // Render synthesised sample - int toff = partialOff.pcmplace; - int minorplace = partialOff.pcmoffset >> 14; - Bit32s filterInput; - Bit32s filtval = getFiltEnvelope(); - - //synth->printDebug("Filtval: %d", filtval); - - if ((patchCache->waveform & 1) == 0) { - // Square waveform. Made by combining two pregenerated bandlimited - // sawtooth waveforms - Bit32u ofsA = ((toff << 2) + minorplace) % noteLookup->waveformSize[0]; - int width = FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[pulsewidth], 7); - Bit32u ofsB = (ofsA + width) % noteLookup->waveformSize[0]; - Bit16s pa = noteLookup->waveforms[0][ofsA]; - Bit16s pb = noteLookup->waveforms[0][ofsB]; - filterInput = pa - pb; - // Non-bandlimited squarewave - /* - ofs = FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[patchCache->pulsewidth], 8); - if (toff < ofs) - sample = 1 * WGAMP; - else - sample = -1 * WGAMP; - */ - } else { - // Sawtooth. Made by combining the full cosine and half cosine according - // to how it looks on the MT-32. What it really does it takes the - // square wave and multiplies it by a full cosine - int waveoff = (toff << 2) + minorplace; - if (toff < noteLookup->sawTable[pulsewidth]) - filterInput = noteLookup->waveforms[1][waveoff % noteLookup->waveformSize[1]]; - else - filterInput = noteLookup->waveforms[2][waveoff % noteLookup->waveformSize[2]]; - // This is the correct way - // Seems slow to me (though bandlimited) -- doesn't seem to - // sound any better though - /* - //int pw = (patchCache->pulsewidth * pulsemod[filtval]) >> 8; - - Bit32u ofs = toff % (noteLookup->div2 >> 1); - - Bit32u ofs3 = toff + FIXEDPOINT_UMULT(noteLookup->div2, synth->tables.pwFactor[patchCache->pulsewidth], 9); - ofs3 = ofs3 % (noteLookup->div2 >> 1); - - pa = noteLookup->waveforms[0][ofs]; - pb = noteLookup->waveforms[0][ofs3]; - sample = ((pa - pb) * noteLookup->waveforms[2][toff]) / 2; - */ - } - - //Very exact filter - if (filtval > ((FILTERGRAN * 15) / 16)) - filtval = ((FILTERGRAN * 15) / 16); - sample = (Bit32s)(floorf((synth->iirFilter)((float)filterInput, &history[0], synth->tables.filtCoeff[filtval][(int)patchCache->filtEnv.resonance])) / synth->tables.resonanceFactor[patchCache->filtEnv.resonance]); - if (sample < -32768) { - synth->printDebug("Overdriven amplitude for %d: %d:=%d < -32768", patchCache->waveform, filterInput, sample); - sample = -32768; - } - else if (sample > 32767) { - synth->printDebug("Overdriven amplitude for %d: %d:=%d > 32767", patchCache->waveform, filterInput, sample); - sample = 32767; - } - } - } - - // Add calculated delta to our waveform offset - Bit32u absOff = ((partialOff.pcmplace << 16) | partialOff.pcmoffset); - absOff += delta; - partialOff.pcmplace = (Bit16u)((absOff & 0xFFFF0000) >> 16); - partialOff.pcmoffset = (Bit16u)(absOff & 0xFFFF); - - // Put volume envelope over generated sample - sample = FIXEDPOINT_SMULT(sample, ampEnvVal, 9); - sample = FIXEDPOINT_SMULT(sample, volume, 7); - envs[EnvelopeType_amp].envpos++; - envs[EnvelopeType_pitch].envpos++; - envs[EnvelopeType_filt].envpos++; - - *partialBuf++ = (Bit16s)sample; - } - // We may have deactivated and broken out of the loop before the end of the buffer, - // if so then fill the remainder with 0s. - if (++length > 0) - memset(partialBuf, 0, length * 2); - return &myBuffer[0]; -} - -void Partial::setBend(float factor) { - if (!patchCache->useBender || factor == 0.0f) { - bendShift = 4096; - return; - } - // NOTE:KG: We can't do this smoothly with lookup tables, unless we use several MB. - // FIXME:KG: Bend should be influenced by pitch key-follow too, according to docs. - float bendSemitones = factor * patchCache->benderRange; // -24 .. 24 - float mult = powf(2.0f, bendSemitones / 12.0f); - synth->printDebug("setBend(): factor=%f, benderRange=%f, semitones=%f, mult=%f\n", factor, patchCache->benderRange, bendSemitones, mult); - bendShift = (int)(mult * 4096.0f); -} - -Bit16s *Partial::mixBuffers(Bit16s * buf1, Bit16s *buf2, int len) { - if (buf1 == NULL) - return buf2; - if (buf2 == NULL) - return buf1; - - Bit16s *outBuf = buf1; -#if MT32EMU_USE_MMX >= 1 - // KG: This seems to be fine - int donelen = i386_mixBuffers(buf1, buf2, len); - len -= donelen; - buf1 += donelen; - buf2 += donelen; -#endif - while (len--) { - *buf1 = *buf1 + *buf2; - buf1++, buf2++; - } - return outBuf; -} - -Bit16s *Partial::mixBuffersRingMix(Bit16s * buf1, Bit16s *buf2, int len) { - if (buf1 == NULL) - return NULL; - if (buf2 == NULL) { - Bit16s *outBuf = buf1; - while (len--) { - if (*buf1 < -8192) - *buf1 = -8192; - else if (*buf1 > 8192) - *buf1 = 8192; - buf1++; - } - return outBuf; - } - - Bit16s *outBuf = buf1; -#if MT32EMU_USE_MMX >= 1 - // KG: This seems to be fine - int donelen = i386_mixBuffersRingMix(buf1, buf2, len); - len -= donelen; - buf1 += donelen; - buf2 += donelen; -#endif - while (len--) { - float a, b; - a = ((float)*buf1) / 8192.0f; - b = ((float)*buf2) / 8192.0f; - a = (a * b) + a; - if (a>1.0) - a = 1.0; - if (a<-1.0) - a = -1.0; - *buf1 = (Bit16s)(a * 8192.0f); - buf1++; - buf2++; - //buf1[i] = (Bit16s)(((Bit32s)buf1[i] * (Bit32s)buf2[i]) >> 10) + buf1[i]; - } - return outBuf; -} - -Bit16s *Partial::mixBuffersRing(Bit16s * buf1, Bit16s *buf2, int len) { - if (buf1 == NULL) { - return NULL; - } - if (buf2 == NULL) { - return NULL; - } - - Bit16s *outBuf = buf1; -#if MT32EMU_USE_MMX >= 1 - // FIXME:KG: Not really checked as working - int donelen = i386_mixBuffersRing(buf1, buf2, len); - len -= donelen; - buf1 += donelen; - buf2 += donelen; -#endif - while (len--) { - float a, b; - a = ((float)*buf1) / 8192.0f; - b = ((float)*buf2) / 8192.0f; - a *= b; - if (a>1.0) - a = 1.0; - if (a<-1.0) - a = -1.0; - *buf1 = (Bit16s)(a * 8192.0f); - buf1++; - buf2++; - } - return outBuf; -} - -void Partial::mixBuffersStereo(Bit16s *buf1, Bit16s *buf2, Bit16s *outBuf, int len) { - if (buf2 == NULL) { - while (len--) { - *outBuf++ = *buf1++; - *outBuf++ = 0; - } - } else if (buf1 == NULL) { - while (len--) { - *outBuf++ = 0; - *outBuf++ = *buf2++; - } - } else { - while (len--) { - *outBuf++ = *buf1++; - *outBuf++ = *buf2++; - } - } -} - -bool Partial::produceOutput(Bit16s *partialBuf, long length) { - if (!isActive() || alreadyOutputed) - return false; - if (poly == NULL) { - synth->printDebug("*** ERROR: poly is NULL at Partial::produceOutput()!"); - return false; - } - - Bit16s *pairBuf = NULL; - // Check for dependant partial - if (pair != NULL) { - if (!pair->alreadyOutputed) { - // Note: pair may have become NULL after this - pairBuf = pair->generateSamples(length); - } - } else if (useNoisePair) { - // Generate noise for pairless ring mix - pairBuf = synth->tables.noiseBuf; - } - - Bit16s *myBuf = generateSamples(length); - - if (myBuf == NULL && pairBuf == NULL) - return false; - - Bit16s *p1buf, *p2buf; - - if (structurePosition == 0 || pairBuf == NULL) { - p1buf = myBuf; - p2buf = pairBuf; - } else { - p2buf = myBuf; - p1buf = pairBuf; - } - - //synth->printDebug("mixType: %d", mixType); - - Bit16s *mixedBuf; - switch (mixType) { - case 0: - // Standard sound mix - mixedBuf = mixBuffers(p1buf, p2buf, length); - break; - - case 1: - // Ring modulation with sound mix - mixedBuf = mixBuffersRingMix(p1buf, p2buf, length); - break; - - case 2: - // Ring modulation alone - mixedBuf = mixBuffersRing(p1buf, p2buf, length); - break; - - case 3: - // Stereo mixing. One partial to one speaker channel, one to another. - // FIXME:KG: Surely we should be multiplying by the left/right volumes here? - mixBuffersStereo(p1buf, p2buf, partialBuf, length); - return true; - - default: - mixedBuf = mixBuffers(p1buf, p2buf, length); - break; - } - - if (mixedBuf == NULL) - return false; - - Bit16s leftvol, rightvol; - leftvol = patchCache->pansetptr->leftvol; - rightvol = patchCache->pansetptr->rightvol; - -#if MT32EMU_USE_MMX >= 2 - // FIXME:KG: This appears to introduce crackle - int donelen = i386_partialProductOutput(length, leftvol, rightvol, partialBuf, mixedBuf); - length -= donelen; - mixedBuf += donelen; - partialBuf += donelen * 2; -#endif - while (length--) { - *partialBuf++ = (Bit16s)(((Bit32s)*mixedBuf * (Bit32s)leftvol) >> 15); - *partialBuf++ = (Bit16s)(((Bit32s)*mixedBuf * (Bit32s)rightvol) >> 15); - mixedBuf++; - } - return true; -} - -Bit32s Partial::getFiltEnvelope() { - int reshigh; - - int cutoff, depth; - - EnvelopeStatus *tStat = &envs[EnvelopeType_filt]; - - if (tStat->decaying) { - reshigh = tStat->envbase; - reshigh = (reshigh + ((tStat->envdist * tStat->envpos) / tStat->envsize)); - if (tStat->envpos >= tStat->envsize) - reshigh = 0; - } else { - if (tStat->envstat==4) { - reshigh = patchCache->filtsustain; - if (!poly->sustain) { - startDecay(EnvelopeType_filt, reshigh); - } - } else { - if ((tStat->envstat==-1) || (tStat->envpos >= tStat->envsize)) { - if (tStat->envstat==-1) - tStat->envbase = 0; - else - tStat->envbase = patchCache->filtEnv.envlevel[tStat->envstat]; - tStat->envstat++; - tStat->envpos = 0; - if (tStat->envstat == 3) { - tStat->envsize = synth->tables.envTime[(int)patchCache->filtEnv.envtime[tStat->envstat]]; - } else { - Bit32u envTime = (int)patchCache->filtEnv.envtime[tStat->envstat]; - if (tStat->envstat > 1) { - int envDiff = abs(patchCache->filtEnv.envlevel[tStat->envstat] - patchCache->filtEnv.envlevel[tStat->envstat - 1]); - if (envTime > synth->tables.envDeltaMaxTime[envDiff]) { - envTime = synth->tables.envDeltaMaxTime[envDiff]; - } - } - - tStat->envsize = (synth->tables.envTime[envTime] * keyLookup->envTimeMult[(int)patchCache->filtEnv.envtkf]) >> 8; - } - - tStat->envsize++; - tStat->envdist = patchCache->filtEnv.envlevel[tStat->envstat] - tStat->envbase; - } - - reshigh = tStat->envbase; - reshigh = (reshigh + ((tStat->envdist * tStat->envpos) / tStat->envsize)); - - } - tStat->prevlevel = reshigh; - } - - cutoff = patchCache->filtEnv.cutoff; - - //if (patchCache->waveform==1) reshigh = (reshigh * 3) >> 2; - - depth = patchCache->filtEnv.envdepth; - - //int sensedep = (depth * 127-patchCache->filtEnv.envsense) >> 7; - depth = FIXEDPOINT_UMULT(depth, synth->tables.tvfVelfollowMult[poly->vel][(int)patchCache->filtEnv.envsense], 8); - - int bias = patchCache->tvfbias; - int dist; - - if (bias != 0) { - //FIXME:KG: Is this really based on pitch (as now), or key pressed? - //synth->printDebug("Cutoff before %d", cutoff); - if (patchCache->tvfdir == 0) { - if (noteVal < bias) { - dist = bias - noteVal; - cutoff = FIXEDPOINT_UMULT(cutoff, synth->tables.tvfBiasMult[patchCache->tvfblevel][dist], 8); - } - } else { - // > Bias - if (noteVal > bias) { - dist = noteVal - bias; - cutoff = FIXEDPOINT_UMULT(cutoff, synth->tables.tvfBiasMult[patchCache->tvfblevel][dist], 8); - } - - } - //synth->printDebug("Cutoff after %d", cutoff); - } - - depth = (depth * keyLookup->envDepthMult[patchCache->filtEnv.envdkf]) >> 8; - reshigh = (reshigh * depth) >> 7; - - Bit32s tmp; - - cutoff *= filtVal; - cutoff /= realVal; //FIXME:KG: With filter keyfollow 0, this makes no sense. What's correct? - - reshigh *= filtVal; - reshigh /= realVal; //FIXME:KG: As above for cutoff - - if (patchCache->waveform == 1) { - reshigh = (reshigh * 65) / 100; - } - - if (cutoff > 100) - cutoff = 100; - else if (cutoff < 0) - cutoff = 0; - if (reshigh > 100) - reshigh = 100; - else if (reshigh < 0) - reshigh = 0; - tmp = noteLookup->nfiltTable[cutoff][reshigh]; - //tmp *= keyfollow; - //tmp /= realfollow; - - //synth->printDebug("Cutoff %d, tmp %d, freq %d", cutoff, tmp, tmp * 256); - return tmp; -} - -bool Partial::shouldReverb() { - if (!isActive()) - return false; - return patchCache->reverb; -} - -Bit32u Partial::getAmpEnvelope() { - Bit32s tc; - - EnvelopeStatus *tStat = &envs[EnvelopeType_amp]; - - if (!play) - return 0; - - if (tStat->decaying) { - tc = tStat->envbase; - tc += (tStat->envdist * tStat->envpos) / tStat->envsize; - if (tc < 0) - tc = 0; - if ((tStat->envpos >= tStat->envsize) || (tc == 0)) { - play = false; - // Don't have to worry about prevlevel storage or anything, this partial's about to die - return 0; - } - } else { - if ((tStat->envstat == -1) || (tStat->envpos >= tStat->envsize)) { - if (tStat->envstat == -1) - tStat->envbase = 0; - else - tStat->envbase = patchCache->ampEnv.envlevel[tStat->envstat]; - tStat->envstat++; - tStat->envpos = 0; - if (tStat->envstat == 4) { - //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize); - tc = patchCache->ampEnv.envlevel[3]; - if (!poly->sustain) - startDecay(EnvelopeType_amp, tc); - else - tStat->sustaining = true; - goto PastCalc; - } - Bit8u targetLevel = patchCache->ampEnv.envlevel[tStat->envstat]; - tStat->envdist = targetLevel - tStat->envbase; - Bit32u envTime = patchCache->ampEnv.envtime[tStat->envstat]; - if (targetLevel == 0) { - tStat->envsize = synth->tables.envDecayTime[envTime]; - } else { - int envLevelDelta = abs(tStat->envdist); - if (envTime > synth->tables.envDeltaMaxTime[envLevelDelta]) { - envTime = synth->tables.envDeltaMaxTime[envLevelDelta]; - } - tStat->envsize = synth->tables.envTime[envTime]; - } - - // Time keyfollow is used by all sections of the envelope (confirmed on CM-32L) - tStat->envsize = FIXEDPOINT_UMULT(tStat->envsize, keyLookup->envTimeMult[(int)patchCache->ampEnv.envtkf], 8); - - switch (tStat->envstat) { - case 0: - //Spot for velocity time follow - //Only used for first attack - tStat->envsize = FIXEDPOINT_UMULT(tStat->envsize, synth->tables.envTimeVelfollowMult[(int)patchCache->ampEnv.envvkf][poly->vel], 8); - //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize); - break; - case 1: - case 2: - case 3: - //synth->printDebug("Envstat %d, size %d", tStat->envstat, tStat->envsize); - break; - default: - synth->printDebug("Invalid TVA envelope number %d hit!", tStat->envstat); - break; - } - - tStat->envsize++; - - if (tStat->envdist != 0) { - tStat->counter = abs(tStat->envsize / tStat->envdist); - //synth->printDebug("Pos %d, envsize %d envdist %d", tStat->envstat, tStat->envsize, tStat->envdist); - } else { - tStat->counter = 0; - //synth->printDebug("Pos %d, envsize %d envdist %d", tStat->envstat, tStat->envsize, tStat->envdist); - } - } - tc = tStat->envbase; - tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize)); - tStat->count = tStat->counter; -PastCalc: - tc = (tc * (Bit32s)patchCache->ampEnv.level) / 100; - } - - // Prevlevel storage is bottle neck - tStat->prevlevel = tc; - - //Bias level crap stuff now - - for (int i = 0; i < 2; i++) { - if (patchCache->ampblevel[i]!=0) { - int bias = patchCache->ampbias[i]; - if (patchCache->ampdir[i]==0) { - // < Bias - if (noteVal < bias) { - int dist = bias - noteVal; - tc = FIXEDPOINT_UMULT(tc, synth->tables.tvaBiasMult[patchCache->ampblevel[i]][dist], 8); - } - } else { - // > Bias - if (noteVal > bias) { - int dist = noteVal - bias; - tc = FIXEDPOINT_UMULT(tc, synth->tables.tvaBiasMult[patchCache->ampblevel[i]][dist], 8); - } - } - } - } - if (tc < 0) { - synth->printDebug("*** ERROR: tc < 0 (%d) at getAmpEnvelope()", tc); - tc = 0; - } - return (Bit32u)tc; -} - -Bit32s Partial::getPitchEnvelope() { - EnvelopeStatus *tStat = &envs[EnvelopeType_pitch]; - - Bit32s tc; - pitchSustain = false; - if (tStat->decaying) { - if (tStat->envpos >= tStat->envsize) - tc = patchCache->pitchEnv.level[4]; - else { - tc = tStat->envbase; - tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize)); - } - } else { - if (tStat->envstat==3) { - tc = patchCache->pitchsustain; - if (poly->sustain) - pitchSustain = true; - else - startDecay(EnvelopeType_pitch, tc); - } else { - if ((tStat->envstat==-1) || (tStat->envpos >= tStat->envsize)) { - tStat->envstat++; - - tStat->envbase = patchCache->pitchEnv.level[tStat->envstat]; - - Bit32u envTime = patchCache->pitchEnv.time[tStat->envstat]; - int envDiff = abs(patchCache->pitchEnv.level[tStat->envstat] - patchCache->pitchEnv.level[tStat->envstat + 1]); - if (envTime > synth->tables.envDeltaMaxTime[envDiff]) { - envTime = synth->tables.envDeltaMaxTime[envDiff]; - } - - tStat->envsize = (synth->tables.envTime[envTime] * keyLookup->envTimeMult[(int)patchCache->pitchEnv.timekeyfollow]) >> 8; - - tStat->envpos = 0; - tStat->envsize++; - tStat->envdist = patchCache->pitchEnv.level[tStat->envstat + 1] - tStat->envbase; - } - tc = tStat->envbase; - tc = (tc + ((tStat->envdist * tStat->envpos) / tStat->envsize)); - } - tStat->prevlevel = tc; - } - return tc; -} - -void Partial::startDecayAll() { - startDecay(EnvelopeType_amp, envs[EnvelopeType_amp].prevlevel); - startDecay(EnvelopeType_filt, envs[EnvelopeType_filt].prevlevel); - startDecay(EnvelopeType_pitch, envs[EnvelopeType_pitch].prevlevel); - pitchSustain = false; -} - -void Partial::startDecay(EnvelopeType envnum, Bit32s startval) { - EnvelopeStatus *tStat = &envs[envnum]; - - tStat->sustaining = false; - tStat->decaying = true; - tStat->envpos = 0; - tStat->envbase = startval; - - switch (envnum) { - case EnvelopeType_amp: - tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->ampEnv.envtime[4]], keyLookup->envTimeMult[(int)patchCache->ampEnv.envtkf], 8); - tStat->envdist = -startval; - break; - case EnvelopeType_filt: - tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->filtEnv.envtime[4]], keyLookup->envTimeMult[(int)patchCache->filtEnv.envtkf], 8); - tStat->envdist = -startval; - break; - case EnvelopeType_pitch: - tStat->envsize = FIXEDPOINT_UMULT(synth->tables.envDecayTime[(int)patchCache->pitchEnv.time[3]], keyLookup->envTimeMult[(int)patchCache->pitchEnv.timekeyfollow], 8); - tStat->envdist = patchCache->pitchEnv.level[4] - startval; - break; - default: - break; - } - tStat->envsize++; -} diff --git a/engines/sci/sfx/softseq/mt32/partial.h b/engines/sci/sfx/softseq/mt32/partial.h deleted file mode 100644 index 93d8bcd985..0000000000 --- a/engines/sci/sfx/softseq/mt32/partial.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_PARTIAL_H -#define MT32EMU_PARTIAL_H - -namespace MT32Emu { - -class Synth; -struct NoteLookup; - -enum EnvelopeType { - EnvelopeType_amp = 0, - EnvelopeType_filt = 1, - EnvelopeType_pitch = 2 -}; - -struct EnvelopeStatus { - Bit32s envpos; - Bit32s envstat; - Bit32s envbase; - Bit32s envdist; - Bit32s envsize; - - bool sustaining; - bool decaying; - Bit32s prevlevel; - - Bit32s counter; - Bit32s count; -}; - -// Class definition of MT-32 partials. 32 in all. -class Partial { -private: - Synth *synth; - - int ownerPart; // -1 if unassigned - int mixType; - int structurePosition; // 0 or 1 of a structure pair - bool useNoisePair; - - Bit16s myBuffer[MAX_SAMPLE_OUTPUT]; - - // Keyfollowed note value -#if MT32EMU_ACCURATENOTES == 1 - NoteLookup noteLookupStorage; - float noteVal; -#else - int noteVal; - int fineShift; -#endif - const NoteLookup *noteLookup; // LUTs for this noteVal - const KeyLookup *keyLookup; // LUTs for the clamped (12..108) key - - // Keyfollowed filter values - int realVal; - int filtVal; - - // Only used for PCM partials - int pcmNum; - PCMWaveEntry *pcmWave; - - int pulsewidth; - - Bit32u lfoPos; - soundaddr partialOff; - - Bit32u ampEnvVal; - Bit32u pitchEnvVal; - - float history[32]; - - bool pitchSustain; - - int loopPos; - - dpoly *poly; - - int bendShift; - - Bit16s *mixBuffers(Bit16s *buf1, Bit16s *buf2, int len); - Bit16s *mixBuffersRingMix(Bit16s *buf1, Bit16s *buf2, int len); - Bit16s *mixBuffersRing(Bit16s *buf1, Bit16s *buf2, int len); - void mixBuffersStereo(Bit16s *buf1, Bit16s *buf2, Bit16s *outBuf, int len); - - Bit32s getFiltEnvelope(); - Bit32u getAmpEnvelope(); - Bit32s getPitchEnvelope(); - - void initKeyFollow(int freqNum); - -public: - const PatchCache *patchCache; - EnvelopeStatus envs[3]; - bool play; - - PatchCache cachebackup; - - Partial *pair; - bool alreadyOutputed; - Bit32u age; - - Partial(Synth *synth); - ~Partial(); - - int getOwnerPart() const; - int getKey() const; - const dpoly *getDpoly() const; - bool isActive(); - void activate(int part); - void deactivate(void); - void startPartial(dpoly *usePoly, const PatchCache *useCache, Partial *pairPartial); - void startDecay(EnvelopeType envnum, Bit32s startval); - void startDecayAll(); - void setBend(float factor); - bool shouldReverb(); - - // Returns true only if data written to buffer - // This function (unlike the one below it) returns processed stereo samples - // made from combining this single partial with its pair, if it has one. - bool produceOutput(Bit16s * partialBuf, long length); - - // This function produces mono sample output using the partial's private internal buffer - Bit16s *generateSamples(long length); -}; - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/partialManager.cpp b/engines/sci/sfx/softseq/mt32/partialManager.cpp deleted file mode 100644 index 3d3b6302db..0000000000 --- a/engines/sci/sfx/softseq/mt32/partialManager.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <string.h> - -#include "mt32emu.h" - -using namespace MT32Emu; - -PartialManager::PartialManager(Synth *useSynth) { - this->synth = useSynth; - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) - partialTable[i] = new Partial(synth); -} - -PartialManager::~PartialManager(void) { - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) - delete partialTable[i]; -} - -void PartialManager::getPerPartPartialUsage(int usage[9]) { - memset(usage, 0, 9 * sizeof (int)); - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialTable[i]->isActive()) - usage[partialTable[i]->getOwnerPart()]++; - } -} - -void PartialManager::clearAlreadyOutputed() { - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) - partialTable[i]->alreadyOutputed = false; -} - -void PartialManager::ageAll() { - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) - partialTable[i]->age++; -} - -bool PartialManager::shouldReverb(int i) { - return partialTable[i]->shouldReverb(); -} - -bool PartialManager::produceOutput(int i, Bit16s *buffer, Bit32u bufferLength) { - return partialTable[i]->produceOutput(buffer, bufferLength); -} - -void PartialManager::deactivateAll() { - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - partialTable[i]->deactivate(); - } -} - -unsigned int PartialManager::setReserve(Bit8u *rset) { - unsigned int pr = 0; - for (int x = 0; x < 9; x++) { - for (int y = 0; y < rset[x]; y++) { - partialReserveTable[pr] = x; - pr++; - } - } - return pr; -} - -Partial *PartialManager::allocPartial(int partNum) { - Partial *outPartial = NULL; - - // Use the first inactive partial reserved for the specified part (if there are any) - // Otherwise, use the last inactive partial, if any - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (!partialTable[i]->isActive()) { - outPartial = partialTable[i]; - if (partialReserveTable[i] == partNum) - break; - } - } - if (outPartial != NULL) { - outPartial->activate(partNum); - outPartial->age = 0; - } - return outPartial; -} - -unsigned int PartialManager::getFreePartialCount(void) { - int count = 0; - memset(partialPart, 0, sizeof(partialPart)); - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (!partialTable[i]->isActive()) - count++; - else - partialPart[partialTable[i]->getOwnerPart()]++; - } - return count; -} - -/* -bool PartialManager::freePartials(unsigned int needed, int partNum) { - int i; - int myPartPrior = (int)mt32ram.system.reserveSettings[partNum]; - if (myPartPrior<partialPart[partNum]) { - //This can have more parts, must kill off those with less priority - int most, mostPart; - while (needed > 0) { - int selectPart = -1; - //Find the worst offender with more partials than allocated and kill them - most = -1; - mostPart = -1; - int diff; - - for (i=0;i<9;i++) { - diff = partialPart[i] - (int)mt32ram.system.reserveSettings[i]; - - if (diff>0) { - if (diff>most) { - most = diff; - mostPart = i; - } - } - } - selectPart = mostPart; - if (selectPart == -1) { - // All parts are within the allocated limits, you suck - // Look for first partial not of this part that's decaying perhaps? - return false; - } - bool found; - int oldest; - int oldnum; - while (partialPart[selectPart] > (int)mt32ram.system.reserveSettings[selectPart]) { - oldest = -1; - oldnum = -1; - found = false; - for (i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialTable[i]->isActive) { - if (partialTable[i]->ownerPart == selectPart) { - found = true; - if (partialTable[i]->age > oldest) { - oldest = partialTable[i]->age; - oldnum = i; - } - } - } - } - if (!found) break; - partialTable[oldnum]->deactivate(); - --partialPart[selectPart]; - --needed; - } - - } - return true; - - } else { - //This part has reached its max, must kill off its own - bool found; - int oldest; - int oldnum; - while (needed > 0) { - oldest = -1; - oldnum = -1; - found = false; - for (i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialTable[i]->isActive) { - if (partialTable[i]->ownerPart == partNum) { - found = true; - if (partialTable[i]->age > oldest) { - oldest = partialTable[i]->age; - oldnum = i; - } - } - } - } - if (!found) break; - partialTable[oldnum]->deactivate(); - --needed; - } - // Couldn't free enough partials, sorry - if (needed>0) return false; - return true; - } - -} -*/ -bool PartialManager::freePartials(unsigned int needed, int partNum) { - if (needed == 0) { - return true; - } - // Reclaim partials reserved for this part - // Kill those that are already decaying first - /* - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialReserveTable[i] == partNum) { - if (partialTable[i]->ownerPart != partNum) { - if (partialTable[i]->partCache->envs[AMPENV].decaying) { - partialTable[i]->isActive = false; - --needed; - if (needed == 0) - return true; - } - } - } - }*/ - // Then kill those with the lowest part priority -- oldest at the moment - while (needed > 0) { - Bit32u prior = 0; - int priornum = -1; - - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialReserveTable[i] == partNum && partialTable[i]->isActive() && partialTable[i]->getOwnerPart() != partNum) { - /* - if (mt32ram.system.reserveSettings[partialTable[i]->ownerPart] < prior) { - prior = mt32ram.system.reserveSettings[partialTable[i]->ownerPart]; - priornum = i; - }*/ - if (partialTable[i]->age >= prior) { - prior = partialTable[i]->age; - priornum = i; - } - } - } - if (priornum != -1) { - partialTable[priornum]->deactivate(); - --needed; - } else { - break; - } - } - - // Kill off the oldest partials within this part - while (needed > 0) { - Bit32u oldest = 0; - int oldlist = -1; - for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialTable[i]->getOwnerPart() == partNum && partialTable[i]->isActive()) { - if (partialTable[i]->age >= oldest) { - oldest = partialTable[i]->age; - oldlist = i; - } - } - } - if (oldlist != -1) { - partialTable[oldlist]->deactivate(); - --needed; - } else { - break; - } - } - return needed == 0; -} - -const Partial *PartialManager::getPartial(unsigned int partialNum) const { - if (partialNum > MT32EMU_MAX_PARTIALS - 1) - return NULL; - return partialTable[partialNum]; -} diff --git a/engines/sci/sfx/softseq/mt32/partialManager.h b/engines/sci/sfx/softseq/mt32/partialManager.h deleted file mode 100644 index b10f93ff02..0000000000 --- a/engines/sci/sfx/softseq/mt32/partialManager.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_PARTIALMANAGER_H -#define MT32EMU_PARTIALMANAGER_H - -namespace MT32Emu { - -class Synth; - -class PartialManager { -private: - Synth *synth; // Only used for sending debug output - - Partial *partialTable[MT32EMU_MAX_PARTIALS]; - Bit32s partialReserveTable[MT32EMU_MAX_PARTIALS]; - Bit32s partialPart[9]; // The count of partials played per part - -public: - - PartialManager(Synth *synth); - ~PartialManager(); - Partial *allocPartial(int partNum); - unsigned int getFreePartialCount(void); - bool freePartials(unsigned int needed, int partNum); - unsigned int setReserve(Bit8u *rset); - void deactivateAll(); - void ageAll(); - bool produceOutput(int i, Bit16s *buffer, Bit32u bufferLength); - bool shouldReverb(int i); - void clearAlreadyOutputed(); - void getPerPartPartialUsage(int usage[9]); - const Partial *getPartial(unsigned int partialNum) const; -}; - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/structures.h b/engines/sci/sfx/softseq/mt32/structures.h deleted file mode 100644 index ef58c1d20f..0000000000 --- a/engines/sci/sfx/softseq/mt32/structures.h +++ /dev/null @@ -1,284 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_STRUCTURES_H -#define MT32EMU_STRUCTURES_H - -namespace MT32Emu { - -const unsigned int MAX_SAMPLE_OUTPUT = 4096; - -// MT32EMU_MEMADDR() converts from sysex-padded, MT32EMU_SYSEXMEMADDR converts to it -// Roland provides documentation using the sysex-padded addresses, so we tend to use that in code and output -#define MT32EMU_MEMADDR(x) ((((x) & 0x7f0000) >> 2) | (((x) & 0x7f00) >> 1) | ((x) & 0x7f)) -#define MT32EMU_SYSEXMEMADDR(x) ((((x) & 0x1FC000) << 2) | (((x) & 0x3F80) << 1) | ((x) & 0x7f)) - -#ifdef _MSC_VER -#define MT32EMU_ALIGN_PACKED __declspec(align(1)) -typedef unsigned __int64 Bit64u; -typedef signed __int64 Bit64s; -#else -#define MT32EMU_ALIGN_PACKED __attribute__((packed)) -typedef unsigned long long Bit64u; -typedef signed long long Bit64s; -#endif - -typedef unsigned int Bit32u; -typedef signed int Bit32s; -typedef unsigned short int Bit16u; -typedef signed short int Bit16s; -typedef unsigned char Bit8u; -typedef signed char Bit8s; - -// The following structures represent the MT-32's memory -// Since sysex allows this memory to be written to in blocks of bytes, -// we keep this packed so that we can copy data into the various -// banks directly -#if defined(_MSC_VER) || defined (__MINGW32__) -#pragma pack(push, 1) -#else -#pragma pack(1) -#endif - -struct TimbreParam { - struct commonParam { - char name[10]; - Bit8u pstruct12; // 1&2 0-12 (1-13) - Bit8u pstruct34; // #3&4 0-12 (1-13) - Bit8u pmute; // 0-15 (0000-1111) - Bit8u nosustain; // 0-1(Normal, No sustain) - } MT32EMU_ALIGN_PACKED common; - - struct partialParam { - struct wgParam { - Bit8u coarse; // 0-96 (C1,C#1-C9) - Bit8u fine; // 0-100 (-50 to +50 (cents?)) - Bit8u keyfollow; // 0-16 (-1,-1/2,0,1,1/8,1/4,3/8,1/2,5/8,3/4,7/8,1,5/4,3/2,2.s1,s2) - Bit8u bender; // 0,1 (ON/OFF) - Bit8u waveform; // MT-32: 0-1 (SQU/SAW); LAPC-I: WG WAVEFORM/PCM BANK 0 - 3 (SQU/1, SAW/1, SQU/2, SAW/2) - Bit8u pcmwave; // 0-127 (1-128) - Bit8u pulsewid; // 0-100 - Bit8u pwvelo; // 0-14 (-7 - +7) - } MT32EMU_ALIGN_PACKED wg; - - struct envParam { - Bit8u depth; // 0-10 - Bit8u sensitivity; // 1-100 - Bit8u timekeyfollow; // 0-4 - Bit8u time[4]; // 1-100 - Bit8u level[5]; // 1-100 (-50 - +50) - } MT32EMU_ALIGN_PACKED env; - - struct lfoParam { - Bit8u rate; // 0-100 - Bit8u depth; // 0-100 - Bit8u modsense; // 0-100 - } MT32EMU_ALIGN_PACKED lfo; - - struct tvfParam { - Bit8u cutoff; // 0-100 - Bit8u resonance; // 0-30 - Bit8u keyfollow; // 0-16 (-1,-1/2,1/4,0,1,1/8,1/4,3/8,1/2,5/8,3/2,7/8,1,5/4,3/2,2,s1,s2) - Bit8u biaspoint; // 0-127 (<1A-<7C >1A-7C) - Bit8u biaslevel; // 0-14 (-7 - +7) - Bit8u envdepth; // 0-100 - Bit8u envsense; // 0-100 - Bit8u envdkf; // DEPTH KEY FOLL0W 0-4 - Bit8u envtkf; // TIME KEY FOLLOW 0-4 - Bit8u envtime[5]; // 1-100 - Bit8u envlevel[4]; // 1-100 - } MT32EMU_ALIGN_PACKED tvf; - - struct tvaParam { - Bit8u level; // 0-100 - Bit8u velosens; // 0-100 - Bit8u biaspoint1; // 0-127 (<1A-<7C >1A-7C) - Bit8u biaslevel1; // 0-12 (-12 - 0) - Bit8u biaspoint2; // 0-127 (<1A-<7C >1A-7C) - Bit8u biaslevel2; // 0-12 (-12 - 0) - Bit8u envtkf; // TIME KEY FOLLOW 0-4 - Bit8u envvkf; // VELOS KEY FOLL0W 0-4 - Bit8u envtime[5]; // 1-100 - Bit8u envlevel[4]; // 1-100 - } MT32EMU_ALIGN_PACKED tva; - } MT32EMU_ALIGN_PACKED partial[4]; -} MT32EMU_ALIGN_PACKED; - -struct PatchParam { - Bit8u timbreGroup; // TIMBRE GROUP 0-3 (group A, group B, Memory, Rhythm) - Bit8u timbreNum; // TIMBRE NUMBER 0-63 - Bit8u keyShift; // KEY SHIFT 0-48 (-24 - +24 semitones) - Bit8u fineTune; // FINE TUNE 0-100 (-50 - +50 cents) - Bit8u benderRange; // BENDER RANGE 0-24 - Bit8u assignMode; // ASSIGN MODE 0-3 (POLY1, POLY2, POLY3, POLY4) - Bit8u reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON) - Bit8u dummy; // (DUMMY) -} MT32EMU_ALIGN_PACKED; - -struct MemParams { - // NOTE: The MT-32 documentation only specifies PatchTemp areas for parts 1-8. - // The LAPC-I documentation specified an additional area for rhythm at the end, - // where all parameters but fine tune, assign mode and output level are ignored - struct PatchTemp { - PatchParam patch; - Bit8u outlevel; // OUTPUT LEVEL 0-100 - Bit8u panpot; // PANPOT 0-14 (R-L) - Bit8u dummyv[6]; - } MT32EMU_ALIGN_PACKED; - - PatchTemp patchSettings[9]; - - struct RhythmTemp { - Bit8u timbre; // TIMBRE 0-94 (M1-M64,R1-30,OFF) - Bit8u outlevel; // OUTPUT LEVEL 0-100 - Bit8u panpot; // PANPOT 0-14 (R-L) - Bit8u reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON) - } MT32EMU_ALIGN_PACKED; - - RhythmTemp rhythmSettings[85]; - - TimbreParam timbreSettings[8]; - - PatchParam patches[128]; - - // NOTE: There are only 30 timbres in the "rhythm" bank for MT-32; the additional 34 are for LAPC-I and above - struct PaddedTimbre { - TimbreParam timbre; - Bit8u padding[10]; - } MT32EMU_ALIGN_PACKED; - - PaddedTimbre timbres[64 + 64 + 64 + 64]; // Group A, Group B, Memory, Rhythm - - struct SystemArea { - Bit8u masterTune; // MASTER TUNE 0-127 432.1-457.6Hz - Bit8u reverbMode; // REVERB MODE 0-3 (room, hall, plate, tap delay) - Bit8u reverbTime; // REVERB TIME 0-7 (1-8) - Bit8u reverbLevel; // REVERB LEVEL 0-7 (1-8) - Bit8u reserveSettings[9]; // PARTIAL RESERVE (PART 1) 0-32 - Bit8u chanAssign[9]; // MIDI CHANNEL (PART1) 0-16 (1-16,OFF) - Bit8u masterVol; // MASTER VOLUME 0-100 - } MT32EMU_ALIGN_PACKED; - - SystemArea system; -}; - -#if defined(_MSC_VER) || defined (__MINGW32__) -#pragma pack(pop) -#else -#pragma pack() -#endif - -struct PCMWaveEntry { - Bit32u addr; - Bit32u len; - double tune; - bool loop; -}; - -struct soundaddr { - Bit16u pcmplace; - Bit16u pcmoffset; -}; - -struct StereoVolume { - Bit16s leftvol; - Bit16s rightvol; -}; - -// This is basically a per-partial, pre-processed combination of timbre and patch/rhythm settings -struct PatchCache { - bool playPartial; - bool PCMPartial; - int pcm; - char waveform; - int pulsewidth; - int pwsens; - - float pitch; - - int lfodepth; - int lforate; - Bit32u lfoperiod; - int modsense; - - float pitchKeyfollow; - - int filtkeyfollow; - - int tvfbias; - int tvfblevel; - int tvfdir; - - int ampbias[2]; - int ampblevel[2]; - int ampdir[2]; - - int ampdepth; - int amplevel; - - bool useBender; - float benderRange; // 0.0, 1.0, .., 24.0 (semitones) - - TimbreParam::partialParam::envParam pitchEnv; - TimbreParam::partialParam::tvaParam ampEnv; - TimbreParam::partialParam::tvfParam filtEnv; - - Bit32s pitchsustain; - Bit32s filtsustain; - - Bit32u structureMix; - int structurePosition; - int structurePair; - - // The following fields are actually common to all partials in the timbre - bool dirty; - Bit32u partialCount; - bool sustain; - float pitchShift; - bool reverb; - const StereoVolume *pansetptr; -}; - -class Partial; // Forward reference for class defined in partial.h - -struct dpoly { - bool isPlaying; - - unsigned int key; - int freqnum; - int vel; - - bool isDecay; - - const Bit32u *volumeptr; - - Partial *partials[4]; - - bool pedalhold; // This marks keys that have been released on the keyboard, but are being held by the pedal - bool sustain; - - bool isActive() const; - Bit32u getAge() const; -}; - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/synth.cpp b/engines/sci/sfx/softseq/mt32/synth.cpp deleted file mode 100644 index 5ae196dc63..0000000000 --- a/engines/sci/sfx/softseq/mt32/synth.cpp +++ /dev/null @@ -1,1199 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <math.h> -#include <string.h> -#include <stdlib.h> - -#include "mt32emu.h" - -#ifdef MACOSX -// Older versions of Mac OS X didn't supply a powf function. To ensure -// binary compatibility, we force using pow instead of powf (the only -// potential drawback is that it might be a little bit slower). -#define powf pow -#endif - -namespace MT32Emu { - -const int MAX_SYSEX_SIZE = 512; - -const ControlROMMap ControlROMMaps[5] = { - // ID IDc IDbytes PCMmap PCMc tmbrA tmbrAO, tmbrB tmbrBO, tmbrR trC rhythm rhyC rsrv panpot prog - {0x4014, 22, "\000 ver1.04 14 July 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x73A6, 85, 0x57C7, 0x57D0, 0x57E2}, // MT-32 revision 0 - {0x4014, 22, "\000 ver1.06 31 Aug, 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x7414, 85, 0x57D9, 0x57E2, 0x57F4}, // MT-32 revision 0 - {0x4010, 22, "\000 ver1.07 10 Oct, 87 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x73fe, 85, 0x57B1, 0x57BA, 0x57CC}, // MT-32 revision 1 - {0x4010, 22, "\000verX.XX 30 Sep, 88 ", 0x3000, 128, 0x8000, 0x0000, 0xC000, 0x4000, 0x3200, 30, 0x741C, 85, 0x57E5, 0x57EE, 0x5800}, // MT-32 Blue Ridge mod - {0x2205, 22, "\000CM32/LAPC1.02 891205", 0x8100, 256, 0x8000, 0x8000, 0x8080, 0x8000, 0x8500, 64, 0x8580, 85, 0x4F93, 0x4F9C, 0x4FAE} // CM-32L - // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp) -}; - -float iir_filter_normal(float input, float *hist1_ptr, float *coef_ptr) { - float *hist2_ptr; - float output,new_hist; - - hist2_ptr = hist1_ptr + 1; // next history - - // 1st number of coefficients array is overall input scale factor, or filter gain - output = input * (*coef_ptr++); - - output = output - *hist1_ptr * (*coef_ptr++); - new_hist = output - *hist2_ptr * (*coef_ptr++); // poles - - output = new_hist + *hist1_ptr * (*coef_ptr++); - output = output + *hist2_ptr * (*coef_ptr++); // zeros - - *hist2_ptr++ = *hist1_ptr; - *hist1_ptr++ = new_hist; - hist1_ptr++; - hist2_ptr++; - - // i = 1 - output = output - *hist1_ptr * (*coef_ptr++); - new_hist = output - *hist2_ptr * (*coef_ptr++); // poles - - output = new_hist + *hist1_ptr * (*coef_ptr++); - output = output + *hist2_ptr * (*coef_ptr++); // zeros - - *hist2_ptr++ = *hist1_ptr; - *hist1_ptr++ = new_hist; - - return(output); -} - -Bit8u Synth::calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum) { - for (unsigned int i = 0; i < len; i++) { - checksum = checksum + data[i]; - } - checksum = checksum & 0x7f; - if (checksum) - checksum = 0x80 - checksum; - return checksum; -} - -Synth::Synth() { - isOpen = false; - reverbModel = NULL; - partialManager = NULL; - memset(parts, 0, sizeof(parts)); -} - -Synth::~Synth() { - close(); // Make sure we're closed and everything is freed -} - -int Synth::report(ReportType type, const void *data) { - if (myProp.report != NULL) { - return myProp.report(myProp.userData, type, data); - } - return 0; -} - -void Synth::printDebug(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (myProp.printDebug != NULL) { - myProp.printDebug(myProp.userData, fmt, ap); - } else { - vprintf(fmt, ap); - printf("\n"); - } - va_end(ap); -} - -void Synth::initReverb(Bit8u newRevMode, Bit8u newRevTime, Bit8u newRevLevel) { - // FIXME:KG: I don't think it's necessary to recreate the reverbModel... Just set the parameters - if (reverbModel != NULL) - delete reverbModel; - reverbModel = new revmodel(); - - switch (newRevMode) { - case 0: - reverbModel->setroomsize(.1f); - reverbModel->setdamp(.75f); - break; - case 1: - reverbModel->setroomsize(.5f); - reverbModel->setdamp(.5f); - break; - case 2: - reverbModel->setroomsize(.5f); - reverbModel->setdamp(.1f); - break; - case 3: - reverbModel->setroomsize(1.0f); - reverbModel->setdamp(.75f); - break; - default: - reverbModel->setroomsize(.1f); - reverbModel->setdamp(.5f); - break; - } - reverbModel->setdry(1); - reverbModel->setwet((float)newRevLevel / 8.0f); - reverbModel->setwidth((float)newRevTime / 8.0f); -} - -File *Synth::openFile(const char *filename, File::OpenMode mode) { - if (myProp.openFile != NULL) { - return myProp.openFile(myProp.userData, filename, mode); - } - char pathBuf[2048]; - if (myProp.baseDir != NULL) { - strcpy(&pathBuf[0], myProp.baseDir); - strcat(&pathBuf[0], filename); - filename = pathBuf; - } - ANSIFile *file = new ANSIFile(); - if (!file->open(filename, mode)) { - delete file; - return NULL; - } - return file; -} - -void Synth::closeFile(File *file) { - if (myProp.closeFile != NULL) { - myProp.closeFile(myProp.userData, file); - } else { - file->close(); - delete file; - } -} - -bool Synth::loadPreset(File *file) { - bool inSys = false; - Bit8u sysexBuf[MAX_SYSEX_SIZE]; - Bit16u syslen = 0; - bool rc = true; - for (;;) { - Bit8u c; - if (!file->readBit8u(&c)) { - if (!file->isEOF()) { - rc = false; - } - break; - } - sysexBuf[syslen] = c; - if (inSys) { - syslen++; - if (c == 0xF7) { - playSysex(&sysexBuf[0], syslen); - inSys = false; - syslen = 0; - } else if (syslen == MAX_SYSEX_SIZE) { - printDebug("MAX_SYSEX_SIZE (%d) exceeded while processing preset, ignoring message", MAX_SYSEX_SIZE); - inSys = false; - syslen = 0; - } - } else if (c == 0xF0) { - syslen++; - inSys = true; - } - } - return rc; -} - -bool Synth::loadControlROM(const char *filename) { - File *file = openFile(filename, File::OpenMode_read); // ROM File - if (file == NULL) { - return false; - } - bool rc = (file->read(controlROMData, CONTROL_ROM_SIZE) == CONTROL_ROM_SIZE); - - closeFile(file); - if (!rc) - return rc; - - // Control ROM successfully loaded, now check whether it's a known type - controlROMMap = NULL; - for (unsigned int i = 0; i < sizeof (ControlROMMaps) / sizeof (ControlROMMaps[0]); i++) { - if (memcmp(&controlROMData[ControlROMMaps[i].idPos], ControlROMMaps[i].idBytes, ControlROMMaps[i].idLen) == 0) { - controlROMMap = &ControlROMMaps[i]; - return true; - } - } - return false; -} - -bool Synth::loadPCMROM(const char *filename) { - File *file = openFile(filename, File::OpenMode_read); // ROM File - if (file == NULL) { - return false; - } - bool rc = true; - int i; - for (i = 0; i < pcmROMSize; i++) { - Bit8u s; - if (!file->readBit8u(&s)) { - if (!file->isEOF()) { - rc = false; - } - break; - } - Bit8u c; - if (!file->readBit8u(&c)) { - if (!file->isEOF()) { - rc = false; - } else { - printDebug("PCM ROM file has an odd number of bytes! Ignoring last"); - } - break; - } - - short e; - int bit; - int u; - int order[16] = {0, 9, 1 ,2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8}; - - e = 0; - for (u = 0; u < 15; u++) { - if (order[u] < 8) - bit = (s >> (7 - order[u])) & 0x1; - else - bit = (c >> (7 - (order[u] - 8))) & 0x1; - e = e | (short)(bit << (15 - u)); - } - - /* - //Bit16s e = ( ((s & 0x7f) << 4) | ((c & 0x40) << 6) | ((s & 0x80) << 6) | ((c & 0x3f))) << 2; - if (e<0) - e = -32767 - e; - int ut = abs(e); - int dif = 0x7fff - ut; - x = exp(((float)((float)0x8000-(float)dif) / (float)0x1000)); - e = (int)((float)e * (x/3200)); - */ - - // File is companded (dB?), convert to linear PCM - // MINDB = -96 - // MAXDB = -15 - float testval; - testval = (float)((~e) & 0x7fff); - testval = -(testval / 400.00f); - //testval = -(testval / 341.32291666666666666666666666667); - float vol = powf(8, testval / 20) * 32767.0f; - - if (e > 0) - vol = -vol; - - pcmROMData[i] = (Bit16s)vol; - } - if (i != pcmROMSize) { - printDebug("PCM ROM file is too short (expected %d, got %d)", pcmROMSize, i); - rc = false; - } - closeFile(file); - return rc; -} - -bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) { - ControlROMPCMStruct *tps = (ControlROMPCMStruct *)&controlROMData[mapAddress]; - for (int i = 0; i < count; i++) { - int rAddr = tps[i].pos * 0x800; - int rLenExp = (tps[i].len & 0x70) >> 4; - int rLen = 0x800 << rLenExp; - bool rLoop = (tps[i].len & 0x80) != 0; - //Bit8u rFlag = tps[i].len & 0x0F; - Bit16u rTuneOffset = (tps[i].pitchMSB << 8) | tps[i].pitchLSB; - // The number below is confirmed to a reasonable degree of accuracy on CM-32L - double STANDARDFREQ = 442.0; - float rTune = (float)(STANDARDFREQ * pow(2.0, (0x5000 - rTuneOffset) / 4056.0 - 9.0 / 12.0)); - //printDebug("%f,%d,%d", pTune, tps[i].pitchCoarse, tps[i].pitchFine); - if (rAddr + rLen > pcmROMSize) { - printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen); - return false; - } - pcmWaves[i].addr = rAddr; - pcmWaves[i].len = rLen; - pcmWaves[i].loop = rLoop; - pcmWaves[i].tune = rTune; - } - return false; -} - -bool Synth::initRhythmTimbre(int timbreNum, const Bit8u *mem, unsigned int memLen) { - if (memLen < sizeof(TimbreParam::commonParam)) { - return false; - } - TimbreParam *timbre = &mt32ram.timbres[timbreNum].timbre; - memcpy(&timbre->common, mem, 14); - unsigned int memPos = 14; - char drumname[11]; - strncpy(drumname, timbre->common.name, 10); - drumname[10] = 0; - for (int t = 0; t < 4; t++) { - if (((timbre->common.pmute >> t) & 0x1) == 0x1) { - if (memPos + 58 >= memLen) { - return false; - } - memcpy(&timbre->partial[t], mem + memPos, 58); - memPos += 58; - } - } - return true; -} - -bool Synth::initRhythmTimbres(Bit16u mapAddress, Bit16u count) { - const Bit8u *drumMap = &controlROMData[mapAddress]; - int timbreNum = 192; - for (Bit16u i = 0; i < count * 2; i += 2) { - Bit16u address = (drumMap[i + 1] << 8) | drumMap[i]; - /* - // This check is nonsensical when the control ROM is the full 64KB addressable by 16-bit absolute pointers (which it is) - if (address >= CONTROL_ROM_SIZE) { - printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre address 0x%04x", i, address); - return false; - } - */ - if (!initRhythmTimbre(timbreNum++, &controlROMData[address], CONTROL_ROM_SIZE - address)) { - printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre 0x%04x", i, address); - return false; - } - } - return true; -} - -bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int startTimbre) { - for (Bit16u i = mapAddress; i < mapAddress + 0x80; i += 2) { - Bit16u address = (controlROMData[i + 1] << 8) | controlROMData[i]; - if (address + sizeof(TimbreParam) > CONTROL_ROM_SIZE) { - printDebug("Control ROM error: Timbre map entry 0x%04x points to invalid timbre address 0x%04x", i, address); - return false; - } - address = address + offset; - TimbreParam *timbre = &mt32ram.timbres[startTimbre++].timbre; - memcpy(timbre, &controlROMData[address], sizeof(TimbreParam)); - } - return true; -} - -bool Synth::open(SynthProperties &useProp) { - if (isOpen) - return false; - - myProp = useProp; - if (useProp.baseDir != NULL) { - myProp.baseDir = new char[strlen(useProp.baseDir) + 1]; - strcpy(myProp.baseDir, useProp.baseDir); - } - - // This is to help detect bugs - memset(&mt32ram, '?', sizeof(mt32ram)); - - printDebug("Loading Control ROM"); - if (!loadControlROM("CM32L_CONTROL.ROM")) { - if (!loadControlROM("MT32_CONTROL.ROM")) { - printDebug("Init Error - Missing or invalid MT32_CONTROL.ROM"); - report(ReportType_errorControlROM, NULL); - return false; - } - } - - // 512KB PCM ROM for MT-32, etc. - // 1MB PCM ROM for CM-32L, LAPC-I, CM-64, CM-500 - // Note that the size below is given in samples (16-bit), not bytes - pcmROMSize = controlROMMap->pcmCount == 256 ? 512 * 1024 : 256 * 1024; - pcmROMData = new Bit16s[pcmROMSize]; - - printDebug("Loading PCM ROM"); - if (!loadPCMROM("CM32L_PCM.ROM")) { - if (!loadPCMROM("MT32_PCM.ROM")) { - printDebug("Init Error - Missing MT32_PCM.ROM"); - report(ReportType_errorPCMROM, NULL); - return false; - } - } - - printDebug("Initialising Timbre Bank A"); - if (!initTimbres(controlROMMap->timbreAMap, controlROMMap->timbreAOffset, 0)) { - return false; - } - - printDebug("Initialising Timbre Bank B"); - if (!initTimbres(controlROMMap->timbreBMap, controlROMMap->timbreBOffset, 64)) { - return false; - } - - printDebug("Initialising Timbre Bank R"); - if (!initRhythmTimbres(controlROMMap->timbreRMap, controlROMMap->timbreRCount)) { - return false; - } - - printDebug("Initialising Timbre Bank M"); - // CM-64 seems to initialise all bytes in this bank to 0. - memset(&mt32ram.timbres[128], 0, sizeof (mt32ram.timbres[128]) * 64); - - partialManager = new PartialManager(this); - - pcmWaves = new PCMWaveEntry[controlROMMap->pcmCount]; - - printDebug("Initialising PCM List"); - initPCMList(controlROMMap->pcmTable, controlROMMap->pcmCount); - - printDebug("Initialising Rhythm Temp"); - memcpy(mt32ram.rhythmSettings, &controlROMData[controlROMMap->rhythmSettings], controlROMMap->rhythmSettingsCount * 4); - - printDebug("Initialising Patches"); - for (Bit8u i = 0; i < 128; i++) { - PatchParam *patch = &mt32ram.patches[i]; - patch->timbreGroup = i / 64; - patch->timbreNum = i % 64; - patch->keyShift = 24; - patch->fineTune = 50; - patch->benderRange = 12; - patch->assignMode = 0; - patch->reverbSwitch = 1; - patch->dummy = 0; - } - - printDebug("Initialising System"); - // The MT-32 manual claims that "Standard pitch" is 442Hz. - mt32ram.system.masterTune = 0x4A; // Confirmed on CM-64 - mt32ram.system.reverbMode = 0; // Confirmed - mt32ram.system.reverbTime = 5; // Confirmed - mt32ram.system.reverbLevel = 3; // Confirmed - memcpy(mt32ram.system.reserveSettings, &controlROMData[controlROMMap->reserveSettings], 9); // Confirmed - for (Bit8u i = 0; i < 9; i++) { - // This is the default: {1, 2, 3, 4, 5, 6, 7, 8, 9} - // An alternative configuration can be selected by holding "Master Volume" - // and pressing "PART button 1" on the real MT-32's frontpanel. - // The channel assignment is then {0, 1, 2, 3, 4, 5, 6, 7, 9} - mt32ram.system.chanAssign[i] = i + 1; - } - mt32ram.system.masterVol = 100; // Confirmed - if (!refreshSystem()) - return false; - - for (int i = 0; i < 8; i++) { - mt32ram.patchSettings[i].outlevel = 80; - mt32ram.patchSettings[i].panpot = controlROMData[controlROMMap->panSettings + i]; - memset(mt32ram.patchSettings[i].dummyv, 0, sizeof(mt32ram.patchSettings[i].dummyv)); - parts[i] = new Part(this, i); - parts[i]->setProgram(controlROMData[controlROMMap->programSettings + i]); - } - parts[8] = new RhythmPart(this, 8); - - // For resetting mt32 mid-execution - mt32default = mt32ram; - - iirFilter = &iir_filter_normal; - -#ifdef MT32EMU_HAVE_X86 - bool availableSSE = DetectSIMD(); - bool available3DNow = Detect3DNow(); - - if (availableSSE) - report(ReportType_availableSSE, NULL); - if (available3DNow) - report(ReportType_available3DNow, NULL); - - if (available3DNow) { - printDebug("Detected and using SIMD (AMD 3DNow) extensions"); - iirFilter = &iir_filter_3dnow; - report(ReportType_using3DNow, NULL); - } else if (availableSSE) { - printDebug("Detected and using SIMD (Intel SSE) extensions"); - iirFilter = &iir_filter_sse; - report(ReportType_usingSSE, NULL); - } -#endif - - isOpen = true; - isEnabled = false; - - printDebug("*** Initialisation complete ***"); - return true; -} - -void Synth::close(void) { - if (!isOpen) - return; - - tables.freeNotes(); - if (partialManager != NULL) { - delete partialManager; - partialManager = NULL; - } - - if (reverbModel != NULL) { - delete reverbModel; - reverbModel = NULL; - } - - for (int i = 0; i < 9; i++) { - if (parts[i] != NULL) { - delete parts[i]; - parts[i] = NULL; - } - } - if (myProp.baseDir != NULL) { - delete myProp.baseDir; - myProp.baseDir = NULL; - } - - delete[] pcmWaves; - delete[] pcmROMData; - isOpen = false; -} - -void Synth::playMsg(Bit32u msg) { - // FIXME: Implement active sensing - unsigned char code = (unsigned char)((msg & 0x0000F0) >> 4); - unsigned char chan = (unsigned char) (msg & 0x00000F); - unsigned char note = (unsigned char)((msg & 0x00FF00) >> 8); - unsigned char velocity = (unsigned char)((msg & 0xFF0000) >> 16); - isEnabled = true; - - //printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note); - - char part = chantable[chan]; - if (part < 0 || part > 8) { - printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, part, code, velocity); - return; - } - playMsgOnPart(part, code, note, velocity); -} - -void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) { - Bit32u bend; - - //printDebug("Synth::playMsg(0x%02x)",msg); - switch (code) { - case 0x8: - //printDebug("Note OFF - Part %d", part); - // The MT-32 ignores velocity for note off - parts[part]->stopNote(note); - break; - case 0x9: - //printDebug("Note ON - Part %d, Note %d Vel %d", part, note, velocity); - if (velocity == 0) { - // MIDI defines note-on with velocity 0 as being the same as note-off with velocity 40 - parts[part]->stopNote(note); - } else { - parts[part]->playNote(note, velocity); - } - break; - case 0xB: // Control change - switch (note) { - case 0x01: // Modulation - //printDebug("Modulation: %d", velocity); - parts[part]->setModulation(velocity); - break; - case 0x07: // Set volume - //printDebug("Volume set: %d", velocity); - parts[part]->setVolume(velocity); - break; - case 0x0A: // Pan - //printDebug("Pan set: %d", velocity); - parts[part]->setPan(velocity); - break; - case 0x0B: - //printDebug("Expression set: %d", velocity); - parts[part]->setExpression(velocity); - break; - case 0x40: // Hold (sustain) pedal - //printDebug("Hold pedal set: %d", velocity); - parts[part]->setHoldPedal(velocity>=64); - break; - - case 0x79: // Reset all controllers - //printDebug("Reset all controllers"); - //FIXME: Check for accuracy against real thing - parts[part]->setVolume(100); - parts[part]->setExpression(127); - parts[part]->setPan(64); - parts[part]->setBend(0x2000); - parts[part]->setHoldPedal(false); - break; - - case 0x7B: // All notes off - //printDebug("All notes off"); - parts[part]->allNotesOff(); - break; - - default: - printDebug("Unknown MIDI Control code: 0x%02x - vel 0x%02x", note, velocity); - break; - } - - break; - case 0xC: // Program change - //printDebug("Program change %01x", note); - parts[part]->setProgram(note); - break; - case 0xE: // Pitch bender - bend = (velocity << 7) | (note); - //printDebug("Pitch bender %02x", bend); - parts[part]->setBend(bend); - break; - default: - printDebug("Unknown Midi code: 0x%01x - %02x - %02x", code, note, velocity); - break; - } - - //midiOutShortMsg(m_out, msg); -} - -void Synth::playSysex(const Bit8u *sysex, Bit32u len) { - if (len < 2) { - printDebug("playSysex: Message is too short for sysex (%d bytes)", len); - } - if (sysex[0] != 0xF0) { - printDebug("playSysex: Message lacks start-of-sysex (0xF0)"); - return; - } - // Due to some programs (e.g. Java) sending buffers with junk at the end, we have to go through and find the end marker rather than relying on len. - Bit32u endPos; - for (endPos = 1; endPos < len; endPos++) - { - if (sysex[endPos] == 0xF7) - break; - } - if (endPos == len) { - printDebug("playSysex: Message lacks end-of-sysex (0xf7)"); - return; - } - playSysexWithoutFraming(sysex + 1, endPos - 1); -} - -void Synth::playSysexWithoutFraming(const Bit8u *sysex, Bit32u len) { - if (len < 4) { - printDebug("playSysexWithoutFraming: Message is too short (%d bytes)!", len); - return; - } - if (sysex[0] != SYSEX_MANUFACTURER_ROLAND) { - printDebug("playSysexWithoutFraming: Header not intended for this device manufacturer: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]); - return; - } - if (sysex[2] == SYSEX_MDL_D50) { - printDebug("playSysexWithoutFraming: Header is intended for model D-50 (not yet supported): %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]); - return; - } - else if (sysex[2] != SYSEX_MDL_MT32) { - printDebug("playSysexWithoutFraming: Header not intended for model MT-32: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]); - return; - } - playSysexWithoutHeader(sysex[1], sysex[3], sysex + 4, len - 4); -} - -void Synth::playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len) { - if (device > 0x10) { - // We have device ID 0x10 (default, but changeable, on real MT-32), < 0x10 is for channels - printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", (int)device); - return; - } - if (len < 4) { - printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len); - return; - } - unsigned char checksum = calcSysexChecksum(sysex, len - 1, 0); - if (checksum != sysex[len - 1]) { - printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum); - return; - } - len -= 1; // Exclude checksum - switch (command) { - case SYSEX_CMD_DT1: - writeSysex(device, sysex, len); - break; - case SYSEX_CMD_RQ1: - readSysex(device, sysex, len); - break; - default: - printDebug("playSysexWithoutFraming: Unsupported command %02x", command); - return; - } -} - -void Synth::readSysex(unsigned char /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) { -} - -const MemoryRegion memoryRegions[8] = { - {MR_PatchTemp, MT32EMU_MEMADDR(0x030000), sizeof(MemParams::PatchTemp), 9}, - {MR_RhythmTemp, MT32EMU_MEMADDR(0x030110), sizeof(MemParams::RhythmTemp), 85}, - {MR_TimbreTemp, MT32EMU_MEMADDR(0x040000), sizeof(TimbreParam), 8}, - {MR_Patches, MT32EMU_MEMADDR(0x050000), sizeof(PatchParam), 128}, - {MR_Timbres, MT32EMU_MEMADDR(0x080000), sizeof(MemParams::PaddedTimbre), 64 + 64 + 64 + 64}, - {MR_System, MT32EMU_MEMADDR(0x100000), sizeof(MemParams::SystemArea), 1}, - {MR_Display, MT32EMU_MEMADDR(0x200000), MAX_SYSEX_SIZE - 1, 1}, - {MR_Reset, MT32EMU_MEMADDR(0x7F0000), 0x3FFF, 1} -}; - -const int NUM_REGIONS = sizeof(memoryRegions) / sizeof(MemoryRegion); - -void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) { - Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]); - addr = MT32EMU_MEMADDR(addr); - sysex += 3; - len -= 3; - //printDebug("Sysex addr: 0x%06x", MT32EMU_SYSEXMEMADDR(addr)); - // NOTE: Please keep both lower and upper bounds in each check, for ease of reading - - // Process channel-specific sysex by converting it to device-global - if (device < 0x10) { - printDebug("WRITE-CHANNEL: Channel %d temp area 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr)); - if (/*addr >= MT32EMU_MEMADDR(0x000000) && */addr < MT32EMU_MEMADDR(0x010000)) { - int offset; - if (chantable[device] == -1) { - printDebug(" (Channel not mapped to a partial... 0 offset)"); - offset = 0; - } else if (chantable[device] == 8) { - printDebug(" (Channel mapped to rhythm... 0 offset)"); - offset = 0; - } else { - offset = chantable[device] * sizeof(MemParams::PatchTemp); - printDebug(" (Setting extra offset to %d)", offset); - } - addr += MT32EMU_MEMADDR(0x030000) + offset; - } else if (/*addr >= 0x010000 && */ addr < MT32EMU_MEMADDR(0x020000)) { - addr += MT32EMU_MEMADDR(0x030110) - MT32EMU_MEMADDR(0x010000); - } else if (/*addr >= 0x020000 && */ addr < MT32EMU_MEMADDR(0x030000)) { - int offset; - if (chantable[device] == -1) { - printDebug(" (Channel not mapped to a partial... 0 offset)"); - offset = 0; - } else if (chantable[device] == 8) { - printDebug(" (Channel mapped to rhythm... 0 offset)"); - offset = 0; - } else { - offset = chantable[device] * sizeof(TimbreParam); - printDebug(" (Setting extra offset to %d)", offset); - } - addr += MT32EMU_MEMADDR(0x040000) - MT32EMU_MEMADDR(0x020000) + offset; - } else { - printDebug("PlaySysexWithoutHeader: Invalid channel %d address 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr)); - return; - } - } - - // Process device-global sysex (possibly converted from channel-specific sysex above) - for (;;) { - // Find the appropriate memory region - int regionNum; - const MemoryRegion *region = NULL; // Initialised to please compiler - for (regionNum = 0; regionNum < NUM_REGIONS; regionNum++) { - region = &memoryRegions[regionNum]; - if (region->contains(addr)) { - writeMemoryRegion(region, addr, region->getClampedLen(addr, len), sysex); - break; - } - } - if (regionNum == NUM_REGIONS) { - printDebug("Sysex write to unrecognised address %06x, len %d", MT32EMU_SYSEXMEMADDR(addr), len); - break; - } - Bit32u next = region->next(addr, len); - if (next == 0) { - break; - } - addr += next; - sysex += next; - len -= next; - } -} - -void Synth::readMemory(Bit32u addr, Bit32u len, Bit8u *data) { - int regionNum; - const MemoryRegion *region = NULL; - for (regionNum = 0; regionNum < NUM_REGIONS; regionNum++) { - region = &memoryRegions[regionNum]; - if (region->contains(addr)) { - readMemoryRegion(region, addr, len, data); - break; - } - } -} - -void Synth::readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data) { - unsigned int first = region->firstTouched(addr); - //unsigned int last = region->lastTouched(addr, len); - unsigned int off = region->firstTouchedOffset(addr); - len = region->getClampedLen(addr, len); - - unsigned int m; - - switch(region->type) { - case MR_PatchTemp: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.patchSettings[first])[off + m]; - break; - case MR_RhythmTemp: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.rhythmSettings[first])[off + m]; - break; - case MR_TimbreTemp: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.timbreSettings[first])[off + m]; - break; - case MR_Patches: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.patches[first])[off + m]; - break; - case MR_Timbres: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.timbres[first])[off + m]; - break; - case MR_System: - for (m = 0; m < len; m++) - data[m] = ((Bit8u *)&mt32ram.system)[m + off]; - break; - default: - for (m = 0; m < len; m += 2) { - data[m] = 0xff; - if (m + 1 < len) { - data[m+1] = (Bit8u)region->type; - } - } - // TODO: Don't care about the others ATM - break; - } - -} - -void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data) { - unsigned int first = region->firstTouched(addr); - unsigned int last = region->lastTouched(addr, len); - unsigned int off = region->firstTouchedOffset(addr); - switch (region->type) { - case MR_PatchTemp: - for (unsigned int m = 0; m < len; m++) { - ((Bit8u *)&mt32ram.patchSettings[first])[off + m] = data[m]; - } - //printDebug("Patch temp: Patch %d, offset %x, len %d", off/16, off % 16, len); - - for (unsigned int i = first; i <= last; i++) { - int absTimbreNum = mt32ram.patchSettings[i].patch.timbreGroup * 64 + mt32ram.patchSettings[i].patch.timbreNum; - char timbreName[11]; - memcpy(timbreName, mt32ram.timbres[absTimbreNum].timbre.common.name, 10); - timbreName[10] = 0; - printDebug("WRITE-PARTPATCH (%d-%d@%d..%d): %d; timbre=%d (%s), outlevel=%d", first, last, off, off + len, i, absTimbreNum, timbreName, mt32ram.patchSettings[i].outlevel); - if (parts[i] != NULL) { - if (i != 8) { - // Note: Confirmed on CM-64 that we definitely *should* update the timbre here, - // but only in the case that the sysex actually writes to those values - if (i == first && off > 2) { - printDebug(" (Not updating timbre, since those values weren't touched)"); - } else { - parts[i]->setTimbre(&mt32ram.timbres[parts[i]->getAbsTimbreNum()].timbre); - } - } - parts[i]->refresh(); - } - } - break; - case MR_RhythmTemp: - for (unsigned int m = 0; m < len; m++) - ((Bit8u *)&mt32ram.rhythmSettings[first])[off + m] = data[m]; - for (unsigned int i = first; i <= last; i++) { - int timbreNum = mt32ram.rhythmSettings[i].timbre; - char timbreName[11]; - if (timbreNum < 94) { - memcpy(timbreName, mt32ram.timbres[128 + timbreNum].timbre.common.name, 10); - timbreName[10] = 0; - } else { - strcpy(timbreName, "[None]"); - } - printDebug("WRITE-RHYTHM (%d-%d@%d..%d): %d; level=%02x, panpot=%02x, reverb=%02x, timbre=%d (%s)", first, last, off, off + len, i, mt32ram.rhythmSettings[i].outlevel, mt32ram.rhythmSettings[i].panpot, mt32ram.rhythmSettings[i].reverbSwitch, mt32ram.rhythmSettings[i].timbre, timbreName); - } - if (parts[8] != NULL) { - parts[8]->refresh(); - } - break; - case MR_TimbreTemp: - for (unsigned int m = 0; m < len; m++) - ((Bit8u *)&mt32ram.timbreSettings[first])[off + m] = data[m]; - for (unsigned int i = first; i <= last; i++) { - char instrumentName[11]; - memcpy(instrumentName, mt32ram.timbreSettings[i].common.name, 10); - instrumentName[10] = 0; - printDebug("WRITE-PARTTIMBRE (%d-%d@%d..%d): timbre=%d (%s)", first, last, off, off + len, i, instrumentName); - if (parts[i] != NULL) { - parts[i]->refresh(); - } - } - break; - case MR_Patches: - for (unsigned int m = 0; m < len; m++) - ((Bit8u *)&mt32ram.patches[first])[off + m] = data[m]; - for (unsigned int i = first; i <= last; i++) { - PatchParam *patch = &mt32ram.patches[i]; - int patchAbsTimbreNum = patch->timbreGroup * 64 + patch->timbreNum; - char instrumentName[11]; - memcpy(instrumentName, mt32ram.timbres[patchAbsTimbreNum].timbre.common.name, 10); - instrumentName[10] = 0; - Bit8u *n = (Bit8u *)patch; - printDebug("WRITE-PATCH (%d-%d@%d..%d): %d; timbre=%d (%s) %02X%02X%02X%02X%02X%02X%02X%02X", first, last, off, off + len, i, patchAbsTimbreNum, instrumentName, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]); - // FIXME:KG: The below is definitely dodgy. We just guess that this is the patch that the part was using - // based on a timbre match (but many patches could have the same timbre!) - // If this refresh is really correct, we should store the patch number in use by each part. - /* - for (int part = 0; part < 8; part++) { - if (parts[part] != NULL) { - int partPatchAbsTimbreNum = mt32ram.patchSettings[part].patch.timbreGroup * 64 + mt32ram.patchSettings[part].patch.timbreNum; - if (parts[part]->getAbsTimbreNum() == patchAbsTimbreNum) { - parts[part]->setPatch(patch); - parts[part]->RefreshPatch(); - } - } - } - */ - } - break; - case MR_Timbres: - // Timbres - first += 128; - last += 128; - for (unsigned int m = 0; m < len; m++) - ((Bit8u *)&mt32ram.timbres[first])[off + m] = data[m]; - for (unsigned int i = first; i <= last; i++) { - char instrumentName[11]; - memcpy(instrumentName, mt32ram.timbres[i].timbre.common.name, 10); - instrumentName[10] = 0; - printDebug("WRITE-TIMBRE (%d-%d@%d..%d): %d; name=\"%s\"", first, last, off, off + len, i, instrumentName); - // FIXME:KG: Not sure if the stuff below should be done (for rhythm and/or parts)... - // Does the real MT-32 automatically do this? - for (unsigned int part = 0; part < 9; part++) { - if (parts[part] != NULL) { - parts[part]->refreshTimbre(i); - } - } - } - break; - case MR_System: - for (unsigned int m = 0; m < len; m++) - ((Bit8u *)&mt32ram.system)[m + off] = data[m]; - - report(ReportType_devReconfig, NULL); - - printDebug("WRITE-SYSTEM:"); - refreshSystem(); - break; - case MR_Display: - char buf[MAX_SYSEX_SIZE]; - memcpy(&buf, &data[0], len); - buf[len] = 0; - printDebug("WRITE-LCD: %s", buf); - report(ReportType_lcdMessage, buf); - break; - case MR_Reset: - printDebug("RESET"); - report(ReportType_devReset, NULL); - partialManager->deactivateAll(); - mt32ram = mt32default; - for (int i = 0; i < 9; i++) { - parts[i]->refresh(); - } - isEnabled = false; - break; - } -} - -bool Synth::refreshSystem() { - memset(chantable, -1, sizeof(chantable)); - - for (unsigned int i = 0; i < 9; i++) { - //LOG(LOG_MISC|LOG_ERROR,"Part %d set to MIDI channel %d",i,mt32ram.system.chanAssign[i]); - if (mt32ram.system.chanAssign[i] == 16 && parts[i] != NULL) { - parts[i]->allSoundOff(); - } else { - chantable[(int)mt32ram.system.chanAssign[i]] = (char)i; - } - } - //FIXME:KG: This is just an educated guess. - // The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here) - // The MT-32 documentation claims a range of 432.1Hz-457.6Hz - masterTune = 440.0f * powf(2.0f, (mt32ram.system.masterTune - 64.0f) / (128.0f * 12.0f)); - printDebug(" Master Tune: %f", masterTune); - printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel); - report(ReportType_newReverbMode, &mt32ram.system.reverbMode); - report(ReportType_newReverbTime, &mt32ram.system.reverbTime); - report(ReportType_newReverbLevel, &mt32ram.system.reverbLevel); - - if (myProp.useDefaultReverb) { - initReverb(mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel); - } else { - initReverb(myProp.reverbType, myProp.reverbTime, mt32ram.system.reverbLevel); - } - - Bit8u *rset = mt32ram.system.reserveSettings; - printDebug(" Partial reserve: 1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]); - int pr = partialManager->setReserve(rset); - if (pr != 32) - printDebug(" (Partial Reserve Table with less than 32 partials reserved!)"); - rset = mt32ram.system.chanAssign; - printDebug(" Part assign: 1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]); - printDebug(" Master volume: %d", mt32ram.system.masterVol); - masterVolume = (Bit16u)(mt32ram.system.masterVol * 32767 / 100); - if (!tables.init(this, pcmWaves, (float)myProp.sampleRate, masterTune)) { - report(ReportType_errorSampleRate, NULL); - return false; - } - return true; -} - -bool Synth::dumpTimbre(File *file, const TimbreParam *timbre, Bit32u address) { - // Sysex header - if (!file->writeBit8u(0xF0)) - return false; - if (!file->writeBit8u(0x41)) - return false; - if (!file->writeBit8u(0x10)) - return false; - if (!file->writeBit8u(0x16)) - return false; - if (!file->writeBit8u(0x12)) - return false; - - char lsb = (char)(address & 0x7f); - char isb = (char)((address >> 7) & 0x7f); - char msb = (char)(((address >> 14) & 0x7f) | 0x08); - - //Address - if (!file->writeBit8u(msb)) - return false; - if (!file->writeBit8u(isb)) - return false; - if (!file->writeBit8u(lsb)) - return false; - - //Data - if (file->write(timbre, 246) != 246) - return false; - - //Checksum - unsigned char checksum = calcSysexChecksum((const Bit8u *)timbre, 246, msb + isb + lsb); - if (!file->writeBit8u(checksum)) - return false; - - //End of sysex - if (!file->writeBit8u(0xF7)) - return false; - return true; -} - -int Synth::dumpTimbres(const char *filename, int start, int len) { - File *file = openFile(filename, File::OpenMode_write); - if (file == NULL) - return -1; - - for (int timbreNum = start; timbreNum < start + len; timbreNum++) { - int useaddr = (timbreNum - start) * 256; - TimbreParam *timbre = &mt32ram.timbres[timbreNum].timbre; - if (!dumpTimbre(file, timbre, useaddr)) - break; - } - closeFile(file); - return 0; -} - -void ProduceOutput1(Bit16s *useBuf, Bit16s *stream, Bit32u len, Bit16s volume) { -#if MT32EMU_USE_MMX > 2 - //FIXME:KG: This appears to introduce crackle - int donelen = i386_produceOutput1(useBuf, stream, len, volume); - len -= donelen; - stream += donelen * 2; - useBuf += donelen * 2; -#endif - int end = len * 2; - while (end--) { - *stream = *stream + (Bit16s)(((Bit32s)*useBuf++ * (Bit32s)volume)>>15); - stream++; - } -} - -void Synth::render(Bit16s *stream, Bit32u len) { - memset(stream, 0, len * sizeof (Bit16s) * 2); - if (!isEnabled) - return; - while (len > 0) { - Bit32u thisLen = len > MAX_SAMPLE_OUTPUT ? MAX_SAMPLE_OUTPUT : len; - doRender(stream, thisLen); - len -= thisLen; - stream += 2 * thisLen; - } -} - -void Synth::doRender(Bit16s *stream, Bit32u len) { - partialManager->ageAll(); - - if (myProp.useReverb) { - for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialManager->shouldReverb(i)) { - if (partialManager->produceOutput(i, &tmpBuffer[0], len)) { - ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume); - } - } - } - Bit32u m = 0; - for (unsigned int i = 0; i < len; i++) { - sndbufl[i] = (float)stream[m] / 32767.0f; - m++; - sndbufr[i] = (float)stream[m] / 32767.0f; - m++; - } - reverbModel->processreplace(sndbufl, sndbufr, outbufl, outbufr, len, 1); - m=0; - for (unsigned int i = 0; i < len; i++) { - stream[m] = (Bit16s)(outbufl[i] * 32767.0f); - m++; - stream[m] = (Bit16s)(outbufr[i] * 32767.0f); - m++; - } - for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (!partialManager->shouldReverb(i)) { - if (partialManager->produceOutput(i, &tmpBuffer[0], len)) { - ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume); - } - } - } - } else { - for (unsigned int i = 0; i < MT32EMU_MAX_PARTIALS; i++) { - if (partialManager->produceOutput(i, &tmpBuffer[0], len)) - ProduceOutput1(&tmpBuffer[0], stream, len, masterVolume); - } - } - - partialManager->clearAlreadyOutputed(); - -#if MT32EMU_MONITOR_PARTIALS == 1 - samplepos += len; - if (samplepos > myProp.SampleRate * 5) { - samplepos = 0; - int partialUsage[9]; - partialManager->GetPerPartPartialUsage(partialUsage); - printDebug("1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7]); - printDebug("Rhythm: %02d TOTAL: %02d", partialUsage[8], MT32EMU_MAX_PARTIALS - partialManager->GetFreePartialCount()); - } -#endif -} - -const Partial *Synth::getPartial(unsigned int partialNum) const { - return partialManager->getPartial(partialNum); -} - -const Part *Synth::getPart(unsigned int partNum) const { - if (partNum > 8) - return NULL; - return parts[partNum]; -} - -} diff --git a/engines/sci/sfx/softseq/mt32/synth.h b/engines/sci/sfx/softseq/mt32/synth.h deleted file mode 100644 index 9d57c8d3cd..0000000000 --- a/engines/sci/sfx/softseq/mt32/synth.h +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_SYNTH_H -#define MT32EMU_SYNTH_H - -#include <stdarg.h> - -class revmodel; - -namespace MT32Emu { - -class File; -class TableInitialiser; -class Partial; -class PartialManager; -class Part; - -enum ReportType { - // Errors - ReportType_errorControlROM = 1, - ReportType_errorPCMROM, - ReportType_errorSampleRate, - - // Progress - ReportType_progressInit, - - // HW spec - ReportType_availableSSE, - ReportType_available3DNow, - ReportType_usingSSE, - ReportType_using3DNow, - - // General info - ReportType_lcdMessage, - ReportType_devReset, - ReportType_devReconfig, - ReportType_newReverbMode, - ReportType_newReverbTime, - ReportType_newReverbLevel -}; - -struct SynthProperties { - // Sample rate to use in mixing - int sampleRate; - - // Flag to activate reverb. True = use reverb, False = no reverb - bool useReverb; - // True to use software set reverb settings, False to set reverb settings in - // following parameters - bool useDefaultReverb; - // When not using the default settings, this specifies one of the 4 reverb types - // 1 = Room 2 = Hall 3 = Plate 4 = Tap - unsigned char reverbType; - // This specifies the delay time, from 0-7 (not sure of the actual MT-32's measurement) - unsigned char reverbTime; - // This specifies the reverb level, from 0-7 (not sure of the actual MT-32's measurement) - unsigned char reverbLevel; - // The name of the directory in which the ROM and data files are stored (with trailing slash/backslash) - // Not used if "openFile" is set. May be NULL in any case. - char *baseDir; - // This is used as the first argument to all callbacks - void *userData; - // Callback for reporting various errors and information. May be NULL - int (*report)(void *userData, ReportType type, const void *reportData); - // Callback for debug messages, in vprintf() format - void (*printDebug)(void *userData, const char *fmt, va_list list); - // Callback for providing an implementation of File, opened and ready for use - // May be NULL, in which case a default implementation will be used. - File *(*openFile)(void *userData, const char *filename, File::OpenMode mode); - // Callback for closing a File. May be NULL, in which case the File will automatically be close()d/deleted. - void (*closeFile)(void *userData, File *file); -}; - -// This is the specification of the Callback routine used when calling the RecalcWaveforms -// function -typedef void (*recalcStatusCallback)(int percDone); - -// This external function recreates the base waveform file (waveforms.raw) using a specifed -// sampling rate. The callback routine provides interactivity to let the user know what -// percentage is complete in regenerating the waveforms. When a NULL pointer is used as the -// callback routine, no status is reported. -bool RecalcWaveforms(char * baseDir, int sampRate, recalcStatusCallback callBack); - -typedef float (*iir_filter_type)(float input,float *hist1_ptr, float *coef_ptr); - -const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41; - -const Bit8u SYSEX_MDL_MT32 = 0x16; -const Bit8u SYSEX_MDL_D50 = 0x14; - -const Bit8u SYSEX_CMD_RQ1 = 0x11; // Request data #1 -const Bit8u SYSEX_CMD_DT1 = 0x12; // Data set 1 -const Bit8u SYSEX_CMD_WSD = 0x40; // Want to send data -const Bit8u SYSEX_CMD_RQD = 0x41; // Request data -const Bit8u SYSEX_CMD_DAT = 0x42; // Data set -const Bit8u SYSEX_CMD_ACK = 0x43; // Acknowledge -const Bit8u SYSEX_CMD_EOD = 0x45; // End of data -const Bit8u SYSEX_CMD_ERR = 0x4E; // Communications error -const Bit8u SYSEX_CMD_RJC = 0x4F; // Rejection - -const unsigned int CONTROL_ROM_SIZE = 64 * 1024; - -struct ControlROMPCMStruct -{ - Bit8u pos; - Bit8u len; - Bit8u pitchLSB; - Bit8u pitchMSB; -}; - -struct ControlROMMap { - Bit16u idPos; - Bit16u idLen; - const char *idBytes; - Bit16u pcmTable; - Bit16u pcmCount; - Bit16u timbreAMap; - Bit16u timbreAOffset; - Bit16u timbreBMap; - Bit16u timbreBOffset; - Bit16u timbreRMap; - Bit16u timbreRCount; - Bit16u rhythmSettings; - Bit16u rhythmSettingsCount; - Bit16u reserveSettings; - Bit16u panSettings; - Bit16u programSettings; -}; - -enum MemoryRegionType { - MR_PatchTemp, MR_RhythmTemp, MR_TimbreTemp, MR_Patches, MR_Timbres, MR_System, MR_Display, MR_Reset -}; - -class MemoryRegion { -public: - MemoryRegionType type; - Bit32u startAddr, entrySize, entries; - - int lastTouched(Bit32u addr, Bit32u len) const { - return (offset(addr) + len - 1) / entrySize; - } - int firstTouchedOffset(Bit32u addr) const { - return offset(addr) % entrySize; - } - int firstTouched(Bit32u addr) const { - return offset(addr) / entrySize; - } - Bit32u regionEnd() const { - return startAddr + entrySize * entries; - } - bool contains(Bit32u addr) const { - return addr >= startAddr && addr < regionEnd(); - } - int offset(Bit32u addr) const { - return addr - startAddr; - } - Bit32u getClampedLen(Bit32u addr, Bit32u len) const { - if (addr + len > regionEnd()) - return regionEnd() - addr; - return len; - } - Bit32u next(Bit32u addr, Bit32u len) const { - if (addr + len > regionEnd()) { - return regionEnd() - addr; - } - return 0; - } -}; - - -class Synth { -friend class Part; -friend class RhythmPart; -friend class Partial; -friend class Tables; -private: - bool isEnabled; - - iir_filter_type iirFilter; - - PCMWaveEntry *pcmWaves; // Array - - const ControlROMMap *controlROMMap; - Bit8u controlROMData[CONTROL_ROM_SIZE]; - Bit16s *pcmROMData; - int pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM - - Bit8s chantable[32]; - - #if MT32EMU_MONITOR_PARTIALS == 1 - static Bit32s samplepos = 0; - #endif - - Tables tables; - - MemParams mt32ram, mt32default; - - revmodel *reverbModel; - - float masterTune; - Bit16u masterVolume; - - bool isOpen; - - PartialManager *partialManager; - Part *parts[9]; - - Bit16s tmpBuffer[MAX_SAMPLE_OUTPUT * 2]; - float sndbufl[MAX_SAMPLE_OUTPUT]; - float sndbufr[MAX_SAMPLE_OUTPUT]; - float outbufl[MAX_SAMPLE_OUTPUT]; - float outbufr[MAX_SAMPLE_OUTPUT]; - - SynthProperties myProp; - - bool loadPreset(File *file); - void initReverb(Bit8u newRevMode, Bit8u newRevTime, Bit8u newRevLevel); - void doRender(Bit16s * stream, Bit32u len); - - void playAddressedSysex(unsigned char channel, const Bit8u *sysex, Bit32u len); - void readSysex(unsigned char channel, const Bit8u *sysex, Bit32u len); - void writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data); - void readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data); - - bool loadControlROM(const char *filename); - bool loadPCMROM(const char *filename); - bool dumpTimbre(File *file, const TimbreParam *timbre, Bit32u addr); - int dumpTimbres(const char *filename, int start, int len); - - bool initPCMList(Bit16u mapAddress, Bit16u count); - bool initRhythmTimbres(Bit16u mapAddress, Bit16u count); - bool initTimbres(Bit16u mapAddress, Bit16u offset, int startTimbre); - bool initRhythmTimbre(int drumNum, const Bit8u *mem, unsigned int memLen); - bool refreshSystem(); - -protected: - int report(ReportType type, const void *reportData); - File *openFile(const char *filename, File::OpenMode mode); - void closeFile(File *file); - void printDebug(const char *fmt, ...); - -public: - static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum); - - Synth(); - ~Synth(); - - // Used to initialise the MT-32. Must be called before any other function. - // Returns true if initialization was sucessful, otherwise returns false. - bool open(SynthProperties &useProp); - - // Closes the MT-32 and deallocates any memory used by the synthesizer - void close(void); - - // Sends a 4-byte MIDI message to the MT-32 for immediate playback - void playMsg(Bit32u msg); - void playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity); - - // Sends a string of Sysex commands to the MT-32 for immediate interpretation - // The length is in bytes - void playSysex(const Bit8u *sysex, Bit32u len); - void playSysexWithoutFraming(const Bit8u *sysex, Bit32u len); - void playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len); - void writeSysex(unsigned char channel, const Bit8u *sysex, Bit32u len); - - // This callback routine is used to have the MT-32 generate samples to the specified - // output stream. The length is in whole samples, not bytes. (I.E. in 16-bit stereo, - // one sample is 4 bytes) - void render(Bit16s * stream, Bit32u len); - - const Partial *getPartial(unsigned int partialNum) const; - - void readMemory(Bit32u addr, Bit32u len, Bit8u *data); - - // partNum should be 0..7 for Part 1..8, or 8 for Rhythm - const Part *getPart(unsigned int partNum) const; -}; - -} - -#endif diff --git a/engines/sci/sfx/softseq/mt32/tables.cpp b/engines/sci/sfx/softseq/mt32/tables.cpp deleted file mode 100644 index 4591ea22e3..0000000000 --- a/engines/sci/sfx/softseq/mt32/tables.cpp +++ /dev/null @@ -1,749 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "mt32emu.h" - -#ifdef MACOSX -// Older versions of Mac OS X didn't supply a powf function. To ensure -// binary compatibility, we force using pow instead of powf (the only -// potential drawback is that it might be a little bit slower). -#define powf pow -#endif - -#define FIXEDPOINT_MAKE(x, point) ((Bit32u)((1 << point) * x)) - -namespace MT32Emu { - -//Amplitude time velocity follow exponential coefficients -static const double tvcatconst[5] = {0.0, 0.002791309, 0.005942882, 0.012652792, 0.026938637}; -static const double tvcatmult[5] = {1.0, 1.072662811, 1.169129367, 1.288579123, 1.229630539}; - -// These are division constants for the TVF depth key follow -static const Bit32u depexp[5] = {3000, 950, 485, 255, 138}; - -//Envelope time keyfollow exponential coefficients -static const double tkcatconst[5] = {0.0, 0.005853144, 0.011148054, 0.019086143, 0.043333215}; -static const double tkcatmult[5] = {1.0, 1.058245688, 1.048488989, 1.016049301, 1.097538067}; - -// Begin filter stuff - -// Pre-warp the coefficients of a numerator or denominator. -// Note that a0 is assumed to be 1, so there is no wrapping -// of it. -static void prewarp(double *a1, double *a2, double fc, double fs) { - double wp; - - wp = 2.0 * fs * tan(DOUBLE_PI * fc / fs); - - *a2 = *a2 / (wp * wp); - *a1 = *a1 / wp; -} - -// Transform the numerator and denominator coefficients -// of s-domain biquad section into corresponding -// z-domain coefficients. -// -// Store the 4 IIR coefficients in array pointed by coef -// in following order: -// beta1, beta2 (denominator) -// alpha1, alpha2 (numerator) -// -// Arguments: -// a0-a2 - s-domain numerator coefficients -// b0-b2 - s-domain denominator coefficients -// k - filter gain factor. initially set to 1 -// and modified by each biquad section in such -// a way, as to make it the coefficient by -// which to multiply the overall filter gain -// in order to achieve a desired overall filter gain, -// specified in initial value of k. -// fs - sampling rate (Hz) -// coef - array of z-domain coefficients to be filled in. -// -// Return: -// On return, set coef z-domain coefficients -static void bilinear(double a0, double a1, double a2, double b0, double b1, double b2, double *k, double fs, float *coef) { - double ad, bd; - - // alpha (Numerator in s-domain) - ad = 4. * a2 * fs * fs + 2. * a1 * fs + a0; - // beta (Denominator in s-domain) - bd = 4. * b2 * fs * fs + 2. * b1* fs + b0; - - // update gain constant for this section - *k *= ad/bd; - - // Denominator - *coef++ = (float)((2. * b0 - 8. * b2 * fs * fs) / bd); // beta1 - *coef++ = (float)((4. * b2 * fs * fs - 2. * b1 * fs + b0) / bd); // beta2 - - // Nominator - *coef++ = (float)((2. * a0 - 8. * a2 * fs * fs) / ad); // alpha1 - *coef = (float)((4. * a2 * fs * fs - 2. * a1 * fs + a0) / ad); // alpha2 -} - -// a0-a2: numerator coefficients -// b0-b2: denominator coefficients -// fc: Filter cutoff frequency -// fs: sampling rate -// k: overall gain factor -// coef: pointer to 4 iir coefficients -static void szxform(double *a0, double *a1, double *a2, double *b0, double *b1, double *b2, double fc, double fs, double *k, float *coef) { - // Calculate a1 and a2 and overwrite the original values - prewarp(a1, a2, fc, fs); - prewarp(b1, b2, fc, fs); - bilinear(*a0, *a1, *a2, *b0, *b1, *b2, k, fs, coef); -} - -static void initFilter(float fs, float fc, float *icoeff, float Q) { - float *coef; - double a0, a1, a2, b0, b1, b2; - - double k = 1.5; // Set overall filter gain factor - coef = icoeff + 1; // Skip k, or gain - - // Section 1 - a0 = 1.0; - a1 = 0; - a2 = 0; - b0 = 1.0; - b1 = 0.765367 / Q; // Divide by resonance or Q - b2 = 1.0; - szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef); - coef += 4; // Point to next filter section - - // Section 2 - a0 = 1.0; - a1 = 0; - a2 = 0; - b0 = 1.0; - b1 = 1.847759 / Q; - b2 = 1.0; - szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef); - - icoeff[0] = (float)k; -} - -void Tables::initFiltCoeff(float samplerate) { - for (int j = 0; j < FILTERGRAN; j++) { - for (int res = 0; res < 31; res++) { - float tres = resonanceFactor[res]; - initFilter((float)samplerate, (((float)(j+1.0)/FILTERGRAN)) * ((float)samplerate/2), filtCoeff[j][res], tres); - } - } -} - -void Tables::initEnvelopes(float samplerate) { - for (int lf = 0; lf <= 100; lf++) { - float elf = (float)lf; - - // General envelope - // This formula fits observation of the CM-32L by +/- 0.03s or so for the second time value in the filter, - // when all other times were 0 and all levels were 100. Note that variations occur depending on the level - // delta of the section, which we're not fully emulating. - float seconds = powf(2.0f, (elf / 8.0f) + 7.0f) / 32768.0f; - int samples = (int)(seconds * samplerate); - envTime[lf] = samples; - - // Cap on envelope times depending on the level delta - if (elf == 0) { - envDeltaMaxTime[lf] = 63; - } else { - float cap = 11.0f * (float)log(elf) + 64; - if (cap > 100.0f) { - cap = 100.0f; - } - envDeltaMaxTime[lf] = (int)cap; - } - - - // This (approximately) represents the time durations when the target level is 0. - // Not sure why this is a special case, but it's seen to be from the real thing. - seconds = powf(2, (elf / 8.0f) + 6) / 32768.0f; - envDecayTime[lf] = (int)(seconds * samplerate); - - // I am certain of this: Verified by hand LFO log - lfoPeriod[lf] = (Bit32u)(((float)samplerate) / (powf(1.088883372f, (float)lf) * 0.021236044f)); - } -} - -void Tables::initMT32ConstantTables(Synth *synth) { - int lf; - synth->printDebug("Initialising Pitch Tables"); - for (lf = -108; lf <= 108; lf++) { - tvfKeyfollowMult[lf + 108] = (int)(256 * powf(2.0f, (float)(lf / 24.0f))); - //synth->printDebug("KT %d = %d", f, keytable[f+108]); - } - - for (int res = 0; res < 31; res++) { - resonanceFactor[res] = powf((float)res / 30.0f, 5.0f) + 1.0f; - } - - int period = 65536; - - for (int ang = 0; ang < period; ang++) { - int halfang = (period / 2); - int angval = ang % halfang; - float tval = (((float)angval / (float)halfang) - 0.5f) * 2; - if (ang >= halfang) - tval = -tval; - sintable[ang] = (Bit16s)(tval * 50.0f) + 50; - } - - int velt, dep; - float tempdep; - for (velt = 0; velt < 128; velt++) { - for (dep = 0; dep < 5; dep++) { - if (dep > 0) { - float ff = (float)(exp(3.5f * tvcatconst[dep] * (59.0f - (float)velt)) * tvcatmult[dep]); - tempdep = 256.0f * ff; - envTimeVelfollowMult[dep][velt] = (int)tempdep; - //if ((velt % 16) == 0) { - // synth->printDebug("Key %d, depth %d, factor %d", velt, dep, (int)tempdep); - //} - } else - envTimeVelfollowMult[dep][velt] = 256; - } - - for (dep = -7; dep < 8; dep++) { - float fldep = (float)abs(dep) / 7.0f; - fldep = powf(fldep,2.5f); - if (dep < 0) - fldep = fldep * -1.0f; - pwVelfollowAdd[dep+7][velt] = Bit32s((fldep * (float)velt * 100) / 128.0); - } - } - - for (dep = 0; dep <= 100; dep++) { - for (velt = 0; velt < 128; velt++) { - float fdep = (float)dep * 0.000347013f; // Another MT-32 constant - float fv = ((float)velt - 64.0f)/7.26f; - float flogdep = powf(10, fdep * fv); - float fbase; - - if (velt > 64) - synth->tables.tvfVelfollowMult[velt][dep] = (int)(flogdep * 256.0); - else { - //lff = 1 - (pow(((128.0 - (float)lf) / 64.0),.25) * ((float)velt / 96)); - fbase = 1 - (powf(((float)dep / 100.0f),.25f) * ((float)(64-velt) / 96.0f)); - synth->tables.tvfVelfollowMult[velt][dep] = (int)(fbase * 256.0); - } - //synth->printDebug("Filvel dep %d velt %d = %x", dep, velt, filveltable[velt][dep]); - } - } - - for (lf = 0; lf < 128; lf++) { - float veloFract = lf / 127.0f; - for (int velsens = 0; velsens <= 100; velsens++) { - float sensFract = (velsens - 50) / 50.0f; - if (velsens < 50) { - tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, veloFract * -sensFract * 127.0f / 20.0f), 8); - } else { - tvaVelfollowMult[lf][velsens] = FIXEDPOINT_MAKE(1.0f / powf(2.0f, (1.0f - veloFract) * sensFract * 127.0f / 20.0f), 8); - } - } - } - - for (lf = 0; lf <= 100; lf++) { - // Converts the 0-100 range used by the MT-32 to volume multiplier - volumeMult[lf] = FIXEDPOINT_MAKE(powf((float)lf / 100.0f, FLOAT_LN), 7); - } - - for (lf = 0; lf <= 100; lf++) { - float mv = lf / 100.0f; - float pt = mv - 0.5f; - if (pt < 0) - pt = 0; - - // Original (CC version) - //pwFactor[lf] = (int)(pt * 210.04f) + 128; - - // Approximation from sample comparison - pwFactor[lf] = (int)(pt * 179.0f) + 128; - } - - for (unsigned int i = 0; i < MAX_SAMPLE_OUTPUT; i++) { - int myRand; - myRand = rand(); - //myRand = ((myRand - 16383) * 7168) >> 16; - // This one is slower but works with all values of RAND_MAX - myRand = (int)((myRand - RAND_MAX / 2) / (float)RAND_MAX * (7168 / 2)); - //FIXME:KG: Original ultimately set the lowest two bits to 0, for no obvious reason - noiseBuf[i] = (Bit16s)myRand; - } - - float tdist; - float padjtable[51]; - for (lf = 0; lf <= 50; lf++) { - if (lf == 0) - padjtable[lf] = 7; - else if (lf == 1) - padjtable[lf] = 6; - else if (lf == 2) - padjtable[lf] = 5; - else if (lf == 3) - padjtable[lf] = 4; - else if (lf == 4) - padjtable[lf] = 4 - (0.333333f); - else if (lf == 5) - padjtable[lf] = 4 - (0.333333f * 2); - else if (lf == 6) - padjtable[lf] = 3; - else if ((lf > 6) && (lf <= 12)) { - tdist = (lf-6.0f) / 6.0f; - padjtable[lf] = 3.0f - tdist; - } else if ((lf > 12) && (lf <= 25)) { - tdist = (lf - 12.0f) / 13.0f; - padjtable[lf] = 2.0f - tdist; - } else { - tdist = (lf - 25.0f) / 25.0f; - padjtable[lf] = 1.0f - tdist; - } - //synth->printDebug("lf %d = padj %f", lf, padjtable[lf]); - } - - float lfp, depf, finalval, tlf; - int depat, pval, depti; - for (lf = 0; lf <= 10; lf++) { - // I believe the depth is cubed or something - - for (depat = 0; depat <= 100; depat++) { - if (lf > 0) { - depti = abs(depat - 50); - tlf = (float)lf - padjtable[depti]; - if (tlf < 0) - tlf = 0; - lfp = (float)exp(0.713619942f * tlf) / 407.4945111f; - - if (depat < 50) - finalval = 4096.0f * powf(2, -lfp); - else - finalval = 4096.0f * powf(2, lfp); - pval = (int)finalval; - - pitchEnvVal[lf][depat] = pval; - //synth->printDebug("lf %d depat %d pval %d tlf %f lfp %f", lf,depat,pval, tlf, lfp); - } else { - pitchEnvVal[lf][depat] = 4096; - //synth->printDebug("lf %d depat %d pval 4096", lf, depat); - } - } - } - for (lf = 0; lf <= 100; lf++) { - // It's linear - verified on MT-32 - one of the few things linear - lfp = ((float)lf * 0.1904f) / 310.55f; - - for (depat = 0; depat <= 100; depat++) { - depf = ((float)depat - 50.0f) / 50.0f; - //finalval = pow(2, lfp * depf * .5); - finalval = 4096.0f + (4096.0f * lfp * depf); - - pval = (int)finalval; - - lfoShift[lf][depat] = pval; - - //synth->printDebug("lf %d depat %d pval %x", lf,depat,pval); - } - } - - for (lf = 0; lf <= 12; lf++) { - for (int distval = 0; distval < 128; distval++) { - float amplog, dval; - if (lf == 0) { - amplog = 0; - dval = 1; - tvaBiasMult[lf][distval] = 256; - } else { - /* - amplog = powf(1.431817011f, (float)lf) / FLOAT_PI; - dval = ((128.0f - (float)distval) / 128.0f); - amplog = exp(amplog); - dval = powf(amplog, dval) / amplog; - tvaBiasMult[lf][distval] = (int)(dval * 256.0); - */ - // Lets assume for a second it's linear - - // Distance of full volume reduction - amplog = (float)(12.0f / (float)lf) * 24.0f; - if (distval > amplog) { - tvaBiasMult[lf][distval] = 0; - } else { - dval = (amplog - (float)distval) / amplog; - tvaBiasMult[lf][distval] = (int)(dval * 256.0f); - } - } - //synth->printDebug("Ampbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvaBiasMult[lf][distval],amplog); - } - } - - for (lf = 0; lf <= 14; lf++) { - for (int distval = 0; distval < 128; distval++) { - float filval = fabsf((float)((lf - 7) * 12) / 7.0f); - float amplog, dval; - if (lf == 7) { - amplog = 0; - dval = 1; - tvfBiasMult[lf][distval] = 256; - } else { - //amplog = pow(1.431817011, filval) / FLOAT_PI; - amplog = powf(1.531817011f, filval) / FLOAT_PI; - dval = (128.0f - (float)distval) / 128.0f; - amplog = (float)exp(amplog); - dval = powf(amplog,dval)/amplog; - if (lf < 8) { - tvfBiasMult[lf][distval] = (int)(dval * 256.0f); - } else { - dval = powf(dval, 0.3333333f); - if (dval < 0.01f) - dval = 0.01f; - dval = 1 / dval; - tvfBiasMult[lf][distval] = (int)(dval * 256.0f); - } - } - //synth->printDebug("Fbias lf %d distval %d = %f (%x) %f", lf, distval, dval, tvfBiasMult[lf][distval],amplog); - } - } -} - -// Per-note table initialisation follows - -static void initSaw(NoteLookup *noteLookup, Bit32s div2) { - int tmpdiv = div2 << 16; - for (int rsaw = 0; rsaw <= 100; rsaw++) { - float fsaw; - if (rsaw < 50) - fsaw = 50.0f; - else - fsaw = (float)rsaw; - - //(66 - (((A8 - 50) / 50) ^ 0.63) * 50) / 132 - float sawfact = (66.0f - (powf((fsaw - 50.0f) / 50.0f, 0.63f) * 50.0f)) / 132.0f; - noteLookup->sawTable[rsaw] = (int)(sawfact * (float)tmpdiv) >> 16; - //synth->printDebug("F %d divtable %d saw %d sawtable %d", f, div, rsaw, sawtable[f][rsaw]); - } -} - -static void initDep(KeyLookup *keyLookup, float f) { - for (int dep = 0; dep < 5; dep++) { - if (dep == 0) { - keyLookup->envDepthMult[dep] = 256; - keyLookup->envTimeMult[dep] = 256; - } else { - float depfac = 3000.0f; - float ff, tempdep; - depfac = (float)depexp[dep]; - - ff = (f - (float)MIDDLEC) / depfac; - tempdep = powf(2, ff) * 256.0f; - keyLookup->envDepthMult[dep] = (int)tempdep; - - ff = (float)(exp(tkcatconst[dep] * ((float)MIDDLEC - f)) * tkcatmult[dep]); - keyLookup->envTimeMult[dep] = (int)(ff * 256.0f); - } - } - //synth->printDebug("F %f d1 %x d2 %x d3 %x d4 %x d5 %x", f, noteLookup->fildepTable[0], noteLookup->fildepTable[1], noteLookup->fildepTable[2], noteLookup->fildepTable[3], noteLookup->fildepTable[4]); -} - -Bit16s Tables::clampWF(Synth *synth, const char *n, float ampVal, double input) { - Bit32s x = (Bit32s)(input * ampVal); - if (x < -ampVal - 1) { - synth->printDebug("%s==%d<-WGAMP-1!", n, x); - x = (Bit32s)(-ampVal - 1); - } else if (x > ampVal) { - synth->printDebug("%s==%d>WGAMP!", n, x); - x = (Bit32s)ampVal; - } - return (Bit16s)x; -} - -File *Tables::initWave(Synth *synth, NoteLookup *noteLookup, float ampVal, float div2, File *file) { - int iDiv2 = (int)div2; - noteLookup->waveformSize[0] = iDiv2 << 1; - noteLookup->waveformSize[1] = iDiv2 << 1; - noteLookup->waveformSize[2] = iDiv2 << 2; - for (int i = 0; i < 3; i++) { - if (noteLookup->waveforms[i] == NULL) { - noteLookup->waveforms[i] = new Bit16s[noteLookup->waveformSize[i]]; - } - } - if (file != NULL) { - for (int i = 0; i < 3 && file != NULL; i++) { - size_t len = noteLookup->waveformSize[i]; - for (unsigned int j = 0; j < len; j++) { - if (!file->readBit16u((Bit16u *)¬eLookup->waveforms[i][j])) { - synth->printDebug("Error reading wave file cache!"); - file->close(); - file = NULL; - break; - } - } - } - } - if (file == NULL) { - double sd = DOUBLE_PI / div2; - - for (int fa = 0; fa < (iDiv2 << 1); fa++) { - // sa ranges from 0 to 2PI - double sa = fa * sd; - - // Calculate a sample for the bandlimited sawtooth wave - double saw = 0.0; - int sincs = iDiv2 >> 1; - double sinus = 1.0; - for (int sincNum = 1; sincNum <= sincs; sincNum++) { - saw += sin(sinus * sa) / sinus; - sinus++; - } - - // This works pretty well - // Multiplied by 0.84 so that the spikes caused by bandlimiting don't overdrive the amplitude - noteLookup->waveforms[0][fa] = clampWF(synth, "saw", ampVal, -saw / (0.5 * DOUBLE_PI) * 0.84); - noteLookup->waveforms[1][fa] = clampWF(synth, "cos", ampVal, -cos(sa / 2.0)); - noteLookup->waveforms[2][fa * 2] = clampWF(synth, "cosoff_0", ampVal, -cos(sa - DOUBLE_PI)); - noteLookup->waveforms[2][fa * 2 + 1] = clampWF(synth, "cosoff_1", ampVal, -cos((sa + (sd / 2)) - DOUBLE_PI)); - } - } - return file; -} - -static void initFiltTable(NoteLookup *noteLookup, float freq, float rate) { - for (int tr = 0; tr <= 200; tr++) { - float ftr = (float)tr; - - // Verified exact on MT-32 - if (tr > 100) - ftr = 100.0f + (powf((ftr - 100.0f) / 100.0f, 3.0f) * 100.0f); - - // I think this is the one - float brsq = powf(10.0f, (tr / 50.0f) - 1.0f); - noteLookup->filtTable[0][tr] = (int)((freq * brsq) / (rate / 2) * FILTERGRAN); - if (noteLookup->filtTable[0][tr]>=((FILTERGRAN*15)/16)) - noteLookup->filtTable[0][tr] = ((FILTERGRAN*15)/16); - - float brsa = powf(10.0f, ((tr / 55.0f) - 1.0f)) / 2.0f; - noteLookup->filtTable[1][tr] = (int)((freq * brsa) / (rate / 2) * FILTERGRAN); - if (noteLookup->filtTable[1][tr]>=((FILTERGRAN*15)/16)) - noteLookup->filtTable[1][tr] = ((FILTERGRAN*15)/16); - } -} - -static void initNFiltTable(NoteLookup *noteLookup, float freq, float rate) { - for (int cf = 0; cf <= 100; cf++) { - float cfmult = (float)cf; - - for (int tf = 0;tf <= 100; tf++) { - float tfadd = (float)tf; - - //float freqsum = exp((cfmult + tfadd) / 30.0f) / 4.0f; - //float freqsum = 0.15f * exp(0.45f * ((cfmult + tfadd) / 10.0f)); - - float freqsum = powf(2.0f, ((cfmult + tfadd) - 40.0f) / 16.0f); - - noteLookup->nfiltTable[cf][tf] = (int)((freq * freqsum) / (rate / 2) * FILTERGRAN); - if (noteLookup->nfiltTable[cf][tf] >= ((FILTERGRAN * 15) / 16)) - noteLookup->nfiltTable[cf][tf] = ((FILTERGRAN * 15) / 16); - } - } -} - -File *Tables::initNote(Synth *synth, NoteLookup *noteLookup, float note, float rate, float masterTune, PCMWaveEntry *pcmWaves, File *file) { - float freq = (float)(masterTune * pow(2.0, ((double)note - MIDDLEA) / 12.0)); - float div2 = rate * 2.0f / freq; - noteLookup->div2 = (int)div2; - - if (noteLookup->div2 == 0) - noteLookup->div2 = 1; - - initSaw(noteLookup, noteLookup->div2); - - //synth->printDebug("Note %f; freq=%f, div=%f", note, freq, rate / freq); - file = initWave(synth, noteLookup, (const float)WGAMP, div2, file); - - // Create the pitch tables - if (noteLookup->wavTable == NULL) - noteLookup->wavTable = new Bit32u[synth->controlROMMap->pcmCount]; - double rateMult = 32000.0 / rate; - double tuner = freq * 65536.0f; - for (int pc = 0; pc < synth->controlROMMap->pcmCount; pc++) { - noteLookup->wavTable[pc] = (int)(tuner / pcmWaves[pc].tune * rateMult); - } - - initFiltTable(noteLookup, freq, rate); - initNFiltTable(noteLookup, freq, rate); - return file; -} - -bool Tables::initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float masterTune) { - const char *NoteNames[12] = { - "C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B " - }; - char filename[64]; - int intRate = (int)rate; - char version[4] = {0, 0, 0, 5}; - sprintf(filename, "waveformcache-%d-%.2f.raw", intRate, masterTune); - - File *file = NULL; - char header[20]; - strncpy(header, "MT32WAVE", 8); - int pos = 8; - // Version... - for (int i = 0; i < 4; i++) - header[pos++] = version[i]; - header[pos++] = (char)((intRate >> 24) & 0xFF); - header[pos++] = (char)((intRate >> 16) & 0xFF); - header[pos++] = (char)((intRate >> 8) & 0xFF); - header[pos++] = (char)(intRate & 0xFF); - int intTuning = (int)masterTune; - header[pos++] = (char)((intTuning >> 8) & 0xFF); - header[pos++] = (char)(intTuning & 0xFF); - header[pos++] = 0; - header[pos] = (char)((masterTune - intTuning) * 10); -#if MT32EMU_WAVECACHEMODE < 2 - bool reading = false; - file = synth->openFile(filename, File::OpenMode_read); - if (file != NULL) { - char fileHeader[20]; - if (file->read(fileHeader, 20) == 20) { - if (memcmp(fileHeader, header, 20) == 0) { - Bit16u endianCheck; - if (file->readBit16u(&endianCheck)) { - if (endianCheck == 1) { - reading = true; - } else { - synth->printDebug("Endian check in %s does not match expected", filename); - } - } else { - synth->printDebug("Unable to read endian check in %s", filename); - } - } else { - synth->printDebug("Header of %s does not match expected", filename); - } - } else { - synth->printDebug("Error reading 16 bytes of %s", filename); - } - if (!reading) { - file->close(); - file = NULL; - } - } else { - synth->printDebug("Unable to open %s for reading", filename); - } -#endif - - float progress = 0.0f; - bool abort = false; - synth->report(ReportType_progressInit, &progress); - for (int f = LOWEST_NOTE; f <= HIGHEST_NOTE; f++) { - synth->printDebug("Initialising note %s%d", NoteNames[f % 12], (f / 12) - 2); - NoteLookup *noteLookup = ¬eLookups[f - LOWEST_NOTE]; - file = initNote(synth, noteLookup, (float)f, rate, masterTune, pcmWaves, file); - progress = (f - LOWEST_NOTE + 1) / (float)NUM_NOTES; - abort = synth->report(ReportType_progressInit, &progress) != 0; - if (abort) - break; - } - -#if MT32EMU_WAVECACHEMODE == 0 || MT32EMU_WAVECACHEMODE == 2 - if (file == NULL) { - file = synth->openFile(filename, File::OpenMode_write); - if (file != NULL) { - if (file->write(header, 20) == 20 && file->writeBit16u(1)) { - for (int f = 0; f < NUM_NOTES; f++) { - for (int i = 0; i < 3 && file != NULL; i++) { - int len = noteLookups[f].waveformSize[i]; - for (int j = 0; j < len; j++) { - if (!file->writeBit16u(noteLookups[f].waveforms[i][j])) { - synth->printDebug("Error writing waveform cache file"); - file->close(); - file = NULL; - break; - } - } - } - } - } else { - synth->printDebug("Error writing 16-byte header to %s - won't continue saving", filename); - } - } else { - synth->printDebug("Unable to open %s for writing - won't be created", filename); - } - } -#endif - - if (file != NULL) - synth->closeFile(file); - return !abort; -} - -void Tables::freeNotes() { - for (int t = 0; t < 3; t++) { - for (int m = 0; m < NUM_NOTES; m++) { - if (noteLookups[m].waveforms[t] != NULL) { - delete[] noteLookups[m].waveforms[t]; - noteLookups[m].waveforms[t] = NULL; - noteLookups[m].waveformSize[t] = 0; - } - if (noteLookups[m].wavTable != NULL) { - delete[] noteLookups[m].wavTable; - noteLookups[m].wavTable = NULL; - } - } - } - initialisedMasterTune = 0.0f; -} - -Tables::Tables() { - initialisedSampleRate = 0.0f; - initialisedMasterTune = 0.0f; - memset(¬eLookups, 0, sizeof(noteLookups)); -} - -bool Tables::init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune) { - if (sampleRate <= 0.0f) { - synth->printDebug("Bad sampleRate (%d <= 0.0f)", sampleRate); - return false; - } - if (initialisedSampleRate == 0.0f) { - initMT32ConstantTables(synth); - } - if (initialisedSampleRate != sampleRate) { - initFiltCoeff(sampleRate); - initEnvelopes(sampleRate); - for (int key = 12; key <= 108; key++) { - initDep(&keyLookups[key - 12], (float)key); - } - } - if (initialisedSampleRate != sampleRate || initialisedMasterTune != masterTune) { - freeNotes(); - if (!initNotes(synth, pcmWaves, sampleRate, masterTune)) { - return false; - } - initialisedSampleRate = sampleRate; - initialisedMasterTune = masterTune; - } - return true; -} - -} diff --git a/engines/sci/sfx/softseq/mt32/tables.h b/engines/sci/sfx/softseq/mt32/tables.h deleted file mode 100644 index d9af5114b2..0000000000 --- a/engines/sci/sfx/softseq/mt32/tables.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Copyright (c) 2003-2005 Various contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef MT32EMU_TABLES_H -#define MT32EMU_TABLES_H - -namespace MT32Emu { - -// Mathematical constants -const double DOUBLE_PI = 3.1415926535897932384626433832795; -const double DOUBLE_LN = 2.3025850929940456840179914546844; -const float FLOAT_PI = 3.1415926535897932384626433832795f; -const float FLOAT_LN = 2.3025850929940456840179914546844f; - -// Filter settings -const int FILTERGRAN = 512; - -// Amplitude of waveform generator -// FIXME: This value is the amplitude possible whilst avoiding -// overdriven values immediately after filtering when playing -// back SQ3MT.MID. Needs to be checked. -const int WGAMP = 12382; - -const int MIDDLEC = 60; -const int MIDDLEA = 69; // By this I mean "A above middle C" - -// FIXME:KG: may only need to do 12 to 108 -// 12..108 is the range allowed by note on commands, but the key can be modified by pitch keyfollow -// and adjustment for timbre pitch, so the results can be outside that range. -// Should we move it (by octave) into the 12..108 range, or keep it in 0..127 range, -// or something else altogether? -const int LOWEST_NOTE = 12; -const int HIGHEST_NOTE = 127; -const int NUM_NOTES = HIGHEST_NOTE - LOWEST_NOTE + 1; // Number of slots for note LUT - -class Synth; - -struct NoteLookup { - Bit32u div2; - Bit32u *wavTable; - Bit32s sawTable[101]; - int filtTable[2][201]; - int nfiltTable[101][101]; - Bit16s *waveforms[3]; - Bit32u waveformSize[3]; -}; - -struct KeyLookup { - Bit32s envTimeMult[5]; // For envelope time adjustment for key pressed - Bit32s envDepthMult[5]; -}; - -class Tables { - float initialisedSampleRate; - float initialisedMasterTune; - void initMT32ConstantTables(Synth *synth); - static Bit16s clampWF(Synth *synth, const char *n, float ampVal, double input); - static File *initWave(Synth *synth, NoteLookup *noteLookup, float ampsize, float div2, File *file); - bool initNotes(Synth *synth, PCMWaveEntry *pcmWaves, float rate, float tuning); - void initEnvelopes(float sampleRate); - void initFiltCoeff(float samplerate); -public: - // Constant LUTs - Bit32s tvfKeyfollowMult[217]; - Bit32s tvfVelfollowMult[128][101]; - Bit32s tvfBiasMult[15][128]; - Bit32u tvaVelfollowMult[128][101]; - Bit32s tvaBiasMult[13][128]; - Bit16s noiseBuf[MAX_SAMPLE_OUTPUT]; - Bit16s sintable[65536]; - Bit32s pitchEnvVal[16][101]; - Bit32s envTimeVelfollowMult[5][128]; - Bit32s pwVelfollowAdd[15][128]; - float resonanceFactor[31]; - Bit32u lfoShift[101][101]; - Bit32s pwFactor[101]; - Bit32s volumeMult[101]; - - // LUTs varying with sample rate - Bit32u envTime[101]; - Bit32u envDeltaMaxTime[101]; - Bit32u envDecayTime[101]; - Bit32u lfoPeriod[101]; - float filtCoeff[FILTERGRAN][31][8]; - - // Various LUTs for each note and key - NoteLookup noteLookups[NUM_NOTES]; - KeyLookup keyLookups[97]; - - Tables(); - bool init(Synth *synth, PCMWaveEntry *pcmWaves, float sampleRate, float masterTune); - File *initNote(Synth *synth, NoteLookup *noteLookup, float note, float rate, float tuning, PCMWaveEntry *pcmWaves, File *file); - void freeNotes(); -}; - -} - -#endif |