[Scummvm-cvs-logs] CVS: scummvm adilb.cpp,NONE,1.1.2.1 akos.cpp,NONE,1.3.2.1 gui.cpp,NONE,1.6.2.1 debugrl.cpp,NONE,1.1.2.1

Vincent Hamm yazoo at users.sourceforge.net
Wed Dec 19 16:28:03 CET 2001


Update of /cvsroot/scummvm/scummvm
In directory usw-pr-cvs1:/tmp/cvs-serv10734

Added Files:
      Tag: exp_1
	adilb.cpp akos.cpp gui.cpp debugrl.cpp 
Log Message:


--- NEW FILE: adilb.cpp ---
#include "stdafx.h"
#include "scumm.h"
#include "sound.h"

void AdlibChannel::set_transpose(int8 transpose) {
	AdlibChannel *s;

	for(s=this; s; s = s->_next) {
		_se->adlib_note_on(s->_channel, s->_note + transpose, s->_part->_mod_eff);
	}
}

void AdlibChannel::set_mod(int mod) {
	AdlibChannel *s;

	for(s=this; s; s = s->_next) {
		_se->adlib_note_on(s->_channel, s->_note + s->_part->_transpose_eff, mod);
	}
}

void AdlibChannel::off() {
	AdlibChannel *tmp;

	_se->adlib_key_off(_channel);

	tmp = _prev;

	if (_next)
		_next->_prev = tmp;
	if (tmp)
		tmp->_next = _next;
	else
		_part->_s3 = _next;
	_part = NULL;
}

const byte volume_table[] = {
0, 4, 7, 11,
13, 16, 18, 20,
22, 24, 26, 27,
29, 30, 31, 33,
34, 35, 36, 37,
38, 39, 40, 41,
42, 43, 44, 44,
45, 46, 47, 47,
48, 49, 49, 50,
51, 51, 52, 53,
53, 54, 54, 55,
55, 56, 56, 57,
57, 58, 58, 59,
59, 60, 60, 60,
61, 61, 62, 62,
62, 63, 63, 63
};

void AdlibChannel::key_on(Part *part, byte note, byte velocity) {
	Instrument *instr = &part->_instr;
	int c;
	byte vol_1,vol_2;

	_twochan = instr->feedback&1;
	_note = note;
	_waitforpedal = false;
	_duration = instr->duration;
	if (_duration != 0)
		_duration *= 63;

	vol_1 = (instr->oplvl_1&0x3F) + lookup_table_a[velocity>>1][instr->waveform_1>>2];
	if (vol_1 > 0x3F)
		vol_1 = 0x3F;
	_vol_1 = vol_1;

	vol_2 = (instr->oplvl_2&0x3F) + lookup_table_a[velocity>>1][instr->waveform_2>>2];
	if (vol_2 > 0x3F)
		vol_2 = 0x3F;
	_vol_2 = vol_2;

	c = part->_vol_eff >> 2;
	
	vol_2 = volume_table[lookup_table_a[vol_2][c]];
	if (_twochan)
		vol_1 = volume_table[lookup_table_a[vol_1][c]];
	
	_se->adlib_setup_channel(_channel, instr, vol_1, vol_2);
	_se->adlib_note_on_ex(_channel, part->_transpose_eff + note, part->_mod_eff);

	if (instr->flags_a & 0x80) {
		unk5(&_s10a, &_s11a, instr->flags_a, &instr->s12a);
	} else {
		_s10a.active = 0;
	}
	
	if (instr->flags_b & 0x80) {
		unk5(&_s10b, &_s11b, instr->flags_b, &instr->s12b); 
	} else {
		_s10b.active = 0;
	}
}

const byte s35_table_1[16] = {
29,28,27,0,
3,4,7,8,
13,16,17,20,
21,30,31,0
};

const uint16 s35_table_2[16] = {
0x2FF,0x1F,0x7,0x3F,
0x0F,0x0F,0x0F,0x3,
0x3F,0x0F,0x0F,0x0F,
0x3,0x3E,0x1F, 0
};

static const uint16 s102_table_1[] = {
1, 2, 4, 5,
6, 7, 8, 9,
10, 12, 14, 16,
18, 21, 24, 30,
36, 50, 64, 82,
100, 136, 160, 192,
240, 276, 340, 460,
600, 860, 1200, 1600
};

int random_nr(int a) {
	static byte _rand_seed = 1;
	if (_rand_seed&1) {
		_rand_seed>>=1;
		_rand_seed ^= 0xB8;
	} else {
		_rand_seed>>=1;
	}
	return _rand_seed * a >> 8;
}

