Esempio n. 1
0
void
scir_unlock_resource(resource_mgr_t *mgr, resource_t *res, int resnum, int restype)
{
	if (!res) {
		sciprintf("Resmgr: Warning: Attempt to unlock non-existant"
			  " resource %s.%03d!\n",
			  sci_resource_types[restype], resnum);
		return;
	}

	if (res->status != SCI_STATUS_LOCKED) {
		sciprintf("Resmgr: Warning: Attempt to unlock unlocked"
			  " resource %s.%03d\n",
			  sci_resource_types[res->type], res->number);
		return;
	}

	if (!--res->lockers) { /* No more lockers? */
		res->status = SCI_STATUS_ALLOCATED;
		mgr->memory_locked -= res->size;
		_scir_add_to_lru(mgr, res);
	}

	_scir_free_old_resources(mgr, 0);
}
Esempio n. 2
0
static void
print_map_mem(int sci, int ins, int rhythm, char *mt32)
{
#ifdef DEBUG_MT32_TO_GM
	char name[11];

	strncpy(name, mt32, 10);
	name[10] = 0;

	if (ins == SFX_UNMAPPED || (ins == SFX_MAPPED_TO_RHYTHM && rhythm == SFX_UNMAPPED)) {
		sciprintf("[MT32-to-GM] No mapping available for [%i] `%s'\n",
			  sci, name);
		return;
	}

	if (ins == SFX_MAPPED_TO_RHYTHM) {
		sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' [R] (%i)\n",
			  sci, name, GM_Percussion_Names[rhythm], rhythm);
		return;
	}

	sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n",
		  sci, name, GM_Instrument_Names[ins], ins);
#endif
}
Esempio n. 3
0
resource_t *
scir_find_resource(resource_mgr_t *mgr, int type, int number, int lock)
{
	resource_t *retval;

	if (number >= sci_max_resource_nr[mgr->sci_version]) {
		int modded_number = number % sci_max_resource_nr[mgr->sci_version];
		sciprintf("[resmgr] Requested invalid resource %s.%d, mapped to %s.%d\n",
			  sci_resource_types[type], number,
			  sci_resource_types[type], modded_number);
		number = modded_number;
	}

	retval = scir_test_resource(mgr, type, number);

	if (!retval)
		return NULL;

	if (!retval->status)
		_scir_load_resource(mgr, retval, 0);

	else if (retval->status == SCI_STATUS_ENQUEUED)
		_scir_remove_from_lru(mgr, retval);
	/* Unless an error occured, the resource is now either
	** locked or allocated, but never queued or freed.  */

	if (lock) {
		if (retval->status == SCI_STATUS_ALLOCATED) {
			retval->status = SCI_STATUS_LOCKED;
			retval->lockers = 0;
			mgr->memory_locked += retval->size;
		}

		++retval->lockers;

	} else if (retval->status != SCI_STATUS_LOCKED) { /* Don't lock it */
		if (retval->status == SCI_STATUS_ALLOCATED)
			_scir_add_to_lru(mgr, retval);
	}

	_scir_free_old_resources(mgr, retval->status == SCI_STATUS_ALLOCATED);

	if (retval->data)
		return retval;
	else {
		sciprintf("Resmgr: Failed to read %s.%03d\n",
			  sci_resource_types[retval->type], retval->number);
		return NULL;
	}
}
Esempio n. 4
0
static void
_scir_add_to_lru(resource_mgr_t *mgr, resource_t *res)
{
	if (res->status != SCI_STATUS_ALLOCATED) {
		sciprintf("Resmgr: Oops: trying to enqueue resource with state"
			  " %d\n", res->status);
		return;
	}

	res->prev = NULL;
	res->next = mgr->lru_first;
	mgr->lru_first = res;
	if (!mgr->lru_last)
		mgr->lru_last = res;
	if (res->next)
		res->next->prev = res;

	mgr->memory_lru += res->size;
#if (SCI_VERBOSE_RESMGR > 1)
	fprintf(stderr, "Adding %s.%03d (%d bytes) to lru control: %d bytes total\n",
		sci_resource_types[res->type], res->number, res->size,
		mgr->memory_lru);

#endif

	res->status = SCI_STATUS_ENQUEUED;
}
Esempio n. 5
0
static int
fluidsynth_init(sfx_softseq_t *self, byte *data_ptr, int data_length,
		byte *data2_ptr, int data2_length)
{
	int sfont_id;
	double min, max;

	if (0) {
		sciprintf("FluidSynth ERROR: Mono sound output not supported.\n");
		return SFX_ERROR;
	}

	gmseq = sfx_find_sequencer("General MIDI");
	if (!gmseq) {
		sciprintf("FluidSynth ERROR: Unable to find General MIDI sequencer.\n");
		return SFX_ERROR;
	}

	settings = new_fluid_settings();

	fluid_settings_getnum_range(settings, "synth.sample-rate", &min, &max);
	if (SAMPLE_RATE < min || SAMPLE_RATE > max) {
		sciprintf("FluidSynth ERROR: Sample rate '%i' not supported. Valid "
			"range is (%i-%i).\n", SAMPLE_RATE, (int) min, (int) max);
		delete_fluid_settings(settings);
		return SFX_ERROR;
	}

	fluid_settings_setnum(settings, "synth.sample-rate", SAMPLE_RATE);
	fluid_settings_setnum(settings, "synth.gain", 0.5f);

	synth = new_fluid_synth(settings);

	if ((sfont_id = fluid_synth_sfload(synth, soundfont, 1)) < 0) {
		delete_fluid_synth(synth);
		delete_fluid_settings(settings);
		return SFX_ERROR;
	}

	gmseq->open(data_length, data_ptr, data2_length, data2_ptr,
		    &midi_writer_fluidsynth);

	return SFX_OK;
}
Esempio n. 6
0
static void
print_map_rhythm_mem(int sci, int rhythm, char *mt32)
{
#ifdef DEBUG_MT32_TO_GM
	char name[11];

	strncpy(name, mt32, 10);
	name[10] = 0;

	if (rhythm == SFX_UNMAPPED) {
		sciprintf("[MT32-to-GM] No mapping available for [%i] `%s'\n",
			  sci, name);
		return;
	}

	sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n",
		  sci, name, GM_Percussion_Names[rhythm], rhythm);
