kolibrios/programs/develop/libraries/ufmod/readme_ru.htm
Yogev Ezra d21a6e85e7 Added libraries/ufmod source code.
git-svn-id: svn://kolibrios.org@1845 a494cfbc-eb01-0410-851d-a64ba20cac60
2011-02-04 20:13:33 +00:00

33 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html lang=ru><head><meta http-equiv=Content-Type content="text/html; charset=windows-1251"><title>uFMOD</title></head><body style='margin:0'><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#E7E7E7 align=center><td height=20 style='color:#708090;font-size:9pt;font-family:Arial,Aerial'>[ <a href='en.htm'>English</a> | <a href='es.htm'>Espa&#241;ol</a> | Pycc&#954;u&#250; ]<tr bgcolor=#708090><td height=1></table><center><h2 style='font-size:14pt;font-family:Arial,Aerial'>&#956;FMOD v1.25 для KolibriOS</h2></center><div style='font-size:10pt;font-family:Arial,Aerial;text-align:justify;margin:8'><p>uFMOD - это компактная, шустрая, надёжная, мультиплатформенная библиотека для качественного воспроизведения аудио в формате XM, разработанная полностью на ассемблере. XM может храниться в отдельном файле или предварительно загружен в память. Поддерживаются также битые и не совсем стандартные файлы. Библиотека распространяется с открытым исходным кодом и примерами для следующих компиляторов: FASM, MASM32 и NASM.<p>Версия для KolibriOS должна исправно работать на любых конфигурациях, удовлетворяющих следующим требованиям:<ol><li>Минимальная ревизия SVN ядра и драйверов KolibriOS: 574. Последние версии дистрибутивов и обновления SVN можно скачать с официального сайта: <a href='http://www.kolibrios.org/'>www.kolibrios.org</a>.<li>Звуковая карточка, поддерживаемая аудио-библиотекой <a href='http://infinity-sound.narod.ru/'>Infinity Sound</a> - это встроенный звуковой драйвер KolibriOS. На данный момент драйвер поддерживает многие встроенные кодеки совместимые со стандартом AC'97.</ol>Ваша конфигурация удовлетворяет вышеперечисленным требованиям, но uFMOD на ней отказывается работать? - Пожалуйста, сообщите нам об этом (<a href='#ci'>контактные данные</a> приводятся в низу данной страницы).<p><ul><li><a href='#1'>Прежде чем начать</a><li><a href='#2'>Утилиты</a><ul><li><a href='#21'>XMStrip</a><li><a href='#22'>Eff</a></ul><li><a href='#3'>Компиляция библиотеки</a><li><a href='#4'>Примеры</a><li><a href='#5'>Дополнительное уменьшение размера</a><li><a href='#6'>ЧаВо</a><li><a href='#7'>Благодарности</a></ul><p>&nbsp;<br><a name='1'><b>Прежде чем начать</b></a><p>KolibriOS - это операционная система, написанная на ассемблере. Поэтому у неё такой маленький размер и такая высокая производительность, но только не в ущерб возможностям этой полноценной операционки, как Вы, возможно, уже убедились. Аналогичная идеология поддерживается и в проекте uFMOD ;)<p>Основную часть данного руководства можно успешно выполнить прямо в самой системе Kolibri. Тем не менее, так как многие новички в программировании Kolibri предпочитают компилировать свои проекты в Windows и потом переносить их в Kolibri для тестирования, в данном руководстве мы применим кросскомпиляцию.<p>&nbsp;<br><a name='2'><b>Утилиты</b></a><p>Есть пара бесплатных утилит для использования совместно с uFMOD: XMStrip и Eff. Пока что ни одна из них не портирована в Kolibri. Поэтому можете скачать любой из других дистрибутивов uFMOD (для Win32, Linux или Unix/BSD) и использовать утилиты кроссплатформенно. Независимо от выбранного дистрибутива, обе утилиты совмещают в себе консольный и графический (GUI) интерфейсы. Режим GUI интуитивно понятен. Давайте рассмотрим консольный интерфейс.<p><table border=0 cellpadding=0 cellspacing=0 bgcolor=#708090 style='font-size:9pt;font-family:Arial,Aerial'><tr><td colspan=3 height=1><tr height=18><td style='color:#E7E7E7'><b>&nbsp;SVN&nbsp;</b><td bgcolor=#E7E7E7>&nbsp;<a href='http://ufmod.svn.sourceforge.net/viewvc/ufmod'>Исходники доступны через SVN</a>&nbsp;<td width=1><tr><td colspan=3 height=1></table><p><a name='21'><b><i>XMStrip</i></b></a> обрабатывает заданный XM файл с целью уменьшения размера, без потери качества звучания. В процессе обработки, XMStrip удаляет неиспользующиеся инструменты и партитуры, вырезает комментарии и перепаковывает внутренние структуры файла для уменьшения размера и повышения скорости загрузки. Для начала, откроем консоль и введём <code>xmstrip /h</code>, чтобы получить следующее сообщение:<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: xmstrip [options] file [output]
file - input file name.
output - optional output file name.
options:
/c - clean only (don't strip)
When [output] is not specified, XMSTRIP
attempts to overwrite the input. If file
name contains spaces, enclose it in "".</font></td></tr></table></center><p>Если имя сохраняемого файла не указано, XMStrip перезапишет заданный файл. Если имя файла содержит пробелы, его необходимо заключить в кавычки ("").<p>Имейте в виду, что другие проигрыватели XM файлов, возможно, откажутся воспроизводить файл, обработанный XMStrip. Опция <b>/c</b> предусмотрена для восстановления таких файлов или обработки обычных XM файлов, которые планируется проигрывать не только в uFMOD.<p><a name='22'><b><i>Eff</i></b></a> предназначается для опытных кодеров, желающих сэкономить каждый байт в своих приложениях. Для этого нужно выделить только те функции uFMOD, которые действительно будут использованы в целевом приложении, перекомпилировать библиотеку и получить наименьший возможный размер. Вот, что выдаёт <code>eff /h</code> :<p><center><table border=0 cellpadding=8><tr bgcolor=#000000><td><pre><font color=#FFFFFF> USAGE: eff [options] file
file - input file name
options:
/Dm - generate a masm32/tasm dump
/Dd - generate a Pascal (Delphi) dump
/Dc - generate a C/C++ dump
/Ds - generate an RCDATA resource dump
/Di - disable infoAPI:
uFMOD_GetStats, uFMOD_GetRowOrder,
uFMOD_GetTitle and uFMOD_GetTime
/Dp - disable uFMOD_Pause, uFMOD_Resume
and XM_SUSPENDED
/Dv - disable volume control
/Dj - disable Jump2Pattern
/Df - disable loading XM from file
/Dl - disable XM_NOLOOP
/M - mark & clear unused chunks of
data in a masm32/tasm compatible dump</font></td></tr></table></center><p>Последний параметр - имя XM файла, на использование которого ориентируются следующие параметры оптимизации:<ul><li><b>/Dm</b> создаёт текстовый дамп данного XM файла для использования в исходнике на MASM32 или TASM. Синтаксис совместим с FASM и NASM. Вместе с тем, и FASM и NASM позволяют включать в исполнимый образ содержимое произвольных файлов напрямую. Данную опцию необходимо включить при использовании ключа <b>/M</b> (см. ниже).<li><b>/Dd</b> и <b>/Dc</b> создают подобные дампы, но для Pascal (Delphi, Kylix, FreePascal) или C/C++ соответственно.<li><b>/Ds</b> создаёт аналогичный дамп в формате RCDATA, который используется в скриптах описания ресурсов (*.rc). В KolibriOS данная опция бесполезна.<li>Ключ <b>/Di</b> отключает все информативные функции: uFMOD_GetStats, uFMOD_GetRowOrder, uFMOD_GetTitle и uFMOD_GetTime. Это даёт выигрыш не только в размере библиотеки, но и в скорости.<li><b>/Dp</b> отключает функции uFMOD_Pause и uFMOD_Resume и поддержку флага XM_SUSPENDED. Если Вы не собираетесь использовать pause/resume, включите этот ключ в параметры командной строки для экономии ещё нескольких байт.<li>uFMOD_SetVolume увеличивает не только размер библиотеки, но ещё и загрузку CPU. Добавьте ключ <b>/Dv</b>, чтобы отключить эту функцию и сэкономить несколько байт и тактов ;)<li><b>/Dj</b> отключает функцию Jump2Pattern. Данная функция предназначена для очень специфичных задач и, поэтому, используется редко. В разделе <a href='#5'>"Дополнительное уменьшение размера"</a> подробно описано использование Jump2Pattern.<li>Вам не нужна поддержка загрузки файлов - только проигрывание из памяти? Тогда, не задумываясь, включайте <b>/Df</b> для дополнительного уменьшения размера.<li>Ключ <b>/Dl</b> (маленькая L) отключает поддержку флага XM_NOLOOP (и, следовательно, благотворно влияет на размер и скорость).<li>Совсем "экстремальный" вид оптимизации предусмотрен специально для ассемблерщиков. В каждом XM файле есть цепочки байт, которые зарезервированы на будущее, или просто содержат комментарии или любую другую, не имеющую отношения к проигрыванию, информацию. <b>/M</b> выделяет эти "дыры", предоставляя возможность заполнить их полезной информацией (разместить данные или даже код). Пример src/Masm32/ как раз использует эту опцию.</ul>Eff создаёт файл EFF.INC и, согласно заданным опциям, текстовый дамп. Рассмотрим несколько одинаковых примеров (все верны):<p><b>eff /Dmpvjfl /M file.xm<br>eff /M /Dm /Dp /Dv /Dj /Df /Dl file.xm<br>eff -M -Dmpvjfl file.xm</b><p>Любой из предыдущих примеров создаст ассемблерный дамп, выделит "дыры" и предварительно заполнит их нулями. Файл EFF.INC содержит список эффектов XM, которые действительно используются в заданном файле, и некоторые дополнительные флаги для отключения pause/resume, регулятора громкости, Jump2Pattern, поддержки файлов и XM_NOLOOP. Поместите этот новый EFF.INC в src/ufmodlib/src/ и перекомпилируйте библиотеку (в следующем разделе освещены некоторые вопросы касающиеся компиляции исходников библиотеки). Теперь у Вас имеется свой собственный оптимизированный билд uFMOD, но имейте в виду, что в этом билде включены не все эффекты XM. Поэтому, не следует использовать его для проигрывания других XM файлов, отличных от обработанного утилитой Eff!<p>&nbsp;<br><a name='3'><b>Компиляция библиотеки</b></a><p>Необходимость компиляции исходников библиотеки uFMOD возникает при использовании утилиты <a href='#22'>Eff</a>, а также для включения особых режимов и опций, которые отключены в сборке по умолчанию (см. таблицу <b>Опции</b> ниже). Для тех, кто хочет попрактиковаться в ассемблере и/или разобраться в библиотеке на самом низком уровне, и предназначен данный раздел.<p>Исходники uFMOD расположены в src/ufmodlib/src/:<ul>
<li><span style='color:#800080'><b>eff.inc</b></span> - этот заголовочный файл создаётся утилитой <a href='#22'>Eff</a>. Не рекомендуется редактировать данный файл вручную! Настоящие кодеры не обращают внимания на подобные предупреждения, но всё же... :)<li><span style='color:#800080'><b>ufmod.inc</b></span> содержит подробное описание API uFMOD для использования в проектах на ASM/C/C++.<li><span style='color:#800080'><b>ufmod-codec.h</b></span> содержит описание альтернативного API uFMOD, которое предоставляется библиотекой в режиме AC97SND - этот режим предназначен для использования в плеерах аудио-файлов, вроде AC'97 MP3 Player Serge'я.<li>В <span style='color:#008080'><b>core.asm</b></span> находится большая часть исходного кода uFMOD. Этот самый файл присутствует во всех дистрибутивах библиотеки: KolibriOS, Unix/BSD, Linux и Win32. Загрузка XM-файла, смешивание каналов, наложение эффектов и многие другие общие для всех дистрибутивов алгоритмы реализованы в данном файле.<li><span style='color:#008080'><b>ufmod.asm</b></span> содержит платформозависимые процедуры: файловый В/В, общение со звуковым драйвером и т.д. Поэтому, содержимое данного файла различается в дистрибутивах для разных ОСей.<li><span style='color:#008080'><b>fasm.asm</b></span> хранит определения констант, структур и т.д. под синтаксис Flat Assembler (FASM). Этот файл позволяет собирать библиотеку с помощью FASM.<li><span style='color:#008080'><b>masm.asm</b></span> хранит определения констант, структур и т.д. под синтаксис MASM32. Этот файл позволяет собирать библиотеку с помощью MASM32.<li><span style='color:#008080'><b>nasm.asm</b></span> хранит определения констант, структур и т.д. под синтаксис Netwide Assembler (NASM). Этот файл позволяет собирать библиотеку с помощью NASM.</ul>Следующим после внесения изменений в исходники шагом является компиляция. Чтобы пересобрать ufmod.obj, сначала откройте в текстовом редакторе батник src/ufmodlib/makeobj.bat. Всё, что находится между следующих строк:<pre>rem *** CONFIG START</pre>и<pre>rem *** CONFIG END</pre>подлежит настройке. Обратите внимание на секцию <code>Pathes</code>. Там есть такая опция:<pre>SET UF_NASM=\nasm</pre>Если у Вас установлен NASM, удостоверьтесь, что путь в данной опции указывает точно туда, где находится nasmw.exe. Допустим, NASM установлен в <code>D:\TOOLS\NASM</code>. В таком случае, необходимо скорректировать опцию следующим образом:<pre>SET UF_NASM=D:\TOOLS\NASM</pre>Не все пути необходимы для успешной компиляции. Например, если Вы намерены использовать FASM, не нужно настраивать UF_NASM. Проверьте правильность всех путей, необходимых для компиляции. Теперь настройте параметры конфигурации, согласно следующей таблице:<p><table border=0 cellpadding=4 cellspacing=2 style='font-size:10pt;font-family:Arial,Aerial'><tr bgcolor=#708090 style='color:#E7E7E7;font-weight:bold'><td>Опция<td>Описание<td width=200>Значения<tr valign=top><td>UF_RAMP<td>Данная опция позволяет настроить механизм интерполяции, который предназначен для погашения щелчков - резкие перепады амплитуды сигнала, характерные для трекерской музыки. С другой стороны, интерполяция вносит искажение в высокочастотные спектральные составляющие сигнала, что иногда бывает заметно. STRONG - это значение по умолчанию, рекомендуемое для большинства приложений. В данном режиме миксер сглаживает резкие перепады амплитуды, применяя линейную 128-ступенчатую интерполяцию. WEAK накладывает лишь 16 ступеней - этот режим менее эффективен, чем STRONG, но зато вероятность деградации сигнала в этом режиме ниже. NONE вообще отключает интерполяцию. Без сглаживания не будет и деградации, но большинство композиций без сглаживания будет звучать заметно хуже из-за наложения щелчков. Особым образом сбалансированные композиции без сглаживания могут звучать лучше.<td>NONE, WEAK, STRONG<tr bgcolor=#E7E7E7 valign=top><td>UF_FREQ<td>Частота дискретизации (в Гц). 48КГц является значением, рекомендуемым для большинства приложений.<td>22050, 44100, 48000<tr valign=top><td>UF_ASM<td>Ассемблер. Да, uFMOD можно собирать разными ассемблерами - выбирайте тот, который больше нравится :)<td>MASM, NASM, FASM<tr bgcolor=#E7E7E7 valign=top><td>UF_MODE<td>NORMAL - это значение по умолчанию. Ничего особенного. UNSAFE отключает проверку правильности формата XM перед загрузкой композиции. Если Вы уверены, что все композиции, которые будут проигрываться в вашем приложении, корректны (правильность формата XM-файла можно проверить в Eff или XMStrip), можете пересобрать библиотеку в режиме UNSAFE, чтобы выйграть в размере и скорости загрузки. Имейте в виду, что загрузка неправильного XM-файла в режиме UNSAFE может привести к краху! В режиме AC97SND библиотека представляет собой кодек для проигрывателя AC'97 MP3 Player Serge'я. Данный режим может быть полезен и для других проектов сходной направленности. Описание API данного режима можно найти в ufmod-codec.h.<td>NORMAL, UNSAFE, AC97SND</table><p>Запустите батник, чтобы собрать библиотеку. Вот и всё!<p>&nbsp;<br><a name='4'><b>Примеры</b></a><p>В данный дистрибутив вошли 2 примера: mini и jmp2pat. Откомпилированные экзешники находятся в bin/. Заметьте, что экзешники представлены без сжатия.<ul><li><b>mini</b> - это простейший пример фонового проигрывания музыки из памяти.<li><b>jmp2pat</b> - это пример использования функции Jump2Pattern. В данном примере проигрывается композитный XM, любезно предоставленный товарищем Kim (он же norki). Описание техники создания и использования подобных композиций можно найти в следующем разделе.</ul><p>&nbsp;<br><a name='5'><b>Дополнительное уменьшение размера</b></a><p>Утилита <a href='#22'>Eff</a> предназначена для оптимизации и уменьшения размера библиотеки uFMOD.<p>Если Вы собираетесь включить XM статически в экзешник, можете попробовать оптимизировать сначала сам XM. Modplug Player умеет сжимать XM-композиции по схеме APDCM, но учтите, что этот тип сжатия пагубно влияет на качество звучания! Утилита <a href='#21'>XMStrip</a> перепаковывает XM файл без потери качества.<p>Если Вы уверены в корректности формата всех композиций, которые будут использованы в приложении, можете пересобрать библиотеку в режиме UNSAFE.<p>Упаковщики, вроде mtappack diamond'а, умеют ужимать экзешники. Тем не менее, для наглядности, все примеры предоставлены без сжатия!<p>Есть ещё один хитрый способ оптимизации размера XM-файлов, который заключается в совмещении сразу нескольких композиций в одном файле. При этом можно удалять лишние экземпляры повторяющихся инструментов, если таковые имеются, что очень заметно сказывается на размере конечного файла. Даже без оптимизации инструментов размер композитного файла должен получиться меньше суммы размеров отдельных файлов, так как заголовки всех файлов заменяются одним общим. Давайте рассмотрим пример с тремя файлами:<pre>
<b>Файл 1 :</b> XM1_HEADER P11 P12 P13 I11 I12
<b>Файл 2 :</b> XM2_HEADER P21 P22 P23 P24 I21 I22 I23 I24
<b>Файл 3 :</b> XM3_HEADER P31 I31
</pre><i><b>Пояснение:</b> XMn_HEADER - это заголовок n-ного файла. Pnm - это m-ная партитура n-ного файла. Inm - это m-ный инструмент n-ного файла.</i><p>Для начала, совместим все 3 композиции без оптимизации инструментов:<pre>
<b>Файл 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I23 I24 I31
</pre>Представьте, что I12 очень похож или идентичен I23; I24 и I31 тоже практически одинаковы. Мы можем заставить партитуры P2n использовать I12 вместо I23, а P31 переключить на I24. Тогда мы сможем удалить I23 и I31:<pre>
<b>Файл 4 :</b> XM4_HEADER P11 P12 P13 P21 P22 P23 P24 P31 I11 I12 I21 I22 I24
</pre>Необходимо скорректировать команды зацикливания и ссылки на партитуры в композициях 2 и 3 после совмещения. Конечно, можно совмещать и большее количество композиций, но формат XM имеет ограничения на максимальное количество партитур и инструментов в файле. Все операции над XM-файлами надлежит проводить в специальном ПО - трекере. Для проигрывания композитного файла достаточно одного вызова функции uFMOD_PlaySong. Далее нужно использовать функцию uFMOD_Jump2Pattern для проигрывания отдельных композиций из общего файла в произвольной последовательности. Например, uFMOD_Jump2Pattern(3) переключится на вторую композицию, uFMOD_Jump2Pattern(7) начнёт проигрывать третью, а uFMOD_Jump2Pattern(0) вернётся обратно к первой. Точные значения индексов стартовых партитур каждой композиции после совмещения легко вычислить в уме, но можно и в трекере подсмотреть :) Пример <b>jmp2pat</b> использует данный способ оптимизации.<p>В использовании Jump2Pattern есть ещё один плюс - переключение происходит гораздо быстрее (практически моментально) чем при остановке текущей композиции и последующей загрузке новой. Можете брать на вооружение эту фишку для реализации решений, требующих максимально быстрого переключения музыкального фона.<p>&nbsp;<br><a name='6'><b>ЧаВо</b></a><p><span style='color:#008080'><b>В:</b> Библиотека uFMOD действительно бесплатна для любого использования, включая коммерческое?</span><br><b>О:</b> Да, текущая версия абсолютно бесплатна для использования в любых целях.<p><span style='color:#008080'><b>В:</b> Где бы достать композиции в формате XM?</span><br><b>О:</b> <a href='http://modarchive.org/'>The Mod Archive</a> содержит внушительных размеров архив с бесплатными трекерскими композициями в формате XM, IT, S3M и MOD. <a href='http://www.modplug.com/'>Open Modplug Tracker</a> умеет конвертировать IT, S3M и MOD в XM без потери качества. В сети много талантливых композиторов, которые бесплатно выкладывают свои работы. Не забывайте указывать соответствующие пометки об авторстве!<p><span style='color:#008080'><b>В:</b> Существует ли какая-либо связь между проектом uFMOD и разработками Firelight Technologies&#174;: FMOD и miniFMOD?</span><br><b>О:</b> На данный момент никакой связи уже нет. До 2004го года включительно проект uFMOD основывался на исходных кодах библиотеки miniFMOD. С тех пор, код uFMOD был полностью переписан, оснащён новыми функциями, оптимизирован и отлажен. Таким образом, uFMOD более не связан ни с FMOD, ни с miniFMOD.<p><span style='color:#008080'><b>В:</b> Некоторые разработчики утверждают, что их библиотеки увеличивают экзешники на N-ное количество килобайт. На сколько килобайт увеличивается размер экзешника при использовании uFMOD?</span><br><b>О:</b> Точного ответа на этот вопрос нет, так как этот размер зависит от многих факторов: используемые характеристики библиотеки (особенно при использовании утилиты Eff), основной код программы, размер XM-файла (если XM включается в образ экзешника). Размер также зависит от опций линкера. Пример bin/mini занимает 4768 байт без сжатия.<p><span style='color:#008080'><b>В:</b> Где можно раздобыть официальное описание формата XM?</span><br><b>О:</b> Полного официального описания современного формата XM нет. Позвольте предложить взамен этот документ: <a href='http://sourceforge.net/project/showfiles.php?group_id=158498&package_id=234625'>"The Unofficial XM File Format Specification: FastTracker II, ADPCM and Stripped Module Subformats"</a> (только на англ.). В данном документе описаны многие тонкости работы с форматом XM, включая все нестандартные расширения, которые на данный момент поддерживает uFMOD. К тому же, из исходников ModPlug (на C++) можно почерпнуть массу полезной информации по трекерским форматам файлов.<p>&nbsp;<br><a name='7'><b>Благодарности</b></a><p>antarman, Barracuda, bogrus, chris_b, cresta, dododo, flaith, Four-F, GL#0M, norki, q_q, SofT MANiAC, S_T_A_S_, voodooattack и yoxola за помощь в устранении ошибок, предложения по улучшению библиотеки, примеры использования под разные компиляторы и всё остальное, так или иначе помогающее нам в развитии проекта.<p><a href='http://wasm.ru'>[WASM.RU]</a> и <a href='http://sf.net'>SourceForge.net</a> за поддержку и хостинг.<p>&nbsp;<br><b>Автор&#169;тво</b><p>Исходные коды uFMOD и сопровождающие утилитарные приложения &#169; 2005 - 2007 Asterix и Quantum.<br>Все права защищены.<p>Композиции:<ul><li>Minimal III &#169; 2006 - 2007 SofT MANiAC (CoolPHat).<li>BlitzXMK.XM из примера Jump2Pat &#169; 2007 Kim (он же - norki).</ul></div><table border=0 cellpadding=0 cellspacing=0 width=100%><tr bgcolor=#708090><td height=1><tr bgcolor=#E7E7E7><td height=52 style='color:#708090;font-size:10pt;font-family:Arial,Aerial' align=center>Нашли ошибку? Желаете задать вопрос разработчикам или высказать предложение по улучшению библиотеки?<br>Разрабатываете интересный проект с использованием uFMOD? Вам сюда: <a href='mailto:ufmod@users.sf.net' name='ci'>ufmod@users.sf.net</a></table></body></html>