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:
parent
b1a6c9096d
commit
35472fe7f1
11 changed files with 3710 additions and 2605 deletions
|
@ -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.
|
||||
|
|
|
@ -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&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[]
|
||||
|
|
|
@ -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
218
apps/codecs/libasap/anylang.h
Normal file
218
apps/codecs/libasap/anylang.h
Normal 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_ */
|
|
@ -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
|
@ -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. */
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue