Commit e9291bdd authored by hunterk's avatar hunterk
Browse files

add source files to begin buildbot integration

parent e5da7d3b
CXX=g++
CXXFLAGS=-O2 -fpic -fno-stack-protector -fvisibility=hidden -fsigned-char -fwrapv -funroll-loops -std=c++11 -Wall -I./ -Wa,--fatal-warnings $(EXTRA_CXXFLAGS)
CPPFLAGS=-D_GNU_SOURCE=1
LIBS=-lpthread
LIBNAME=supafaust.so
include common.mk
OBJ=libretro.o $(OBJ_MDFN) $(OBJ_SNES)
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
all: $(OBJ) $(OBJ_SNES)
$(CXX) $(CXXFLAGS) -s -shared -o $(LIBNAME) $^ $(LIBS)
@cat supafaust.tar.xz.zip >> $(LIBNAME)
@zip --adjust-sfx $(LIBNAME)
clean:
rm -f -- $(OBJ) $(OBJ_SNES) $(LIBNAME)
.PHONY: all clean
Minimum recommended CPU is a dual-core, dual-issue superscalar ARMv7 CPU with
NEON(e.g. Cortex A7), running at 900MHz for most SNES games, and at 1200MHz
for SuperFX, SA-1, and CX4 games.
Special chips supported: DSP-1, DSP-2, CX4, SuperFX, SA-1, S-DD1, MSU1
MSU1 support may have performance issues with runahead and/or state rewinding.
SPC playback is supported, to an extent.
Save states are not currently compatible across different architectures
(e.g. 32-bit ARM vs 64-bit ARM).
Save states are not currently sanitized properly on load, so don't load
save states from untrusted sources.
Core option changes take effect upon game load.
Setting "supafaust_frame_begin_vblank" to "disabled" will improve performance
but also increase input lag on most games.
Setting "supafaust_thread_affinity_emu" to "0x3" and
"supafaust_thread_affinity_ppu" to "0xc" may give better performance on a
quad-core CPU.
Setting "supafaust_renderer" to "st", to disable multithreaded PPU rendering,
may improve performance on systems with only a single CPU with a single core.
Unzip a shared object file for source code.
Official builds are compiled with Debian Stretch GCC 6.x toolchains.
#!/bin/sh
make clean && make CXX="arm-linux-gnueabihf-g++" EXTRA_CXXFLAGS="-mcpu=cortex-a7 -mfpu=neon" LIBNAME="supafaust-arm32-cortex-a7.so" -j4 && \
make clean && make CXX="arm-linux-gnueabihf-g++" EXTRA_CXXFLAGS="-mcpu=cortex-a9 -mfpu=neon" LIBNAME="supafaust-arm32-cortex-a9.so" -j4 && \
make clean && make CXX="arm-linux-gnueabihf-g++" EXTRA_CXXFLAGS="-mcpu=cortex-a15 -mfpu=neon" LIBNAME="supafaust-arm32-cortex-a15.so" -j4 && \
make clean && make CXX="arm-linux-gnueabihf-g++" EXTRA_CXXFLAGS="-mcpu=cortex-a53 -mfpu=neon" LIBNAME="supafaust-arm32-cortex-a53.so" -j4 && \
make clean && make CXX="aarch64-linux-gnu-g++" EXTRA_CXXFLAGS="-mcpu=cortex-a53" LIBNAME="supafaust-arm64.so" -j4 && \
true
#!/bin/sh
make clean && make CXX="g++" EXTRA_CXXFLAGS="-mtune=atom -fno-PIC -fpic -mcmodel=small" LIBNAME="supafaust-x86_64.so" -j4 && \
true
# TODO: need to set up proper toolchains
#make clean && make CXX="g++" EXTRA_CXXFLAGS="-march=pentium3 -mtune=atom -fno-PIC -fno-pic" LIBNAME="supafaust-x86.so" -j4 && \
#make clean && make CXX="i686-w64-mingw32-g++" EXTRA_CXXFLAGS="-march=pentium3 -mtune=atom -fno-PIC -fno-pic" LIBS="-static -lwinmm" OBJ_PLATFORM="mednafen/mthreading/MThreading_Win32.o mednafen/win32-common.o" LIBNAME="supafaust-x86.dll" -j4 && \
#make clean && make CXX="x86_64-w64-mingw32-g++" EXTRA_CXXFLAGS="-mtune=atom -fno-PIC -fno-pic -mcmodel=small" LIBS="-static -lwinmm" OBJ_PLATFORM="mednafen/mthreading/MThreading_Win32.o mednafen/win32-common.o" LIBNAME="supafaust-x86_64.dll" -j4 && \
#
#!/bin/sh
git -C . archive --format=tar --prefix=supafaust/ HEAD^{tree} | xz > "supafaust.tar.xz" && \
zip supafaust.tar.xz.zip supafaust.tar.xz && \
./build-arm.sh && \
./build-x86.sh && \
true
OBJ_PLATFORM=mednafen/mthreading/MThreading_POSIX.o
OBJ_MDFN=mednafen/mednafen.o mednafen/git.o mednafen/error.o mednafen/settings.o mednafen/mempatcher.o mednafen/state.o mednafen/string/string.o mednafen/Stream.o mednafen/FileStream.o mednafen/VirtualFS.o mednafen/NativeVFS.o mednafen/ExtMemStream.o mednafen/MemoryStream.o mednafen/sound/DSPUtility.o mednafen/sound/OwlResampler.o mednafen/video/Deinterlacer_Blend.o mednafen/video/Deinterlacer_Simple.o mednafen/video/Deinterlacer.o mednafen/video/surface.o mednafen/Time.o $(OBJ_PLATFORM) mednafen/tests.o mednafen/cheat_formats/snes.o mednafen/hash/sha1.o mednafen/hash/sha256.o mednafen/player.o mednafen/SNSFLoader.o mednafen/SPCReader.o mednafen/MTStreamReader.o
OBJ_SNES=mednafen/snes_faust/apu.o mednafen/snes_faust/cpu.o mednafen/snes_faust/ppu.o mednafen/snes_faust/ppu_mt.o mednafen/snes_faust/ppu_mtrender.o mednafen/snes_faust/cart.o mednafen/snes_faust/input.o mednafen/snes_faust/snes.o mednafen/snes_faust/cart/dsp1.o mednafen/snes_faust/cart/dsp2.o mednafen/snes_faust/cart/sdd1.o mednafen/snes_faust/cart/cx4.o mednafen/snes_faust/cart/superfx.o mednafen/snes_faust/cart/sa1.o mednafen/snes_faust/cart/sa1cpu.o mednafen/snes_faust/msu1.o mednafen/snes_faust/ppu_st.o
This diff is collapsed.
This diff is collapsed.
/******************************************************************************/
/* Mednafen - Multi-system Emulator */
/******************************************************************************/
/* ExtMemStream.cpp:
** Copyright (C) 2012-2018 Mednafen Team
**
** This program 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.
**
** This program 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 this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ExtMemStream.h"
namespace Mednafen
{
/*
TODO: Proper negative position behavior?
*/
ExtMemStream::ExtMemStream(void* p, uint64 s) : data_buffer((uint8*)p), data_buffer_size(s), ro(false), position(0)
{
}
ExtMemStream::ExtMemStream(const void* p, uint64 s) : data_buffer((uint8*)p), data_buffer_size(s), ro(true), position(0)
{
}
ExtMemStream::~ExtMemStream()
{
close();
}
uint64 ExtMemStream::attributes(void)
{
return (ATTRIBUTE_READABLE | ATTRIBUTE_WRITEABLE | ATTRIBUTE_SEEKABLE);
}
uint8 *ExtMemStream::map(void) noexcept
{
return data_buffer;
}
uint64 ExtMemStream::map_size(void) noexcept
{
return data_buffer_size;
}
void ExtMemStream::unmap(void) noexcept
{
}
INLINE void ExtMemStream::grow_if_necessary(uint64 new_required_size, uint64 hole_end)
{
if(new_required_size > data_buffer_size)
throw MDFN_Error(0, _("Attempt to grow fixed size ExtMemStream."));
}
uint64 ExtMemStream::read(void *data, uint64 count, bool error_on_eos)
{
//printf("%llu %llu %llu\n", position, count, data_buffer_size);
if(count > data_buffer_size)
{
if(error_on_eos)
throw MDFN_Error(0, _("Unexpected EOF"));
count = data_buffer_size;
}
if(position > (data_buffer_size - count))
{
if(error_on_eos)
throw MDFN_Error(0, _("Unexpected EOF"));
if(data_buffer_size > position)
count = data_buffer_size - position;
else
count = 0;
}
memmove(data, &data_buffer[position], count);
position += count;
return count;
}
void ExtMemStream::write(const void *data, uint64 count)
{
uint64 nrs = position + count;
if(ro)
throw MDFN_Error(EINVAL, _("Write attempted to read-only ExtMemStream."));
if(nrs < position)
throw MDFN_Error(ErrnoHolder(EFBIG));
grow_if_necessary(nrs, position);
memmove(&data_buffer[position], data, count);
position += count;
}
void ExtMemStream::truncate(uint64 length)
{
grow_if_necessary(length, length);
data_buffer_size = length;
}
void ExtMemStream::seek(int64 offset, int whence)
{
uint64 new_position;
switch(whence)
{
default:
throw MDFN_Error(ErrnoHolder(EINVAL));
break;
case SEEK_SET:
new_position = offset;
break;
case SEEK_CUR:
new_position = position + offset;
break;
case SEEK_END:
new_position = data_buffer_size + offset;
break;
}
if(new_position < 0)
throw MDFN_Error(ErrnoHolder(EINVAL));
position = new_position;
}
uint64 ExtMemStream::tell(void)
{
return position;
}
uint64 ExtMemStream::size(void)
{
return data_buffer_size;
}
void ExtMemStream::flush(void)
{
}
void ExtMemStream::close(void)
{
data_buffer = nullptr;
data_buffer_size = 0;
position = 0;
}
int ExtMemStream::get_line(std::string &str)
{
str.clear(); // or str.resize(0)??
while((uint64)position < data_buffer_size)
{
uint8 c = data_buffer[position++];
if(c == '\r' || c == '\n' || c == 0)
return(c);
str.push_back(c); // Should be faster than str.append(1, c)
}
return(str.length() ? 256 : -1);
}
}
/******************************************************************************/
/* Mednafen - Multi-system Emulator */
/******************************************************************************/
/* ExtMemStream.h:
** Copyright (C) 2012-2018 Mednafen Team
**
** This program 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.
**
** This program 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 this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __MDFN_EXTMEMSTREAM_H
#define __MDFN_EXTMEMSTREAM_H
#include "Stream.h"
namespace Mednafen
{
class ExtMemStream : public Stream
{
public:
ExtMemStream(void*, uint64);
ExtMemStream(const void*, uint64);
virtual ~ExtMemStream() override;
virtual uint64 attributes(void) override;
virtual uint8 *map(void) noexcept override;
virtual uint64 map_size(void) noexcept override;
virtual void unmap(void) noexcept override;
virtual uint64 read(void *data, uint64 count, bool error_on_eos = true) override;
virtual void write(const void *data, uint64 count) override;
virtual void truncate(uint64 length) override;
virtual void seek(int64 offset, int whence) override;
virtual uint64 tell(void) override;
virtual uint64 size(void) override;
virtual void flush(void) override;
virtual void close(void) override;
virtual int get_line(std::string &str) override;
private:
uint8* data_buffer;
uint64 data_buffer_size;
const bool ro;
uint64 position;
void grow_if_necessary(uint64 new_required_size, uint64 hole_end);
};
}
#endif
/******************************************************************************/
/* Mednafen - Multi-system Emulator */
/******************************************************************************/
/* FileStream.cpp:
** Copyright (C) 2010-2018 Mednafen Team
**
** This program 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.
**
** This program 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 this program; if not, write to the Free Software Foundation, Inc.,
** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Note: use seek(0, SEEK_CUR) instead of flush() for synchronization when mixing reads and writes,
// as fseek() is guaranteed to be safe for this purpose, while fflush() is a bit undefined/implementation-defined
// in this regard.
#include <mednafen/types.h>
#include "FileStream.h"
#include <mednafen/mednafen.h>
#include <trio/trio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef WIN32
#include <mednafen/win32-common.h>
#else
#include <unistd.h>
#include <sys/file.h>
#endif
#ifdef HAVE_MMAP
#include <sys/mman.h>
#endif
namespace Mednafen
{
// Some really bad preprocessor abuse follows to handle platforms that don't have fseeko and ftello...and of course
// for largefile support on Windows:
#ifndef HAVE_FSEEKO
#define fseeko fseek
#endif
#ifndef HAVE_FTELLO
#define ftello ftell
#endif
#define STRUCT_STAT struct stat
#if SIZEOF_OFF_T == 4
#ifdef HAVE_FOPEN64
#define fopen fopen64
#endif
#ifdef HAVE_FTELLO64
#undef ftello
#define ftello ftello64
#endif
#ifdef HAVE_FSEEKO64
#undef fseeko
#define fseeko fseeko64
#endif
#ifdef HAVE_FSTAT64
#define fstat fstat64
#define stat stat64
#undef STRUCT_STAT
#define STRUCT_STAT struct stat64
#endif
#ifdef HAVE_FTRUNCATE64
#define ftruncate ftruncate64
#endif
#endif
FileStream::FileStream(const std::string& path, const uint32 mode, const int do_lock) : OpenedMode(mode), mapping(NULL), mapping_size(0), locked(false), prev_was_write(-1)
{
const char* fpom;
int open_flags;
path_save = path;
switch(mode)
{
default:
throw MDFN_Error(0, _("Unknown FileStream mode."));
case MODE_READ:
fpom = "rb";
open_flags = O_RDONLY;
break;
case MODE_READ_WRITE:
fpom = "r+b";
open_flags = O_RDWR | O_CREAT;
break;
case MODE_WRITE: // Truncation is handled near the end of the constructor.
case MODE_WRITE_INPLACE:
fpom = "wb";
open_flags = O_WRONLY | O_CREAT;
break;
case MODE_WRITE_SAFE:
fpom = "wb";
open_flags = O_WRONLY | O_CREAT | O_EXCL;
break;
}
#ifdef O_BINARY
open_flags |= O_BINARY;
#elif defined(_O_BINARY)
open_flags |= _O_BINARY;
#endif
#ifdef WIN32
auto perm_mode = _S_IREAD | _S_IWRITE;
#else
auto perm_mode = S_IRUSR | S_IWUSR;
#endif
#if defined(S_IRGRP)
perm_mode |= S_IRGRP;
#endif
#if defined(S_IROTH)
perm_mode |= S_IROTH;
#endif
if(path.find('\0') != std::string::npos)
throw MDFN_Error(EINVAL, _("Error opening file \"%s\": %s"), path_save.c_str(), _("Null character in path."));
int tmpfd;
#ifdef WIN32
{
bool invalid_utf8;
std::u16string u16path = UTF8_to_UTF16(path, &invalid_utf8, true);
if(invalid_utf8)
throw MDFN_Error(EINVAL, _("Error opening file \"%s\": %s"), path_save.c_str(), _("Invalid UTF-8 in path."));
tmpfd = ::_wopen((const wchar_t*)u16path.c_str(), open_flags, perm_mode);
}
#else
tmpfd = ::open(path.c_str(), open_flags, perm_mode);
#endif
if(tmpfd == -1)
{
ErrnoHolder ene(errno);
throw MDFN_Error(ene.Errno(), _("Error opening file \"%s\": %s"), path_save.c_str(), ene.StrError());
}
fp = ::fdopen(tmpfd, fpom);
if(!fp)
{
ErrnoHolder ene(errno);
::close(tmpfd);
throw MDFN_Error(ene.Errno(), _("Error opening file \"%s\": %s"), path_save.c_str(), ene.StrError());
}
//
if(do_lock) // Lock before truncation
{
try
{
lock(do_lock < 0);
}
catch(...)
{
try { close(); } catch(...) { }
throw;
}
}
if(mode == MODE_WRITE)
{
try
{
truncate(0);
}
catch(...)
{
try { close(); } catch(...) { }
throw;
}
}
}
FileStream::~FileStream()
{
try
{
#if 0
if(fp && (attributes() & ATTRIBUTE_WRITEABLE))
{
MDFN_printf(_("FileStream::close() not explicitly called for file \"%s\" opened for writing!\n"), path_save.c_str());
}
#endif
close();
}
catch(std::exception &e)
{
MDFND_OutputNotice(MDFN_NOTICE_ERROR, e.what());
}
}
uint64 FileStream::attributes(void)
{
uint64 ret = ATTRIBUTE_SEEKABLE;
switch(OpenedMode)
{
case MODE_READ:
ret |= ATTRIBUTE_READABLE;
break;
case MODE_READ_WRITE:
ret |= ATTRIBUTE_READABLE | ATTRIBUTE_WRITEABLE;
break;
case MODE_WRITE_INPLACE:
case MODE_WRITE_SAFE:
case MODE_WRITE:
ret |= ATTRIBUTE_WRITEABLE;
break;
}
return ret;
}
uint8 *FileStream::map(void) noexcept
{
if(!mapping)
{
#ifdef HAVE_MMAP
uint64 length = size();
int prot = 0;
int flags = 0;
void* tptr;
if(OpenedMode == MODE_READ)
{
prot |= PROT_READ; // | PROT_EXEC;
flags |= MAP_PRIVATE;
}
else
{
prot |= PROT_WRITE;
prot |= MAP_SHARED;
}
if(length > SIZE_MAX)
return(NULL);
tptr = mmap(NULL, length, prot, flags, fileno(fp), 0);
if(tptr != (void*)-1)
{
mapping = tptr;