Mercurial > audlegacy-plugins
view src/adplug/core/rix.cxx @ 1510:3a252050736c
replace tuple_formatter_process_string() with tuple_formatter_make_title_string() except that for streamings.
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Tue, 21 Aug 2007 17:11:59 +0900 |
parents | 4709ce4e209e |
children | be86c72a06c9 |
line wrap: on
line source
/* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * rix.cpp - Softstar RIX OPL Format Player by palxex <palxex.ys168.com> * BSPAL <BSPAL.ys168.com> */ #include "rix.h" #include "debug.h" const unsigned char CrixPlayer::adflag[] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }; const unsigned char CrixPlayer::reg_data[] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; const unsigned char CrixPlayer::ad_C0_offs[] = { 0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8 }; const unsigned char CrixPlayer::modify[] = { 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17, 12, 15, 16, 0, 14, 0, 17, 0, 13, 0 }; const unsigned char CrixPlayer::bd_reg_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x01, 0x01, 0x03, 0x0F, 0x05, 0x00, 0x01, 0x03, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x0F, 0x07, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x04, 0x00, 0x08, 0x0C, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x04, 0x00, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x0F, 0x0B, 0x00, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0F, 0x0B, 0x00, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x0B, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x0B, 0x00, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char CrixPlayer::for40reg[] = { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F }; unsigned short CrixPlayer::mus_time = 0x4268; /*** public methods *************************************/ CPlayer * CrixPlayer::factory (Copl * newopl) { return new CrixPlayer (newopl); } CrixPlayer::CrixPlayer (Copl * newopl):CPlayer (newopl), flag_mkf (0), file_buffer (0), buf_addr (0) { } CrixPlayer::~CrixPlayer () { if (file_buffer) delete[]file_buffer; } bool CrixPlayer::load (VFSFile * fd, const CFileProvider & fp) { binistream *f = fp.open (fd); if (!f) return false; unsigned long i = 0; std::string filename (fd->uri); if (stricmp (filename.substr (filename.length () - 4, 4).c_str (), ".mkf") == 0) { flag_mkf = 1; f->seek (0); int offset = f->readInt (4); f->seek (offset); } if (f->readInt (2) != 0x55aa) { fp.close (f); return false; } file_buffer = new unsigned char[fp.filesize (f) + 1]; f->seek (0); while (!f->eof ()) file_buffer[i++] = f->readInt (1); length = i; fp.close (f); if (!flag_mkf) buf_addr = file_buffer; rewind (0); return true; } bool CrixPlayer::update () { int_08h_entry (); return !play_end; } void CrixPlayer::rewind (int subsong) { I = 0; T = 0; mus_block = 0; ins_block = 0; rhythm = 0; music_on = 0; pause_flag = 0; band = 0; band_low = 0; e0_reg_flag = 0; bd_modify = 0; sustain = 0; play_end = 0; pos = index = 0; memset (f_buffer, 0, sizeof (unsigned short) * 300); memset (a0b0_data2, 0, sizeof (unsigned short) * 11); memset (a0b0_data3, 0, 18); memset (a0b0_data4, 0, 18); memset (a0b0_data5, 0, 96); memset (addrs_head, 0, 96); memset (insbuf, 0, 28 * sizeof (unsigned short)); memset (displace, 0, 11 * sizeof (unsigned short)); memset (reg_bufs, 0, 18 * sizeof (ADDT)); if (flag_mkf) { unsigned int *buf_index = (unsigned int *) file_buffer; int offset1 = buf_index[subsong], offset2; while ((offset2 = buf_index[++subsong]) == offset1); length = offset2 - offset1 + 1; buf_addr = file_buffer + offset1; } opl->init (); opl->write (1, 32); // go to OPL2 mode set_new_int (); data_initial (); } unsigned int CrixPlayer::getsubsongs () { if (flag_mkf) { unsigned int *buf_index = (unsigned int *) file_buffer; int songs = buf_index[0] / 4, i = 0; for (i = 0; i < songs; i++) if (buf_index[i + 1] == buf_index[i]) songs--; return songs; } else return 1; } float CrixPlayer::getrefresh () { return 70.0f; } /*------------------Implemention----------------------------*/ inline void CrixPlayer::set_new_int () { // if(!ad_initial()) exit(1); ad_initial (); } /*----------------------------------------------------------*/ inline void CrixPlayer::Pause () { register unsigned short i; pause_flag = 1; for (i = 0; i < 11; i++) switch_ad_bd (i); } /*----------------------------------------------------------*/ inline void CrixPlayer::ad_a0b0l_reg_ (unsigned short index, unsigned short p2, unsigned short p3) { // unsigned short i = p2+a0b0_data2[index]; a0b0_data4[index] = p3; a0b0_data3[index] = p2; } inline void CrixPlayer::data_initial () { rhythm = buf_addr[2]; mus_block = (buf_addr[0x0D] << 8) + buf_addr[0x0C]; ins_block = (buf_addr[0x09] << 8) + buf_addr[0x08]; I = mus_block + 1; if (rhythm != 0) { // ad_a0b0_reg(6); // ad_a0b0_reg(7); // ad_a0b0_reg(8); ad_a0b0l_reg_ (8, 0x18, 0); ad_a0b0l_reg_ (7, 0x1F, 0); } bd_modify = 0; // ad_bd_reg(); band = 0; music_on = 1; } /*----------------------------------------------------------*/ inline unsigned short CrixPlayer::ad_initial () { register unsigned short i, j, k = 0; for (i = 0; i < 25; i++) { f_buffer[i * 12] = (unsigned int) ((i * 24 + 10000) * 0.27461678223 + 4) >> 3; for (int t = 1; t < 12; t++) f_buffer[i * 12 + t] = (unsigned int) ((double) f_buffer[i * 12 + t - 1] * 1.06); } for (i = 0; i < 8; i++) for (j = 0; j < 12; j++) { a0b0_data5[k] = i; addrs_head[k] = j; k++; } //ad_bd_reg(); //ad_08_reg(); //for(i=0;i<9;i++) ad_a0b0_reg(i); e0_reg_flag = 0x20; //for(i=0;i<18;i++) ad_bop(0xE0+reg_data[i],0); //ad_bop(1,e0_reg_flag); return 1; //ad_test(); } /*----------------------------------------------------------*/ inline void CrixPlayer::ad_bop (unsigned short reg, unsigned short value) { if (reg == 2 || reg == 3) AdPlug_LogWrite ("switch OPL2/3 mode!\n"); opl->write (reg & 0xff, value & 0xff); } /*--------------------------------------------------------------*/ inline void CrixPlayer::int_08h_entry () { unsigned short band_sus = 1; while (band_sus) { if (sustain <= 0) { band_sus = rix_proc (); if (band_sus) sustain += band_sus; else { play_end = 1; break; } } else { if (band_sus) sustain -= 14; /* aging */ break; } } } /*--------------------------------------------------------------*/ inline unsigned short CrixPlayer::rix_proc () { unsigned char ctrl = 0; if (music_on == 0 || pause_flag == 1) return 0; band = 0; while (buf_addr[I] != 0x80 && I < length - 1) { band_low = buf_addr[I - 1]; ctrl = buf_addr[I]; I += 2; switch (ctrl & 0xF0) { case 0x90: rix_get_ins (); rix_90_pro (ctrl & 0x0F); break; case 0xA0: rix_A0_pro (ctrl & 0x0F, ((unsigned short) band_low) << 6); break; case 0xB0: rix_B0_pro (ctrl & 0x0F, band_low); break; case 0xC0: switch_ad_bd (ctrl & 0x0F); if (band_low != 0) rix_C0_pro (ctrl & 0x0F, band_low); break; default: band = (ctrl << 8) + band_low; break; } if (band != 0) return band; } music_ctrl (); I = mus_block + 1; band = 0; music_on = 1; return 0; } /*--------------------------------------------------------------*/ inline void CrixPlayer::rix_get_ins () { int i; unsigned char *baddr = (&buf_addr[ins_block]) + (band_low << 6); for (i = 0; i < 28; i++) insbuf[i] = (baddr[i * 2 + 1] << 8) + baddr[i * 2]; } /*--------------------------------------------------------------*/ inline void CrixPlayer::rix_90_pro (unsigned short ctrl_l) { if (rhythm == 0 || ctrl_l < 6) { ins_to_reg (modify[ctrl_l * 2], insbuf, insbuf[26]); ins_to_reg (modify[ctrl_l * 2 + 1], insbuf + 13, insbuf[27]); return; } else if (ctrl_l > 6) { ins_to_reg (modify[ctrl_l * 2 + 6], insbuf, insbuf[26]); return; } else { ins_to_reg (12, insbuf, insbuf[26]); ins_to_reg (15, insbuf + 13, insbuf[27]); return; } } /*--------------------------------------------------------------*/ inline void CrixPlayer::rix_A0_pro (unsigned short ctrl_l, unsigned short index) { if (rhythm == 0 || ctrl_l <= 6) { prepare_a0b0 (ctrl_l, index > 0x3FFF ? 0x3FFF : index); ad_a0b0l_reg (ctrl_l, a0b0_data3[ctrl_l], a0b0_data4[ctrl_l]); } else return; } /*--------------------------------------------------------------*/ inline void CrixPlayer::prepare_a0b0 (unsigned short index, unsigned short v) /* important ! */ { short high = 0, low = 0; unsigned int res; int res1 = (v - 0x2000) * 0x19; if (res1 == (int) 0xff) return; low = res1 / 0x2000; if (low < 0) { low = 0x18 - low; high = (signed short) low < 0 ? 0xFFFF : 0; res = high; res <<= 16; res += low; low = ((signed short) res) / (signed short) 0xFFE7; a0b0_data2[index] = low; low = res; res = low - 0x18; high = (signed short) res % 0x19; low = (signed short) res / 0x19; if (high != 0) { low = 0x19; low = low - high; } } else { res = high = low; low = (signed short) res / (signed short) 0x19; a0b0_data2[index] = low; res = high; low = (signed short) res % (signed short) 0x19; } low = (signed short) low *(signed short) 0x18; displace[index] = low; } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_a0b0l_reg (unsigned short index, unsigned short p2, unsigned short p3) { unsigned short data; unsigned short i = p2 + a0b0_data2[index]; a0b0_data4[index] = p3; a0b0_data3[index] = p2; i = ((signed short) i <= 0x5F ? i : 0x5F); i = ((signed short) i >= 0 ? i : 0); data = f_buffer[addrs_head[i] + displace[index] / 2]; ad_bop (0xA0 + index, data); data = a0b0_data5[i] * 4 + (p3 < 1 ? 0 : 0x20) + ((data >> 8) & 3); ad_bop (0xB0 + index, data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::rix_B0_pro (unsigned short ctrl_l, unsigned short index) { register int temp = 0; if (rhythm == 0 || ctrl_l < 6) temp = modify[ctrl_l * 2 + 1]; else { temp = ctrl_l > 6 ? ctrl_l * 2 : ctrl_l * 2 + 1; temp = modify[temp + 6]; } for40reg[temp] = index > 0x7F ? 0x7F : index; ad_40_reg (temp); } /*--------------------------------------------------------------*/ inline void CrixPlayer::rix_C0_pro (unsigned short ctrl_l, unsigned short index) { register unsigned short i = index >= 12 ? index - 12 : 0; if (ctrl_l < 6 || rhythm == 0) { ad_a0b0l_reg (ctrl_l, i, 1); return; } else { if (ctrl_l != 6) { if (ctrl_l == 8) { ad_a0b0l_reg (ctrl_l, i, 0); ad_a0b0l_reg (7, i + 7, 0); } } else ad_a0b0l_reg (ctrl_l, i, 0); bd_modify |= bd_reg_data[ctrl_l]; ad_bd_reg (); return; } } /*--------------------------------------------------------------*/ inline void CrixPlayer::switch_ad_bd (unsigned short index) { if (rhythm == 0 || index < 6) ad_a0b0l_reg (index, a0b0_data3[index], 0); else { bd_modify &= (~bd_reg_data[index]), ad_bd_reg (); } } /*--------------------------------------------------------------*/ inline void CrixPlayer::ins_to_reg (unsigned short index, unsigned short *insb, unsigned short value) { register unsigned short i; for (i = 0; i < 13; i++) reg_bufs[index].v[i] = insb[i]; reg_bufs[index].v[13] = value & 3; ad_bd_reg (), ad_08_reg (), ad_40_reg (index), ad_C0_reg (index), ad_60_reg (index), ad_80_reg (index), ad_20_reg (index), ad_E0_reg (index); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_E0_reg (unsigned short index) { unsigned short data = e0_reg_flag == 0 ? 0 : (reg_bufs[index].v[13] & 3); ad_bop (0xE0 + reg_data[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_20_reg (unsigned short index) { unsigned short data = (reg_bufs[index].v[9] < 1 ? 0 : 0x80); data += (reg_bufs[index].v[10] < 1 ? 0 : 0x40); data += (reg_bufs[index].v[5] < 1 ? 0 : 0x20); data += (reg_bufs[index].v[11] < 1 ? 0 : 0x10); data += (reg_bufs[index].v[1] & 0x0F); ad_bop (0x20 + reg_data[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_80_reg (unsigned short index) { unsigned short data = (reg_bufs[index].v[7] & 0x0F), temp = reg_bufs[index].v[4]; data |= (temp << 4); ad_bop (0x80 + reg_data[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_60_reg (unsigned short index) { unsigned short data = reg_bufs[index].v[6] & 0x0F, temp = reg_bufs[index].v[3]; data |= (temp << 4); ad_bop (0x60 + reg_data[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_C0_reg (unsigned short index) { unsigned short data = reg_bufs[index].v[2]; if (adflag[index] == 1) return; data *= 2, data |= (reg_bufs[index].v[12] < 1 ? 1 : 0); ad_bop (0xC0 + ad_C0_offs[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_40_reg (unsigned short index) { unsigned int res = 0; unsigned short data = 0, temp = reg_bufs[index].v[0]; data = 0x3F - (0x3F & reg_bufs[index].v[8]), data *= for40reg[index], data *= 2, data += 0x7F, res = data; data = res / 0xFE, data -= 0x3F, data = -data, data |= temp << 6; ad_bop (0x40 + reg_data[index], data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_bd_reg () { unsigned short data = rhythm < 1 ? 0 : 0x20; data |= bd_modify; ad_bop (0xBD, data); } /*--------------------------------------------------------------*/ inline void CrixPlayer::ad_a0b0_reg (unsigned short index) { ad_bop (0xA0 + index, 0); ad_bop (0xB0 + index, 0); } /*--------------------------------------------------------------*/ inline void CrixPlayer::music_ctrl () { register int i; for (i = 0; i < 11; i++) switch_ad_bd (i); }