void struct10_setup(Struct10 *s10) {
	int b,c,d,e,f,g,h;
	byte t;

	b = s10->unk3;
	f = s10->active - 1;

	t = s10->unk7[f];
	e = s102_table_1[lookup_table_a[t&0x7F][b]];
	if (t&0x80) {
		e = random_nr(e);
	}
	if (e==0)
		e++;
	
	s10->num_steps = s10->speed_lo_max = e;

	if (f != 2) {
		c = s10->unk2;
		g = s10->start_value;
		t = s10->unk8[f];
		d = lookup_volume(c, (t&0x7F) - 31);
		if (t&0x80) {
			d = random_nr(d);
		}
		if (d+g > c) {
			h = c - g;
		} else {
			h = d;
			if (d+g<0)
				h = -g;
		}
		h -= s10->cur_val;
	} else {
		h = 0;
	}

	s10->speed_hi = h / e;
	if (h<0) {
		h = -h;
		s10->direction = -1;
	} else {
		s10->direction = 1;
	}

	s10->speed_lo = h % e;
	s10->speed_lo_counter = 0;
}

byte struct10_unk3(Struct10 *s10, Struct11 *s11) {
	byte result = 0;
	int i;

	if (s10->unk6 && (s10->unk6-=17)<=0) {
		s10->active = 0;
		return 0;
	}

	i = s10->cur_val + s10->speed_hi;
	s10->speed_lo_counter += s10->speed_lo;
	if (s10->speed_lo_counter >= s10->speed_lo_max) {
		s10->speed_lo_counter -= s10->speed_lo_max;
		i += s10->direction;
	}
	if (s10->cur_val != i || s10->modwheel != s10->modwheel_last) {
		s10->cur_val = i;
		s10->modwheel_last = s10->modwheel;
		i = lookup_volume(i, s10->modwheel_last);
		if (i != s11->modify_val) {
			s11->modify_val = i;
			result = 1;
		}
	}
	assert(s10->num_steps>=0);
	if (!--s10->num_steps) {
		s10->active++;
		if (s10->active > 4) {
			if (s10->loop) {
				s10->active = 1;
				result |= 2;
				struct10_setup(s10);
			} else {
				s10->active = 0;
			}
		} else {
			struct10_setup(s10);
		}
	}

	return result;
}

void struct10_unk1(Struct10 *s10, Struct12 *s12) {
	s10->active = 1;
	s10->cur_val = 0;
	s10->modwheel_last = 31;
	s10->unk6 = s12->a;
	if (s10->unk6)
		s10->unk6 *= 63;
	s10->unk7[0] = s12->b;
	s10->unk7[1] = s12->d;
	s10->unk7[2] = s12->f;
	s10->unk7[3] = s12->g;

	s10->unk8[0] = s12->c;
	s10->unk8[1] = s12->e;
	s10->unk8[2] = 0;
	s10->unk8[3] = s12->h;
		
	struct10_setup(s10);
}


void AdlibChannel::unk5(Struct10 *s10, Struct11 *s11, byte flags, Struct12 *s12) {
	s11->modify_val = 0;
	s11->unk4 = flags & 0x40;
	s10->loop = flags & 0x20;
	s11->unk5 = flags & 0x10;
	s11->param = s35_table_1[flags&0xF];
	s10->unk2 = s35_table_2[flags&0xF];
	s10->unk3 = 31;
	if (s11->unk4) {
		s10->modwheel = _part->_modwheel>>2;
	} else {
		s10->modwheel = 31;
	}

	switch(s11->param) {
	case 0:
		s10->start_value = _vol_2;
		break;
	case 13:
		s10->start_value = _vol_1;
		break;
	case 30:
		s10->start_value = 31;
		s11->s10->modwheel = 0;
		break;
	case 31:
		s10->start_value = 0;
		s11->s10->unk3 = 0;
		break;
	default:
		s10->start_value = _se->adlib_read_param(_channel, s11->param);
	}

	struct10_unk1(s10, s12);
}


void AdlibChannel::unk1(Struct10 *s10, Struct11 *s11) {
	byte code;

	code = struct10_unk3(s10,s11);

	if (code&1) {
		switch(s11->param) {
		case 0:
			_vol_2 = s10->start_value + s11->modify_val;
			_se->adlib_set_param(_channel, 0, volume_table[lookup_table_a[_vol_2][_part->_vol_eff>>2]]);
			break;
		case 13:
			_vol_1 = s10->start_value + s11->modify_val;
			if (_twochan) {
				_se->adlib_set_param(_channel, 13, volume_table[lookup_table_a[_vol_1][_part->_vol_eff>>2]]);
			} else {
				_se->adlib_set_param(_channel, 13, _vol_1);
			}
			break;
		case 30:
			s11->s10->modwheel = s11->modify_val;
			break;
		case 31:
			s11->s10->unk3 = s11->modify_val;
			break;
		default:
			_se->adlib_set_param(_channel, s11->param, s10->start_value + s11->modify_val);
			break;
		}
	}

	if (code&2 && s11->unk5)
		_se->adlib_key_onoff(_channel);
}


