struct instr { word y0; byte y2; } struct freqmod { byte zz0; byte zz1; /* freqmod_incr */ byte zz2; /* freqmod_mult */ byte zz3; byte zz4; /* freqmod_table */ } struct instrument { struct channel *z6; struct freqmod *z8; byte z10; /* on/off */ byte z14; /* transpose */ word z1c; /* 128th transpose */ } struct channel { byte x0; /* active */ struct instrument *x2; /* pointer to instrument???? */ word x4; /* note */ byte x6; /* notelen */ word x8; /* freqmod_table */ byte xa; /* freqmod_offset */ byte xb; /* freqmod_incr */ byte xc; /* freqmod_mult */ byte xd; word xe; /* freqmod */ struct instr x10; struct instr x38; word x60; /* modulation?? */ } channel *get_channel(int i) { return &channels[i]; } int init_instruments() { for (i = 0; i < 6; i++) { instruments[i].z0 = 0; instruments[i].z2 = 0; instruments[i].z4 = 0; channel = get_channel(i); instruments[i].z6 = channel; channel->x2 = &instruments[i]; instruments[i].z8 = get_struct_19f4(i); } init_channels(); } int init_channels() { winning_channel = 0; for (i = 0; i < 6; i++) { channels[i].x0 = 0; channels[i].x10.y26 = &channels[i].x38; channels[i].x38.y26 = &channels[i].x10; } word_1a7e = 0; } int set_note(instrument??, int note, int vol) { channel = ???->x6; loc2 = ???->x8; channel->x4 = note; channel->x5 = 0; channel->x6 = loc2->r0; channel->x8 = freqmod_table + 256 * loc2->r4; channel->xa = 0; channel->xb = loc2->r1; channel->xc = loc2->r2; channel->xe = 0; channel->x60 = 0; channel->x0 = 1; find_winning_channel(); channel->xc = fixmul_tab[vol>>1][loc2->r3]; } play_note_in_channel(channel) { if (channel != winning_channel) return; if (channel->x2->z10) { play_note(((winning_channel->x2->z14 + winning_channel->x4) << 7) + winning_channel->x2->z1c + winning_channel->x60 + winning_channel->xe); } else { spk_off(); } } int timer_3 { if (winning_channel == 0) return; word_1a7e += 3433; while (word_1a7e >= 4167) { word_1a7e -= 4167; for (i = 0; i < 6; i++) { if (channels[i].x0 != 1) continue; if (channels[i].x6 && !--channels[i].x6) { channels[i].x0 = 0; find_winning_channel(); return; } if (channels[i].xb && channels[i].xc) { channels[i].xa += channels[i].xb; channels[i].xe = (channels[i].x8[channels[i].xa] * channels[i].xc) >> 4; } if (++byte_1ccc <= 3) continue; byte_1ccc = 0; if (channels[i].x10.y0) sub_3e74(&channels[i], &channels[i].x10, &channels[i].x10.y22); if (channels[i].x38.y0) sub_3e74(&channels[i], &channels[i].x38, &channels[i].x38.y22); } if (winning_channel->x2->z10) { play_note(((winning_channel->x2->z14 + winning_channel->x4) << 7) + winning_channel->x2->z1c + winning_channel->x60 + winning_channel->xe); } else { spk_off(); } } } find_winning_channel() { int max = 0; for (i = 0; i < 6; i++) { if (channels[i].x0 != 1) continue; if (channels[i].x2->z14 >= max) { /* highest instrument wins */ winning_channel = &channels[i]; max = channels[i].x2->z14; } } if (!winning_channel || !winning_channel->x2->z10) { spk_off(); return; } else { play_note(((winning_channel->x2->z14 + winning_channel->x4) << 7) + winning_channel->x2->z1c + winning_channel->x60 + winning_channel->xe); } } sub_3e74(channel, instr, instr2) { if (!(sub_40f0(instr, instr2) & 1)) return; switch (instr2->q2) { case 0: case 1: channel->x60 = instr2->q0 << 4; break; case 2: channel->xb = channel->x2->z8->zz1 + instr2->q0; break; case 3: channel->xc = channel->x2->z8->zz2 + instr2->q0; break; case 4: channel->x8 = freqmod_table + 256 * (channel->x2->z8->zz4 + instr2->q0); break; case 5: instr2->q4->yy14 = instr2->q0; case 6: instr2->q4->yy13 = instr2->q0; } } int sub_4002(instr) { ax = instr->y13; cx = instr->y0; loca = instr->y13; loc1 = cx; cx = instr->yb[loc1]; } int sub_40f0(instr, instr2) { result = 0; if (instr->y4) { instr->y4 -= 17; if (instr->y4 <= 0) { instr->y0 = 0; return 0; } } di = instr->y2 + instr->y1a; instr->y20 += instr->y1e; if (instr->y20 >= instr->y16) { instr->y20 -= instr->y16; di += instr->y1c; } if (instr->y2 != di || instr->y14 != instr->y15) { instr->y2 = di; instr->y15 = instr->y14; di = fixmul(instr->y2, instr->y15); if (di != instr2->q0) { instr2->q0 = di; result = 1; } } if (--instr->y18) return result; if (++instr->y0 > 4) { if (instr->ya) { instr->y0 = 1; result |= 2; } else { instr->y0 = 0; return result; } } sub_4002(instr); return result; } int fixmul(int a, int b) { if (b == 0) return 0; if (b = 0x1f) return a; if (a <= 63 && a >= -63) { if (b < 0) { if (a < 0) { return fixmul_table[-a][-b]; } else { return fixmul_table[a][-b]; } } else { if (a < 0) { return fixmul_table[-a][b]; } else { return fixmul_table[a][b]; } } } return ((long long)b * (a+1)) >> 5 }