1
0
Fork 0
forked from len0rd/rockbox

sync asap codec to ASAP 2.1

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24511 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dominik Wenger 2010-02-04 17:31:10 +00:00
parent b1a6c9096d
commit 35472fe7f1
11 changed files with 3710 additions and 2605 deletions

View file

@ -1,37 +1,58 @@
People who have contributed to ASAP
-----------------------------------
Authors
-------
Atari800 Development Team (http://atari800.sourceforge.net)
* 6502 and POKEY emulation used in 0.x.y versions of ASAP
Piotr Fusik {asapwww!<fox@scene.pl>}::
Creator and main developer.
Zdenek Eisenhammer <pg@pinknet.cz>
* testing
Atari800 Emulator Developers {asapwww!(http://atari800.sourceforge.net)}::
6502 and POKEY emulation used in 0.x.y versions of ASAP.
Piotr Fusik <fox@scene.pl>
* author and maintainer of ASAP
Zdenek Eisenhammer {asapwww!<pg@pinknet.cz>}::
Testing.
Maciek Konecki <maciusk1@wp.pl>
* porting to C#
Henryk Karpowicz {asapwww!<henkar@poczta.tygrys.net>}::
CMC routine modified for the CM3 format.
Marcin Lewandowski <jaskier@atari8.info>
* 6502 routines for playing CMC, MPT, TMC and TM2
Maciek Konecki {asapwww!<maciusk1@wp.pl>}::
Porting to C#.
Perry McFarlane <perry_m@fastmail.fm>
* POKEY reverse-engineering
Marek Konopka {asapwww!<konop11@poczta.onet.pl>}::
6502 routine for playing DLT.
Kostas Nakos <knakos@gmail.com>
* compilation for Windows CE
Marcin Lewandowski {asapwww!<jaskier@atari8.info>}::
6502 routines for playing CMC, MPT, TMC and TM2.
Slawomir Sledz <slaves@scene.pl>
* testing
Adrian Matoga {asapwww!<epi@atari8.info>}::
COVOX information and test files. Testing.
Radek Sterba <raster@infos.cz>
* 6502 routine for playing RMT
* testing
Perry McFarlane {asapwww!<perry_m@fastmail.fm>}::
POKEY reverse-engineering.
Lukasz Sychowicz <xray@scene.pl>
* Windows icons
* testing
Kostas Nakos {asapwww!<knakos@gmail.com>}::
Windows CE testing.
Michal Szpilowski <miker@atari.pl>
* testing
Mariusz Rozwadowski {asapwww!<ramosc64@o2.pl>}::
Suggested CMS, CM3 and DLT format support.
Slawomir Sledz {asapwww!<slaves@scene.pl>}::
Testing.
David Spilka::
6502 routine for playing CMS.
Radek Sterba {asapwww!<raster@infos.cz>}::
6502 routine for playing RMT.
Testing.
Lukasz Sychowicz {asapwww!<xray@scene.pl>}::
Windows icons.
Testing.
Pawel Szewczyk {asapwww!<ripek@op.pl>}::
Windows setup graphics.
Michal Szpilowski {asapwww!<miker@atari.pl>}::
Testing.
Grzegorz Zyla {asapwww!<gsunr@poczta.onet.pl>}::
XBMC plugin testing.

View file

@ -1,59 +1,142 @@
ASAP - Another Slight Atari Player
----------------------------------
==================================
ASAP is a player of Atari 8-bit music for modern computers.
It emulates the POKEY sound chip and the 6502 processor.
The project was initially based on the routines from the Atari800 emulator,
// This file is in AsciiDoc format. It is converted to README.html.
:Compact-Option:
ifdef::asapwww[]
http://sourceforge.net/projects/asap/files/asap/[Download] |
http://asap.git.sourceforge.net/git/gitweb.cgi?p=asap/asap;a=summary[Browse source code (Git)] |
http://sourceforge.net/scm/?type=git&group_id=154391[Get latest source code (Git)] |
http://sourceforge.net/projects/asap/[SourceForge project page]
endif::asapwww[]
ASAP is a player of http://en.wikipedia.org/wiki/Atari_8-bit_family[8-bit Atari]
music for modern computers.
It emulates the http://en.wikipedia.org/wiki/POKEY[POKEY sound chip]
and the http://en.wikipedia.org/wiki/6502[6502 processor].
The project was initially based on the routines from the
http://atari800.sourceforge.net/[Atari800 emulator],
but the current version has a completely new original emulation core.
The ASAP project includes the following programs:
* ASAP2WAV - portable command-line utility that generates WAV files
* WASAP - tiny player for Windows
* plugin for Apollo
* plugin for foobar2000 0.9
* plugin for GSPlayer
* plugin for MOC
* plugin for Winamp
* plugin for XMMS
* DirectShow source filter (for Windows Media Player)
* Java version of ASAP2WAV
* Java applet
* Java midlet
* C# version of ASAP2WAV
ASAP includes the following programs:
The following input formats are supported:
* SAP (Slight Atari Player - standard file format for playing Atari 8-bit
music on modern computers)
* CMC (Chaos Music Composer)
* CMR (CMC Rzog)
* DMC (DoublePlay CMC)
* MPT (Music ProTracker)
* MPD (MPT DoublePlay)
* RMT (Raster Music Tracker)
* TMC, TM8 (Theta Music Composer 1.x)
* TM2 (Theta Music Composer 2.x)
- asapconv - portable command-line converter {asapwin=}
- WASAP - tiny player for Windows {asapwin=}
- plugin for http://koti.welho.com/hylinen/apollo/[Apollo] {asapwin=}
- plugin for http://foobar2000.org/[foobar2000] {asapwin=}
- plugin for http://hp.vector.co.jp/authors/VA032810/[GSPlayer] {asapwin=}{asapwince=}
- plugin for http://moc.daper.net/[MOC]
- plugin for http://www.winamp.com/[Winamp] {asapwin=}
- plugin for http://www.microsoft.com/windows/windowsmedia/player/[Windows Media Player] {asapwin=}
- plugin for http://xbmc.org/[XBMC] {asapwin=}
- plugin for http://xmms.org/[XMMS]
- plugin for http://www.un4seen.com/[XMPlay] {asapwin=}
- POKEY sound emulation DLL for http://raster.infos.cz/atari/rmt/rmt.htm[Raster Music Tracker] {asapwin=}
- Java version of ASAP2WAV - command-line converter to WAV files {asapjava=}
- Java applet - for web pages {asapjava=}{asapwww?(see link:applet.html[online demo])}
- Java midlet - for mobile devices {asapjava=}
- C# version of ASAP2WAV
- experimental JScript version of ASAP2WAV running in Windows Script Host {asapjavascript=}
- experimental JavaScript version of ASAP2WAV running in Firefox {asapjavascript=}
- Flash player - for web pages {asapflash=}{asapwww?(see link:flash.html[online demo])}
If you are looking for Atari 8-bit music, there is a single big collection
of it called Atari SAP Music Archive (http://asma.atari.org).
{asapports}The summary of the differences between the above versions is in link:PORTS.xml[this table].
If you are interested in the ASAP project, please subscribe its mailing list:
https://lists.sourceforge.net/lists/listinfo/asap-users
As in the Atari800 project, this is a combined list for end users
and for developers. Once you subscribe, you can post comments, ideas
and questions about ASAP. They will be answered ASAP. ;-)
There are other projects which use ASAP:
If, for some reason, you do not want to subscribe the mailing list,
but have a bug report, feature request or a small code patch, you can use
the sf.net tracker. Use "Bugs", "Feature Requests" or "Patches" link
on this page:
http://sourceforge.net/projects/asap/
- http://mmsap.sourceforge.net/[mmSAP 2] - standalone player for GNU/Linux with GTK+ user interface
- http://www.rockbox.org/[Rockbox] - open source firmware for MP3 players
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 included GNU General Public License for more details.
Input file formats
------------------
ASAP supports the following file formats (determined by the filename extension):
SAP (Slight Atari Player)::
The format designed for playing 8-bit Atari music on modern computers.
All other formats can be converted to SAP.
http://asma.atari.org/[Atari SAP Music Archive (ASMA)]
is a single big collection of SAP files.
CMC (Chaos Music Composer)::
Atari music editor from early 1990s.
CM3 (CMC "3/4")::
CMC with modified pattern length.
CMR (CMC "Rzog")::
CMC with modified bass sounds.
CMS (Stereo Double CMC)::
Stereo CMC.
DMC (DoublePlay CMC)::
CMC with 6502 routine executed at double rate of the original CMC.
DLT (Delta Music Composer)::
Atari music editor from 1990s.
MPT (Music ProTracker)::
Atari music editor from 1990s.
MPD (MPT DoublePlay)::
MPT with 6502 routine executed at double rate of the original MPT.
RMT (http://raster.infos.cz/atari/rmt/rmt.htm[Raster Music Tracker])::
Modern Atari music editor running on Windows.
TMC, TM8 (http://jaskier.atari8.info/[Theta Music Composer] 1.x)::
Atari music editor from late 1990s.
The two file extensions are treated identically and played in stereo.
TM8 means it's stereo (8-channel) music while TMC can be either mono or stereo.
TM2 (http://jaskier.atari8.info/[Theta Music Composer] 2.x)::
Modern Atari music editor.
ifdef::asapsrc[]
include::INSTALL[]
endif::asapsrc[]
ifdef::asapflash[]
include::flash/USAGE[]
endif::asapflash[]
ifdef::asapjava[]
include::java/USAGE[]
endif::asapjava[]
ifdef::asapjavascript[]
include::javascript/USAGE[]
endif::asapjavascript[]
ifdef::asapwin[]
include::win32/USAGE[]
endif::asapwin[]
ifdef::asapwince[]
include::gsplayer/USAGE[]
endif::asapwince[]
include::NEWS[]
include::CREDITS[]
Feedback
--------
If you are interested in the ASAP project, please subscribe its
https://lists.sourceforge.net/lists/listinfo/asap-users[mailing list].
This list is for users and developers.
Once you subscribe, you can post comments, ideas and questions about ASAP.
They will be answered ASAP. ;-)
Use http://sourceforge.net/tracker/?group_id=154391[tracker]
to submit bug reports, feature requests and small code patches.
ifdef::asapwww[]
image::http://sflogo.sourceforge.net/sflogo.php?group_id=154391&amp;type=13["Get ASAP - Another Slight Atari Player at SourceForge.net. Fast, secure and Free Open Source software downloads",width=120,height=30,link="http://sourceforge.net/projects/asap/"]
endif::asapwww[]

View file

@ -1,5 +1,5 @@
Library: asap-1.2.0
Imported: 2008-26-07 by Dominik Wenger
Library: asap-2.1.0
Imported: 2010-02-02 by Dominik Wenger
This directory contains a local version of asap (http://asap.sourceforge.net/) for decoding Atari 8bit .sap
audio streams.
@ -14,12 +14,8 @@ The Licence is the same as the rest of Rockbox.
IMPORT DETAILS
The .[ch] files in apps/codec/asap are copied from ASAP.
Some #defines were added, so it uses the ci-> Pointer.
A small modification was needed in asap.h Line 120.
(changed the delta buffer to signed char)
Also players.h (contains binarys of players) was generated and copied
players.h (contains binarys of players) was generated and copied
into Rockbox.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,218 @@
/*
* anylang.h - C/Java/C#/JavaScript/ActionScript abstraction layer
*
* Copyright (C) 2007-2010 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
*/
#ifndef _ANYLANG_H_
#define _ANYLANG_H_
#if defined(JAVA) || defined(CSHARP) || defined(JAVASCRIPT) || defined(ACTIONSCRIPT)
#define FALSE false
#define TRUE true
#define NULL null
#define _ .
#define PRIVATE
#define CONST
#define OUT_STRING STRING
#else
#define C
#include <string.h>
#define PRIVATE static
#define FUNC(type, name, pars) type name pars
#define P(type, name) type name
#define V(type, name) type name
#define CONST const
#define _ ->
#define PTR *
#define ADDRESSOF &
#define CAST(type) (type)
#define TO_INT(x) (int) (x)
#define TO_BYTE(x) (byte) (x)
#define BYTEARRAY byte *
#define BOOLARRAY abool *
#define VOIDPTR void *
#define UBYTE(data) (data)
#define SBYTE(data) (signed char) (data)
#define CONST_ARRAY(type, name) static const type name[] = {
#define END_CONST_ARRAY }
#define ZERO_ARRAY(array) memset(array, 0, sizeof(array))
#define COPY_ARRAY(dest, dest_offset, src, src_offset, len) \
memcpy(dest + dest_offset, src + src_offset, len)
#define NEW_ARRAY(type, name, size) \
type name[size]
#define INIT_ARRAY(array) memset(array, 0, sizeof(array))
#define STRING const char *
#define OUT_STRING char *
#define CHARAT(s, i) (s)[i]
#define CHARCODEAT(s, i) (s)[i]
#define CHARCODE(c) (c)
#define EQUAL_STRINGS(s1, s2) (strcmp(s1, s2) == 0)
#define EMPTY_STRING(s) (s)[0] = '\0'
#define SUBSTR(s, i) (s + i)
#define BYTES_TO_STRING(dest, src, src_offset, len) \
do { memcpy(dest, src + src_offset, len); (dest)[len] = '\0'; } while (FALSE)
#define SUBSTRING(dest, src, src_offset, len) \
do { memcpy(dest, src + src_offset, len); (dest)[len] = '\0'; } while (FALSE)
#define RESOURCE const byte *
#define GET_RESOURCE(name, ext) name##_##ext
#endif /* defined(JAVA) || defined(CSHARP) || defined(JAVASCRIPT) || defined(ACTIONSCRIPT) */
#ifdef JAVA
#define abool boolean
#define FUNC(type, name, pars) private static type name pars
#define P(type, name) type name
#define V(type, name) type name
#define PTR
#define ADDRESSOF
#define CAST(type) (type)
#define TO_INT(x) (int) (x)
#define TO_BYTE(x) (byte) (x)
#define BYTEARRAY byte[]
#define BOOLARRAY boolean[]
#define VOIDPTR byte[]
#define UBYTE(data) ((data) & 0xff)
#define SBYTE(data) (byte) (data)
#define CONST_ARRAY(type, name) private static final type[] name = {
#define END_CONST_ARRAY }
#define sizeof(array) array.length
#define ZERO_ARRAY(array) for (int ii = 0; ii < array.length; ii++) array[ii] = 0
#define COPY_ARRAY(dest, dest_offset, src, src_offset, len) \
System.arraycopy(src, src_offset, dest, dest_offset, len)
#define NEW_ARRAY(type, name, size) \
type[] name = new type[size]
#define INIT_ARRAY(array)
#define STRING String
#define CHARAT(s, i) (s).charAt(i)
#define CHARCODEAT(s, i) (s).charAt(i)
#define CHARCODE(c) (c)
#define strlen(s) (s).length()
#define EQUAL_STRINGS(s1, s2) (s1).equals(s2)
#define EMPTY_STRING(s) (s) = ""
#define SUBSTR(s, i) (s).substring(i)
#define BYTES_TO_STRING(dest, src, src_offset, len) \
(dest) = new String(src, src_offset, len)
#define SUBSTRING(dest, src, src_offset, len) \
(dest) = (src).substring(src_offset, src_offset + len)
#define RESOURCE byte[]
#define GET_RESOURCE(name, ext) getResourceBytes(#name + "." + #ext)
#elif defined(CSHARP)
#define abool bool
#define FUNC(type, name, pars) private static type name pars
#define P(type, name) type name
#define V(type, name) type name
#define PTR
#define ADDRESSOF
#define CAST(type) (type)
#define TO_INT(x) (int) (x)
#define TO_BYTE(x) (byte) (x)
#define BYTEARRAY byte[]
#define BOOLARRAY bool[]
#define VOIDPTR byte[]
#define UBYTE(data) (data)
#define SBYTE(data) (sbyte) (data)
#define CONST_ARRAY(type, name) private static readonly type[] name = {
#define END_CONST_ARRAY }
#define sizeof(array) array.Length
#define ZERO_ARRAY(array) Array.Clear(array, 0, array.Length)
#define COPY_ARRAY(dest, dest_offset, src, src_offset, len) \
Array.Copy(src, src_offset, dest, dest_offset, len)
#define NEW_ARRAY(type, name, size) \
type[] name = new type[size]
#define INIT_ARRAY(array)
#define STRING string
#define CHARAT(s, i) (s)[i]
#define CHARCODEAT(s, i) (s)[i]
#define CHARCODE(c) (c)
#define strlen(s) (s).Length
#define EQUAL_STRINGS(s1, s2) ((s1) == (s2))
#define EMPTY_STRING(s) (s) = string.Empty
#define SUBSTR(s, i) (s).Substring(i)
#define BYTES_TO_STRING(dest, src, src_offset, len) \
(dest) = System.Text.Encoding.ASCII.GetString(src, src_offset, len)
#define SUBSTRING(dest, src, src_offset, len) \
(dest) = (src).Substring(src_offset, len)
#define RESOURCE byte[]
#define GET_RESOURCE(name, ext) name##_##ext
#elif defined(JAVASCRIPT) || defined(ACTIONSCRIPT)
#ifdef ACTIONSCRIPT
#define abool Boolean
#define char String
#define STRING String
#define BYTEARRAY ByteArray
#define BOOLARRAY Array
#define VOIDPTR ByteArray
#define RESOURCE Array
#define FUNC(type, name, pars) private static function name pars : type
#define P(type, name) name : type
#define V(type, name) var name : type
#define TO_INT(x) int(x)
#define CONST_ARRAY(type, name) private static const name : Array = [
#else
#define FUNC(type, name, pars) function name pars
#define P(type, name) name
#define V(type, name) var name
#define TO_INT(x) Math.floor(x)
#define CONST_ARRAY(type, name) var name = [
#endif
#define PTR
#define ADDRESSOF
#define CAST(type)
#define TO_BYTE(x) ((x) & 0xff)
#define UBYTE(data) (data)
#define SBYTE(data) ((data) < 0x80 ? (data) : (data) - 256)
#define END_CONST_ARRAY ]
#define sizeof(array) array.length
#define ZERO_ARRAY(array) for (V(int, ii) = 0; ii < array.length; ii++) array[ii] = 0
#define COPY_ARRAY(dest, dest_offset, src, src_offset, len) \
for (V(int, ii) = 0; ii < len; ii++) dest[dest_offset + ii] = src[src_offset + ii]
#define NEW_ARRAY(type, name, size) \
V(Array, name) = new Array(size)
#define INIT_ARRAY(array) for (V(int, ii) = 0; ii < array.length; ii++) array[ii] = 0
#define CHARAT(s, i) (s).charAt(i)
#define CHARCODEAT(s, i) (s).charCodeAt(i)
#define CHARCODE(c) (c).charCodeAt(0)
#define strlen(s) (s).length
#define EQUAL_STRINGS(s1, s2) ((s1) == (s2))
#define EMPTY_STRING(s) s = ""
#define SUBSTR(s, i) (s).substr(i)
#define BYTES_TO_STRING(dest, src, src_offset, len) \
{ dest = ""; for (V(int, ii) = 0; ii < len; ii++) dest += String.fromCharCode(src[src_offset + ii]); }
#define SUBSTRING(dest, src, src_offset, len) \
dest = (src).substring(src_offset, src_offset + len)
#define GET_RESOURCE(name, ext) name##_##ext
#endif
#endif /* _ANYLANG_H_ */

View file

@ -1,7 +1,7 @@
/*
* apokeysnd.c - another POKEY sound emulator
*
* Copyright (C) 2007-2008 Piotr Fusik
* Copyright (C) 2007-2009 Piotr Fusik
*
* This file is part of ASAP (Another Slight Atari Player),
* see http://asap.sourceforge.net
@ -20,114 +20,109 @@
* along with ASAP; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "codeclib.h"
#if !defined(JAVA) && !defined(CSHARP)
#include <string.h>
#endif
#include "asap_internal.h"
#define memset ci->memset
#define ULTRASOUND_CYCLES 112
#define MUTE_FREQUENCY 1
#define MUTE_INIT 2
#define MUTE_USER 4
CONST_LOOKUP(byte, poly4_lookup) =
{ 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1 };
CONST_LOOKUP(byte, poly5_lookup) =
{ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1,
0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1 };
CONST_ARRAY(byte, poly4_lookup)
0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1
END_CONST_ARRAY;
CONST_ARRAY(byte, poly5_lookup)
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1,
0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1
END_CONST_ARRAY;
FILE_FUNC void init_state(PokeyState PTR pst)
PRIVATE FUNC(void, PokeySound_InitializeChip, (P(PokeyState PTR, pst)))
{
PST audctl = 0;
PST init = FALSE;
PST poly_index = 15 * 31 * 131071;
PST div_cycles = 28;
PST mute1 = MUTE_FREQUENCY | MUTE_USER;
PST mute2 = MUTE_FREQUENCY | MUTE_USER;
PST mute3 = MUTE_FREQUENCY | MUTE_USER;
PST mute4 = MUTE_FREQUENCY | MUTE_USER;
PST audf1 = 0;
PST audf2 = 0;
PST audf3 = 0;
PST audf4 = 0;
PST audc1 = 0;
PST audc2 = 0;
PST audc3 = 0;
PST audc4 = 0;
PST tick_cycle1 = NEVER;
PST tick_cycle2 = NEVER;
PST tick_cycle3 = NEVER;
PST tick_cycle4 = NEVER;
PST period_cycles1 = 28;
PST period_cycles2 = 28;
PST period_cycles3 = 28;
PST period_cycles4 = 28;
PST reload_cycles1 = 28;
PST reload_cycles3 = 28;
PST out1 = 0;
PST out2 = 0;
PST out3 = 0;
PST out4 = 0;
PST delta1 = 0;
PST delta2 = 0;
PST delta3 = 0;
PST delta4 = 0;
PST skctl = 3;
ZERO_ARRAY(PST delta_buffer);
pst _ audctl = 0;
pst _ init = FALSE;
pst _ poly_index = 15 * 31 * 131071;
pst _ div_cycles = 28;
pst _ mute1 = MUTE_FREQUENCY | MUTE_USER;
pst _ mute2 = MUTE_FREQUENCY | MUTE_USER;
pst _ mute3 = MUTE_FREQUENCY | MUTE_USER;
pst _ mute4 = MUTE_FREQUENCY | MUTE_USER;
pst _ audf1 = 0;
pst _ audf2 = 0;
pst _ audf3 = 0;
pst _ audf4 = 0;
pst _ audc1 = 0;
pst _ audc2 = 0;
pst _ audc3 = 0;
pst _ audc4 = 0;
pst _ tick_cycle1 = NEVER;
pst _ tick_cycle2 = NEVER;
pst _ tick_cycle3 = NEVER;
pst _ tick_cycle4 = NEVER;
pst _ period_cycles1 = 28;
pst _ period_cycles2 = 28;
pst _ period_cycles3 = 28;
pst _ period_cycles4 = 28;
pst _ reload_cycles1 = 28;
pst _ reload_cycles3 = 28;
pst _ out1 = 0;
pst _ out2 = 0;
pst _ out3 = 0;
pst _ out4 = 0;
pst _ delta1 = 0;
pst _ delta2 = 0;
pst _ delta3 = 0;
pst _ delta4 = 0;
pst _ skctl = 3;
ZERO_ARRAY(pst _ delta_buffer);
}
ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast)
FUNC(void, PokeySound_Initialize, (P(ASAP_State PTR, ast)))
{
int i;
int reg;
V(int, i);
V(int, reg);
reg = 0x1ff;
for (i = 0; i < 511; i++) {
reg = ((((reg >> 5) ^ reg) & 1) << 8) + (reg >> 1);
AST poly9_lookup[i] = (byte) reg;
ast _ poly9_lookup[i] = TO_BYTE(reg);
}
reg = 0x1ffff;
for (i = 0; i < 16385; i++) {
reg = ((((reg >> 5) ^ reg) & 0xff) << 9) + (reg >> 8);
AST poly17_lookup[i] = (byte) (reg >> 1);
ast _ poly17_lookup[i] = TO_BYTE(reg >> 1);
}
AST sample_offset = 0;
AST sample_index = 0;
AST samples = 0;
AST iir_acc_left = 0;
AST iir_acc_right = 0;
init_state(ADDRESSOF AST base_pokey);
init_state(ADDRESSOF AST extra_pokey);
ast _ sample_offset = 0;
ast _ sample_index = 0;
ast _ samples = 0;
ast _ iir_acc_left = 0;
ast _ iir_acc_right = 0;
PokeySound_InitializeChip(ADDRESSOF ast _ base_pokey);
PokeySound_InitializeChip(ADDRESSOF ast _ extra_pokey);
}
#define CYCLE_TO_SAMPLE(cycle) (((cycle) * ASAP_SAMPLE_RATE + AST sample_offset) / ASAP_MAIN_CLOCK)
#define DO_TICK(ch) \
if (PST init) { \
switch (PST audc##ch >> 4) { \
if (pst _ init) { \
switch (pst _ audc##ch >> 4) { \
case 10: \
case 14: \
PST out##ch ^= 1; \
PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta##ch = -PST delta##ch; \
pst _ out##ch ^= 1; \
pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta##ch = -pst _ delta##ch; \
break; \
default: \
break; \
} \
} \
else { \
int poly = cycle + PST poly_index - (ch - 1); \
int newout = PST out##ch; \
switch (PST audc##ch >> 4) { \
V(int, poly) = cycle + pst _ poly_index - (ch - 1); \
V(int, newout) = pst _ out##ch; \
switch (pst _ audc##ch >> 4) { \
case 0: \
if (poly5_lookup[poly % 31] != 0) { \
if ((PST audctl & 0x80) != 0) \
newout = AST poly9_lookup[poly % 511] & 1; \
if ((pst _ audctl & 0x80) != 0) \
newout = ast _ poly9_lookup[poly % 511] & 1; \
else { \
poly %= 131071; \
newout = (AST poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
newout = (ast _ poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
} \
} \
break; \
@ -140,11 +135,11 @@ ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast)
newout = poly4_lookup[poly % 15]; \
break; \
case 8: \
if ((PST audctl & 0x80) != 0) \
newout = AST poly9_lookup[poly % 511] & 1; \
if ((pst _ audctl & 0x80) != 0) \
newout = ast _ poly9_lookup[poly % 511] & 1; \
else { \
poly %= 131071; \
newout = (AST poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
newout = (ast _ poly17_lookup[poly >> 3] >> (poly & 7)) & 1; \
} \
break; \
case 10: \
@ -157,125 +152,141 @@ ASAP_FUNC void PokeySound_Initialize(ASAP_State PTR ast)
default: \
break; \
} \
if (newout != PST out##ch) { \
PST out##ch = newout; \
PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta##ch = -PST delta##ch; \
if (newout != pst _ out##ch) { \
pst _ out##ch = newout; \
pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta##ch = -pst _ delta##ch; \
} \
}
FILE_FUNC void generate(ASAP_State PTR ast, PokeyState PTR pst, int current_cycle)
/* Fills delta_buffer up to current_cycle basing on current AUDF/AUDC/AUDCTL values. */
PRIVATE FUNC(void, PokeySound_GenerateUntilCycle, (P(ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, current_cycle)))
{
for (;;) {
int cycle = current_cycle;
if (cycle > PST tick_cycle1)
cycle = PST tick_cycle1;
if (cycle > PST tick_cycle2)
cycle = PST tick_cycle2;
if (cycle > PST tick_cycle3)
cycle = PST tick_cycle3;
if (cycle > PST tick_cycle4)
cycle = PST tick_cycle4;
V(int, cycle) = current_cycle;
if (cycle > pst _ tick_cycle1)
cycle = pst _ tick_cycle1;
if (cycle > pst _ tick_cycle2)
cycle = pst _ tick_cycle2;
if (cycle > pst _ tick_cycle3)
cycle = pst _ tick_cycle3;
if (cycle > pst _ tick_cycle4)
cycle = pst _ tick_cycle4;
if (cycle == current_cycle)
break;
if (cycle == PST tick_cycle3) {
PST tick_cycle3 += PST period_cycles3;
if ((PST audctl & 4) != 0 && PST delta1 > 0 && PST mute1 == 0)
PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta1 = -PST delta1;
if (cycle == pst _ tick_cycle3) {
pst _ tick_cycle3 += pst _ period_cycles3;
if ((pst _ audctl & 4) != 0 && pst _ delta1 > 0 && pst _ mute1 == 0)
pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta1 = -pst _ delta1;
DO_TICK(3);
}
if (cycle == PST tick_cycle4) {
PST tick_cycle4 += PST period_cycles4;
if ((PST audctl & 8) != 0)
PST tick_cycle3 = cycle + PST reload_cycles3;
if ((PST audctl & 2) != 0 && PST delta2 > 0 && PST mute2 == 0)
PST delta_buffer[CYCLE_TO_SAMPLE(cycle)] += PST delta2 = -PST delta2;
if (cycle == pst _ tick_cycle4) {
pst _ tick_cycle4 += pst _ period_cycles4;
if ((pst _ audctl & 8) != 0)
pst _ tick_cycle3 = cycle + pst _ reload_cycles3;
if ((pst _ audctl & 2) != 0 && pst _ delta2 > 0 && pst _ mute2 == 0)
pst _ delta_buffer[CYCLE_TO_SAMPLE(cycle)] += pst _ delta2 = -pst _ delta2;
DO_TICK(4);
}
if (cycle == PST tick_cycle1) {
PST tick_cycle1 += PST period_cycles1;
if ((PST skctl & 0x88) == 8)
PST tick_cycle2 = cycle + PST period_cycles2;
if (cycle == pst _ tick_cycle1) {
pst _ tick_cycle1 += pst _ period_cycles1;
if ((pst _ skctl & 0x88) == 8) /* two-tone, sending 1 (i.e. timer1) */
pst _ tick_cycle2 = cycle + pst _ period_cycles2;
DO_TICK(1);
}
if (cycle == PST tick_cycle2) {
PST tick_cycle2 += PST period_cycles2;
if ((PST audctl & 0x10) != 0)
PST tick_cycle1 = cycle + PST reload_cycles1;
else if ((PST skctl & 8) != 0)
PST tick_cycle1 = cycle + PST period_cycles1;
if (cycle == pst _ tick_cycle2) {
pst _ tick_cycle2 += pst _ period_cycles2;
if ((pst _ audctl & 0x10) != 0)
pst _ tick_cycle1 = cycle + pst _ reload_cycles1;
else if ((pst _ skctl & 8) != 0) /* two-tone */
pst _ tick_cycle1 = cycle + pst _ period_cycles1;
DO_TICK(2);
}
}
}
#ifdef APOKEYSND
#define CURRENT_CYCLE 0
#define CURRENT_SAMPLE 0
#define DO_STORE(reg) \
if (data == pst _ reg) \
break; \
pst _ reg = data;
#else
#define CURRENT_CYCLE ast _ cycle
#define CURRENT_SAMPLE CYCLE_TO_SAMPLE(ast _ cycle)
#define DO_STORE(reg) \
if (data == pst _ reg) \
break; \
PokeySound_GenerateUntilCycle(ast, pst, ast _ cycle); \
pst _ reg = data;
#endif /* APOKEYSND */
#define MUTE_CHANNEL(ch, cond, mask) \
if (cond) { \
PST mute##ch |= mask; \
PST tick_cycle##ch = NEVER; \
pst _ mute##ch |= mask; \
pst _ tick_cycle##ch = NEVER; \
} \
else { \
PST mute##ch &= ~mask; \
if (PST tick_cycle##ch == NEVER && PST mute##ch == 0) \
PST tick_cycle##ch = AST cycle; \
pst _ mute##ch &= ~mask; \
if (pst _ tick_cycle##ch == NEVER && pst _ mute##ch == 0) \
pst _ tick_cycle##ch = CURRENT_CYCLE; \
}
#define DO_ULTRASOUND(ch) \
MUTE_CHANNEL(ch, PST period_cycles##ch <= ULTRASOUND_CYCLES && (PST audc##ch >> 4 == 10 || PST audc##ch >> 4 == 14), MUTE_FREQUENCY)
MUTE_CHANNEL(ch, pst _ period_cycles##ch <= ULTRASOUND_CYCLES && (pst _ audc##ch >> 4 == 10 || pst _ audc##ch >> 4 == 14), MUTE_FREQUENCY)
#define DO_AUDC(ch) \
if (data == PST audc##ch) \
break; \
generate(ast, pst, AST cycle); \
PST audc##ch = data; \
DO_STORE(audc##ch); \
if ((data & 0x10) != 0) { \
data &= 0xf; \
if ((PST mute##ch & MUTE_USER) == 0) \
PST delta_buffer[CYCLE_TO_SAMPLE(AST cycle)] \
+= PST delta##ch > 0 ? data - PST delta##ch : data; \
PST delta##ch = data; \
data = (data & 0xf) << DELTA_SHIFT_POKEY; \
if ((pst _ mute##ch & MUTE_USER) == 0) \
pst _ delta_buffer[CURRENT_SAMPLE] \
+= pst _ delta##ch > 0 ? data - pst _ delta##ch : data; \
pst _ delta##ch = data; \
} \
else { \
data &= 0xf; \
data = (data & 0xf) << DELTA_SHIFT_POKEY; \
DO_ULTRASOUND(ch); \
if (PST delta##ch > 0) { \
if ((PST mute##ch & MUTE_USER) == 0) \
PST delta_buffer[CYCLE_TO_SAMPLE(AST cycle)] \
+= data - PST delta##ch; \
PST delta##ch = data; \
if (pst _ delta##ch > 0) { \
if ((pst _ mute##ch & MUTE_USER) == 0) \
pst _ delta_buffer[CURRENT_SAMPLE] \
+= data - pst _ delta##ch; \
pst _ delta##ch = data; \
} \
else \
PST delta##ch = -data; \
pst _ delta##ch = -data; \
} \
break;
#define DO_INIT(ch, cond) \
MUTE_CHANNEL(ch, PST init && cond, MUTE_INIT)
MUTE_CHANNEL(ch, pst _ init && cond, MUTE_INIT)
ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
FUNC(void, PokeySound_PutByte, (P(ASAP_State PTR, ast), P(int, addr), P(int, data)))
{
PokeyState PTR pst = (addr & AST extra_pokey_mask) != 0
? ADDRESSOF AST extra_pokey : ADDRESSOF AST base_pokey;
V(PokeyState PTR, pst) = (addr & ast _ extra_pokey_mask) != 0
? ADDRESSOF ast _ extra_pokey : ADDRESSOF ast _ base_pokey;
switch (addr & 0xf) {
case 0x00:
if (data == PST audf1)
break;
generate(ast, pst, AST cycle);
PST audf1 = data;
switch (PST audctl & 0x50) {
DO_STORE(audf1);
switch (pst _ audctl & 0x50) {
case 0x00:
PST period_cycles1 = PST div_cycles * (data + 1);
pst _ period_cycles1 = pst _ div_cycles * (data + 1);
break;
case 0x10:
PST period_cycles2 = PST div_cycles * (data + 256 * PST audf2 + 1);
PST reload_cycles1 = PST div_cycles * (data + 1);
pst _ period_cycles2 = pst _ div_cycles * (data + 256 * pst _ audf2 + 1);
pst _ reload_cycles1 = pst _ div_cycles * (data + 1);
DO_ULTRASOUND(2);
break;
case 0x40:
PST period_cycles1 = data + 4;
pst _ period_cycles1 = data + 4;
break;
case 0x50:
PST period_cycles2 = data + 256 * PST audf2 + 7;
PST reload_cycles1 = data + 4;
pst _ period_cycles2 = data + 256 * pst _ audf2 + 7;
pst _ reload_cycles1 = data + 4;
DO_ULTRASOUND(2);
break;
}
@ -284,20 +295,17 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
case 0x01:
DO_AUDC(1)
case 0x02:
if (data == PST audf2)
break;
generate(ast, pst, AST cycle);
PST audf2 = data;
switch (PST audctl & 0x50) {
DO_STORE(audf2);
switch (pst _ audctl & 0x50) {
case 0x00:
case 0x40:
PST period_cycles2 = PST div_cycles * (data + 1);
pst _ period_cycles2 = pst _ div_cycles * (data + 1);
break;
case 0x10:
PST period_cycles2 = PST div_cycles * (PST audf1 + 256 * data + 1);
pst _ period_cycles2 = pst _ div_cycles * (pst _ audf1 + 256 * data + 1);
break;
case 0x50:
PST period_cycles2 = PST audf1 + 256 * data + 7;
pst _ period_cycles2 = pst _ audf1 + 256 * data + 7;
break;
}
DO_ULTRASOUND(2);
@ -305,25 +313,22 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
case 0x03:
DO_AUDC(2)
case 0x04:
if (data == PST audf3)
break;
generate(ast, pst, AST cycle);
PST audf3 = data;
switch (PST audctl & 0x28) {
DO_STORE(audf3);
switch (pst _ audctl & 0x28) {
case 0x00:
PST period_cycles3 = PST div_cycles * (data + 1);
pst _ period_cycles3 = pst _ div_cycles * (data + 1);
break;
case 0x08:
PST period_cycles4 = PST div_cycles * (data + 256 * PST audf4 + 1);
PST reload_cycles3 = PST div_cycles * (data + 1);
pst _ period_cycles4 = pst _ div_cycles * (data + 256 * pst _ audf4 + 1);
pst _ reload_cycles3 = pst _ div_cycles * (data + 1);
DO_ULTRASOUND(4);
break;
case 0x20:
PST period_cycles3 = data + 4;
pst _ period_cycles3 = data + 4;
break;
case 0x28:
PST period_cycles4 = data + 256 * PST audf4 + 7;
PST reload_cycles3 = data + 4;
pst _ period_cycles4 = data + 256 * pst _ audf4 + 7;
pst _ reload_cycles3 = data + 4;
DO_ULTRASOUND(4);
break;
}
@ -332,20 +337,17 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
case 0x05:
DO_AUDC(3)
case 0x06:
if (data == PST audf4)
break;
generate(ast, pst, AST cycle);
PST audf4 = data;
switch (PST audctl & 0x28) {
DO_STORE(audf4);
switch (pst _ audctl & 0x28) {
case 0x00:
case 0x20:
PST period_cycles4 = PST div_cycles * (data + 1);
pst _ period_cycles4 = pst _ div_cycles * (data + 1);
break;
case 0x08:
PST period_cycles4 = PST div_cycles * (PST audf3 + 256 * data + 1);
pst _ period_cycles4 = pst _ div_cycles * (pst _ audf3 + 256 * data + 1);
break;
case 0x28:
PST period_cycles4 = PST audf3 + 256 * data + 7;
pst _ period_cycles4 = pst _ audf3 + 256 * data + 7;
break;
}
DO_ULTRASOUND(4);
@ -353,141 +355,153 @@ ASAP_FUNC void PokeySound_PutByte(ASAP_State PTR ast, int addr, int data)
case 0x07:
DO_AUDC(4)
case 0x08:
if (data == PST audctl)
break;
generate(ast, pst, AST cycle);
PST audctl = data;
PST div_cycles = ((data & 1) != 0) ? 114 : 28;
DO_STORE(audctl);
pst _ div_cycles = ((data & 1) != 0) ? 114 : 28;
/* TODO: tick_cycles */
switch (data & 0x50) {
case 0x00:
PST period_cycles1 = PST div_cycles * (PST audf1 + 1);
PST period_cycles2 = PST div_cycles * (PST audf2 + 1);
pst _ period_cycles1 = pst _ div_cycles * (pst _ audf1 + 1);
pst _ period_cycles2 = pst _ div_cycles * (pst _ audf2 + 1);
break;
case 0x10:
PST period_cycles1 = PST div_cycles * 256;
PST period_cycles2 = PST div_cycles * (PST audf1 + 256 * PST audf2 + 1);
PST reload_cycles1 = PST div_cycles * (PST audf1 + 1);
pst _ period_cycles1 = pst _ div_cycles * 256;
pst _ period_cycles2 = pst _ div_cycles * (pst _ audf1 + 256 * pst _ audf2 + 1);
pst _ reload_cycles1 = pst _ div_cycles * (pst _ audf1 + 1);
break;
case 0x40:
PST period_cycles1 = PST audf1 + 4;
PST period_cycles2 = PST div_cycles * (PST audf2 + 1);
pst _ period_cycles1 = pst _ audf1 + 4;
pst _ period_cycles2 = pst _ div_cycles * (pst _ audf2 + 1);
break;
case 0x50:
PST period_cycles1 = 256;
PST period_cycles2 = PST audf1 + 256 * PST audf2 + 7;
PST reload_cycles1 = PST audf1 + 4;
pst _ period_cycles1 = 256;
pst _ period_cycles2 = pst _ audf1 + 256 * pst _ audf2 + 7;
pst _ reload_cycles1 = pst _ audf1 + 4;
break;
}
DO_ULTRASOUND(1);
DO_ULTRASOUND(2);
switch (data & 0x28) {
case 0x00:
PST period_cycles3 = PST div_cycles * (PST audf3 + 1);
PST period_cycles4 = PST div_cycles * (PST audf4 + 1);
pst _ period_cycles3 = pst _ div_cycles * (pst _ audf3 + 1);
pst _ period_cycles4 = pst _ div_cycles * (pst _ audf4 + 1);
break;
case 0x08:
PST period_cycles3 = PST div_cycles * 256;
PST period_cycles4 = PST div_cycles * (PST audf3 + 256 * PST audf4 + 1);
PST reload_cycles3 = PST div_cycles * (PST audf3 + 1);
pst _ period_cycles3 = pst _ div_cycles * 256;
pst _ period_cycles4 = pst _ div_cycles * (pst _ audf3 + 256 * pst _ audf4 + 1);
pst _ reload_cycles3 = pst _ div_cycles * (pst _ audf3 + 1);
break;
case 0x20:
PST period_cycles3 = PST audf3 + 4;
PST period_cycles4 = PST div_cycles * (PST audf4 + 1);
pst _ period_cycles3 = pst _ audf3 + 4;
pst _ period_cycles4 = pst _ div_cycles * (pst _ audf4 + 1);
break;
case 0x28:
PST period_cycles3 = 256;
PST period_cycles4 = PST audf3 + 256 * PST audf4 + 7;
PST reload_cycles3 = PST audf3 + 4;
pst _ period_cycles3 = 256;
pst _ period_cycles4 = pst _ audf3 + 256 * pst _ audf4 + 7;
pst _ reload_cycles3 = pst _ audf3 + 4;
break;
}
DO_ULTRASOUND(3);
DO_ULTRASOUND(4);
DO_INIT(1, (data & 0x40) == 0);
DO_INIT(2, (data & 0x50) != 0x50);
DO_INIT(3, (data & 0x20) == 0);
DO_INIT(4, (data & 0x28) != 0x28);
break;
case 0x09:
/* TODO: STIMER */
break;
case 0x0f:
PST skctl = data;
PST init = ((data & 3) == 0);
DO_INIT(1, (PST audctl & 0x40) == 0);
DO_INIT(2, (PST audctl & 0x50) != 0x50);
DO_INIT(3, (PST audctl & 0x20) == 0);
DO_INIT(4, (PST audctl & 0x28) != 0x28);
DO_STORE(skctl);
pst _ init = ((data & 3) == 0);
DO_INIT(1, (pst _ audctl & 0x40) == 0);
DO_INIT(2, (pst _ audctl & 0x50) != 0x50);
DO_INIT(3, (pst _ audctl & 0x20) == 0);
DO_INIT(4, (pst _ audctl & 0x28) != 0x28);
break;
default:
break;
}
}
ASAP_FUNC int PokeySound_GetRandom(ASAP_State PTR ast, int addr)
FUNC(int, PokeySound_GetRandom, (P(ASAP_State PTR, ast), P(int, addr), P(int, cycle)))
{
PokeyState PTR pst = (addr & AST extra_pokey_mask) != 0
? ADDRESSOF AST extra_pokey : ADDRESSOF AST base_pokey;
int i;
if (PST init)
V(PokeyState PTR, pst) = (addr & ast _ extra_pokey_mask) != 0
? ADDRESSOF ast _ extra_pokey : ADDRESSOF ast _ base_pokey;
V(int, i);
if (pst _ init)
return 0xff;
i = AST cycle + PST poly_index;
if ((PST audctl & 0x80) != 0)
return AST poly9_lookup[i % 511];
i = cycle + pst _ poly_index;
if ((pst _ audctl & 0x80) != 0)
return ast _ poly9_lookup[i % 511];
else {
int j;
V(int, j);
i %= 131071;
j = i >> 3;
i &= 7;
return ((AST poly17_lookup[j] >> i) + (AST poly17_lookup[j + 1] << (8 - i))) & 0xff;
return ((ast _ poly17_lookup[j] >> i) + (ast _ poly17_lookup[j + 1] << (8 - i))) & 0xff;
}
}
FILE_FUNC void end_frame(ASAP_State PTR ast, PokeyState PTR pst, int cycle_limit)
PRIVATE FUNC(void, end_frame, (P(ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, cycle_limit)))
{
int m;
generate(ast, pst, cycle_limit);
PST poly_index += cycle_limit;
m = ((PST audctl & 0x80) != 0) ? 15 * 31 * 511 : 15 * 31 * 131071;
if (PST poly_index >= 2 * m)
PST poly_index -= m;
if (PST tick_cycle1 != NEVER)
PST tick_cycle1 -= cycle_limit;
if (PST tick_cycle2 != NEVER)
PST tick_cycle2 -= cycle_limit;
if (PST tick_cycle3 != NEVER)
PST tick_cycle3 -= cycle_limit;
if (PST tick_cycle4 != NEVER)
PST tick_cycle4 -= cycle_limit;
V(int, m);
PokeySound_GenerateUntilCycle(ast, pst, cycle_limit);
pst _ poly_index += cycle_limit;
m = ((pst _ audctl & 0x80) != 0) ? 15 * 31 * 511 : 15 * 31 * 131071;
if (pst _ poly_index >= 2 * m)
pst _ poly_index -= m;
if (pst _ tick_cycle1 != NEVER)
pst _ tick_cycle1 -= cycle_limit;
if (pst _ tick_cycle2 != NEVER)
pst _ tick_cycle2 -= cycle_limit;
if (pst _ tick_cycle3 != NEVER)
pst _ tick_cycle3 -= cycle_limit;
if (pst _ tick_cycle4 != NEVER)
pst _ tick_cycle4 -= cycle_limit;
}
ASAP_FUNC void PokeySound_StartFrame(ASAP_State PTR ast)
FUNC(void, PokeySound_StartFrame, (P(ASAP_State PTR, ast)))
{
ZERO_ARRAY(AST base_pokey.delta_buffer);
if (AST extra_pokey_mask != 0)
ZERO_ARRAY(AST extra_pokey.delta_buffer);
ZERO_ARRAY(ast _ base_pokey.delta_buffer);
if (ast _ extra_pokey_mask != 0)
ZERO_ARRAY(ast _ extra_pokey.delta_buffer);
}
ASAP_FUNC void PokeySound_EndFrame(ASAP_State PTR ast, int current_cycle)
FUNC(void, PokeySound_EndFrame, (P(ASAP_State PTR, ast), P(int, current_cycle)))
{
end_frame(ast, ADDRESSOF AST base_pokey, current_cycle);
if (AST extra_pokey_mask != 0)
end_frame(ast, ADDRESSOF AST extra_pokey, current_cycle);
AST sample_offset += current_cycle * ASAP_SAMPLE_RATE;
AST sample_index = 0;
AST samples = AST sample_offset / ASAP_MAIN_CLOCK;
AST sample_offset %= ASAP_MAIN_CLOCK;
end_frame(ast, ADDRESSOF ast _ base_pokey, current_cycle);
if (ast _ extra_pokey_mask != 0)
end_frame(ast, ADDRESSOF ast _ extra_pokey, current_cycle);
ast _ sample_offset += current_cycle * ASAP_SAMPLE_RATE;
ast _ sample_index = 0;
ast _ samples = TO_INT(ast _ sample_offset / ASAP_MAIN_CLOCK);
ast _ sample_offset %= ASAP_MAIN_CLOCK;
}
ASAP_FUNC int PokeySound_Generate(ASAP_State PTR ast, byte ARRAY buffer, int buffer_offset, int blocks, ASAP_SampleFormat format)
/* Fills buffer with samples from delta_buffer. */
FUNC(int, PokeySound_Generate, (P(ASAP_State PTR, ast), P(BYTEARRAY, buffer), P(int, buffer_offset), P(int, blocks), P(ASAP_SampleFormat, format)))
{
int i = AST sample_index;
int samples = AST samples;
int acc_left = AST iir_acc_left;
int acc_right = AST iir_acc_right;
V(int, i) = ast _ sample_index;
V(int, samples) = ast _ samples;
V(int, acc_left) = ast _ iir_acc_left;
V(int, acc_right) = ast _ iir_acc_right;
if (blocks < samples - i)
samples = i + blocks;
else
blocks = samples - i;
for (; i < samples; i++) {
int sample;
acc_left += (AST base_pokey.delta_buffer[i] << 20) - (acc_left * 3 >> 10);
#ifdef ACTIONSCRIPT
acc_left += ast _ base_pokey.delta_buffer[i] - (acc_left * 3 >> 10);
var sample : Number = acc_left / 33553408;
buffer.writeFloat(sample);
if (ast.extra_pokey_mask != 0) {
acc_right += ast _ extra_pokey.delta_buffer[i] - (acc_right * 3 >> 10);
sample = acc_right / 33553408;
}
buffer.writeFloat(sample);
#else
V(int, sample);
acc_left += ast _ base_pokey.delta_buffer[i] - (acc_left * 3 >> 10);
sample = acc_left >> 10;
#define STORE_SAMPLE \
if (sample < -32767) \
@ -496,43 +510,89 @@ ASAP_FUNC int PokeySound_Generate(ASAP_State PTR ast, byte ARRAY buffer, int buf
sample = 32767; \
switch (format) { \
case ASAP_FORMAT_U8: \
buffer[buffer_offset++] = (byte) ((sample >> 8) + 128); \
buffer[buffer_offset++] = CAST(byte) ((sample >> 8) + 128); \
break; \
case ASAP_FORMAT_S16_LE: \
buffer[buffer_offset++] = (byte) sample; \
buffer[buffer_offset++] = (byte) (sample >> 8); \
buffer[buffer_offset++] = TO_BYTE(sample); \
buffer[buffer_offset++] = TO_BYTE(sample >> 8); \
break; \
case ASAP_FORMAT_S16_BE: \
buffer[buffer_offset++] = (byte) (sample >> 8); \
buffer[buffer_offset++] = (byte) sample; \
buffer[buffer_offset++] = TO_BYTE(sample >> 8); \
buffer[buffer_offset++] = TO_BYTE(sample); \
break; \
}
STORE_SAMPLE;
if (AST extra_pokey_mask != 0) {
acc_right += (AST extra_pokey.delta_buffer[i] << 20) - (acc_right * 3 >> 10);
if (ast _ extra_pokey_mask != 0) {
acc_right += ast _ extra_pokey.delta_buffer[i] - (acc_right * 3 >> 10);
sample = acc_right >> 10;
STORE_SAMPLE;
}
#endif /* ACTIONSCRIPT */
}
if (i == AST samples) {
acc_left += AST base_pokey.delta_buffer[i] << 20;
acc_right += AST extra_pokey.delta_buffer[i] << 20;
if (i == ast _ samples) {
acc_left += ast _ base_pokey.delta_buffer[i];
acc_right += ast _ extra_pokey.delta_buffer[i];
}
AST sample_index = i;
AST iir_acc_left = acc_left;
AST iir_acc_right = acc_right;
ast _ sample_index = i;
ast _ iir_acc_left = acc_left;
ast _ iir_acc_right = acc_right;
#ifdef APOKEYSND
return buffer_offset;
#else
return blocks;
#endif
}
ASAP_FUNC abool PokeySound_IsSilent(const PokeyState PTR pst)
FUNC(abool, PokeySound_IsSilent, (P(CONST PokeyState PTR, pst)))
{
return ((PST audc1 | PST audc2 | PST audc3 | PST audc4) & 0xf) == 0;
return ((pst _ audc1 | pst _ audc2 | pst _ audc3 | pst _ audc4) & 0xf) == 0;
}
ASAP_FUNC void PokeySound_Mute(const ASAP_State PTR ast, PokeyState PTR pst, int mask)
FUNC(void, PokeySound_Mute, (P(CONST ASAP_State PTR, ast), P(PokeyState PTR, pst), P(int, mask)))
{
MUTE_CHANNEL(1, (mask & 1) != 0, MUTE_USER);
MUTE_CHANNEL(2, (mask & 2) != 0, MUTE_USER);
MUTE_CHANNEL(3, (mask & 4) != 0, MUTE_USER);
MUTE_CHANNEL(4, (mask & 8) != 0, MUTE_USER);
}
#ifdef APOKEYSND
static ASAP_State asap;
__declspec(dllexport) void APokeySound_Initialize(abool stereo)
{
asap.extra_pokey_mask = stereo ? 0x10 : 0;
PokeySound_Initialize(&asap);
PokeySound_Mute(&asap, &asap.base_pokey, 0);
PokeySound_Mute(&asap, &asap.extra_pokey, 0);
PokeySound_StartFrame(&asap);
}
__declspec(dllexport) void APokeySound_PutByte(int addr, int data)
{
PokeySound_PutByte(&asap, addr, data);
}
__declspec(dllexport) int APokeySound_GetRandom(int addr, int cycle)
{
return PokeySound_GetRandom(&asap, addr, cycle);
}
__declspec(dllexport) int APokeySound_Generate(int cycles, byte buffer[], ASAP_SampleFormat format)
{
int len;
PokeySound_EndFrame(&asap, cycles);
len = PokeySound_Generate(&asap, buffer, 0, asap.samples, format);
PokeySound_StartFrame(&asap);
return len;
}
__declspec(dllexport) void APokeySound_About(const char **name, const char **author, const char **description)
{
*name = "Another POKEY sound emulator, v" ASAP_VERSION;
*author = "Piotr Fusik, (C) " ASAP_YEARS;
*description = "Part of ASAP, http://asap.sourceforge.net";
}
#endif /* APOKEYSND */

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
* asap.h - public interface of the ASAP engine
* asap.h - public interface of ASAP
*
* Copyright (C) 2005-2008 Piotr Fusik
* Copyright (C) 2005-2010 Piotr Fusik
*
* This file is part of ASAP (Another Slight Atari Player),
* see http://asap.sourceforge.net
@ -29,17 +29,19 @@ extern "C" {
#endif
/* ASAP version. */
#define ASAP_VERSION_MAJOR 1
#define ASAP_VERSION_MINOR 2
#define ASAP_VERSION_MAJOR 2
#define ASAP_VERSION_MINOR 1
#define ASAP_VERSION_MICRO 0
#define ASAP_VERSION "1.2.0"
#define ASAP_VERSION "2.1.0"
/* Short credits of the ASAP engine. */
#define ASAP_YEARS "2005-2008"
#define ASAP_YEARS "2005-2010"
#define ASAP_CREDITS \
"Another Slight Atari Player (C) 2005-2008 Piotr Fusik\n" \
"CMC, MPT, TMC players (C) 1994-2005 Marcin Lewandowski\n" \
"RMT player (C) 2002-2005 Radek Sterba\n"
"Another Slight Atari Player (C) 2005-2010 Piotr Fusik\n" \
"CMC, MPT, TMC, TM2 players (C) 1994-2005 Marcin Lewandowski\n" \
"RMT player (C) 2002-2005 Radek Sterba\n" \
"DLT player (C) 2009 Marek Konopka\n" \
"CMS player (C) 1999 David Spilka\n"
/* Short GPL notice.
Display after the credits. */
@ -49,6 +51,32 @@ extern "C" {
"by the Free Software Foundation; either version 2 of the License,\n" \
"or (at your option) any later version."
/* Maximum length of AUTHOR, NAME and DATE tags including the terminator. */
#define ASAP_INFO_CHARS 128
/* Maximum length of a "mm:ss.xxx" string including the terminator. */
#define ASAP_DURATION_CHARS 10
/* Maximum length of a supported input file.
You can assume that files longer than this are not supported by ASAP. */
#define ASAP_MODULE_MAX 65000
/* Maximum number of songs in a file. */
#define ASAP_SONGS_MAX 32
/* Output sample rate. */
#define ASAP_SAMPLE_RATE 44100
/* WAV file header length. */
#define ASAP_WAV_HEADER_BYTES 44
/* Output formats. */
typedef enum {
ASAP_FORMAT_U8 = 8, /* unsigned char */
ASAP_FORMAT_S16_LE = 16, /* signed short, little-endian */
ASAP_FORMAT_S16_BE = -16 /* signed short, big-endian */
} ASAP_SampleFormat;
/* Useful type definitions. */
#ifndef FALSE
#define FALSE 0
@ -59,24 +87,25 @@ extern "C" {
typedef int abool;
typedef unsigned char byte;
/* Information about a file. */
/* Information about a music file. */
typedef struct {
char author[128]; /* author's name */
char name[128]; /* title */
char date[128]; /* creation date */
char author[ASAP_INFO_CHARS]; /* author's name */
char name[ASAP_INFO_CHARS]; /* title */
char date[ASAP_INFO_CHARS]; /* creation date */
int channels; /* 1 for mono or 2 for stereo */
int songs; /* number of subsongs */
int default_song; /* 0-based index of the "main" subsong */
int durations[32]; /* lengths of songs, in milliseconds, -1 = unspecified */
abool loops[32]; /* whether songs repeat or not */
int durations[ASAP_SONGS_MAX]; /* lengths of songs, in milliseconds, -1 = indeterminate */
abool loops[ASAP_SONGS_MAX]; /* whether songs repeat or not */
/* the following technical information should not be used outside ASAP. */
char type;
int type;
int fastplay;
int music;
int init;
int player;
int covox_addr;
int header_len;
byte song_pos[128];
byte song_pos[ASAP_SONGS_MAX];
} ASAP_ModuleInfo;
/* POKEY state.
@ -117,7 +146,7 @@ typedef struct {
int delta3;
int delta4;
int skctl;
signed char delta_buffer[888];
int delta_buffer[888];
} PokeyState;
/* Player state.
@ -140,6 +169,8 @@ typedef struct {
int timer4_cycle;
int irqst;
int extra_pokey_mask;
int consol;
byte covox[4];
PokeyState base_pokey;
PokeyState extra_pokey;
int sample_offset;
@ -160,23 +191,6 @@ typedef struct {
byte memory[65536];
} ASAP_State;
/* Maximum length of a "mm:ss.xxx" string including the terminator. */
#define ASAP_DURATION_CHARS 10
/* Maximum length of a supported input file.
You can assume that files longer than this are not supported by ASAP. */
#define ASAP_MODULE_MAX 65000
/* Output sample rate. */
#define ASAP_SAMPLE_RATE 44100
/* Output formats. */
typedef enum {
ASAP_FORMAT_U8 = 8, /* unsigned char */
ASAP_FORMAT_S16_LE = 16, /* signed short, little-endian */
ASAP_FORMAT_S16_BE = -16 /* signed short, big-endian */
} ASAP_SampleFormat;
/* Parses the string in the "mm:ss.xxx" format
and returns the number of milliseconds or -1 if an error occurs. */
int ASAP_ParseDuration(const char *s);
@ -203,7 +217,7 @@ abool ASAP_GetModuleInfo(ASAP_ModuleInfo *module_info, const char *filename,
const byte module[], int module_len);
/* Loads music data.
"as" is the destination structure.
"ast" is the destination structure.
"filename" determines file format.
"module" is the music data (contents of the file).
"module_len" is the number of data bytes.
@ -212,39 +226,50 @@ abool ASAP_GetModuleInfo(ASAP_ModuleInfo *module_info, const char *filename,
ASAP_Load() returns true on success.
If false is returned, the structure is invalid and you cannot
call the following functions. */
abool ASAP_Load(ASAP_State *as, const char *filename,
abool ASAP_Load(ASAP_State *ast, const char *filename,
const byte module[], int module_len);
/* Enables silence detection.
Makes ASAP finish playing after the specified period of silence.
"as" is ASAP state initialized by ASAP_Load().
"ast" is ASAP state initialized by ASAP_Load().
"seconds" is the minimum length of silence that ends playback. */
void ASAP_DetectSilence(ASAP_State *as, int seconds);
void ASAP_DetectSilence(ASAP_State *ast, int seconds);
/* Prepares ASAP to play the specified song of the loaded module.
"as" is ASAP state initialized by ASAP_Load().
"ast" is ASAP state initialized by ASAP_Load().
"song" is a zero-based index which must be less than the "songs" field
of the ASAP_ModuleInfo structure.
"duration" is playback time in milliseconds - use durations[song]
unless you want to override it. -1 means indefinitely. */
void ASAP_PlaySong(ASAP_State *as, int song, int duration);
void ASAP_PlaySong(ASAP_State *ast, int song, int duration);
/* Mutes the selected POKEY channels.
This is only useful for people who want to grab samples of individual
instruments.
"as" is ASAP state after calling ASAP_PlaySong().
"ast" is ASAP state after calling ASAP_PlaySong().
"mask" is a bit mask which selects POKEY channels to be muted.
Bits 0-3 control the base POKEY channels,
bits 4-7 control the extra POKEY channels. */
void ASAP_MutePokeyChannels(ASAP_State *as, int mask);
void ASAP_MutePokeyChannels(ASAP_State *ast, int mask);
/* Returns current position in milliseconds.
"ast" is ASAP state initialized by ASAP_PlaySong(). */
int ASAP_GetPosition(const ASAP_State *ast);
/* Rewinds the current song.
"as" is ASAP state initialized by ASAP_PlaySong().
"ast" is ASAP state initialized by ASAP_PlaySong().
"position" is the requested absolute position in milliseconds. */
void ASAP_Seek(ASAP_State *as, int position);
void ASAP_Seek(ASAP_State *ast, int position);
/* Fills the specified buffer with WAV file header.
"ast" is ASAP state initialized by ASAP_PlaySong() with a positive "duration".
"buffer" is buffer of ASAP_WAV_HEADER_BYTES bytes.
"format" is the format of samples. */
void ASAP_GetWavHeader(const ASAP_State *ast, byte buffer[],
ASAP_SampleFormat format);
/* Fills the specified buffer with generated samples.
"as" is ASAP state initialized by ASAP_PlaySong().
"ast" is ASAP state initialized by ASAP_PlaySong().
"buffer" is the destination buffer.
"buffer_len" is the length of this buffer in bytes.
"format" is the format of samples.
@ -252,7 +277,7 @@ void ASAP_Seek(ASAP_State *as, int position);
(less than buffer_len if reached the end of the song).
Normally you use a buffer of a few kilobytes or less,
and call ASAP_Generate() in a loop or via a callback. */
int ASAP_Generate(ASAP_State *as, void *buffer, int buffer_len,
int ASAP_Generate(ASAP_State *ast, void *buffer, int buffer_len,
ASAP_SampleFormat format);
/* Checks whether information in the specified file can be edited. */

View file

@ -1,7 +1,7 @@
/*
* asap_internal.h - private interface of the ASAP engine
* asap_internal.h - private interface of ASAP
*
* Copyright (C) 2005-2008 Piotr Fusik
* Copyright (C) 2005-2010 Piotr Fusik
*
* This file is part of ASAP (Another Slight Atari Player),
* see http://asap.sourceforge.net
@ -24,34 +24,36 @@
#ifndef _ASAP_INTERNAL_H_
#define _ASAP_INTERNAL_H_
#if !defined(JAVA) && !defined(CSHARP)
#include "anylang.h"
#ifndef C
#define ASAP_SONGS_MAX 32
#define ASAP_SAMPLE_RATE 44100
#endif
#ifdef JAVA
#define ASAP_FORMAT_U8 8
#define ASAP_FORMAT_S16_LE 16
#define ASAP_FORMAT_S16_BE -16
#define ASAP_SampleFormat int
#elif defined(CSHARP) || defined(JAVASCRIPT)
#define ASAP_FORMAT_U8 ASAP_SampleFormat.U8
#define ASAP_FORMAT_S16_LE ASAP_SampleFormat.S16LE
#define ASAP_FORMAT_S16_BE ASAP_SampleFormat.S16BE
#elif defined(ACTIONSCRIPT)
#define ASAP_SampleFormat int
#else /* C */
#include "asap.h"
#define CONST_LOOKUP(type, name) \
static const type name[]
#define FILE_FUNC static
#define ASAP_FUNC
#define PTR *
#define ADDRESSOF &
#define ARRAY *
#define VOIDPTR void *
#define UBYTE(data) (data)
#define SBYTE(data) (signed char) (data)
#define STRING const char *
#define ZERO_ARRAY(array) memset(array, 0, sizeof(array))
#define COPY_ARRAY(dest, dest_offset, src, src_offset, len) \
memcpy(dest + dest_offset, src + src_offset, len)
#define NEW_ARRAY(type, name, size) \
type name[size]
#define INIT_ARRAY(array) memset(array, 0, sizeof(array))
#define AST ast->
#define PST pst->
#define MODULE_INFO module_info->
#define ASAP_OBX const byte *
#define GET_OBX(name) name##_obx
int ASAP_GetByte(ASAP_State *ast, int addr);
void ASAP_PutByte(ASAP_State *ast, int addr, int data);
@ -60,7 +62,7 @@ void Cpu_RunScanlines(ASAP_State *ast, int scanlines);
void PokeySound_Initialize(ASAP_State *ast);
void PokeySound_StartFrame(ASAP_State *ast);
void PokeySound_PutByte(ASAP_State *ast, int addr, int data);
int PokeySound_GetRandom(ASAP_State *ast, int addr);
int PokeySound_GetRandom(ASAP_State *ast, int addr, int cycle);
void PokeySound_EndFrame(ASAP_State *ast, int cycle_limit);
int PokeySound_Generate(ASAP_State *ast, byte buffer[], int buffer_offset, int blocks, ASAP_SampleFormat format);
abool PokeySound_IsSilent(const PokeyState *pst);
@ -68,11 +70,11 @@ void PokeySound_Mute(const ASAP_State *ast, PokeyState *pst, int mask);
#ifdef ASAPSCAN
abool call_6502_player(ASAP_State *ast);
extern abool cpu_trace;
void print_cpu_state(const ASAP_State *ast, int pc, int a, int x, int y, int s, int nz, int vdi, int c);
extern int cpu_trace;
void trace_cpu(const ASAP_State *ast, int pc, int a, int x, int y, int s, int nz, int vdi, int c);
#endif
#endif /* !defined(JAVA) && !defined(CSHARP) */
#endif /* C */
#define ASAP_MAIN_CLOCK 1773447
@ -83,11 +85,32 @@ void print_cpu_state(const ASAP_State *ast, int pc, int a, int x, int y, int s,
#define NEVER 0x800000
#define dGetByte(addr) UBYTE(AST memory[addr])
#define dPutByte(addr, data) AST memory[addr] = (byte) (data)
#define DELTA_SHIFT_POKEY 20
#define DELTA_SHIFT_GTIA 20
#define DELTA_SHIFT_COVOX 17
/* 6502 player types */
#define ASAP_TYPE_SAP_B 1
#define ASAP_TYPE_SAP_C 2
#define ASAP_TYPE_SAP_D 3
#define ASAP_TYPE_SAP_S 4
#define ASAP_TYPE_CMC 5
#define ASAP_TYPE_CM3 6
#define ASAP_TYPE_CMR 7
#define ASAP_TYPE_CMS 8
#define ASAP_TYPE_DLT 9
#define ASAP_TYPE_MPT 10
#define ASAP_TYPE_RMT 11
#define ASAP_TYPE_TMC 12
#define ASAP_TYPE_TM2 13
#define dGetByte(addr) UBYTE(ast _ memory[addr])
#define dPutByte(addr, data) ast _ memory[addr] = CAST(byte) (data)
#define dGetWord(addr) (dGetByte(addr) + (dGetByte((addr) + 1) << 8))
#define GetByte(addr) (((addr) & 0xf900) == 0xd000 ? ASAP_GetByte(ast, addr) : dGetByte(addr))
#define PutByte(addr, data) do { if (((addr) & 0xf900) == 0xd000) ASAP_PutByte(ast, addr, data); else dPutByte(addr, data); } while (FALSE)
#define RMW_GetByte(dest, addr) do { if (((addr) >> 8) == 0xd2) { dest = ASAP_GetByte(ast, addr); AST cycle--; ASAP_PutByte(ast, addr, dest); AST cycle++; } else dest = dGetByte(addr); } while (FALSE)
#define RMW_GetByte(dest, addr) do { if (((addr) >> 8) == 0xd2) { dest = ASAP_GetByte(ast, addr); ast _ cycle--; ASAP_PutByte(ast, addr, dest); ast _ cycle++; } else dest = dGetByte(addr); } while (FALSE)
#define CYCLE_TO_SAMPLE(cycle) TO_INT(((cycle) * ASAP_SAMPLE_RATE + ast _ sample_offset) / ASAP_MAIN_CLOCK)
#endif /* _ASAP_INTERNAL_H_ */

File diff suppressed because it is too large Load diff

View file

@ -111,7 +111,7 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
/* Amiga MOD File */
[AFMT_MOD] =
AFMT_ENTRY("MOD", "mod", NULL, "mod\0" ),
/* Amiga SAP File */
/* Atari SAP File */
[AFMT_SAP] =
AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ),
/* Cook in RM/RA */