int HookDatas::query_param(int param, byte chan) {
	switch(param) {
	case 18:
		return _jump;
	case 19:
		return _transpose;
	case 20:
		return _part_onoff[chan];
	case 21:
		return _part_volume[chan];
	case 22:
		return _part_program[chan];
	case 23:
		return _part_transpose[chan];
	default:
		return -1;
	}
}

int HookDatas::set(byte cls, byte value, byte chan) {
	switch(cls) {
	case 0:
		_jump = value;
		break;
	case 1:
		_transpose = value;
		break;
	case 2:
		if (chan<16)
			_part_onoff[chan] = value;
		else if (chan==16)
			memset(_part_onoff, value, 16);
		break;
	case 3:
		if (chan<16)
			_part_volume[chan] = value;
		else if (chan==16)
			memset(_part_volume, value, 16);
		break;
	case 4:
		if (chan<16)
			_part_program[chan] = value;
		else if (chan==16)
			memset(_part_program, value, 16);
		break;
	case 5:
		if (chan<16)
			_part_transpose[chan] = value;
		else if (chan==16)
			memset(_part_transpose, value, 16);
		break;
	default:
		return -1;
	}
	return 0;
}


VolumeFader *SoundEngine::allocate_volume_fader() {
	VolumeFader *vf;
	int i;

	i = 8;
	vf = volume_fader;
	while (vf->active) {
		vf++;
		if (!--i)
			return NULL;
	}

	vf->active = true;
	_active_volume_faders = true;
	return vf;
}


uint32 SoundEngine::proc_16() {
	return _dword_6d8;
}

void SoundEngine::proc_7(uint32 a) {
	_dword_6d8 = a;
}

Player *SoundEngine::get_player_byid(int id) {
	int i;
	Player *s6,*found=NULL;

	for(i=0,s6=players; i<8; i++,s6++) {
		if (s6->_active && s6->_id==(uint16)id) {
			if(found)
				return NULL;
			found = s6;
		}
	}
	return found;
}

int SoundEngine::proc_15(uint a) {
	if (a<8)
		return table_1[a];
	return -1;
}

int SoundEngine::initialize(byte *ptr) {
	int i;
	if (_initialized)
		return -1;
	_master_volume = 127;
	for (i=0; i<8; i++)
		channel_volume[i] = channel_real_volume[i] = table_1[i] = 127;

	create_lookup_table();

	init_players();
	init_sustaining_notes();
	init_volume_fader();
	init_queue();
	init_7();
	init_parts();

	_initialized = true;
	
	return 0;
}

void SoundEngine::init_queue() {
	_queue_adding = false;
	_queue_pos = 0;
	_queue_end = 0;
	_trigger_count = 0;
}

void SoundEngine::init_7() {
	_scanning = false;
	_hardware_type = 1;
}


void AdlibChannel::set_volume(int a) {
	AdlibChannel *s;
	for(s=this; s; s = s->_next) {
		_se->adlib_set_param(s->_channel, 0, volume_table[lookup_table_a[s->_vol_2][a>>2]]);
		if (s->_twochan) {
			_se->adlib_set_param(s->_channel, 13, volume_table[lookup_table_a[s->_vol_1][a>>2]]);
		}
	}
}

void AdlibChannel::set_modwheel(int a) {
	AdlibChannel *s;
	for(s=this; s; s = s->_next) {
		if (s->_s10a.active && s->_s11a.unk4)
			s->_s10a.modwheel = a>>2;
		if (s->_s10b.active && s->_s11b.unk4)
			s->_s10b.modwheel = a>>2;
	}
}

void AdlibChannel::release_pedal() {
	AdlibChannel *s;
	for(s=this; s; s = s->_next) {
		if (s->_waitforpedal)
			s->off();
	}
}

void AdlibChannel::key_off(byte data) {
	AdlibChannel *s;
	for(s=this; s; s = s->_next) {
		if (s->_note == data)
			s->off();
	}
}

void AdlibChannel::key_off_pedal(byte data) {
	AdlibChannel *s;
	for(s=this; s; s = s->_next) {
		if (s->_note == data)
			s->_waitforpedal = true;
	}
}

void AdlibChannel::set_param(byte param, int value) {
	AdlibChannel *s;

	if (param < 28)
		for(s=this; s; s=s->_next)
			_se->adlib_set_param(s->_channel, param, value);
}


void SoundEngine::adlib_write(byte port, byte value) {
	if (_adlib_reg_cache[port] == value)
		return;
	_adlib_reg_cache[port] = value;
	OPLWriteReg(_opl, port, value);
}

void SoundEngine::adlib_key_off(int chan) {
	byte port = chan + 0xB0;
	adlib_write(port, adlib_read(port)&~0x20);
}

void SoundEngine::adlib_init() {
	_adlib_reg_cache = (byte*)calloc(256,1);
	_opl = OPLCreate(OPL_TYPE_YM3812,3579545,22050);
	adlib_write(1,0x20);
	adlib_write(8,0x40);
	adlib_write(0xBD, 0x00);
}