#endif
}
Esempio n. 7
0
static void
print_map_rhythm(int sci, int ins, int rhythm, int mt32)
{
#ifdef DEBUG_MT32_TO_GM
	if (ins == SFX_UNMAPPED || (ins == SFX_MAPPED_TO_RHYTHM && rhythm == SFX_UNMAPPED)) {
		sciprintf("[MT32-to-GM] No mapping available for [%i] `%s' [R] (%i)\n",
			  sci, MT32_RhythmTimbreMaps[mt32].name, mt32);
		return;
	}

	if (ins == SFX_MAPPED_TO_RHYTHM) {
		sciprintf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' [R] (%i)\n",
			  sci, MT32_RhythmTimbreMaps[mt32].name, mt32,
			  GM_Percussion_Names[rhythm], rhythm);
		return;
	}

	sciprintf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' (%i)\n",
		  sci, MT32_RhythmTimbreMaps[mt32].name, mt32,
		  GM_Instrument_Names[ins], ins);
#endif
}
Esempio n. 8
0
static void
pcmout_sdl_exit(sfx_pcm_device_t *self)
{
	SDL_PauseAudio (1);
	SDL_CloseAudio();
	sfx_audbuf_free(&audio_buffer);

	SDL_QuitSubSystem(SDL_INIT_AUDIO);

	if (!SDL_WasInit(SDL_INIT_EVERYTHING)) {
		sciprintf("[SND:SDL] No active SDL subsystems found.. shutting down SDL\n");
		SDL_Quit();
	}
}
Esempio n. 9
0
static void
pcmout_alsa_exit(sfx_pcm_device_t *self)
{
	int err;

	run_thread = 0;
	sciprintf("[SND:ALSA] Waiting for PCM thread to exit... ");
	if (!pthread_join(thread, NULL))
		sciprintf("OK\n");
	else
		sciprintf("Failed\n");

	pthread_mutex_destroy(&mutex);

	if ((err = snd_pcm_drop(handle)) < 0) {
		sciprintf("[SND:ALSA] Can't stop PCM device: %s\n", snd_strerror(err));
	}
	if ((err = snd_pcm_close(handle)) < 0) {
		sciprintf("[SND:ALSA] Can't close PCM device: %s\n", snd_strerror(err));
	}

	sfx_audbuf_free(&audio_buffer);
}
Esempio n. 10
0
static void
_scir_load_from_patch_file(int fh, resource_t *res, char *filename)
{
	int really_read;

	res->data = (unsigned char*)sci_malloc(res->size);
	really_read = read(fh, res->data, res->size);

	if (really_read < res->size) {
		sciprintf("Error: Read %d bytes from %s but expected %d!\n",
			  really_read, filename, res->size);
		exit(1);
	}

	res->status = SCI_STATUS_ALLOCATED;
}
Esempio n. 11
0
int
version_parse(char *vn, sci_version_t *result)
{
	char *endptr[3];
	int major = strtol(vn, &endptr[0], 10);
	int minor = strtol(vn + 2, &endptr[1], 10);
	int patchlevel = strtol(vn + 6, &endptr[2], 10);

	if (endptr[0] != vn + 1 || endptr[1] != vn + 5
	    || *endptr[2] != '\0') {
		sciprintf("Warning: Failed to parse version string '%s'\n", vn);
		return 1;
	}

	*result = SCI_VERSION(major, minor, patchlevel);
	return 0;
}
Esempio n. 12
0
static int
mix_init(sfx_pcm_mixer_t *self, sfx_pcm_device_t *device)
{
	self->dev = device;
	self->private_bits /* = P */ = sci_malloc(sizeof(struct mixer_private));
	P->outbuf = P->writebuf = NULL;
	P->lastbuf_len = 0;
	P->compbuf_l = (gint32*)sci_malloc(sizeof(gint32) * device->buf_size);
	P->compbuf_r = (gint32*)sci_malloc(sizeof(gint32) * device->buf_size);
	P->played_this_second = 0;
	P->paused = 0;
#ifdef DEBUG
	sciprintf("[soft-mixer] Initialised device %s v%s (%d Hz, %d/%x)\n",
		  device->name, device->version,
		  device->conf.rate, device->conf.stereo, device->conf.format);
#endif
	return SFX_OK;
}
Esempio n. 13
0
void
version_require_later_than(state_t *s, sci_version_t version)
{
	if (s->version_lock_flag)
		return;

	if (version > s->max_version) {
		sciprintf("Version autodetect conflict: More than %d.%03d.%03d was requested, but less than"
			  "%d.%03d.%03d is required ATM\n",
			  SCI_VERSION_MAJOR(version), SCI_VERSION_MINOR(version), SCI_VERSION_PATCHLEVEL(version),
			  SCI_VERSION_MAJOR(s->max_version), SCI_VERSION_MINOR(s->max_version),
			  SCI_VERSION_PATCHLEVEL(s->max_version));
		return;
	}
	else if (version > s->min_version) {
		s->min_version = version;
		if (s->min_version > s->version)
			s->version = s->min_version;
	}
}
Esempio n. 14
0
void
version_require_earlier_than(state_t *s, sci_version_t version)
{
	if (s->version_lock_flag)
		return;

	if (version <= s->min_version) {
		sciprintf("Version autodetect conflict: Less than %d.%03d.%03d was requested, but "
			  "%d.%03d.%03d is the current minimum\n",
			  SCI_VERSION_MAJOR(version), SCI_VERSION_MINOR(version), SCI_VERSION_PATCHLEVEL(version),
			  SCI_VERSION_MAJOR(s->min_version), SCI_VERSION_MINOR(s->min_version),
			  SCI_VERSION_PATCHLEVEL(s->min_version));
		return;
	}
	else if (version < s->max_version) {
		s->max_version = version -1;
		if (s->max_version < s->version)
			s->version = s->max_version;
	}
}
Esempio n. 15
0
static void
_scir_remove_from_lru(resource_mgr_t *mgr, resource_t *res)
{
	if (res->status != SCI_STATUS_ENQUEUED) {
		sciprintf("Resmgr: Oops: trying to remove resource that isn't"
			  " enqueued\n");
		return;
	}

	if (res->next)
		res->next->prev = res->prev;
	if (res->prev)
		res->prev->next = res->next;
	if (mgr->lru_first == res)
		mgr->lru_first = res->next;
	if (mgr->lru_last == res)
		mgr->lru_last = res->prev;

	mgr->memory_lru -= res->size;

	res->status = SCI_STATUS_ALLOCATED;
}
Esempio n. 16
0
static void
_scir_free_old_resources(resource_mgr_t *mgr, int last_invulnerable)
{
	while (mgr->max_memory < mgr->memory_lru
	       && (!last_invulnerable || mgr->lru_first != mgr->lru_last)) {
		resource_t *goner = mgr->lru_last;
		if (!goner) {
			fprintf(stderr,"Internal error: mgr->lru_last is NULL!\n");
			fprintf(stderr,"LRU-mem= %d\n", mgr->memory_lru);
			fprintf(stderr,"lru_first = %p\n", (void *)mgr->lru_first);
			_scir_print_lru_list(mgr);
		}

		_scir_remove_from_lru(mgr, goner);
		_scir_unalloc(goner);
#ifdef SCI_VERBOSE_RESMGR
		sciprintf("Resmgr-debug: LRU: Freeing %s.%03d (%d bytes)\n",
			  sci_resource_types[goner->type], goner->number,
			  goner->size);
#endif
	}
}
Esempio n. 17
0
static void
_mix_unsubscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed)
{
	int i;
#ifdef DEBUG
	sciprintf("[soft-mixer] Unsubscribing %s-%x\n", feed->debug_name, feed->debug_nr);
#endif
	for (i = 0; i < self->feeds_nr; i++) {
		sfx_pcm_feed_state_t *fs = self->feeds + i;

		if (fs->feed == feed) {
			feed->destroy(feed);

			if (fs->buf)
				sci_free(fs->buf);

			self->feeds_nr--;

			/* Copy topmost into deleted so that we don't have any holes */
			if (i != self->feeds_nr)
				self->feeds[i] = self->feeds[self->feeds_nr];

			if (self->feeds_allocd > 8 && self->feeds_allocd > (self->feeds_nr << 1)) {
				/* Limit memory waste */
				self->feeds_allocd >>= 1;
				self->feeds
					= (sfx_pcm_feed_state_t*)sci_realloc(self->feeds,
						      sizeof(sfx_pcm_feed_state_t)
						      * self->feeds_allocd);
			}

			for (i = 0; i < self->feeds_nr; i++)
				fprintf(stderr, "  Feed #%d: %s-%x\n",
					i, self->feeds[i].feed->debug_name,
					self->feeds[i].feed->debug_nr);

			return;
		}
Esempio n. 18
0
reg_t
kGetEvent(state_t *s, int funct_nr, int argc, reg_t *argv)
{
	int mask = UKPV(0);
	reg_t obj = argv[1];
	sci_event_t e;
	int oldx, oldy;
	int modifier_mask = SCI_VERSION_MAJOR(s->version)==0 ? SCI_EVM_ALL
	                                                     : SCI_EVM_NO_FOOLOCK;

	if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_2NDEVENT) {
		/* Penalty time- too many requests to this function without
		** waiting!  */
		int delay = s->script_000->locals_block->locals[SCI_VARIABLE_GAME_SPEED].offset;

		gfxop_usleep(s->gfx_state, (1000000 * delay) / 60);
	}
  
	/*If there's a simkey pending, and the game wants a keyboard event, use the
	 *simkey instead of a normal event*/
	if (_kdebug_cheap_event_hack && (mask & SCI_EVT_KEYBOARD)) {
		PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/
		PUT_SEL32V(obj, message, _kdebug_cheap_event_hack);
		PUT_SEL32V(obj, modifiers, SCI_EVM_NUMLOCK); /*Numlock on*/
		PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x);
		PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y);
		_kdebug_cheap_event_hack = 0;
		return make_reg(0, 1);
	}
  
	oldx = s->gfx_state->pointer_pos.x;
	oldy = s->gfx_state->pointer_pos.y;
	e = gfxop_get_event(s->gfx_state, mask);

	s->parser_event = NULL_REG; /* Invalidate parser event */

	PUT_SEL32V(obj, x, s->gfx_state->pointer_pos.x);
	PUT_SEL32V(obj, y, s->gfx_state->pointer_pos.y);

	/*  gfxop_set_pointer_position(s->gfx_state, gfx_point(s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y)); */


	if (e.type)
		s->kernel_opt_flags &= ~(KERNEL_OPT_FLAG_GOT_EVENT
					 | KERNEL_OPT_FLAG_GOT_2NDEVENT);
	else {
		if (s->kernel_opt_flags & KERNEL_OPT_FLAG_GOT_EVENT)
			s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_2NDEVENT;
		else
			s->kernel_opt_flags |= KERNEL_OPT_FLAG_GOT_EVENT;
	}

	switch(e.type)
		{
		case SCI_EVT_QUIT:
			quit_vm();
			break;

		case SCI_EVT_KEYBOARD: {

			if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT)
			    && (e.data == '-')) {

				sciprintf("Debug mode activated\n");

				script_debug_flag = 1; /* Enter debug mode */
				_debug_seeking = _debug_step_running = 0;
				s->onscreen_console = 0;

			} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) {

				script_debug_flag = 1; /* Enter debug mode */
				_debug_seeking = _debug_step_running = 0;
				s->onscreen_console = 1;

			} else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '1')) {

				if (s->visual)
					s->visual->print(GFXW(s->visual), 0);

			} else {
				PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); /*Keyboard event*/
				s->r_acc=make_reg(0, 1);
				PUT_SEL32V(obj, message, e.character);
				/* We only care about the translated
				** character  */
				PUT_SEL32V(obj, modifiers, e.buckybits&modifier_mask);

			}
		} break;

		case SCI_EVT_MOUSE_RELEASE:
		case SCI_EVT_MOUSE_PRESS: {
			int extra_bits=0;

			if(mask & e.type) {
				switch(e.data) {
				case 2: extra_bits=SCI_EVM_LSHIFT|SCI_EVM_RSHIFT; break;
				case 3: extra_bits=SCI_EVM_CTRL;
				default:break;
				}

				PUT_SEL32V(obj, type, e.type);
				PUT_SEL32V(obj, message, 1);
				PUT_SEL32V(obj, modifiers, (e.buckybits|extra_bits)&modifier_mask);
				s->r_acc = make_reg(0, 1);
			}
		} break;

		default: {
			s->r_acc = NULL_REG; /* Unknown or no event */
		}
		}

	if ((s->r_acc.offset) && (stop_on_event)) {
		stop_on_event = 0;
		script_debug_flag = 1;
	}  

	return s->r_acc;
}
Esempio n. 19
0
static void
timer_sdl_internal_callback(void *userdata, byte *dest, int len)
{
	sci_gettime(&last_callback_secs, &last_callback_usecs);
	last_callback_len = len;

	if (sdl_sfx_timer_callback)
		sdl_sfx_timer_callback(sdl_sfx_timer_data);

#if 0
	if (!sfx_audbuf_read_timestamp(&audio_buffer, &ts)) {
		int delta = (buf_size - len) / frame_size;
		sfx_timestamp_t real_ts;
		long deltatime;
		long sec2, usec2;
		sci_gettime(&sec2, &usec2);

		real_ts = sfx_timestamp_add(sfx_new_timestamp(sec, usec, rate), delta);

		deltatime = sfx_timestamp_usecs_diff(ts, real_ts);

		fprintf(stderr, "[SDL] Frames requested: %d  Playing %ld too late. Needed %ldus for computations.\n",
				len / frame_size, deltatime,
			(usec2-usec) + (sec2-sec)*1000000);

		if (abs(deltatime) > DELTA_TIME_LIMIT)
			sciprintf("[SND:SDL] Very high delta time for PCM playback: %ld too late (%d frames in the future)\n",
				  deltatime, sfx_timestamp_frame_diff(sfx_new_timestamp(sec, usec, rate), ts));

#if 0
		if (deltatime < 0) {
			/* Read and discard frames, explicitly underrunning */
			int max_read = len / frame_size;
			int frames_to_kill = sfx_timestamp_frame_diff(real_ts, ts);

			while (frames_to_kill) {
				int d = frames_to_kill > max_read? max_read : frames_to_kill;
				sfx_audbuf_read(&audio_buffer, dest, d);
				frames_to_kill -= d;
			}
		}
#endif
	}
#endif
	sfx_audbuf_read(&audio_buffer, dest, len / frame_size);

#if 0
	if (!fil) {
		fil = fopen("/tmp/sdl.log", "w");
	}
	{
		int i;
		int end = len / frame_size;
		gint16 *d = dest;
		fprintf(fil, "Writing %d/%d\n", len, frame_size);
		for (i = 0; i < end; i++) {
			fprintf(fil, "\t%d\t%d\n", d[0], d[1]);
			d += 2;
		}
	}
#endif
}
Esempio n. 20
0
static int
fluidsynth_midi_write(struct _midi_writer *self, unsigned char *buf, int len)
{
	if (buf[0] == 0xf0)
		sciprintf("FluidSynth: Skipping sysex message.\n");
	else if (len == 2) {
		guint8 command, channel;

		command = buf[0] & 0xf0;
		channel = buf[0] & 0x0f;

		switch(command) {
		case 0xc0:
			fluid_synth_program_change(synth, channel, buf[1]);
			break;
		default:
			printf("FluidSynth: MIDI command [%02x %02x] not supported\n", buf[0], buf[1]);
		}
	}
	else if (len == 3) {
		guint8 command, channel;

		command = buf[0] & 0xf0;
		channel = buf[0] & 0x0f;

		switch(command) {
		case 0x80:
			fluid_synth_noteoff(synth, channel, buf[1]);
			break;
		case 0x90:
			fluid_synth_noteon(synth, channel, buf[1], buf[2]);
			break;
		case 0xb0:
			switch (buf[1]) {
			case 0x06:
				/* Data Entry Slider - course */
				if (rpn[channel] == 0)
					fluid_synth_pitch_wheel_sens(synth, channel, buf[2]);
				else
					sciprintf("FluidSynth: RPN %i not supported\n", rpn[channel]);
			case 0x64:
				/* Registered Parameter Number (RPN) - fine */
				rpn[channel] &= ~0x7f;
				rpn[channel] |= buf[2] & 0x7f;
				break;
			case 0x65:
				/* Registered Parameter Number (RPN) - course */
				rpn[channel] &= ~0x3f80;
				rpn[channel] |= (buf[2] & 0x7f) << 7;
				break;
			default:
				fluid_synth_cc(synth, channel, buf[1], buf[2]);
			}
			break;
		case 0xe0:
			fluid_synth_pitch_bend(synth, channel, (buf[2] << 7) | buf[1]);
			break;
		default:
			sciprintf("FluidSynth: MIDI command [%02x %02x %02x] not supported\n", buf[0], buf[1], buf[2]);
		}
	}
	else
		sciprintf("FluidSynth: Skipping invalid message of %i bytes.\n", len);

	return SFX_OK;
}
Esempio n. 21
0
const char *  /* Original version by Solomon Peachy */
version_guess_from_hashcode(sci_version_t *result, int *res_version, guint32 *code)
{
	int i;
	int fd = -1;
	int left = VERSION_DETECT_HASH_SIZE;
	guint32 hash_code;
	guint8 buf[VERSION_DETECT_BUF_SIZE];

	if (IS_VALID_FD(fd = sci_open("resource.001", O_RDONLY|O_BINARY))) {
		hash_code = HASHCODE_MAGIC_RESOURCE_001;
	} else if (IS_VALID_FD(fd = sci_open("resource.000", O_RDONLY|O_BINARY))) {
		hash_code = HASHCODE_MAGIC_RESOURCE_000;
	} else {
		sciprintf("Warning: Could not find RESOURCE.000 or RESOURCE.001, cannot determine hash code\n");
		*code = 0;
		/* complete and utter failure */
		return NULL;
	}

	while (left > 0) {
		int len = read(fd, buf, left < VERSION_DETECT_BUF_SIZE ? left : VERSION_DETECT_BUF_SIZE);

		if (len == -1) {
			sciprintf("Warning: read error while computing hash code for resource file\n");
			*code = 0;
			return NULL;
		}

		if (len == 0)
			/* EOF */
			break;

		for (i = 0; i < len; i++)
			hash_code = (hash_code * 19) + *(buf + i);

		/* This is the string hashing algorithm used by Objective Caml 3.08; the general idea
		** of multiplying the previous hash code with a prime number between 5 and 23 appears
		** to be generally considered to be a "good" approach to exhausting the entire 32 bit
		** number space in a somewhat equal distribution. For large chunks of data, such as
		** SCI resource files, this should both perform well and yield a good distribution,
		** or at least that's what standard library designers have been assuming for quite a
		** while. */

		left -= len;
	}

	close(fd);

	*code = hash_code;

	for (i = 0 ; sci_games[i].name ; i++) {
		if (sci_games[i].id == hash_code) {
			*result = sci_games[i].version;
			*res_version = sci_games[i].res_version;
			return sci_games[i].name;
		}
	}

	return NULL; /* Failed to find matching game */
}
Esempio n. 22
0
sfx_instrument_map_t *
sfx_instrument_map_mt32_to_gm(byte *data, size_t size)
{
	int memtimbres, patches;
	guint8 group, number, keyshift, finetune, bender_range;
	guint8 *patchpointer;
	guint32 pos;
	sfx_instrument_map_t * map;
	int i;
	int type;

	map = sfx_instrument_map_new(0);

	for (i = 0; i < SFX_INSTRUMENTS_NR; i++) {
		map->patch_map[i].patch = MT32_PresetTimbreMaps[i].gm_instr;
		map->patch_key_shift[i] = 0;
		map->patch_volume_adjust[i] = 0;
		map->patch_bend_range[i] = 12;
		map->velocity_map_index[i] = SFX_NO_VELOCITY_MAP;
	}

	map->percussion_volume_adjust = 0;
	map->percussion_velocity_map_index = SFX_NO_VELOCITY_MAP;

	for (i = 0; i < SFX_RHYTHM_NR; i++) {
		map->percussion_map[i] = MT32_PresetRhythmKeymap[i];
		map->percussion_velocity_scale[i] = SFX_MAX_VELOCITY;
	}

	if (!data) {
		sciprintf("[MT32-to-GM] No MT-32 patch data supplied, using default mapping\n");
		return map;
	}

	type = sfx_instrument_map_detect(data, size);

	if (type == SFX_MAP_UNKNOWN) {
		sciprintf("[MT32-to-GM] Patch data format unknown, using default mapping\n");
		return map;
	}
	if (type == SFX_MAP_MT32_GM) {
		sciprintf("[MT32-to-GM] Patch data format not supported, using default mapping\n");
		return map;
	}

	memtimbres = *(data + 0x1EB);
	pos = 0x1EC + memtimbres * 0xF6;

	if (size > pos && ((0x100 * *(data + pos) + *(data +pos + 1)) == 0xABCD)) {
		patches = 96;
		pos += 2 + 8 * 48;
	} else
		patches = 48;

	sciprintf("[MT32-to-GM] %d MT-32 Patches detected\n", patches);
	sciprintf("[MT32-to-GM] %d MT-32 Memory Timbres\n", memtimbres);

	sciprintf("[MT32-to-GM] Mapping patches..\n");

	for (i = 0; i < patches; i++) {
		char *name;

		if (i < 48)
			patchpointer = data + 0x6B + 8 * i;
		else
			patchpointer = data + 0x1EC + 8 * (i - 48) + memtimbres * 0xF6 + 2;

		group = *patchpointer;
		number = *(patchpointer + 1);
		keyshift = *(patchpointer + 2);
		finetune = *(patchpointer + 3);
		bender_range = *(patchpointer + 4);

		switch (group) {
		case 0:
			map->patch_map[i].patch = MT32_PresetTimbreMaps[number].gm_instr;
			map->patch_map[i].rhythm = MT32_PresetTimbreMaps[number].gm_rhythm_key;
			print_map(i, map->patch_map[i].patch, map->patch_map[i].rhythm, number);
			break;
		case 1:
			map->patch_map[i].patch = MT32_PresetTimbreMaps[number + 64].gm_instr;
			map->patch_map[i].rhythm = MT32_PresetTimbreMaps[number + 64].gm_rhythm_key;
			print_map(i, map->patch_map[i].patch, map->patch_map[i].rhythm, number + 64);
			break;
		case 2:
			name = (char *) data + 0x1EC + number * 0xF6;
			map->patch_map[i].patch = lookup_instrument(name);
			map->patch_map[i].rhythm = SFX_UNMAPPED;
			print_map_mem(i, map->patch_map[i].patch, map->patch_map[i].rhythm, name);
			break;
		case 3:
			map->patch_map[i].patch = MT32_RhythmTimbreMaps[number].gm_instr;
			map->patch_map[i].rhythm = SFX_UNMAPPED;
			print_map_rhythm(i, map->patch_map[i].patch, map->patch_map[i].rhythm, number);
			break;
		default:
			break;
		}

		/* map->patch_key_shift[i] = (int) (keyshift & 0x3F) - 24; */
		map->patch_bend_range[i] = bender_range & 0x1F;
	}

	if (size > pos && ((0x100 * *(data + pos) + *(data + pos + 1)) == 0xDCBA)) {
		sciprintf("[MT32-to-GM] Mapping percussion..\n");

		for (i = 0; i < 64 ; i++) {
			number = *(data + pos + 4 * i + 2);

			if (number < 64) {
				char *name = (char *) data + 0x1EC + number * 0xF6;
				map->percussion_map[i + 23] = lookup_rhythm_key(name);
				print_map_rhythm_mem(i, map->percussion_map[i + 23], name);
			} else {
				if (number < 94) {
					map->percussion_map[i + 23] = MT32_RhythmTimbreMaps[number - 64].gm_rhythmkey;
					print_map_rhythm(i, SFX_MAPPED_TO_RHYTHM, map->percussion_map[i + 23], number - 64);
				} else
					map->percussion_map[i + 23] = SFX_UNMAPPED;
			}

			map->percussion_velocity_scale[i + 23] = *(data + pos + 4 * i + 3) * SFX_MAX_VELOCITY / 100;
		}
	}

	return map;
}
Esempio n. 23
0
static int
pcmout_alsa_init(sfx_pcm_device_t *self)
{
	unsigned int rrate;
	int err, dir;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_sw_params_t *swparams;
	pthread_attr_t attr;

	snd_pcm_hw_params_alloca(&hwparams);
	snd_pcm_sw_params_alloca(&swparams);

	err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0);
	if (err < 0) {
		sciprintf("[SND:ALSA] Playback open error: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_any(handle, hwparams);
	if (err < 0) {
		sciprintf("[SND:ALSA] Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		sciprintf("[SND:ALSA] Access type not available for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_set_format(handle, hwparams, format);
	if (err < 0) {
		sciprintf("[SND:ALSA] Sample format not available for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
	if (err < 0) {
		sciprintf("[SND:ALSA] Channels count (%i) not available for playback: %s\n", channels, snd_strerror(err));
		return SFX_ERROR;
	}
	rrate = rate;
	err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0);
	if (err < 0) {
		sciprintf("[SND:ALSA] Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
		return SFX_ERROR;
	}
	if (rrate != rate) {
		sciprintf("[SND:ALSA] Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_get_buffer_size(hwparams, (snd_pcm_uframes_t*)&buffer_size);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to get buffer size for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set period time %i for playback: %s\n", period_time, snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params_get_period_size(hwparams, (snd_pcm_uframes_t*)&period_size, &dir);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to get period size for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	if (period_size >= buffer_size) {
		sciprintf("[SND:ALSA] Period size %i matches or exceeds buffer size %i\n", period_size, buffer_size);
		return SFX_ERROR;
	}
	err = snd_pcm_hw_params(handle, hwparams);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set hw params for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_sw_params_current(handle, swparams);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to determine current swparams for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set avail min for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set transfer align for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}
	err = snd_pcm_sw_params(handle, swparams);
	if (err < 0) {
		sciprintf("[SND:ALSA] Unable to set sw params for playback: %s\n", snd_strerror(err));
		return SFX_ERROR;
	}

	self->buf_size = buffer_size;
	self->conf.rate = rate;
	self->conf.stereo = channels > 1;
	self->conf.format = SFX_PCM_FORMAT_S16_NATIVE;

	frame_size = SFX_PCM_FRAME_SIZE(self->conf);

	sfx_audbuf_init(&audio_buffer, self->conf);

	if (pthread_mutex_init(&mutex, NULL) != 0) {
		sciprintf("[SND:ALSA] Failed to create mutex\n");
		return SFX_ERROR;
	}

	run_thread = 1;
	if (pthread_create(&thread, NULL, alsa_thread, self) != 0) {
		sciprintf("[SND:ALSA] Failed to create thread\n");
		return SFX_ERROR;
	}

	return SFX_OK;
}
Esempio n. 24
0
static void
mix_subscribe(sfx_pcm_mixer_t *self, sfx_pcm_feed_t *feed)
{
	sfx_pcm_feed_state_t *fs;
	ACQUIRE_LOCK();
	if (!self->feeds) {
		self->feeds_allocd = 2;
		self->feeds = (sfx_pcm_feed_state_t*)sci_malloc(sizeof(sfx_pcm_feed_state_t)
					 * self->feeds_allocd);
	} else if (self->feeds_allocd == self->feeds_nr) {
		self->feeds_allocd += 2;
		self->feeds = (sfx_pcm_feed_state_t*)sci_realloc(self->feeds,
					  sizeof(sfx_pcm_feed_state_t)
					  * self->feeds_allocd);
	}

	fs = self->feeds + self->feeds_nr++;
	fs->feed = feed;

	feed->frame_size = SFX_PCM_FRAME_SIZE(feed->conf);

	/*	fs->buf_size = (self->dev->buf_size
			  * (feed->conf.rate
			     + self->dev->conf.rate - 1))
		/ self->dev->conf.rate;
	*/
	/* For the sake of people without 64 bit CPUs: */
	fs->buf_size = 2 + /* Additional safety */
		(self->dev->buf_size *
			(1 + (feed->conf.rate / self->dev->conf.rate)));
fprintf(stderr, " ---> %d/%d/%d/%d = %d\n",
	self->dev->buf_size,
	feed->conf.rate,
	self->dev->conf.rate,
	feed->frame_size,
	fs->buf_size);

	fs->buf = (byte*)sci_malloc(fs->buf_size * feed->frame_size);
fprintf(stderr, " ---> --> %d for %p at %p\n", fs->buf_size * feed->frame_size, (void *)fs, (void *)fs->buf);
{int i; for (i = 0; i < fs->buf_size * feed->frame_size; i++)
fs->buf[i] = 0xa5; }
	fs->scount = urat(0, 1);
	fs->spd = urat(feed->conf.rate, self->dev->conf.rate);
	fs->scount.den = fs->spd.den;
	fs->ch_old.left = 0;
	fs->ch_old.right = 0;
	fs->ch_new.left = 0;
	fs->ch_new.right = 0;
	fs->mode = SFX_PCM_FEED_MODE_ALIVE;

	/* If the feed can't provide us with timestamps, we don't need to wait for it to do so */
	fs->pending_review = (feed->get_timestamp)? 1 : 0;

	fs->frame_bufstart = 0;

#ifdef DEBUG
	sciprintf("[soft-mixer] Subscribed %s-%x (%d Hz, %d/%x) at %d+%d/%d, buffer size %d\n",
		  feed->debug_name, feed->debug_nr, feed->conf.rate, feed->conf.stereo, feed->conf.format,
		  fs->spd.val, fs->spd.nom, fs->spd.den, fs->buf_size);
#endif
	RELEASE_LOCK();
}
Esempio n. 25
0
static void
_scir_load_resource(resource_mgr_t *mgr, resource_t *res, int protect)
{
	char *cwd = sci_getcwd();
	char filename[14];
	int fh;
	resource_t backup;

	memcpy(&backup, res, sizeof(resource_t));
	/* Enter resource directory */
	chdir(mgr->resource_path);

	/* First try lower-case name */
	if (res->file == SCI_RESOURCE_FILE_PATCH) {

		if (!patch_sprintfers[mgr->sci_version]) {
			sciprintf("Resource manager's SCI version (%d) has no patch file name printers -> internal error!\n",
				  mgr->sci_version);
			exit(1);
		}

		/* Get patch file name */
		patch_sprintfers[mgr->sci_version](filename, res);
	} else
		sprintf(filename, "resource.%03i", res->file);

	fh = open(filename, O_RDONLY | O_BINARY);


	if (!IS_VALID_FD(fh)) {
		char *raiser = filename;
		while (*raiser) {
			*raiser = toupper(*raiser); /* Uppercasify */
			++raiser;
		}
		fh = sci_open(filename, O_RDONLY|O_BINARY);
	}    /* Try case-insensitively name */

	if (!IS_VALID_FD(fh)) {
		sciprintf("Failed to open %s/%s!\n",
			  mgr->resource_path, filename);
		res->data = NULL;
		res->status = SCI_STATUS_NOMALLOC;
		res->size = 0;
		chdir(cwd);
		free(cwd);
		return;
	}


	lseek(fh, res->file_offset, SEEK_SET);

	if (res->file == SCI_RESOURCE_FILE_PATCH)
		_scir_load_from_patch_file(fh, res, filename);
	else if (!decompressors[mgr->sci_version]) {
		/* Check whether we support this at all */
		sciprintf("Resource manager's SCI version (%d) is invalid!\n",
			  mgr->sci_version);
		exit(1);
	} else {
		int error = /* Decompress from regular resource file */
			decompressors[mgr->sci_version](res, fh, mgr->sci_version);

		if (error) {
			sciprintf("Error %d occured while reading %s.%03d"
				  " from resource file: %s\n",
				  error, sci_resource_types[res->type], res->number,
				  sci_error_types[error]);

			if (protect)
				memcpy(res, &backup, sizeof(resource_t));

			res->data = NULL;
			res->status = SCI_STATUS_NOMALLOC;
			res->size = 0;
			chdir(cwd);
			free(cwd);
			return;
		}
	}

	close(fh);
	chdir(cwd);
	free(cwd);
}
Esempio n. 26
0
resource_mgr_t *
scir_new_resource_manager(char *dir, int version,
			  char allow_patches, int max_memory)
{
	int resource_error = 0;
	resource_mgr_t *mgr = (resource_mgr_t*)sci_malloc(sizeof(resource_mgr_t));
	char *caller_cwd = sci_getcwd();
	int resmap_version = version;

	if (chdir(dir)) {
		sciprintf("Resmgr: Directory '%s' is invalid!\n", dir);
		free(caller_cwd);
		return NULL;
	}

	mgr->max_memory = max_memory;

	mgr->memory_locked = 0;
	mgr->memory_lru = 0;

	mgr->resource_path = dir;

	mgr->resources = NULL;

	if (version <= SCI_VERSION_01_VGA_ODD
	    /* || version == SCI_VERSION_AUTODETECT -- subsumed by the above line */) {
		resource_error =
			sci0_read_resource_map(dir,
					       &mgr->resources,
					       &mgr->resources_nr,
					       &resmap_version);

		if (resource_error >= SCI_ERROR_CRITICAL) {
			sciprintf("Resmgr: Error while loading resource map: %s\n",
				  sci_error_types[resource_error]);
			if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND)
				sciprintf("Running SCI games without a resource map is not supported ATM\n");
			sci_free(mgr);
			chdir(caller_cwd);
			free(caller_cwd);
			return NULL;
		}

		if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) {
			/* fixme: Try reading w/o resource.map */
			resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND;
		}

		if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) {
			/* Initialize empty resource manager */
			_scir_init_trivial(mgr);
			resource_error = 0;
		}

	}

	if ((version == SCI_VERSION_1_EARLY)||
	    (version == SCI_VERSION_1_LATE)||
	    (version == SCI_VERSION_1_1)||
	    ((resmap_version == SCI_VERSION_AUTODETECT)&&(version == SCI_VERSION_AUTODETECT)))
	{
		resource_error =
			sci1_read_resource_map(dir,
					       &mgr->resources,
					       &mgr->resources_nr,
					       &resmap_version);

		if (resource_error >= SCI_ERROR_CRITICAL) {
			sciprintf("Resmgr: Error while loading resource map: %s\n",
				  sci_error_types[resource_error]);
			if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND)
				sciprintf("Running SCI games without a resource map is not supported ATM\n");
			sci_free(mgr);
			chdir(caller_cwd);
			free(caller_cwd);
			return NULL;
		}

		if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) {
			/* fixme: Try reading w/o resource.map */
			resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND;
		}

		if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) {
			/* Initialize empty resource manager */
			_scir_init_trivial(mgr);
			resource_error = 0;
		}

		resmap_version = SCI_VERSION_1;
	}
		
	if (!mgr->resources || !mgr->resources_nr) {
		if (mgr->resources) {
			free(mgr->resources);
			mgr->resources = NULL;
		}
		sciprintf("Resmgr: Could not retreive a resource list!\n");
		sci_free(mgr);
		chdir(caller_cwd);
		free(caller_cwd);
		return NULL;
	}

	mgr->lru_first = NULL;
	mgr->lru_last = NULL;

	mgr->allow_patches = allow_patches;

	qsort(mgr->resources, mgr->resources_nr, sizeof(resource_t),
	      resourcecmp); /* Sort resources */

	if (version == SCI_VERSION_AUTODETECT)
		switch (resmap_version) {
		case SCI_VERSION_0:
			if (scir_test_resource(mgr, sci_vocab,
					       VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) {
				version = sci_test_view_type(mgr);
				if (version == SCI_VERSION_01_VGA)
				{
					sciprintf("Resmgr: Detected KQ5 or similar\n");
				} else {
					sciprintf("Resmgr: Detected SCI0\n");
					version = SCI_VERSION_0;
				}
			} else if (scir_test_resource(mgr, sci_vocab,
						      VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) {
				version = sci_test_view_type(mgr);
				if (version == SCI_VERSION_01_VGA)
				{
					sciprintf("Resmgr: Detected KQ5 or similar\n");
				} else {
					if (scir_test_resource(mgr, sci_vocab, 912)) {
						sciprintf("Resmgr: Running KQ1 or similar, using SCI0 resource encoding\n");
						version = SCI_VERSION_0;
					} else {
						version = SCI_VERSION_01;
						sciprintf("Resmgr: Detected SCI01\n");
					}
				}
			} else {
				version = sci_test_view_type(mgr);
				if (version == SCI_VERSION_01_VGA)
				{
					sciprintf("Resmgr: Detected KQ5 or similar\n");
				} else {
					sciprintf("Resmgr: Warning: Could not find vocabulary; assuming SCI0 w/o parser\n");
					version = SCI_VERSION_0;
				}
			} break;
		case SCI_VERSION_01_VGA_ODD:
			version = resmap_version;
			sciprintf("Resmgr: Detected Jones/CD or similar\n");
			break;
		case SCI_VERSION_1:
		{
			resource_t *res = scir_test_resource(mgr, sci_script, 0);
			
			mgr->sci_version = version = SCI_VERSION_1_EARLY;
			_scir_load_resource(mgr, res, 1);
			
			if (res->status == SCI_STATUS_NOMALLOC)
			    mgr->sci_version = version = SCI_VERSION_1_LATE;

			/* No need to handle SCI 1.1 here - it was done in resource_map.c */
			break;
		}
		default:
			sciprintf("Resmgr: Warning: While autodetecting: Couldn't"
				  " determine SCI version!\n");
		}

	if (!resource_error)
	{
		if (version <= SCI_VERSION_01)
			sci0_read_resource_patches(dir,
						   &mgr->resources,
						   &mgr->resources_nr);
		else
			sci1_read_resource_patches(dir,
						   &mgr->resources,
						   &mgr->resources_nr);

		qsort(mgr->resources, mgr->resources_nr, sizeof(resource_t),
		      resourcecmp); /* Sort resources */
	}

	mgr->sci_version = version;

	chdir(caller_cwd);
	free(caller_cwd);

	return mgr;
}