/* * ASAP.ppcs - C# version of ASAP * * Copyright (C) 2008-2009 Piotr Fusik * * This file is part of ASAP (Another Slight Atari Player), * see http://asap.sourceforge.net * * ASAP 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. * * ASAP 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 ASAP; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define CSHARP using System; using System.IO; namespace ASAP { public enum ASAP_SampleFormat { U8, S16LE, S16BE } public class ASAP_ModuleInfo { public string author; public string name; public string date; public int channels; public int songs; public int default_song; public readonly int[] durations = new int[32]; public readonly bool[] loops = new bool[32]; internal int type; internal int fastplay; internal int music; internal int init; internal int player; internal int covox_addr; internal int header_len; internal readonly byte[] song_pos = new byte[128]; } internal class PokeyState { internal int audctl; internal bool init; internal int poly_index; internal int div_cycles; internal int mute1; internal int mute2; internal int mute3; internal int mute4; internal int audf1; internal int audf2; internal int audf3; internal int audf4; internal int audc1; internal int audc2; internal int audc3; internal int audc4; internal int tick_cycle1; internal int tick_cycle2; internal int tick_cycle3; internal int tick_cycle4; internal int period_cycles1; internal int period_cycles2; internal int period_cycles3; internal int period_cycles4; internal int reload_cycles1; internal int reload_cycles3; internal int out1; internal int out2; internal int out3; internal int out4; internal int delta1; internal int delta2; internal int delta3; internal int delta4; internal int skctl; internal readonly int[] delta_buffer = new int[888]; } public class ASAP_State { internal int cycle; internal int cpu_pc; internal int cpu_a; internal int cpu_x; internal int cpu_y; internal int cpu_s; internal int cpu_nz; internal int cpu_c; internal int cpu_vdi; internal int scanline_number; internal int nearest_event_cycle; internal int next_scanline_cycle; internal int timer1_cycle; internal int timer2_cycle; internal int timer4_cycle; internal int irqst; internal int extra_pokey_mask; internal int consol; internal readonly byte[] covox = new byte[4]; internal readonly PokeyState base_pokey = new PokeyState(); internal readonly PokeyState extra_pokey = new PokeyState(); internal int sample_offset; internal int sample_index; internal int samples; internal int iir_acc_left; internal int iir_acc_right; public readonly ASAP_ModuleInfo module_info = new ASAP_ModuleInfo(); internal int tmc_per_frame; internal int tmc_per_frame_counter; internal int current_song; internal int current_duration; internal int blocks_played; internal int silence_cycles; internal int silence_cycles_counter; internal readonly byte[] poly9_lookup = new byte[511]; internal readonly byte[] poly17_lookup = new byte[16385]; internal readonly byte[] memory = new byte[65536]; } public class ASAP_Player { #include "acpu.c" #include "apokeysnd.c" #include "asap.c" #undef const readonly ASAP_State ast = new ASAP_State(); public const string Version = "2.0.0"; public const int ModuleMax = 65000; public const int SampleRate = ASAP_SAMPLE_RATE; public const int WavHeaderBytes = 44; public static bool IsOurFile(string filename) { return ASAP_IsOurFile(filename); } public static ASAP_ModuleInfo GetModuleInfo(string filename, byte[] module, int module_len) { ASAP_ModuleInfo module_info = new ASAP_ModuleInfo(); if (!ASAP_GetModuleInfo(module_info, filename, module, module_len)) throw new Exception(); return module_info; } public static int ParseDuration(string s) { int i = s.IndexOf(':'); int r = 0; if (i >= 0) { r = int.Parse(s.Substring(0, i)) * 60000; s = s.Substring(i + 1); } i = s.IndexOf(' '); if (i >= 0) s = s.Substring(0, i); r += (int) (double.Parse(s, System.Globalization.CultureInfo.InvariantCulture) * 1000); return r; } public void Load(string filename, byte[] module, int module_len) { if (!ASAP_Load(ast, filename, module, module_len)) throw new Exception(); } public ASAP_ModuleInfo GetModuleInfo() { return ast.module_info; } public void PlaySong(int song, int duration) { ASAP_PlaySong(ast, song, duration); } public void MutePokeyChannels(int mask) { ASAP_MutePokeyChannels(ast, mask); } public int GetPosition() { return ASAP_GetPosition(ast); } public void Seek(int position) { ASAP_Seek(ast, position); } public void GetWavHeader(byte[] buffer, ASAP_SampleFormat format) { ASAP_GetWavHeader(ast, buffer, format); } public int Generate(byte[] buffer, ASAP_SampleFormat format) { return ASAP_Generate(ast, buffer, buffer.Length, format); } } }