struct AdlibSetParams {
	byte a,b,c,d;
};

static const byte channel_mappings[9] = {
	0, 1, 2, 8,
	9,10,16,17,
	18
};

static const byte channel_mappings_2[9] = {
	3, 4, 5, 11,
	12,13,19,20,
	21
};

static const AdlibSetParams adlib_setparam_table[] = {
{0x40,0,63,63}, /* level */
{0xE0,2,0,0},   /* unused */
{0x40,6,192,0}, /* level key scaling */
{0x20,0,15,0},  /* modulator frequency multiple */
{0x60,4,240,15},/* attack rate */
{0x60,0,15,15}, /* decay rate */
{0x80,4,240,15}, /* sustain level */
{0x80,0,15,15}, /* release rate */
{0xE0,0,3,0},   /* waveform select */
{0x20,7,128,0}, /* amp mod */
{0x20,6,64,0},  /* vib */
{0x20,5,32,0},  /* eg typ */
{0x20,4,16,0},  /* ksr */
{0xC0,0,1,0},   /* decay alg */
{0xC0,1,14,0}   /* feedback */
};

void SoundEngine::adlib_set_param(int channel, byte param, int value) {
	const AdlibSetParams *as;
	byte port;

	assert(channel>=0 && channel<9);

	if (param <= 12) {
		port = channel_mappings_2[channel];
	} else if (param <= 25) {
		param -= 13;
		port = channel_mappings[channel];
	} else if (param <= 27) {
		param -= 13;
		port = channel;
	} else if (param==28 || param==29) {
		if (param==28)
			value -= 15;
		else
			value -= 383;
		value <<= 4;
		channel_table_2[channel] = value;
		adlib_playnote(channel, curnote_table[channel] + value);
		return;
	}else {
		return;
	}

	as = &adlib_setparam_table[param];
	if (as->d)
		value = as->d - value;
	port += as->a;
	adlib_write(port, (adlib_read(port) & ~as->c) | (((byte)value)<<as->b));
}

static const byte octave_numbers[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7
};

static const byte note_numbers[]= {
 3,   4,   5,   6,   7,   8,   9,  10,
11,  12,  13,  14,   3,   4,   5,   6,
 7,   8,   9,  10,  11,  12,  13,  14,
 3,   4,   5,   6,   7,   8,   9,  10,
11,  12,  13,  14,   3,   4,   5,   6,
 7,   8,   9,  10,  11,  12,  13,  14,
 3,   4,   5,   6,   7,   8,   9,  10,
11,  12,  13,  14,   3,   4,   5,   6,
 7,   8,   9,  10,  11,  12,  13,  14,
 3,   4,   5,   6,   7,   8,   9,  10,
11,  12,  13,  14,   3,   4,   5,   6,
 7,   8,   9,  10,  11,  12,  13,  14,
 3,   4,   5,   6,   7,   8,   9,  10,
11,  12,  13,  14,   3,   4,   5,   6,
 7,   8,   9,  10,  11,  12,  13,  14,
 3,   4,   5,   6,   7,   8,   9,  10
};

static const byte note_to_f_num[] = {
 90,  91,  92,  92,  93,  94,  94,  95,
 96,  96,  97,  98,  98,  99, 100, 101,
101, 102, 103, 104, 104, 105, 106, 107,
107, 108, 109, 110, 111, 111, 112, 113,
114, 115, 115, 116, 117, 118, 119, 120,
121, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 132, 133, 134,
135, 136, 137, 138, 139, 140, 141, 142,
143, 145, 146, 147, 148, 149, 150, 151,
152, 153, 154, 155, 157, 158, 159, 160,
161, 162, 163, 165, 166, 167, 168, 169,
171, 172, 173, 174, 176, 177, 178, 180,
181, 182, 184, 185, 186, 188, 189, 190,
192, 193, 194, 196, 197, 199, 200, 202,
203, 205, 206, 208, 209, 211, 212, 214,
215, 217, 218, 220, 222, 223, 225, 226,
228, 230, 231, 233, 235, 236, 238, 240,
242, 243, 245, 247, 249, 251, 252, 254,
};

void SoundEngine::adlib_playnote(int channel, int note) {
	byte old,oct,notex;
	int note2;
	int i;

	note2 = (note>>7) - 4;

	oct = octave_numbers[note2]<<2;
	notex = note_numbers[note2];

	old = adlib_read(channel + 0xB0);
	if (old&0x20) {
		old &= ~0x20;
		if (oct > old) {
			if (notex < 6) {
				notex += 12;
				oct -= 4;
			}
		} else if (oct < old) {
			if (notex > 11) {
				notex -= 12;
				oct += 4;
			}
		}
	}
	
	i = (notex<<3) + ((note>>4)&0x7);
	adlib_write(channel + 0xA0, note_to_f_num[i]);
	adlib_write(channel + 0xB0, oct|0x20);
}

