...
 
Commits (56)
......@@ -36,13 +36,16 @@ jobs:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -qq -y install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx
command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx openssh-client
- save_cache:
key: v1-SRB2-APT
paths:
- /var/cache/apt/archives
- checkout
- run:
name: Compile without network support
command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1
- run:
name: Clean build
command: make -C src LINUX=1 clean
- restore_cache:
......
......@@ -15,6 +15,7 @@ matrix:
- p7zip-full
- gcc-4.4
compiler: gcc-4.4
env: GCC44=1
#gcc-4.4 (Ubuntu/Linaro 4.4.7-8ubuntu1) 4.4.7
- os: linux
addons:
......@@ -27,6 +28,7 @@ matrix:
- p7zip-full
- gcc-4.6
compiler: gcc-4.6
env: GCC46=1
#gcc-4.6 (Ubuntu/Linaro 4.6.4-6ubuntu2) 4.6.4
- os: linux
addons:
......@@ -39,9 +41,11 @@ matrix:
- p7zip-full
- gcc-4.7
compiler: gcc-4.7
env: GCC47=1
#gcc-4.7
- os: linux
compiler: gcc
env: GCC48=1
#gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
- os: linux
addons:
......@@ -56,6 +60,7 @@ matrix:
- p7zip-full
- gcc-4.8
compiler: gcc-4.8
env: GCC48=1
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
......@@ -70,7 +75,7 @@ matrix:
- p7zip-full
- gcc-7
compiler: gcc-7
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough"
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough" GCC72=1
#gcc-7 (Ubuntu 7.2.0-1ubuntu1~14.04) 7.2.0 20170802
- os: linux
addons:
......@@ -85,7 +90,7 @@ matrix:
- p7zip-full
- gcc-8
compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow"
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1
#gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0
- os: linux
compiler: clang
......
......@@ -4,7 +4,7 @@ project(libgme)
include (CheckCXXCompilerFlag)
# When version is changed, also change the one in gme/gme.h to match
set(GME_VERSION 0.6.0 CACHE INTERNAL "libgme Version")
set(GME_VERSION 0.6.2 CACHE INTERNAL "libgme Version")
# 2.6+ always assumes FATAL_ERROR, but 2.4 and below don't.
# Of course, 2.4 might work, in which case you're welcome to drop
......@@ -57,6 +57,8 @@ if (USE_GME_NSFE AND NOT USE_GME_NSF)
SET(USE_GME_NSF 1 CACHE BOOL "Enable NES NSF music emulation" FORCE)
endif()
option(BUILD_SHARED_LIBS "Build shared library (set to OFF for static library)" ON)
# Check for GCC "visibility" support.
if (CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag (-fvisibility=hidden __LIBGME_TEST_VISIBILITY)
......@@ -79,10 +81,10 @@ if (CMAKE_COMPILER_IS_GNUCXX)
endif()
endif()
endif() # test visibility
endif (CMAKE_COMPILER_IS_GNUCXX)
# Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
# Cache this result
set( LIBGME_HAVE_GCC_VISIBILITY ${ENABLE_VISIBILITY} CACHE BOOL "GCC support for hidden visibility")
endif (CMAKE_COMPILER_IS_GNUCXX)
# Shared library defined here
add_subdirectory(gme)
......
Game_Music_Emu Change Log
-------------------------
Game_Music_Emu 0.6.0
--------------------
- Note: A 0.5.6 release was referenced but never tagged or packaged.
- SPC improvements:
- Switched to newer snes_spc 0.9.0 for SPC emulation. Uses fast DSP.
- Fixed Spc_Emu::gain().
- Fixed support for files <0x10200 bytes.
- Other bugfixes:
- Fixed a couple of GBS bugs, one involving access of memory after
realloc.
- Blip_Buffer works on systems where 'double' is a single-precision
floating-point type.
- Fix uninitialized buffer size in dual_resampler.
- Compilation warnings squashed out as of clang 3.3-pre and gcc 4.7.2.
- API changes/additions:
- Removed documentation of C++ interface, as the C interface in gme.h is
the only supported one.
- Added gme_enable_accuracy() for enabling more accurate sound emulation
options (currently affects SPC only).
- Build system improvements:
- Add pkg_config support.
- Fix build on case-insensitive systems.
- Allow for install on Cygwin.
- Fix install on multilib systems, such as many 64-bit distros (CMake must
be able to figure out your system's libsuffix, if any).
- C++ implementation symbols are not leaked into the resultant library
file (requires symbol visibility support).
- Sample player improvements:
- Can toggle fast/accurate emulation (with the 'A' key).
Game_Music_Emu 0.5.5
--------------------
- CMake build support has been added. You can build Game_Music_Emu as
a shared library and install it so that you do not have to include your
own copy if you know libgme will be present on your target system.
Requires CMake 2.6 or higher.
Game_Music_Emu 0.5.2
--------------------
- *TONS* of changes and improvements. You should re-read the new header
files and documentation as the changes will allow you to simplify your
code a lot (it might even be simpler to just rewrite it). Existing code
should continue to work without changes in most cases (see Deprecated
features in gme.txt).
- New file formats: AY, HES, KSS, SAP, NSFE
- All-new comprehensive C interface (also usable from C++). Simplifies
many things, especially file loading, and brings everything together in
one header file (gme.h).
- Information tags and track names and times can be accessed for all
game music formats
- New features supported by all emulators: end of track fading,
automatic silence detection, adjustable song tempo, seek to new time in
track
- Updated mini player example to support track names and times, echo,
tempo, and channel muting, and added visual waveform display
- Improved configuration to use blargg_config.h, which you can modify
and keep when you update to a newer libary version. Includes flag for
library to automatically handle gzipped files using zlib (so you don't
need to use Gzip_File_Reader anymore).
- GBS: Fixed wave channel to not reset waveform when APU is powered off
(affected Garfield). Also improved invalid bank selection (affected Game
& Watch and others).
- VGM: Added support for alternate noise shifter register
configurations, used by other systems like the BBC Micro.
- SPC: Removed IPL ROM dump from emulator, as none of the SPC files I
scanned needed it, and an SPC file can include a copy if necessary. Also
re-enabled supposed clamping in gaussian interpolation between the third
and fourth lookups, though I don't know whether it matters
- Added Music_Emu::load_mem() to use music data already in memory
(without copying it)
- Added Music_Emu::warning(), which reports minor problems when loading
and playing a music file
- Added Music_Emu::set_gain() for uniform adjustment of gain. Can only
be set during initialization, so not useful as a general volume control.
- Added custom operator new to ensure that no exceptions are thrown in
the library (I'd use std::nothrow if it were part of pre-ISO (ARM) C++)
- Added BLIP_BUFFER_FAST flag to blargg_config.h to use a lower quality
bandlimited synthesis in "classic" emulators, which might help
performance on ancient processors (measure first!). Don't use this
unless absolutely necessary, as quality suffers.
- Improved performance a bit for x86 platforms
- Text files now in DOS newline format so they will open in Notepad
properly
- Removed requirement that file header structures not have any padding
added to the end
- Fixed common bug in all CPU emulators where negative program counter
could crash emulator (occurred during a negative branch from the
beginning of memory). Also fixed related bug in Z80 emulator for
IX/IY+displacement mode.
- Eliminated all warnings when compiling on gcc 4.0. The following
generates no diagnostics:
gcc -S gme/*.cpp -o /dev/null -ansi -fno-gnu-keywords
-fno-nonansi-builtins -pedantic -W -Wabi -Wall -Wcast-align
-Wcast-qual -Wchar-subscripts -Wdisabled-optimization -Werror
-Winline -Wlong-long -Wmultichar -Winvalid-offsetof
-Wnon-virtual-dtor -Woverloaded-virtual -Wparentheses
-Wpointer-arith -Wredundant-decls -Wreorder -Wsign-compare
-Wsign-promo -Wunknown-pragmas -Wwrite-strings
Game_Music_Emu 0.3.0
--------------------
- Added more demos, including music player using the SDL multimedia
library for sound, and improved documentation
- All: Improved interface to emulators to allow simpler setup and
loading. Instead of various init() functions, all now support
set_sample_rate( long rate ) and load( const char* file_path ).
- All: Removed error return from start_track() and play(), and added
error_count() to get the total number of emulation errors since the
track was last started. See demos for examples of new usage.
- All: Fixed mute_voices() muting to be preserved after loading files
and starting tracks, instead of being cleared as it was whenever a track
was started
- VGM: Rewrote Vgm_Emu to support Sega Genesis/Mega Drive FM sound at
any sample rate with optional FM oversampling, support for alternate
YM2612 sound cores, and support for optional YM2413
- VGM: Added tempo control, useful for slowing 60Hz NTSC Sega Genesis
music to 50Hz PAL
- VGM: Removed Vgm_Emu::track_data(), since I realized that this
information is already present in the VGM header (oops!)
- GYM: Changed Gym_Emu::track_length() operation (see Gym_Emu.h)
- NSF: Added support for Sunsoft FME-7 sound chip used by Gimmick
soundtrack
- NSF: Fixed Namco 106 problems with Final Lap and others
- Moved library sources to gme/ directory to reduce clutter, and merged
boost/ functionality into blargg_common.h
- Added Gzip_File_Reader for transparently using gzipped files
Game_Music_Emu 0.2.4
--------------------
- Created a discussion forum for problems and feedback:
http://groups-beta.google.com/group/blargg-sound-libs
- Changed error return value of Blip_Buffer::sample_rate() (also for
Stereo_Buffer, Effects_Buffer, etc.) to blargg_err_t (defined in
blargg_common.h), to make error reporting consistent with other
functions. This means the "no error" return value is the opposite of
what it was before, which will break current code which checks the error
return value:
// current code (broken)
if ( !buf.sample_rate( samples_per_sec ) )
out_of_memory();
// quick-and-dirty fix (just remove the ! operation)
if ( buf.sample_rate( samples_per_sec ) )
out_of_memory();
// proper fix
blargg_err_t error = buf.sample_rate( samples_per_sec );
if ( error )
report_error( error );
- Implemented workaround for MSVC++ 6 compiler limitations, allowing it
to work on that compiler again
- Added sample clamping to avoid wrap-around at high volumes, allowing
higher volume with little distortion
- Added to-do list and design notes
- Added Music_Emu::skip( long sample_count ) to skip ahead in current
track
- Added Gym_Emu::track_length() and Vgm_Emu::track_length() for
determining the length of non-looped GYM and VGM files
- Partially implemented DMC non-linearity when its value is directly set
using $4011, which reduces previously over-emphasized "popping" of
percussion on some games (TMNT II in particular)
- Fixed Fir_Resampler, used for SPC and GYM playback (was incorrectly
using abs() instead of fabs()...argh)
- Fixed SPC emulation bugs: eliminated clicks in Plok! soundtrack and
now stops sample slightly earlier than the end, as the SNES does. Fixed
a totally broken CPU addressing mode.
- Fixed Konami VRC6 saw wave (was very broken before). Now VRC6 music
sounds decent
- Fixed a minor GBS emulation bug
- Fixed GYM loop point bug when track was restarted before loop point
had been reached
- Made default GBS frequency equalization less muffled
- Added pseudo-surround effect removal for SPC files
- Added Music_Emu::voice_names() which returns names for each voice.
- Added BLARGG_SOURCE_BEGIN which allows custom compiler options to be
easily set for library sources
- Changed assignment of expansion sound chips in Nsf_Emu to be spread
more evenly when using Effects_Buffer
- Changed 'size_t' values in Blip_Buffer interface to 'long'
- Changed demo to generate a WAVE sound file rather than an AIFF file
Game_Music_Emu 0.2.0
--------------------
- Redid framework and rewrote/cleaned up emulators
- Changed licensing to GNU Lesser General Public License (LGPL)
- Added Sega Genesis GYM and Super Nintendo SPC emulators
- Added Namco-106 and Konami VRC6 sound chip support to NSF emulator
- Eliminated use of static mutable data in emulators, allowing
multi-instance safety
Game_Music_Emu 0.1.0
--------------------
- First release
Please see the git version history (e.g. git shortlog tags/0.6.0..tags/0.6.1)
for the accurate change log.
/* C example that opens a game music file and records 10 seconds to "out.wav" */
static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
#include "gme/gme.h"
#include "Wave_Writer.h" /* wave_ functions for writing sound file */
......@@ -10,10 +8,15 @@ static char filename [] = "test.nsf"; /* opens this file (can be any music type)
void handle_error( const char* str );
int main()
int main(int argc, char *argv[])
{
const char *filename = "test.nsf"; /* Default file to open */
if ( argc >= 2 )
filename = argv[1];
long sample_rate = 44100; /* number of samples per second */
int track = 0; /* index of track to play (0 = first) */
/* index of track to play (0 = first) */
int track = argc >= 3 ? atoi(argv[2]) : 0;
/* Open music file in new emulator */
Music_Emu* emu;
......
// C++ example that opens a game music file and records 10 seconds to "out.wav"
static char filename [] = "test.nsf"; /* opens this file (can be any music type) */
#include "gme/Music_Emu.h"
#include "Wave_Writer.h"
......@@ -10,10 +8,15 @@ static char filename [] = "test.nsf"; /* opens this file (can be any music type)
void handle_error( const char* str );
int main()
int main(int argc, char *argv[])
{
const char *filename = "test.nsf"; /* Default file to open */
if ( argc >= 2 )
filename = argv[1];
long sample_rate = 44100; // number of samples per second
int track = 0; // index of track to play (0 = first)
// index of track to play (0 = first)
int track = argc >= 3 ? atoi(argv[2]) : 0;
// Determine file type
gme_type_t file_type;
......
Game_Music_Emu 0.6.0
Game_Music_Emu 0.6.2
--------------------
Author : Shay Green <gblargg@gmail.com>
Website: http://www.slack.net/~ant/libs/
Forum : http://groups.google.com/group/blargg-sound-libs
Source : https://code.google.com/p/game-music-emu/
License: GNU Lesser General Public License (LGPL)
Author : Shay Green <gblargg@gmail.com>
Maintainer : Michael Pyne <mpyne@purinchu.net>
Website : https://bitbucket.org/mpyne/game-music-emu/
Source : https://bitbucket.org/mpyne/game-music-emu/
License : GNU Lesser General Public License (LGPL), see LICENSE.txt
Contents
--------
......
......@@ -143,7 +143,7 @@ add_definitions(-DBLARGG_BUILD_DLL)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# Add library to be compiled.
add_library(gme SHARED ${libgme_SRCS})
add_library(gme ${libgme_SRCS})
# The version is the release. The "soversion" is the API version. As long
# as only build fixes are performed (i.e. no backwards-incompatible changes
......@@ -159,4 +159,4 @@ install(TARGETS gme LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib) # DLL platforms
install(FILES ${EXPORTED_HEADERS} DESTINATION include/gme)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib/pkgconfig)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libgme.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig)
......@@ -22,8 +22,13 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
const char Data_Reader::eof_error [] = "Unexpected end of file";
#define RETURN_VALIDITY_CHECK( cond ) \
do { if ( unlikely( !(cond) ) ) return "Corrupt file"; } while(0)
blargg_err_t Data_Reader::read( void* p, long s )
{
RETURN_VALIDITY_CHECK( s > 0 );
long result = read_avail( p, s );
if ( result != s )
{
......@@ -38,6 +43,8 @@ blargg_err_t Data_Reader::read( void* p, long s )
blargg_err_t Data_Reader::skip( long count )
{
RETURN_VALIDITY_CHECK( count >= 0 );
char buf [512];
while ( count )
{
......@@ -54,7 +61,8 @@ long File_Reader::remain() const { return size() - tell(); }
blargg_err_t File_Reader::skip( long n )
{
assert( n >= 0 );
RETURN_VALIDITY_CHECK( n >= 0 );
if ( !n )
return 0;
return seek( tell() + n );
......@@ -67,13 +75,14 @@ Subset_Reader::Subset_Reader( Data_Reader* dr, long size )
in = dr;
remain_ = dr->remain();
if ( remain_ > size )
remain_ = size;
remain_ = max( 0l, size );
}
long Subset_Reader::remain() const { return remain_; }
long Subset_Reader::read_avail( void* p, long s )
{
s = max( 0l, s );
if ( s > remain_ )
s = remain_;
remain_ -= s;
......@@ -85,7 +94,7 @@ long Subset_Reader::read_avail( void* p, long s )
Remaining_Reader::Remaining_Reader( void const* h, long size, Data_Reader* r )
{
header = (char const*) h;
header_end = header + size;
header_end = header + max( 0l, size );
in = r;
}
......@@ -93,6 +102,7 @@ long Remaining_Reader::remain() const { return header_end - header + in->remain(
long Remaining_Reader::read_first( void* out, long count )
{
count = max( 0l, count );
long first = header_end - header;
if ( first )
{
......@@ -107,8 +117,9 @@ long Remaining_Reader::read_first( void* out, long count )
long Remaining_Reader::read_avail( void* out, long count )
{
count = max( 0l, count );
long first = read_first( out, count );
long second = count - first;
long second = max( 0l, count - first );
if ( second )
{
second = in->read_avail( (char*) out + first, second );
......@@ -120,8 +131,9 @@ long Remaining_Reader::read_avail( void* out, long count )
blargg_err_t Remaining_Reader::read( void* out, long count )
{
count = max( 0l, count );
long first = read_first( out, count );
long second = count - first;
long second = max( 0l, count - first );
if ( !second )
return 0;
return in->read( (char*) out + first, second );
......@@ -131,7 +143,7 @@ blargg_err_t Remaining_Reader::read( void* out, long count )
Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
begin( (const char*) p ),
size_( s )
size_( max( 0l, s ) )
{
pos = 0;
}
......@@ -141,6 +153,7 @@ long Mem_File_Reader::size() const { return size_; }
long Mem_File_Reader::read_avail( void* p, long s )
{
long r = remain();
s = max( 0l, s );
if ( s > r )
s = r;
memcpy( p, begin + pos, s );
......@@ -152,6 +165,7 @@ long Mem_File_Reader::tell() const { return pos; }
blargg_err_t Mem_File_Reader::seek( long n )
{
RETURN_VALIDITY_CHECK( n >= 0 );
if ( n > size_ )
return eof_error;
pos = n;
......@@ -164,7 +178,7 @@ Callback_Reader::Callback_Reader( callback_t c, long size, void* d ) :
callback( c ),
data( d )
{
remain_ = size;
remain_ = max( 0l, size );
}
long Callback_Reader::remain() const { return remain_; }
......@@ -173,13 +187,14 @@ long Callback_Reader::read_avail( void* out, long count )
{
if ( count > remain_ )
count = remain_;
if ( Callback_Reader::read( out, count ) )
if ( count < 0 || Callback_Reader::read( out, count ) )
count = -1;
return count;
}
blargg_err_t Callback_Reader::read( void* out, long count )
{
RETURN_VALIDITY_CHECK( count >= 0 );
if ( count > remain_ )
return eof_error;
return callback( data, out, count );
......@@ -210,11 +225,12 @@ long Std_File_Reader::size() const
long Std_File_Reader::read_avail( void* p, long s )
{
return fread( p, 1, s, (FILE*) file_ );
return fread( p, 1, max( 0l, s ), (FILE*) file_ );
}
blargg_err_t Std_File_Reader::read( void* p, long s )
{
RETURN_VALIDITY_CHECK( s > 0 );
if ( s == (long) fread( p, 1, s, (FILE*) file_ ) )
return 0;
if ( feof( (FILE*) file_ ) )
......
......@@ -129,6 +129,8 @@ private:
};
#ifdef HAVE_ZLIB_H
#include <zlib.h>
// Gzip compressed file reader
class Gzip_File_Reader : public File_Reader {
public:
......@@ -143,7 +145,7 @@ public:
long tell() const;
blargg_err_t seek( long );
private:
void* file_;
gzFile file_;
long size_;
};
#endif
......
......@@ -178,6 +178,11 @@ blargg_long Music_Emu::msec_to_samples( blargg_long msec ) const
return (sec * sample_rate() + msec * sample_rate() / 1000) * stereo;
}
long Music_Emu::tell_samples() const
{
return out_time;
}
long Music_Emu::tell() const
{
blargg_long rate = sample_rate() * stereo;
......@@ -185,14 +190,18 @@ long Music_Emu::tell() const
return sec * 1000 + (out_time - sec * rate) * 1000 / rate;
}
blargg_err_t Music_Emu::seek( long msec )
blargg_err_t Music_Emu::seek_samples( long time )
{
blargg_long time = msec_to_samples( msec );
if ( time < out_time )
RETURN_ERR( start_track( current_track_ ) );
return skip( time - out_time );
}
blargg_err_t Music_Emu::seek( long msec )
{
return seek_samples( msec_to_samples( msec ) );
}
blargg_err_t Music_Emu::skip( long count )
{
require( current_track() >= 0 ); // start_track() must have been called already
......
......@@ -41,9 +41,15 @@ public:
// Number of milliseconds (1000 msec = 1 second) played since beginning of track
long tell() const;
// Number of samples generated since beginning of track
long tell_samples() const;
// Seek to new time in track. Seeking backwards or far forward can take a while.
blargg_err_t seek( long msec );
// Equivalent to restarting track then skipping n samples
blargg_err_t seek_samples( long n );
// Skip n samples
blargg_err_t skip( long n );
......
......@@ -134,6 +134,9 @@ blargg_err_t Nsfe_Info::load( Data_Reader& in, Nsf_Emu* nsf_emu )
RETURN_ERR( in.read( block_header, sizeof block_header ) );
blargg_long size = get_le32( block_header [0] );
blargg_long tag = get_le32( block_header [1] );
if ( size <= 0 )
return "Corrupt file";
//debug_printf( "tag: %c%c%c%c\n", char(tag), char(tag>>8), char(tag>>16), char(tag>>24) );
......
......@@ -433,9 +433,7 @@ void Snes_Spc::cpu_write( int data, int addr, rel_time_t time )
#endif
// Registers other than $F2 and $F4-$F7
//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
// TODO: this is a bit on the fragile side
if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
if ( reg != 2 && (reg < 4 || reg > 7) ) // 36%
cpu_write_smp_reg( data, time, reg );
}
// High mem/address wrap-around
......
......@@ -76,8 +76,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// TODO: remove non-wrapping versions?
#define SPC_NO_SP_WRAPAROUND 0
#define SET_SP( v ) (sp = ram + 0x101 + (v))
#define GET_SP() (sp - 0x101 - ram)
#define SET_SP( v ) (sp = ram + 0x101 + ((uint8_t) v))
#define GET_SP() (uint8_t (sp - 0x101 - ram))
#if SPC_NO_SP_WRAPAROUND
#define PUSH16( v ) (sp -= 2, SET_LE16( sp, v ))
......@@ -485,7 +485,7 @@ loop:
case 0xAF: // MOV (X)+,A
WRITE_DP( 0, x, a + no_read_before_write );
x++;
x = (uint8_t) (x + 1);
goto loop;
// 5. 8-BIT LOGIC OPERATION COMMANDS
......@@ -808,7 +808,7 @@ loop:
unsigned temp = y * a;
a = (uint8_t) temp;
nz = ((temp >> 1) | temp) & 0x7F;
y = temp >> 8;
y = (uint8_t) (temp >> 8);
nz |= y;
goto loop;
}
......@@ -838,6 +838,7 @@ loop:
nz = (uint8_t) a;
a = (uint8_t) a;
y = (uint8_t) y;
goto loop;
}
......@@ -1004,7 +1005,7 @@ loop:
case 0x7F: // RET1
temp = *sp;
SET_PC( GET_LE16( sp + 1 ) );
sp += 3;
SET_SP( GET_SP() + 3 );
goto set_psw;
case 0x8E: // POP PSW
POP( temp );
......
......@@ -18,6 +18,19 @@ all other #include lines. */
#undef require
#define require( expr ) assert( expr )
// Use to provide hints to compiler for optimized code layout in situations where we
// can almost always expect a conditional to go one way or the other. Should only be
// used in situations where an unexpected branch is truly exceptional though!
#undef likely
#undef unlikely
#ifdef __GNUC__
#define likely( x ) __builtin_expect(x, 1)
#define unlikely( x ) __builtin_expect(x, 0)
#else
#define likely( x ) (x)
#define unlikely( x ) (x)
#endif
// Like printf() except output goes to debug log file. Might be defined to do
// nothing (not even evaluate its arguments).
// void debug_printf( const char* format, ... );
......
......@@ -337,7 +337,9 @@ BLARGG_EXPORT gme_err_t gme_play ( Music_Emu* me, int n, short* p )
BLARGG_EXPORT void gme_set_fade ( Music_Emu* me, int start_msec ) { me->set_fade( start_msec ); }
BLARGG_EXPORT int gme_track_ended ( Music_Emu const* me ) { return me->track_ended(); }
BLARGG_EXPORT int gme_tell ( Music_Emu const* me ) { return me->tell(); }
BLARGG_EXPORT int gme_tell_samples ( Music_Emu const* me ) { return me->tell_samples(); }
BLARGG_EXPORT gme_err_t gme_seek ( Music_Emu* me, int msec ) { return me->seek( msec ); }
BLARGG_EXPORT gme_err_t gme_seek_samples ( Music_Emu* me, int n ) { return me->seek_samples( n ); }
BLARGG_EXPORT int gme_voice_count ( Music_Emu const* me ) { return me->voice_count(); }
BLARGG_EXPORT void gme_ignore_silence ( Music_Emu* me, int disable ) { me->ignore_silence( disable != 0 ); }
BLARGG_EXPORT void gme_set_tempo ( Music_Emu* me, double t ) { me->set_tempo( t ); }
......
/* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.6.0 */
/* Game_Music_Emu 0.6.1 */
#ifndef GME_H
#define GME_H
......@@ -8,7 +8,7 @@
extern "C" {
#endif
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */
#define GME_VERSION 0x000601 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t;
......@@ -47,9 +47,15 @@ int gme_track_ended( Music_Emu const* );
/* Number of milliseconds (1000 = one second) played since beginning of track */
int gme_tell( Music_Emu const* );
/* Number of samples generated since beginning of track */
int gme_tell_samples( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */
gme_err_t gme_seek( Music_Emu*, int msec );
/* Equivalent to restarting track then skipping n samples */
gme_err_t gme_seek_samples( Music_Emu*, int n );
/******** Informational ********/
......
......@@ -3,7 +3,7 @@
# later are used by pkg-config.
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
lib_suffix=
lib_suffix=@LIB_SUFFIX@
libdir=${exec_prefix}/lib${lib_suffix}
includedir=${prefix}/include
......@@ -13,3 +13,4 @@ URL: http://code.google.com/p/game-music-emu/
Version: @GME_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lgme
Libs.private: -lstdc++
/* Game music emulator library C interface (also usable from C++) */
/* Game_Music_Emu 0.6.0 */
/* Game_Music_Emu 0.6.1 */
#ifndef GME_H
#define GME_H
......@@ -8,7 +8,7 @@
extern "C" {
#endif
#define GME_VERSION 0x000600 /* 1 byte major, 1 byte minor, 1 byte patch-level */
#define GME_VERSION 0x000601 /* 1 byte major, 1 byte minor, 1 byte patch-level */
/* Error string returned by library functions, or NULL if no error (success) */
typedef const char* gme_err_t;
......@@ -47,9 +47,15 @@ int gme_track_ended( Music_Emu const* );
/* Number of milliseconds (1000 = one second) played since beginning of track */
int gme_tell( Music_Emu const* );
/* Number of samples generated since beginning of track */
int gme_tell_samples( Music_Emu const* );
/* Seek to new time in track. Seeking backwards or far forward can take a while. */
gme_err_t gme_seek( Music_Emu*, int msec );
/* Equivalent to restarting track then skipping n samples */
gme_err_t gme_seek_samples( Music_Emu*, int n );
/******** Informational ********/
......
Game_Music_Emu 0.6.0: Game Music Emulators
Game_Music_Emu 0.6.2: Game Music Emulators
------------------------------------------
Game_Music_Emu is a collection of video game music file emulators that
support the following formats and systems:
......@@ -34,30 +34,45 @@ several architectures, Mac OS, MorphOS, Xbox, PlayStation Portable,
GP2X, and Nintendo DS.
Author : Shay Green <gblargg@gmail.com>
Website: http://www.slack.net/~ant/
Forum : http://groups.google.com/group/blargg-sound-libs
Website: https://bitbucket.org/mpyne/game-music-emu/wiki/Home
License: GNU Lesser General Public License (LGPL)
Current Maintainer: Michael Pyne <mpyne@purinchu.net>
Getting Started
---------------
Build a program consisting of demo/basics.c, demo/Wave_Writer.cpp, and
all source files in gme/. If you have CMake 2.6 or later, execute
all source files in gme/.
run cmake
cd demo
run make
Or, if you have CMake 2.6 or later, execute at a command prompt (from the
extracted source directory):
Be sure "test.nsf" is in the same directory as the program. Running it
mkdir build
cd build
cmake ../ # <-- Pass any needed CMake flags here
make # To build the library
cd demo
make # To build the demo itself
Be sure "test.nsf" is in the same directory as the demo program. Running it
should generate the recording "out.wav".
You can use "make install" to install the library. To choose where to install
the library to, use the CMake argument "-DCMAKE_INSTALL_PREFIX=/usr/local"
(and replace /usr/local with the base path you wish to use). Alternately, you
can specify the base path to install to when you run "make install" by passing
'DESTDIR=/usr/local' on the make install command line (again, replace
/usr/local as appropriate).
To build a static library instead of shared (the default), pass
-DBUILD_SHARED_LIBS=OFF to the cmake command when running cmake.
A slightly more extensive demo application is available in the player/
directory. It requires SDL to build.
Read gme.txt for more information. Post to the discussion forum for
assistance.
Files
-----
gme.txt General notes about the library
......
......@@ -377,6 +377,12 @@ if(${SRB2_CONFIG_HAVE_PNG} AND ${SRB2_CONFIG_HAVE_ZLIB})
set(SRB2_HAVE_PNG ON)
add_definitions(-DHAVE_PNG)
add_definitions(-D_LARGEFILE64_SOURCE)
set(SRB2_PNG_SOURCES apng.c)
set(SRB2_PNG_HEADERS apng.h)
prepend_sources(SRB2_PNG_SOURCES)
prepend_sources(SRB2_PNG_HEADERS)
source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS}
${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS})
else()
message(WARNING "You have specified that PNG is available but it was not found. SRB2 may not compile correctly.")
endif()
......
......@@ -338,6 +338,8 @@ endif
LIBS+=$(PNG_LDFLAGS)
CFLAGS+=$(PNG_CFLAGS)
OBJS+=$(OBJDIR)/apng.o
endif
ifdef HAVE_LIBGME
......
......@@ -7,6 +7,10 @@
# and other things
#
ifdef GCC81
GCC80=1
endif
ifdef GCC80
GCC72=1
endif
......@@ -116,6 +120,7 @@ WFLAGS+=-Wfloat-equal
#WFLAGS+=-Wtraditional
ifdef VCHELP
WFLAGS+=-Wdeclaration-after-statement
WFLAGS+=-Wno-error=declaration-after-statement
endif
WFLAGS+=-Wundef
ifndef GCC295
......@@ -189,12 +194,6 @@ ifdef GCC46
WFLAGS+=-Wno-suggest-attribute=noreturn
endif
ifndef MINGW
ifdef GCC45
WFLAGS+=-Wunsuffixed-float-constants
endif
endif
ifdef NOLDWARNING
LDFLAGS+=-Wl,--as-needed
endif
......@@ -208,6 +207,9 @@ WFLAGS+=$(OLDWFLAGS)
ifdef GCC43
#WFLAGS+=-Wno-error=clobbered
endif
ifdef GCC44
WFLAGS+=-Wno-error=array-bounds
endif
ifdef GCC46
WFLAGS+=-Wno-error=suggest-attribute=noreturn
endif
......@@ -228,6 +230,7 @@ ifdef GCC80
WFLAGS+=-Wno-format-overflow
WFLAGS+=-Wno-stringop-truncation
WFLAGS+=-Wno-stringop-overflow
WFLAGS+=-Wno-error=multistatement-macros
endif
......
/*
Copyright 2019, James R.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <string.h>
#include "apng.h"
#define APNG_INFO_acTL 0x20000U
#define APNG_WROTE_acTL 0x10000U
struct apng_info_def
{
png_uint_32 mode;
png_uint_32 valid;
png_uint_32 num_frames;
png_uint_32 num_plays;
long start_acTL;/* acTL is written here */
png_flush_ptr output_flush_fn;
apng_seek_ptr output_seek_fn;
apng_tell_ptr output_tell_fn;
apng_set_acTL_ptr set_acTL_fn;
};
/* PROTOS (FUCK COMPILER) */
void apng_seek (png_structp, apng_const_infop, size_t);
size_t apng_tell (png_structp, apng_const_infop);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void apng_flush (png_structp, apng_infop);
#ifdef PNG_STDIO_SUPPORTED
void apng_default_flush (png_structp);
#endif/* PNG_STDIO_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
void apng_default_seek (png_structp, size_t);
size_t apng_default_tell (png_structp);
#endif/* PNG_STDIO_SUPPORTED */
void apng_write_IEND (png_structp);
void apng_write_acTL (png_structp, png_uint_32, png_uint_32);
#ifndef PNG_WRITE_APNG_SUPPORTED
png_uint_32 apng_set_acTL_dummy (png_structp, png_infop,
png_uint_32, png_uint_32);
#endif/* PNG_WRITE_APNG_SUPPORTED */
apng_infop
apng_create_info_struct (png_structp pngp)
{
apng_infop ainfop;
(void)pngp;
if (( ainfop = calloc(sizeof (apng_info),1) ))
{
apng_set_write_fn(pngp, ainfop, 0, 0, 0, 0, 0);
apng_set_set_acTL_fn(pngp, ainfop, 0);
}
return ainfop;
}
void
apng_destroy_info_struct (png_structp pngp, apng_infopp ainfopp)
{
(void)pngp;
if (!( pngp && ainfopp ))
return;
free((*ainfopp));
}
void
apng_seek (png_structp pngp, apng_const_infop ainfop, size_t l)
{
(*(ainfop->output_seek_fn))(pngp, l);
}
size_t
apng_tell (png_structp pngp, apng_const_infop ainfop)
{
return (*(ainfop->output_tell_fn))(pngp);
}
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void
apng_flush (png_structp pngp, apng_infop ainfop)
{
if (ainfop->output_flush_fn)
(*(ainfop->output_flush_fn))(pngp);
}
#ifdef PNG_STDIO_SUPPORTED
void
apng_default_flush (png_structp pngp)
{
if (!( pngp ))
return;
fflush((png_FILE_p)png_get_io_ptr);
}
#endif/* PNG_STDIO_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
void
apng_default_seek (png_structp pngp, size_t l)
{
if (!( pngp ))
return;
if (fseek((png_FILE_p)png_get_io_ptr(pngp), (long)l, SEEK_SET) == -1)
png_error(pngp, "Seek Error");
}
size_t
apng_default_tell (png_structp pngp)
{
long l;
if (!( pngp ))
{
png_error(pngp, "Call to apng_default_tell with NULL pngp failed");
}
if (( l = ftell((png_FILE_p)png_get_io_ptr(pngp)) ) == -1)
png_error(pngp, "Tell Error");
return (size_t)l;
}
#endif/* PNG_STDIO_SUPPORTED */
void
apng_set_write_fn (png_structp pngp, apng_infop ainfop, png_voidp iop,
png_rw_ptr write_f, png_flush_ptr flush_f,
apng_seek_ptr seek_f, apng_tell_ptr tell_f)
{
if (!( pngp && ainfop ))
return;
png_set_write_fn(pngp, iop, write_f, flush_f);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
if (!flush_f)
ainfop->output_flush_fn = &apng_default_flush;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_flush_fn = flush_f;
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_STDIO_SUPPORTED
if (!seek_f)
ainfop->output_seek_fn = &apng_default_seek;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_seek_fn = seek_f;
#ifdef PNG_STDIO_SUPPORTED
if (!seek_f)
ainfop->output_tell_fn = apng_default_tell;
else
#endif/* PNG_STDIO_SUPPORTED */
ainfop->output_tell_fn = tell_f;
}
void
apng_write_IEND (png_structp pngp)
{
png_byte chunkc[] = "IEND";
png_write_chunk(pngp, chunkc, 0, 0);
}
void
apng_write_acTL (png_structp pngp, png_uint_32 frames, png_uint_32 plays)
{
png_byte chunkc[] = "acTL";
png_byte buf[8];
png_save_uint_32(buf, frames);
png_save_uint_32(buf + 4, plays);
png_write_chunk(pngp, chunkc, buf, 8);
}
png_uint_32
apng_set_acTL (png_structp pngp, png_infop infop, apng_infop ainfop,
png_uint_32 frames, png_uint_32 plays)
{
(void)pngp;
(void)infop;
if (!( pngp && infop && ainfop ))
return 0;
ainfop->num_frames = frames;
ainfop->num_plays = plays;
ainfop->valid |= APNG_INFO_acTL;
return 1;
}
void
apng_write_info_before_PLTE (png_structp pngp, png_infop infop,
apng_infop ainfop)
{
if (!( pngp && infop && ainfop ))
return;
png_write_info_before_PLTE(pngp, infop);
if (( ainfop->valid & APNG_INFO_acTL )&&!( ainfop->mode & APNG_WROTE_acTL ))
{
ainfop->start_acTL = apng_tell(pngp, ainfop);
apng_write_acTL(pngp, 0, 0);
/* modified for runtime dynamic linking */
(*(ainfop->set_acTL_fn))(pngp, infop, PNG_UINT_31_MAX, 0);
ainfop->mode |= APNG_WROTE_acTL;
}
}
void
apng_write_info (png_structp pngp, png_infop infop,
apng_infop ainfop)
{
apng_write_info_before_PLTE(pngp, infop, ainfop);
png_write_info(pngp, infop);
}
void
apng_write_end (png_structp pngp, png_infop infop, apng_infop ainfop)
{
(void)infop;
apng_write_IEND(pngp);
apng_seek(pngp, ainfop, ainfop->start_acTL);
apng_write_acTL(pngp, ainfop->num_frames, ainfop->num_plays);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
#ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
apng_flush(pngp, infop);
#endif/* PNG_WRITE_FLUSH_SUPPORTED */
#endif/* PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED */
}
#ifndef PNG_WRITE_APNG_SUPPORTED
png_uint_32
apng_set_acTL_dummy (png_structp pngp, png_infop infop,
png_uint_32 frames, png_uint_32 plays)
{
(void)pngp;
(void)infop;
(void)frames;
(void)plays;
return 0;
}
#endif/* PNG_WRITE_APNG_SUPPORTED */
/* Dynamic runtime linking capable! (Hopefully.) */
void
apng_set_set_acTL_fn (png_structp pngp, apng_infop ainfop,
apng_set_acTL_ptr set_acTL_f)
{
(void)pngp;
if (!ainfop->set_acTL_fn)
#ifndef PNG_WRITE_APNG_SUPPORTED
ainfop->set_acTL_fn = &apng_set_acTL_dummy;
#else
ainfop->set_acTL_fn = &png_set_acTL;
#endif/* PNG_WRITE_APNG_SUPPORTED */
else
ainfop->set_acTL_fn = set_acTL_f;
}
/*
Copyright 2019, James R.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef APNG_H
#define APNG_H
#ifndef _MSC_VER
#ifndef _WII
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#endif
#endif
#ifndef _LFS64_LARGEFILE
#define _LFS64_LARGEFILE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 0
#endif
#include <png.h>
typedef struct apng_info_def apng_info;
typedef apng_info * apng_infop;
typedef const apng_info * apng_const_infop;
typedef apng_info * * apng_infopp;
typedef void (*apng_seek_ptr)(png_structp, size_t);
typedef size_t (*apng_tell_ptr)(png_structp);
typedef png_uint_32 (*apng_set_acTL_ptr)(png_structp, png_infop,
png_uint_32, png_uint_32);
apng_infop apng_create_info_struct (png_structp png_ptr);
void apng_destroy_info_struct (png_structp png_ptr,
apng_infopp info_ptr_ptr);
/* Call the following functions in place of the libpng counterparts. */
png_uint_32 apng_set_acTL (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr,
png_uint_32 num_frames, png_uint_32 num_plays);
void apng_write_info_before_PLTE (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_write_info (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_write_end (png_structp png_ptr, png_infop info_ptr,
apng_infop ainfo_ptr);
void apng_set_write_fn (png_structp png_ptr, apng_infop ainfo_ptr,
png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn,
apng_seek_ptr output_seek_fn, apng_tell_ptr output_tell_fn);
void apng_set_set_acTL_fn (png_structp png_ptr, apng_infop ainfo_ptr,
apng_set_acTL_ptr set_acTL_fn);
#endif/* APNG_H */
......@@ -2415,6 +2415,8 @@ static void CL_RemovePlayer(INT32 playernum, INT32 reason)
#ifdef HAVE_BLUA
LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting
#else
(void)reason;
#endif
// Reset player data
......
......@@ -1130,6 +1130,10 @@ void D_SRB2Main(void)
// Setup default unlockable conditions
M_SetupDefaultConditionSets();
// Setup character tables
// Have to be done here before files are loaded
M_InitCharacterTables();
// load wad, including the main wad file
CONS_Printf("W_InitMultipleFiles(): Adding IWAD and main PWADs.\n");
if (!W_InitMultipleFiles(startupwadfiles))
......
......@@ -19,7 +19,7 @@
#define __D_NET__
// Max computers in a game
#define MAXNETNODES 32
#define MAXNETNODES (MAXPLAYERS+4)
#define BROADCASTADDR MAXNETNODES
#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
//#define NETSPLITSCREEN // Kart's splitscreen netgame feature
......
......@@ -435,11 +435,11 @@ static void readAnimTex(MYFILE *f, INT32 num)
static boolean findFreeSlot(INT32 *num)
{
// Send the character select entry to a free slot.
while (*num < 32 && PlayerMenu[*num].status != IT_DISABLED)
while (*num < MAXSKINS && PlayerMenu[*num].status != IT_DISABLED)
*num = *num+1;
// No more free slots. :(
if (*num >= 32)
if (*num >= MAXSKINS)
return false;
// Found one! ^_^
......