void SoundEngine::adlib_note_on(int chan, byte note, int mod) {
	int code;
	assert(chan>=0 && chan<9);
	code = (note<<7) + mod;
	curnote_table[chan] = code;
	adlib_playnote(chan, channel_table_2[chan] + code);
}

void SoundEngine::adlib_note_on_ex(int chan, byte note, int mod) {
	int code;
	assert(chan>=0 && chan<9);
	code = (note<<7) + mod;
	curnote_table[chan] = code;
	channel_table_2[chan] = 0;
	adlib_playnote(chan, code);
}

void SoundEngine::adlib_setup_channel(int chan, Instrument *instr, byte vol_1, byte vol_2) {
	byte port;

	assert(chan>=0 && chan<9);

	port = channel_mappings[chan];
	adlib_write(port + 0x20, instr->flags_1);
	adlib_write(port + 0x40, (instr->oplvl_1|0x3F) - vol_1);
	adlib_write(port + 0x60, ~instr->atdec_1);
	adlib_write(port + 0x80, ~instr->sustrel_1);
	adlib_write(port + 0xE0, instr->waveform_1);
	
	port = channel_mappings_2[chan];
	adlib_write(port + 0x20, instr->flags_2);
	adlib_write(port + 0x40, (instr->oplvl_2|0x3F) - vol_2);
	adlib_write(port + 0x60, ~instr->atdec_2);
	adlib_write(port + 0x80, ~instr->sustrel_2);
	adlib_write(port + 0xE0, instr->waveform_2);

	adlib_write((byte)chan + 0xC0, instr->feedback);
}

int SoundEngine::adlib_read_param(int chan, byte param) {
	const AdlibSetParams *as;
	byte val;
	byte port;

	assert(chan>=0 && chan<9);

	if (param <= 12) {
		port = channel_mappings_2[chan];
	} else if (param <= 25) {
		param -= 13;
		port = channel_mappings[chan];
	} else if (param <= 27) {
		param -= 13;
		port = chan;
	} else if (param==28) {
		return 0xF;
	} else if (param==29) {
		return 0x17F;
	} else {
		return 0;
	}

	as = &adlib_setparam_table[param];
	val = adlib_read(port + as->a);
	val &= as->c;
	val >>= as->b;
	if (as->d)
		val = as->d - val;

	return val;
}



--- NEW FILE: akos.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001  Ludvig Strigeus
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/akos.cpp,v 1.3.2.1 2001/12/20 00:27:21 yazoo Exp $
 *
[...1059 lines suppressed...]
	case 1: return a!=b;
	case 2: return a<b;
	case 3: return a<=b;
	case 4: return a>b;
	default: return a>=b;
	}
}

int Scumm::getAnimVar(Actor *a, byte var) {
	assert(var>=0 && var<=15);
	return a->animVariable[var];
}

void Scumm::setAnimVar(Actor *a, byte var, int value) {
	assert(var>=0 && var<=15);
	a->animVariable[var] = value;
}


#endif

--- NEW FILE: gui.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001 The ScummVM project
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/gui.cpp,v 1.6.2.1 2001/12/20 00:27:21 yazoo Exp $
 */

#include "stdafx.h"
#include "scumm.h"
#include "gui.h"

enum {
	SAVELOAD_DIALOG,
	PAUSE_DIALOG
};

void Gui::draw(int start,int end) {
	int i;

	if (end==-1)
		end=start;

	for (i=0; i<sizeof(_widgets) / sizeof(_widgets[0]); i++) {
		const GuiWidget *w = _widgets[i];
		if (w) {
			_parentX = 0;
			_parentY = 0;
			while (w->_type != GUI_NONE) {
				if (w->_id>=start && w->_id<=end && (w->_page&(1<<_cur_page)) ) {
					drawWidget(w);
				}
				if (w->_flags & GWF_PARENT) {
					_parentX += w->_x;
					_parentY += w->_y;
				}
				w++;
			}
		}
	}
}

const GuiWidget *Gui::widgetFromPos(int x, int y) {
	int i;

	for (i=sizeof(_widgets) / sizeof(_widgets[0])-1; i>=0; i--) {
		const GuiWidget *w = _widgets[i];
		if (w) {
			while (w->_type != GUI_NONE) {
				if ((w->_page&(1<<_cur_page)) && w->_id && 
						(uint16)(x-w->_x) < w->_w && (uint16)(y-w->_y) < w->_h)
					return w;
				if (w->_flags & GWF_PARENT) {
					x -= w->_x;
					y -= w->_y;
				}
				w++;
			}
		}
	}
	return NULL;
}

void Gui::drawString(const char *str, int x, int y, int w, byte color, bool center) {
	StringTab *st = &_s->string[5];
	st->charset = 1;
	st->center = center;
	st->color = color;
	st->xpos = x;
	st->ypos = y;
	st->right = x + w;
	_s->_messagePtr = (byte*)str;
	_s->drawString(5);
}

void Gui::drawWidget(const GuiWidget *w) {
	const char *s;
	int x,y;

	x = w->_x;
	y = w->_y;

	if (w->_flags & GWF_CLEARBG)
		widgetClear(w);
		
	if (w->_flags & GWF_BORDER) {
		widgetBorder(w);
		x += 4;
		y += 4;
	}

	switch(w->_type) {
	case GUI_TEXT:
		s = queryString(w->_string_number,w->_id);
		if (s)
			drawString(s, x+_parentX, y+_parentY, w->_w,
				(_clickWidget && _clickWidget==w->_id) ? _textcolorhi : _textcolor,
				false);
		break;
	case GUI_IMAGE:
		;
	}
}

void Gui::widgetClear(const GuiWidget *wid) {
	int x,y,w,h;
	int i,j;

	x = wid->_x;
	y = wid->_y;
	w = wid->_w;
	h = wid->_h;
	
	byte *ptr = getBasePtr(x,y);
	if(ptr==NULL)
		return;

	_s->setVirtscreenDirty(_vs, x+_parentX, y+_parentY, x+_parentX+w, y+_parentY+h);

	if (wid->_flags & GWF_BORDER) {
		ptr += 320 + 1;
		w-=2;
		h-=2;
	}
	
	while (--h>=0) {
		for(i=0; i<w; i++)
			ptr[i] = _bgcolor;
		ptr += 320;
	}
}

void Gui::widgetBorder(const GuiWidget *w) {
	int x = w->_x, y = w->_y;
	int x2 = x + w->_w-1, y2 = y + w->_h-1;
	int i;
	byte tmp;
	
	hline(x+1,y,x2-1);
	hline(x,y+1,x2);
	vline(x,y+1,y2-1);
	vline(x+1,y,y2);

	tmp = _color;
	_color = _shadowcolor;

	hline(x+1,y2-1,x2);
	hline(x+1,y2,x2-1);
	vline(x2,y+1,y2-1);
	vline(x2-1,y+1,y2);

	_color = tmp;
}

void Gui::hline(int x, int y, int x2) {
	moveto(x,y);
	lineto(x2,y);
}

void Gui::vline(int x, int y, int y2) {
	moveto(x,y);
	lineto(x,y2);
}

void Gui::moveto(int x, int y) {
	_curX = x;
	_curY = y;
}

byte *Gui::getBasePtr(int x, int y) {
	x += _parentX;
	y += _parentY;
	_vs = _s->findVirtScreen(y);
	if (_vs==NULL)
		return NULL;
	return _s->getResourceAddress(rtBuffer, _vs->number+1) + x + (y-_vs->topline)*320 + _s->_screenStartStrip*8;
}

void Gui::lineto(int x, int y) {
	byte *ptr;
	int x2 = _curX;
	int y2 = _curY;

	_curX = x;
	_curY = y;

	if (x2 < x)
		x2^=x^=x2^=x;

	if (y2 < y)
		y2^=y^=y2^=y;

	ptr = getBasePtr(x, y);
	if (ptr==NULL)
		return;

	if (x==x2) {
		/* vertical line */
		while (y++ <= y2) {
			*ptr = _color;
			ptr += 320;
		}
	} else if (y==y2) {
		/* horizontal line */
		while (x++ <= x2) {
			*ptr++ = _color;
		}
	}
}

void Gui::leftMouseClick(int x, int y) {
	const GuiWidget *w = widgetFromPos(x,y);
	int old;
	
	_clickTimer = 0;

	old = _clickWidget;
	_clickWidget = w?w->_id : 0;

	if (old)
		draw(old);
	if (_clickWidget) {
		draw(_clickWidget);
		if(w->_flags&GWF_DELAY)
			_clickTimer = 5;
		else
			handleCommand(_clickWidget);
	}
}

const GuiWidget save_load_dialog[] = {
	{GUI_STAT,0xFF,GWF_DEFAULT|GWF_PARENT,30,20,260,120,0,0},
	{GUI_TEXT,0x01,0,40,5,128,16,0,1}, /* How may I serve you? */
	{GUI_TEXT,0x02,0,40,5,128,16,0,2}, /* Select a game to LOAD */
	{GUI_TEXT,0x04,0,40,5,128,16,0,3}, /* Name your SAVE game */

	{GUI_STAT,0xFF,GWF_DEFAULT,6,16,170,96,0,0},
	{GUI_TEXT,0x01,GWF_DEFAULT,180,20,16,40,0,0},
	{GUI_TEXT,0x01,GWF_DEFAULT,180,66,16,40,0,0},
	{GUI_TEXT,0xFE,GWF_DEFAULT,180,20,16,40,1,0},
	{GUI_TEXT,0xFE,GWF_DEFAULT,180,66,16,40,2,0},
	
	{GUI_TEXT,0x06,GWF_CLEARBG,10,20,160,10,20,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,30,160,10,21,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,40,160,10,22,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,50,160,10,23,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,60,160,10,24,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,70,160,10,25,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,80,160,10,26,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,90,160,10,27,0},
	{GUI_TEXT,0x06,GWF_CLEARBG,10,100,160,10,28,0},

	{GUI_TEXT,0x01,GWF_BUTTON,200,25,54,16,3,4}, /* Save */
	{GUI_TEXT,0x01,GWF_BUTTON,200,45,54,16,4,5}, /* Load */
	{GUI_TEXT,0x01,GWF_BUTTON,200,65,54,16,5,6}, /* Play */
	{GUI_TEXT,0x01,GWF_BUTTON,200,85,54,16,6,8}, /* Quit */

	{GUI_TEXT,0x02,GWF_BUTTON,200,50,54,16,7,7}, /* Cancel */

	{GUI_TEXT,0x04,GWF_BUTTON,200,45,54,16,8,9}, /* Ok */
	{GUI_TEXT,0x04,GWF_BUTTON,200,65,54,16,7,7}, /* Cancel */
	{0}
};

const GuiWidget pause_dialog[] = {
	{GUI_TEXT,0x01,GWF_DEFAULT,50,80,220,16,0,10},
	{0},
};


void Gui::handleCommand(int cmd) {
	int lastEdit = _editString;
	showCaret(false);

	switch(cmd) {
	case 1: /* up button */
		if (_slotIndex==0)
			return;
		getSavegameNames(_slotIndex-9);
		draw(20,28);
		return;
	case 2:
		if (_slotIndex > 80)
			return;
		getSavegameNames(_slotIndex+9);
		draw(20,28);
		return;
	case 3: /* save button */
		_cur_page = 2;
		getSavegameNames(0);
		draw(0,100);
		return;
	case 4: /* load button */
		_cur_page = 1;
		getSavegameNames(0);
		draw(0,100);
		return;
	case 5: /* play button */
		close();
		return;
	case 6: /* quit button */
		exit(1);
		return;
	case 7: /* cancel button */
		_cur_page = 0;
		draw(0,100);
		return;
	case 8:
		if (lastEdit==-1 || game_names[lastEdit][0]==0)
			return;
		_s->_saveLoadSlot = lastEdit + _slotIndex;
		_s->_saveLoadCompatible = false;
		_s->_saveLoadFlag = 1;
		memcpy(_s->_saveLoadName, game_names[lastEdit], sizeof(_s->_saveLoadName));
		close();
		return;
	default:
		if (cmd>=20 && cmd<=28) {
			if(_cur_page==1) {
				if (valid_games[cmd-20]) {
					_s->_saveLoadSlot = cmd-20+_slotIndex;
					_s->_saveLoadCompatible = false;
					_s->_saveLoadFlag = 2;
					close();
				}
				return;
			} else if (_cur_page==2) {
				_clickWidget = cmd;
				editString(cmd - 20);
			}
		}
	}

}

void Gui::getSavegameNames(int start) {
	int i;
	_slotIndex = start;
	for(i=0; i<9; i++,start++) {
		valid_games[i] = _s->getSavegameName(start, game_names[i]);
	}
}

const byte string_map_table_v6[] = {
	117, /* How may I serve you? */
	109, /* Select a game to LOAD */
	108, /* Name your SAVE game */
  96,  /* Save */
	97,  /* Load */
	98,  /* Play */
	99,  /* Cancel */
	100, /* Quit */
	101, /* Ok */
	93,  /* Game paused */
};

const byte string_map_table_v5[] = {
	0, /* How may I serve you? */
	20, /* Select a game to LOAD */
	19, /* Name your SAVE game */
  7,  /* Save */
	8,  /* Load */
	9,  /* Play */
	10,  /* Cancel */
	11, /* Quit */
	12, /* Ok */
	4,  /* Game paused */
};

const char *Gui::queryString(int string, int id) {
	static char namebuf[64];
	if (id>=20 && id<=28) {
		sprintf(namebuf, "%2d. %s", id-20+_slotIndex, game_names[id-20]);
		return namebuf;
	}

	if (_s->_features&GF_AFTER_V6) {
		string = _s->_vars[string_map_table_v6[string-1]];
	} else {
		string = string_map_table_v5[string-1];
	}
	
	return (char*)_s->getStringAddress(string);
}

void Gui::showCaret(bool show) {
	int i;
	char *s;

	if (_editString==-1)
		return;

	i = _editLen;
	s = game_names[_editString];

	if (show) {
		if (i < SAVEGAME_NAME_LEN-1) {
			s[i] = '_';
			s[i+1] = 0;
		}
	} else {
		s[i] = 0;
	}
	
	draw(_editString + 20);

	if (!show)
		_editString = -1;
}

void Gui::editString(int i) {
	char *s = game_names[i];
	if(!valid_games[i]) {
		valid_games[i] = true;
		*s = 0;
	}
	_editString = i;
	_editLen = strlen(s);
	showCaret(true);
}

void Gui::addLetter(byte letter) {
	switch(_dialog) {
	case SAVELOAD_DIALOG:
		if (_editString==-1)
			return;

		if (letter==13) {
			handleCommand(8);
			return;
		}

		if (letter>=32 && letter<128 && _editLen < SAVEGAME_NAME_LEN-1) {
			game_names[_editString][_editLen++] = letter;	
		} else if (letter==8 && _editLen>0) {
			_editLen--;
		}
		showCaret(true);
		break;
	case PAUSE_DIALOG:
		if (letter==32)
			close();
		break;
	}
}

byte Gui::getDefaultColor(int color) {
#if defined(FULL_THROTTLE)
	return 0;
#else
	if (_s->_features&GF_AFTER_V6) {
		if (color==8) color=1;
		return _s->readArray(110, 0, color);
	} else {
		return _s->getStringAddress(21)[color];
	}
#endif
}

void Gui::init(Scumm *s) {
	_s = s;
	_bgcolor = getDefaultColor(0);
	_color = getDefaultColor(1);
	_textcolor = getDefaultColor(2);
	_textcolorhi = getDefaultColor(6);
	_shadowcolor = getDefaultColor(8);
}

void Gui::loop() {
	if (_active==1) {
		_active++;
		draw(0,100);
		_s->_cursorAnimate++;
		_s->gdi._cursorActive = 1;
		_s->pauseSounds(true);
	}
	
	_s->getKeyInput(0);
	if (_s->_mouseButStat&MBS_LEFT_CLICK) {
		leftMouseClick(_s->mouse.x, _s->mouse.y);
	} else if (_s->_lastKeyHit) {
		addLetter(_s->_lastKeyHit);
	}
	
	if (_clickTimer && !--_clickTimer) {
		int old = _clickWidget;
		_clickWidget = 0;
		draw(old);
		handleCommand(old);
	}
	
	_s->drawDirtyScreenParts();
	_s->_mouseButStat = 0;
}

void Gui::close() {
	_s->_fullRedraw = true;
	_s->_completeScreenRedraw = true;
	_s->_cursorAnimate--;
	_s->pauseSounds(false);
	_active = false;
}

void Gui::saveLoadDialog() {
	_widgets[0] = save_load_dialog;
	_editString = -1;
	_cur_page = 0;
	_active = true;
	_dialog = SAVELOAD_DIALOG;
}

void Gui::pause() {
	_widgets[0] = pause_dialog;
	_active = true;
	_dialog = PAUSE_DIALOG;
}

--- NEW FILE: debugrl.cpp ---
#ifdef HAVE_READLINE

#include "debugrl.h"

// A lot of this was ripped straight from the readline fileman.c example.

char* _debugger_commands[] = {
  "help",
  "quit",
  "go",
  "actor",
  "scripts",
  "exit",
  (char *)NULL
};


// forwards decls
char ** scumm_debugger_completion (const char *text, int start, int end);
char * scumm_debugger_command_generator (const char *text, int state);

void initialize_readline () {
  /* Allow conditional parsing of the ~/.inputrc file. */
  rl_readline_name = "scummvm";

  /* Tell the completer that we want a crack first. */
  rl_attempted_completion_function = scumm_debugger_completion;
}

char ** scumm_debugger_completion (const char *text, int start, int end) {

  char **matches;

  matches = (char **)NULL;

  // If this word is at the start of the line, then it is a command
  // to complete.
  if (start == 0) {
    matches = rl_completion_matches (text, scumm_debugger_command_generator);
  } else {
    // At some stage it'd be nice to have symbolic actor name completion
    // or something similarly groovy. Not right now though.
  }

  // This just makes sure that readline doesn't try to use its default
  // completer, which uses filenames in the current dir, if we can't find 
  // a match, since filenames don't have much use in the debuger :)
  // There's probably a nice way to do this once, rather than every time.
  rl_attempted_completion_over = 1;
  
  return (matches);
}


/* Generator function for command completion.  STATE lets us know whether
   to start from scratch; without any state (i.e. STATE == 0), then we
   start at the top of the list. */
char * scumm_debugger_command_generator (const char *text, int state) {

  static int list_index, len;
  char *name;

  /* If this is a new word to complete, initialize now.  This includes
     saving the length of TEXT for efficiency, and initializing the index
     variable to 0. */
  if (!state)
    {
      list_index = 0;
      len = strlen (text);
    }

  /* Return the next name which partially matches from the command list. */
  while (name = _debugger_commands[list_index])
    {
      list_index++;

      if (strncmp (name, text, len) == 0)
        //return (dupstr(name));
        return strdup(name);
    }

  /* If no names matched, then return NULL. */
  return ((char *)NULL);
}

#endif /* HAVE_READLINE */





More information about the Scummvm-git-logs mailing list