Convert to linux line endings.

This commit is contained in:
orbea 2019-02-03 15:38:41 -08:00
parent 9750719074
commit 4c56167446
43 changed files with 16104 additions and 16104 deletions

View File

@ -2,34 +2,34 @@
- Only RetroArch bugs should be filed here. Not core bugs or game bugs
- This is not a forum or a help section, this is strictly developer oriented
## Description
[Description of the bug]
### Expected behavior
[What you expected to happen]
### Actual behavior
[What is actually happening]
### Steps to reproduce the bug
1. [First step]
2. [Second step]
3. [and so on...]
### Bisect Results
## Description
[Description of the bug]
### Expected behavior
[What you expected to happen]
### Actual behavior
[What is actually happening]
### Steps to reproduce the bug
1. [First step]
2. [Second step]
3. [and so on...]
### Bisect Results
[Try to bisect and tell us when this started happening]
### Version/Commit
You can find this information under Information/System Information
- RetroArch: [version/commit]
### Environment information
[Try to bisect and tell us when this started happening]
### Version/Commit
You can find this information under Information/System Information
- RetroArch: [version/commit]
### Environment information
- OS: [The operating system you're running]
- Compiler: [In case you are running local builds]
- Compiler: [In case you are running local builds]

View File

@ -1,58 +1,58 @@
# Contributing to RetroArch
If you are a developer and want to contribute to the development of RetroArch, please read this.
If you have found a bug and want to submit a minor patch or a bug report, please read this as well.
# Submitting a bug report
When submitting a bug report, make sure that the bug is local to RetroArch.
A bug in a libretro core or something deemed to be external is likely to be closed very fast.
If you still suspect a bug in RetroArch, make sure to test with several cores to make sure.
If you have troubles building RetroArch on Linux/BSD/OSX, make sure to paste shell output of ./configure,
as well as config.log and shell output of make. If building on Windows, just paste shell output of make.
If the issue occurs during runtime, make sure to paste RetroArch's verbose log.
If using Phoenix frontend, you can find log in (File -> Show Log) after running.
In console, make sure to run with verbose (-v) flag.
# Pull Requests
Outside contributions are generally only accepted in the form of a pull request. The process is very simple.
Fork RetroArch, make your changes, and issue a pull request on GitHub. This can all be done within the browser.
The changes are reviewed, and might be merged in. If the pull request isn't acceptable at the time,
note that it's possible to continue pushing up commits to your branch.
If you want to develop a larger feature,
we'd like to discuss this first (ideally on IRC) so that you don't risk developing something
that won't be merged. A pull request with a proof-of-concept is fine, but please indicate so.
## libretro API
If you wish to add functionality to libretro's API, it can take some time to merge in, because changes
to libretro API will affect other projects as well, and we highly value API/ABI stability.
Features will only be added when deemed *necessary* for a concrete libretro core to function properly.
Features will not be added on basis of hypothetical libretro implementations.
# Coding style
Having a consistent code style throughout the code base is highly valued.
Please look through the code to get a feel for the coding style.
A pull request may be asked to fix the coding style before submission.
In other cases, a pull request may be followed up with a "style nit commit".
## Non-obvious things:
- Code should be both ISO C99 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
- Warnings are not allowed (-Wall). Make sure your code is warning-free. Note that warning sensitivity differs a bit across compiler versions.
- Using deprecated APIs is discouraged.
# Copyright Headers and AUTHORS
If you have contributed to a part of a source file (a chunk of code that's written by you),
you should add yourself to the copyright header in that file.
If you have contributed significantly
(a feature, a contribution you can "name", e.g. "Added audio driver foo"), you should add yourself to AUTHORS file.
We'd like your full name and email, and which features you have been part of.
# IRC
Active development happens on IRC. (#retroarch @ irc.freenode.org)
We value discussing things in "real-time".
# Commit Access
Contributors who show a track record of making good pull requests over time will eventually get commit access to the repo.
# Contributing to RetroArch
If you are a developer and want to contribute to the development of RetroArch, please read this.
If you have found a bug and want to submit a minor patch or a bug report, please read this as well.
# Submitting a bug report
When submitting a bug report, make sure that the bug is local to RetroArch.
A bug in a libretro core or something deemed to be external is likely to be closed very fast.
If you still suspect a bug in RetroArch, make sure to test with several cores to make sure.
If you have troubles building RetroArch on Linux/BSD/OSX, make sure to paste shell output of ./configure,
as well as config.log and shell output of make. If building on Windows, just paste shell output of make.
If the issue occurs during runtime, make sure to paste RetroArch's verbose log.
If using Phoenix frontend, you can find log in (File -> Show Log) after running.
In console, make sure to run with verbose (-v) flag.
# Pull Requests
Outside contributions are generally only accepted in the form of a pull request. The process is very simple.
Fork RetroArch, make your changes, and issue a pull request on GitHub. This can all be done within the browser.
The changes are reviewed, and might be merged in. If the pull request isn't acceptable at the time,
note that it's possible to continue pushing up commits to your branch.
If you want to develop a larger feature,
we'd like to discuss this first (ideally on IRC) so that you don't risk developing something
that won't be merged. A pull request with a proof-of-concept is fine, but please indicate so.
## libretro API
If you wish to add functionality to libretro's API, it can take some time to merge in, because changes
to libretro API will affect other projects as well, and we highly value API/ABI stability.
Features will only be added when deemed *necessary* for a concrete libretro core to function properly.
Features will not be added on basis of hypothetical libretro implementations.
# Coding style
Having a consistent code style throughout the code base is highly valued.
Please look through the code to get a feel for the coding style.
A pull request may be asked to fix the coding style before submission.
In other cases, a pull request may be followed up with a "style nit commit".
## Non-obvious things:
- Code should be both ISO C99 and ISO C++ compatible. This dual requirement is for XBox360 and MSVC in general. Think of it as a C++ compatible subset of C99.
- Warnings are not allowed (-Wall). Make sure your code is warning-free. Note that warning sensitivity differs a bit across compiler versions.
- Using deprecated APIs is discouraged.
# Copyright Headers and AUTHORS
If you have contributed to a part of a source file (a chunk of code that's written by you),
you should add yourself to the copyright header in that file.
If you have contributed significantly
(a feature, a contribution you can "name", e.g. "Added audio driver foo"), you should add yourself to AUTHORS file.
We'd like your full name and email, and which features you have been part of.
# IRC
Active development happens on IRC. (#retroarch @ irc.freenode.org)
We value discussing things in "real-time".
# Commit Access
Contributors who show a track record of making good pull requests over time will eventually get commit access to the repo.
This typically happens when the "overhead" of looking through pull requests over time becomes a burden.

View File

@ -1,91 +1,91 @@
CELL_BUILD_TOOLS = GCC
CELL_SDK ?= /usr/local/cell
HAVE_LOGGER = 0
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
# system platform
system_platform = unix
ifeq ($(shell uname -a),)
EXE_EXT = .exe
system_platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
system_platform = osx
else ifneq ($(findstring MINGW,$(shell uname -a)),)
system_platform = win
endif
ifeq ($(DEBUG), 1)
PPU_OPTIMIZE_LV := -O0 -g
else
PPU_OPTIMIZE_LV := -O2 -DNDEBUG
endif
STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe
INCFLAGS = -I. -Idefines -Ilibretro-common/include -Ideps/libz
DEFINES = -D__CELLOS_LV2__ -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_SYSUTILS -DHAVE_SYSMODULES -DHAVE_RARCH_EXEC
ifeq ($(DEX_BUILD), 1)
DEFINES += -DDEX_BUILD
endif
ifeq ($(CEX_BUILD), 1)
DEFINES += -DCEX_BUILD
endif
ifeq ($(ODE_BUILD), 1)
DEFINES += -DODE_BUILD
endif
PPU_CFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
PPU_CXXFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
PPU_SRCS = frontend/frontend_salamander.c \
frontend/frontend_driver.c \
frontend/drivers/platform_ps3.c \
frontend/drivers/platform_null.c \
libretro-common/file/file_path.c \
libretro-common/lists/dir_list.c \
libretro-common/lists/string_list.c \
libretro-common/file/retro_dirent.c \
libretro-common/hash/rhash.c \
libretro-common/string/stdstring.c \
libretro-common/encodings/encoding_utf.c \
libretro-common/compat/compat_strl.c \
libretro-common/compat/compat_strcasestr.c \
libretro-common/compat/fopen_utf8.c \
libretro-common/streams/file_stream.c \
libretro-common/vfs/vfs_implementation.c \
libretro-common/file/config_file.c \
file_path_str.c \
verbosity.c
ifeq ($(HAVE_LOGGER), 1)
PPU_CFLAGS += -DHAVE_LOGGER
PPU_SRCS += network/net_logger.c \
libretro-common/net/net_compat.c \
libretro-common/net/net_socket.c
endif
PPU_TARGET = retroarch-salamander_ps3.elf
ifeq ($(CELL_BUILD_TOOLS),SNC)
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
else
PPU_CFLAGS += -std=gnu99
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
PPU_CLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
endif
PPU_LDLIBS += -lm -lnet_stub -lnetctl_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
include $(CELL_MK_DIR)/sdk.target.mk
CELL_BUILD_TOOLS = GCC
CELL_SDK ?= /usr/local/cell
HAVE_LOGGER = 0
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
# system platform
system_platform = unix
ifeq ($(shell uname -a),)
EXE_EXT = .exe
system_platform = win
else ifneq ($(findstring Darwin,$(shell uname -a)),)
system_platform = osx
else ifneq ($(findstring MINGW,$(shell uname -a)),)
system_platform = win
endif
ifeq ($(DEBUG), 1)
PPU_OPTIMIZE_LV := -O0 -g
else
PPU_OPTIMIZE_LV := -O2 -DNDEBUG
endif
STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe
INCFLAGS = -I. -Idefines -Ilibretro-common/include -Ideps/libz
DEFINES = -D__CELLOS_LV2__ -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_SYSUTILS -DHAVE_SYSMODULES -DHAVE_RARCH_EXEC
ifeq ($(DEX_BUILD), 1)
DEFINES += -DDEX_BUILD
endif
ifeq ($(CEX_BUILD), 1)
DEFINES += -DCEX_BUILD
endif
ifeq ($(ODE_BUILD), 1)
DEFINES += -DODE_BUILD
endif
PPU_CFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
PPU_CXXFLAGS := $(PPU_OPTIMIZE_LV) $(INCFLAGS) $(DEFINES)
PPU_SRCS = frontend/frontend_salamander.c \
frontend/frontend_driver.c \
frontend/drivers/platform_ps3.c \
frontend/drivers/platform_null.c \
libretro-common/file/file_path.c \
libretro-common/lists/dir_list.c \
libretro-common/lists/string_list.c \
libretro-common/file/retro_dirent.c \
libretro-common/hash/rhash.c \
libretro-common/string/stdstring.c \
libretro-common/encodings/encoding_utf.c \
libretro-common/compat/compat_strl.c \
libretro-common/compat/compat_strcasestr.c \
libretro-common/compat/fopen_utf8.c \
libretro-common/streams/file_stream.c \
libretro-common/vfs/vfs_implementation.c \
libretro-common/file/config_file.c \
file_path_str.c \
verbosity.c
ifeq ($(HAVE_LOGGER), 1)
PPU_CFLAGS += -DHAVE_LOGGER
PPU_SRCS += network/net_logger.c \
libretro-common/net/net_compat.c \
libretro-common/net/net_socket.c
endif
PPU_TARGET = retroarch-salamander_ps3.elf
ifeq ($(CELL_BUILD_TOOLS),SNC)
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
else
PPU_CFLAGS += -std=gnu99
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
PPU_CLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
endif
PPU_LDLIBS += -lm -lnet_stub -lnetctl_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
include $(CELL_MK_DIR)/sdk.target.mk

View File

@ -1,382 +1,382 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2019 - Stuart Carnie
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#include <stdio.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <memory.h>
#include "../audio_driver.h"
#pragma mark - ringbuffer
typedef struct ringbuffer
{
float *buffer;
size_t cap;
atomic_int len;
size_t writePtr;
size_t readPtr;
} ringbuffer_t;
typedef ringbuffer_t * ringbuffer_h;
static inline size_t rb_len(ringbuffer_h r)
{
return atomic_load_explicit(&r->len, memory_order_relaxed);
}
static inline size_t rb_cap(ringbuffer_h r)
{
return (r->readPtr + r->cap - r->writePtr) % r->cap;
}
static inline size_t rb_avail(ringbuffer_h r)
{
return r->cap - rb_len(r);
}
static inline void rb_advance_write(ringbuffer_h r)
{
r->writePtr = (r->writePtr + 1) % r->cap;
}
static inline void rb_advance_write_n(ringbuffer_h r, size_t n)
{
r->writePtr = (r->writePtr + n) % r->cap;
}
static inline void rb_advance_read(ringbuffer_h r)
{
r->readPtr = (r->readPtr + 1) % r->cap;
}
static inline void rb_len_add(ringbuffer_h r, int n)
{
atomic_fetch_add(&r->len, n);
}
static inline void rb_len_sub(ringbuffer_h r, int n)
{
atomic_fetch_sub(&r->len, n);
}
static void rb_init(ringbuffer_h r, size_t cap)
{
r->buffer = malloc(cap * sizeof(float));
r->cap = cap;
atomic_init(&r->len, 0);
r->writePtr = 0;
r->readPtr = 0;
}
static void rb_free(ringbuffer_h r)
{
free(r->buffer);
bzero(r, sizeof(*r));
}
#define UNLIKELY(x) __builtin_expect((x), 0)
#define LIKELY(x) __builtin_expect((x), 1)
static void rb_write_data(ringbuffer_h r, const float *data, size_t len)
{
size_t avail = rb_avail(r);
size_t n = MIN(len, avail);
size_t first_write = n;
size_t rest_write = 0;
if (r->writePtr + n > r->cap)
{
first_write = r->cap - r->writePtr;
rest_write = n - first_write;
}
memcpy(r->buffer + r->writePtr, data, first_write*sizeof(float));
memcpy(r->buffer, data + first_write, rest_write*sizeof(float));
rb_advance_write_n(r, n);
rb_len_add(r, (int)n);
}
static void rb_read_data(ringbuffer_h r, float *d0, float *d1, size_t len)
{
size_t need = len*2;
do {
size_t have = rb_len(r);
size_t n = MIN(have, need);
int i = 0;
for (; i < n/2; i++)
{
d0[i] = r->buffer[r->readPtr];
rb_advance_read(r);
d1[i] = r->buffer[r->readPtr];
rb_advance_read(r);
}
need -= n;
rb_len_sub(r, (int)n);
if (UNLIKELY(need > 0))
{
/* we got more data */
if (rb_len(r) > 0)
continue;
// underflow
const float quiet = 0.0f;
size_t fill = (need/2)*sizeof(float);
memset_pattern4(&d0[i], &quiet, fill);
memset_pattern4(&d1[i], &quiet, fill);
}
} while (0);
}
#pragma mark - CoreAudio3
static bool g_interrupted;
@interface CoreAudio3 : NSObject {
ringbuffer_t _rb;
dispatch_semaphore_t _sema;
AUAudioUnit *_au;
size_t _bufferSize;
BOOL _nonBlock;
}
@property (nonatomic, readwrite) BOOL nonBlock;
@property (nonatomic, readonly) BOOL paused;
@property (nonatomic, readonly) size_t writeAvailableInBytes;
@property (nonatomic, readonly) size_t bufferSizeInBytes;
- (instancetype)initWithRate:(NSUInteger)rate
latency:(NSUInteger)latency;
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples;
- (void)start;
- (void)stop;
@end
@implementation CoreAudio3
- (instancetype)initWithRate:(NSUInteger)rate
latency:(NSUInteger)latency {
if (self = [super init])
{
_sema = dispatch_semaphore_create(0);
_bufferSize = (latency * rate) / 1000;
_bufferSize *= 2; // stereo
rb_init(&_rb, _bufferSize);
AudioComponentDescription desc = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_DefaultOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple,
};
NSError *err;
AUAudioUnit *au = [[AUAudioUnit alloc] initWithComponentDescription:desc error:&err];
if (err != nil)
return nil;
AVAudioFormat *format = au.outputBusses[0].format;
if (format.channelCount != 2)
return nil;
AVAudioFormat *renderFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:rate channels:2];
[au.inputBusses[0] setFormat:renderFormat error:&err];
if (err != nil)
return nil;
ringbuffer_h rb = &_rb;
__block dispatch_semaphore_t sema = _sema;
au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags * actionFlags, const AudioTimeStamp * timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList * inputData) {
rb_read_data(rb, inputData->mBuffers[0].mData, inputData->mBuffers[1].mData, frameCount);
dispatch_semaphore_signal(sema);
return 0;
};
[au allocateRenderResourcesAndReturnError:&err];
if (err != nil)
return nil;
_au = au;
RARCH_LOG("[CoreAudio3]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)self.bufferSizeInBytes, latency);
[self start];
}
return self;
}
- (void)dealloc {
rb_free(&_rb);
}
- (BOOL)paused {
return !_au.running;
}
- (size_t)bufferSizeInBytes {
return _bufferSize * sizeof(float);
}
- (size_t)writeAvailableInBytes {
return rb_avail(&_rb) * sizeof(float);
}
- (void)start {
NSError *err;
[_au startHardwareAndReturnError:&err];
}
- (void)stop {
[_au stopHardware];
}
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples {
size_t written = 0;
while (!g_interrupted && samples > 0)
{
size_t write_avail = rb_avail(&_rb);
if (write_avail > samples)
write_avail = samples;
rb_write_data(&_rb, data, write_avail);
data += write_avail;
written += write_avail;
samples -= write_avail;
if (_nonBlock)
break;
if (write_avail == 0)
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
}
return written;
}
@end
static void coreaudio3_free(void *data)
{
CoreAudio3 *dev = (__bridge_transfer CoreAudio3 *)data;
if (dev == nil)
return;
[dev stop];
dev = nil;
}
static void *coreaudio3_init(const char *device,
unsigned rate, unsigned latency,
unsigned block_frames,
unsigned *new_rate)
{
CoreAudio3 *dev = [[CoreAudio3 alloc] initWithRate:rate
latency:latency];
*new_rate = rate;
return (__bridge_retained void *)dev;
}
static ssize_t coreaudio3_write(void *data, const void *buf_, size_t size)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
return [dev writeFloat:(const float *)buf_ samples:size/sizeof(float)] * sizeof(float);
}
static void coreaudio3_set_nonblock_state(void *data, bool state)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return;
dev.nonBlock = state;
}
static bool coreaudio3_alive(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
return !dev.paused;
}
static bool coreaudio3_stop(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
[dev stop];
return dev.paused;
}
static bool coreaudio3_start(void *data, bool is_shutdown)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
[dev start];
return !dev.paused;
}
static bool coreaudio3_use_float(void *data)
{
return YES;
}
static size_t coreaudio3_write_avail(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return 0;
return dev.writeAvailableInBytes;
}
static size_t coreaudio3_buffer_size(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return 0;
return dev.bufferSizeInBytes;
}
audio_driver_t audio_coreaudio3 = {
coreaudio3_init,
coreaudio3_write,
coreaudio3_stop,
coreaudio3_start,
coreaudio3_alive,
coreaudio3_set_nonblock_state,
coreaudio3_free,
coreaudio3_use_float,
"coreaudio3",
coreaudio3_write_avail,
coreaudio3_buffer_size,
};
/* RetroArch - A frontend for libretro.
* Copyright (C) 2019 - Stuart Carnie
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#include <stdio.h>
#include <stdatomic.h>
#include <stdlib.h>
#include <memory.h>
#include "../audio_driver.h"
#pragma mark - ringbuffer
typedef struct ringbuffer
{
float *buffer;
size_t cap;
atomic_int len;
size_t writePtr;
size_t readPtr;
} ringbuffer_t;
typedef ringbuffer_t * ringbuffer_h;
static inline size_t rb_len(ringbuffer_h r)
{
return atomic_load_explicit(&r->len, memory_order_relaxed);
}
static inline size_t rb_cap(ringbuffer_h r)
{
return (r->readPtr + r->cap - r->writePtr) % r->cap;
}
static inline size_t rb_avail(ringbuffer_h r)
{
return r->cap - rb_len(r);
}
static inline void rb_advance_write(ringbuffer_h r)
{
r->writePtr = (r->writePtr + 1) % r->cap;
}
static inline void rb_advance_write_n(ringbuffer_h r, size_t n)
{
r->writePtr = (r->writePtr + n) % r->cap;
}
static inline void rb_advance_read(ringbuffer_h r)
{
r->readPtr = (r->readPtr + 1) % r->cap;
}
static inline void rb_len_add(ringbuffer_h r, int n)
{
atomic_fetch_add(&r->len, n);
}
static inline void rb_len_sub(ringbuffer_h r, int n)
{
atomic_fetch_sub(&r->len, n);
}
static void rb_init(ringbuffer_h r, size_t cap)
{
r->buffer = malloc(cap * sizeof(float));
r->cap = cap;
atomic_init(&r->len, 0);
r->writePtr = 0;
r->readPtr = 0;
}
static void rb_free(ringbuffer_h r)
{
free(r->buffer);
bzero(r, sizeof(*r));
}
#define UNLIKELY(x) __builtin_expect((x), 0)
#define LIKELY(x) __builtin_expect((x), 1)
static void rb_write_data(ringbuffer_h r, const float *data, size_t len)
{
size_t avail = rb_avail(r);
size_t n = MIN(len, avail);
size_t first_write = n;
size_t rest_write = 0;
if (r->writePtr + n > r->cap)
{
first_write = r->cap - r->writePtr;
rest_write = n - first_write;
}
memcpy(r->buffer + r->writePtr, data, first_write*sizeof(float));
memcpy(r->buffer, data + first_write, rest_write*sizeof(float));
rb_advance_write_n(r, n);
rb_len_add(r, (int)n);
}
static void rb_read_data(ringbuffer_h r, float *d0, float *d1, size_t len)
{
size_t need = len*2;
do {
size_t have = rb_len(r);
size_t n = MIN(have, need);
int i = 0;
for (; i < n/2; i++)
{
d0[i] = r->buffer[r->readPtr];
rb_advance_read(r);
d1[i] = r->buffer[r->readPtr];
rb_advance_read(r);
}
need -= n;
rb_len_sub(r, (int)n);
if (UNLIKELY(need > 0))
{
/* we got more data */
if (rb_len(r) > 0)
continue;
// underflow
const float quiet = 0.0f;
size_t fill = (need/2)*sizeof(float);
memset_pattern4(&d0[i], &quiet, fill);
memset_pattern4(&d1[i], &quiet, fill);
}
} while (0);
}
#pragma mark - CoreAudio3
static bool g_interrupted;
@interface CoreAudio3 : NSObject {
ringbuffer_t _rb;
dispatch_semaphore_t _sema;
AUAudioUnit *_au;
size_t _bufferSize;
BOOL _nonBlock;
}
@property (nonatomic, readwrite) BOOL nonBlock;
@property (nonatomic, readonly) BOOL paused;
@property (nonatomic, readonly) size_t writeAvailableInBytes;
@property (nonatomic, readonly) size_t bufferSizeInBytes;
- (instancetype)initWithRate:(NSUInteger)rate
latency:(NSUInteger)latency;
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples;
- (void)start;
- (void)stop;
@end
@implementation CoreAudio3
- (instancetype)initWithRate:(NSUInteger)rate
latency:(NSUInteger)latency {
if (self = [super init])
{
_sema = dispatch_semaphore_create(0);
_bufferSize = (latency * rate) / 1000;
_bufferSize *= 2; // stereo
rb_init(&_rb, _bufferSize);
AudioComponentDescription desc = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_DefaultOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple,
};
NSError *err;
AUAudioUnit *au = [[AUAudioUnit alloc] initWithComponentDescription:desc error:&err];
if (err != nil)
return nil;
AVAudioFormat *format = au.outputBusses[0].format;
if (format.channelCount != 2)
return nil;
AVAudioFormat *renderFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:rate channels:2];
[au.inputBusses[0] setFormat:renderFormat error:&err];
if (err != nil)
return nil;
ringbuffer_h rb = &_rb;
__block dispatch_semaphore_t sema = _sema;
au.outputProvider = ^AUAudioUnitStatus(AudioUnitRenderActionFlags * actionFlags, const AudioTimeStamp * timestamp, AUAudioFrameCount frameCount, NSInteger inputBusNumber, AudioBufferList * inputData) {
rb_read_data(rb, inputData->mBuffers[0].mData, inputData->mBuffers[1].mData, frameCount);
dispatch_semaphore_signal(sema);
return 0;
};
[au allocateRenderResourcesAndReturnError:&err];
if (err != nil)
return nil;
_au = au;
RARCH_LOG("[CoreAudio3]: Using buffer size of %u bytes: (latency = %u ms)\n", (unsigned)self.bufferSizeInBytes, latency);
[self start];
}
return self;
}
- (void)dealloc {
rb_free(&_rb);
}
- (BOOL)paused {
return !_au.running;
}
- (size_t)bufferSizeInBytes {
return _bufferSize * sizeof(float);
}
- (size_t)writeAvailableInBytes {
return rb_avail(&_rb) * sizeof(float);
}
- (void)start {
NSError *err;
[_au startHardwareAndReturnError:&err];
}
- (void)stop {
[_au stopHardware];
}
- (ssize_t)writeFloat:(const float *)data samples:(size_t)samples {
size_t written = 0;
while (!g_interrupted && samples > 0)
{
size_t write_avail = rb_avail(&_rb);
if (write_avail > samples)
write_avail = samples;
rb_write_data(&_rb, data, write_avail);
data += write_avail;
written += write_avail;
samples -= write_avail;
if (_nonBlock)
break;
if (write_avail == 0)
dispatch_semaphore_wait(_sema, DISPATCH_TIME_FOREVER);
}
return written;
}
@end
static void coreaudio3_free(void *data)
{
CoreAudio3 *dev = (__bridge_transfer CoreAudio3 *)data;
if (dev == nil)
return;
[dev stop];
dev = nil;
}
static void *coreaudio3_init(const char *device,
unsigned rate, unsigned latency,
unsigned block_frames,
unsigned *new_rate)
{
CoreAudio3 *dev = [[CoreAudio3 alloc] initWithRate:rate
latency:latency];
*new_rate = rate;
return (__bridge_retained void *)dev;
}
static ssize_t coreaudio3_write(void *data, const void *buf_, size_t size)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
return [dev writeFloat:(const float *)buf_ samples:size/sizeof(float)] * sizeof(float);
}
static void coreaudio3_set_nonblock_state(void *data, bool state)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return;
dev.nonBlock = state;
}
static bool coreaudio3_alive(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
return !dev.paused;
}
static bool coreaudio3_stop(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
[dev stop];
return dev.paused;
}
static bool coreaudio3_start(void *data, bool is_shutdown)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return NO;
[dev start];
return !dev.paused;
}
static bool coreaudio3_use_float(void *data)
{
return YES;
}
static size_t coreaudio3_write_avail(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return 0;
return dev.writeAvailableInBytes;
}
static size_t coreaudio3_buffer_size(void *data)
{
CoreAudio3 *dev = (__bridge CoreAudio3 *)data;
if (dev == nil)
return 0;
return dev.bufferSizeInBytes;
}
audio_driver_t audio_coreaudio3 = {
coreaudio3_init,
coreaudio3_write,
coreaudio3_stop,
coreaudio3_start,
coreaudio3_alive,
coreaudio3_set_nonblock_state,
coreaudio3_free,
coreaudio3_use_float,
"coreaudio3",
coreaudio3_write_avail,
coreaudio3_buffer_size,
};

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +1,171 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2018 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_OLD_H
#define __RARCH_CHEEVOS_OLD_H
#ifdef HAVE_NEW_CHEEVOS
#include "../cheevos-new/cheevos.h"
#else
#include <stdint.h>
#include <stdlib.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
/*****************************************************************************
Setup - mainly for debugging
*****************************************************************************/
/* Define this macro to get extra-verbose log for cheevos. */
#undef CHEEVOS_VERBOSE
/*****************************************************************************
End of setup
*****************************************************************************/
#define CHEEVOS_TAG "[CHEEVOS]: "
#ifdef CHEEVOS_VERBOSE
#define CHEEVOS_LOG RARCH_LOG
#define CHEEVOS_ERR RARCH_ERR
#else
void cheevos_log(const char *fmt, ...);
#define CHEEVOS_LOG cheevos_log
#define CHEEVOS_ERR cheevos_log
#endif
typedef struct cheevos_ctx_desc
{
unsigned idx;
char *s;
size_t len;
} cheevos_ctx_desc_t;
typedef enum
{
CHEEVOS_CONSOLE_NONE = 0,
/* Don't change those, the values match the console IDs
* at retroachievements.org. */
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
CHEEVOS_CONSOLE_NINTENDO_64 = 2,
CHEEVOS_CONSOLE_SUPER_NINTENDO = 3,
CHEEVOS_CONSOLE_GAMEBOY = 4,
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE = 5,
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
CHEEVOS_CONSOLE_NINTENDO = 7,
CHEEVOS_CONSOLE_PC_ENGINE = 8,
CHEEVOS_CONSOLE_SEGA_CD = 9,
CHEEVOS_CONSOLE_SEGA_32X = 10,
CHEEVOS_CONSOLE_MASTER_SYSTEM = 11,
CHEEVOS_CONSOLE_PLAYSTATION = 12,
CHEEVOS_CONSOLE_ATARI_LYNX = 13,
CHEEVOS_CONSOLE_NEOGEO_POCKET = 14,
CHEEVOS_CONSOLE_GAME_GEAR = 15,
CHEEVOS_CONSOLE_GAMECUBE = 16,
CHEEVOS_CONSOLE_ATARI_JAGUAR = 17,
CHEEVOS_CONSOLE_NINTENDO_DS = 18,
CHEEVOS_CONSOLE_WII = 19,
CHEEVOS_CONSOLE_WII_U = 20,
CHEEVOS_CONSOLE_PLAYSTATION_2 = 21,
CHEEVOS_CONSOLE_XBOX = 22,
CHEEVOS_CONSOLE_SKYNET = 23,
CHEEVOS_CONSOLE_XBOX_ONE = 24,
CHEEVOS_CONSOLE_ATARI_2600 = 25,
CHEEVOS_CONSOLE_MS_DOS = 26,
CHEEVOS_CONSOLE_ARCADE = 27,
CHEEVOS_CONSOLE_VIRTUAL_BOY = 28,
CHEEVOS_CONSOLE_MSX = 29,
CHEEVOS_CONSOLE_COMMODORE_64 = 30,
CHEEVOS_CONSOLE_ZX81 = 31,
CHEEVOS_CONSOLE_ATARI_7800 = 51
} cheevos_console_t;
enum
{
CHEEVOS_DIRTY_TITLE = 1 << 0,
CHEEVOS_DIRTY_DESC = 1 << 1,
CHEEVOS_DIRTY_POINTS = 1 << 2,
CHEEVOS_DIRTY_AUTHOR = 1 << 3,
CHEEVOS_DIRTY_ID = 1 << 4,
CHEEVOS_DIRTY_BADGE = 1 << 5,
CHEEVOS_DIRTY_CONDITIONS = 1 << 6,
CHEEVOS_DIRTY_VOTES = 1 << 7,
CHEEVOS_DIRTY_DESCRIPTION = 1 << 8,
CHEEVOS_DIRTY_ALL = (1 << 9) - 1
};
enum
{
CHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
CHEEVOS_ACTIVE_HARDCORE = 1 << 1
};
enum
{
CHEEVOS_FORMAT_FRAMES = 0,
CHEEVOS_FORMAT_SECS,
CHEEVOS_FORMAT_MILLIS,
CHEEVOS_FORMAT_SCORE,
CHEEVOS_FORMAT_VALUE,
CHEEVOS_FORMAT_OTHER
};
bool cheevos_load(const void *data);
void cheevos_reset_game(void);
void cheevos_populate_menu(void *data);
bool cheevos_get_description(cheevos_ctx_desc_t *desc);
bool cheevos_apply_cheats(bool *data_bool);
bool cheevos_unload(void);
bool cheevos_toggle_hardcore_mode(void);
void cheevos_test(void);
bool cheevos_set_cheats(void);
void cheevos_set_support_cheevos(bool state);
bool cheevos_get_support_cheevos(void);
cheevos_console_t cheevos_get_console(void);
extern bool cheevos_loaded;
extern bool cheevos_hardcore_active;
extern bool cheevos_hardcore_paused;
extern bool cheevos_state_loaded_flag;
extern int cheats_are_enabled;
extern int cheats_were_enabled;
RETRO_END_DECLS
#endif
#endif /* __RARCH_CHEEVOS_H */
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2018 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_OLD_H
#define __RARCH_CHEEVOS_OLD_H
#ifdef HAVE_NEW_CHEEVOS
#include "../cheevos-new/cheevos.h"
#else
#include <stdint.h>
#include <stdlib.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
/*****************************************************************************
Setup - mainly for debugging
*****************************************************************************/
/* Define this macro to get extra-verbose log for cheevos. */
#undef CHEEVOS_VERBOSE
/*****************************************************************************
End of setup
*****************************************************************************/
#define CHEEVOS_TAG "[CHEEVOS]: "
#ifdef CHEEVOS_VERBOSE
#define CHEEVOS_LOG RARCH_LOG
#define CHEEVOS_ERR RARCH_ERR
#else
void cheevos_log(const char *fmt, ...);
#define CHEEVOS_LOG cheevos_log
#define CHEEVOS_ERR cheevos_log
#endif
typedef struct cheevos_ctx_desc
{
unsigned idx;
char *s;
size_t len;
} cheevos_ctx_desc_t;
typedef enum
{
CHEEVOS_CONSOLE_NONE = 0,
/* Don't change those, the values match the console IDs
* at retroachievements.org. */
CHEEVOS_CONSOLE_MEGA_DRIVE = 1,
CHEEVOS_CONSOLE_NINTENDO_64 = 2,
CHEEVOS_CONSOLE_SUPER_NINTENDO = 3,
CHEEVOS_CONSOLE_GAMEBOY = 4,
CHEEVOS_CONSOLE_GAMEBOY_ADVANCE = 5,
CHEEVOS_CONSOLE_GAMEBOY_COLOR = 6,
CHEEVOS_CONSOLE_NINTENDO = 7,
CHEEVOS_CONSOLE_PC_ENGINE = 8,
CHEEVOS_CONSOLE_SEGA_CD = 9,
CHEEVOS_CONSOLE_SEGA_32X = 10,
CHEEVOS_CONSOLE_MASTER_SYSTEM = 11,
CHEEVOS_CONSOLE_PLAYSTATION = 12,
CHEEVOS_CONSOLE_ATARI_LYNX = 13,
CHEEVOS_CONSOLE_NEOGEO_POCKET = 14,
CHEEVOS_CONSOLE_GAME_GEAR = 15,
CHEEVOS_CONSOLE_GAMECUBE = 16,
CHEEVOS_CONSOLE_ATARI_JAGUAR = 17,
CHEEVOS_CONSOLE_NINTENDO_DS = 18,
CHEEVOS_CONSOLE_WII = 19,
CHEEVOS_CONSOLE_WII_U = 20,
CHEEVOS_CONSOLE_PLAYSTATION_2 = 21,
CHEEVOS_CONSOLE_XBOX = 22,
CHEEVOS_CONSOLE_SKYNET = 23,
CHEEVOS_CONSOLE_XBOX_ONE = 24,
CHEEVOS_CONSOLE_ATARI_2600 = 25,
CHEEVOS_CONSOLE_MS_DOS = 26,
CHEEVOS_CONSOLE_ARCADE = 27,
CHEEVOS_CONSOLE_VIRTUAL_BOY = 28,
CHEEVOS_CONSOLE_MSX = 29,
CHEEVOS_CONSOLE_COMMODORE_64 = 30,
CHEEVOS_CONSOLE_ZX81 = 31,
CHEEVOS_CONSOLE_ATARI_7800 = 51
} cheevos_console_t;
enum
{
CHEEVOS_DIRTY_TITLE = 1 << 0,
CHEEVOS_DIRTY_DESC = 1 << 1,
CHEEVOS_DIRTY_POINTS = 1 << 2,
CHEEVOS_DIRTY_AUTHOR = 1 << 3,
CHEEVOS_DIRTY_ID = 1 << 4,
CHEEVOS_DIRTY_BADGE = 1 << 5,
CHEEVOS_DIRTY_CONDITIONS = 1 << 6,
CHEEVOS_DIRTY_VOTES = 1 << 7,
CHEEVOS_DIRTY_DESCRIPTION = 1 << 8,
CHEEVOS_DIRTY_ALL = (1 << 9) - 1
};
enum
{
CHEEVOS_ACTIVE_SOFTCORE = 1 << 0,
CHEEVOS_ACTIVE_HARDCORE = 1 << 1
};
enum
{
CHEEVOS_FORMAT_FRAMES = 0,
CHEEVOS_FORMAT_SECS,
CHEEVOS_FORMAT_MILLIS,
CHEEVOS_FORMAT_SCORE,
CHEEVOS_FORMAT_VALUE,
CHEEVOS_FORMAT_OTHER
};
bool cheevos_load(const void *data);
void cheevos_reset_game(void);
void cheevos_populate_menu(void *data);
bool cheevos_get_description(cheevos_ctx_desc_t *desc);
bool cheevos_apply_cheats(bool *data_bool);
bool cheevos_unload(void);
bool cheevos_toggle_hardcore_mode(void);
void cheevos_test(void);
bool cheevos_set_cheats(void);
void cheevos_set_support_cheevos(bool state);
bool cheevos_get_support_cheevos(void);
cheevos_console_t cheevos_get_console(void);
extern bool cheevos_loaded;
extern bool cheevos_hardcore_active;
extern bool cheevos_hardcore_paused;
extern bool cheevos_state_loaded_flag;
extern int cheats_are_enabled;
extern int cheats_were_enabled;
RETRO_END_DECLS
#endif
#endif /* __RARCH_CHEEVOS_H */

View File

@ -1,189 +1,189 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "cond.h"
#include "var.h"
#include "../retroarch.h"
#include "../verbosity.h"
/*****************************************************************************
Parsing
*****************************************************************************/
static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr)
{
const char *str = *memaddr;
cheevos_cond_op_t op;
if (*str == '=' && str[1] == '=')
{
op = CHEEVOS_COND_OP_EQUALS;
str += 2;
}
else if (*str == '=')
{
op = CHEEVOS_COND_OP_EQUALS;
str++;
}
else if (*str == '!' && str[1] == '=')
{
op = CHEEVOS_COND_OP_NOT_EQUAL_TO;
str += 2;
}
else if (*str == '<' && str[1] == '=')
{
op = CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL;
str += 2;
}
else if (*str == '<')
{
op = CHEEVOS_COND_OP_LESS_THAN;
str++;
}
else if (*str == '>' && str[1] == '=')
{
op = CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL;
str += 2;
}
else if (*str == '>')
{
op = CHEEVOS_COND_OP_GREATER_THAN;
str++;
}
else
{
CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
op = CHEEVOS_COND_OP_EQUALS;
}
*memaddr = str;
return op;
}
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr)
{
const char* str = *memaddr;
cond->type = CHEEVOS_COND_TYPE_STANDARD;
if (*str != 0 && str[1] == ':')
{
int skip = 2;
switch (*str)
{
case 'R':
cond->type = CHEEVOS_COND_TYPE_RESET_IF;
break;
case 'P':
cond->type = CHEEVOS_COND_TYPE_PAUSE_IF;
break;
case 'A':
cond->type = CHEEVOS_COND_TYPE_ADD_SOURCE;
break;
case 'B':
cond->type = CHEEVOS_COND_TYPE_SUB_SOURCE;
break;
case 'C':
cond->type = CHEEVOS_COND_TYPE_ADD_HITS;
break;
default:
skip = 0;
break;
}
str += skip;
}
cheevos_var_parse(&cond->source, &str);
cond->op = cheevos_cond_parse_operator(&str);
cheevos_var_parse(&cond->target, &str);
cond->curr_hits = 0;
if (*str == '(' || *str == '.')
{
char* end;
cond->req_hits = (unsigned)strtol(str + 1, &end, 10);
str = end + (*end == ')' || *end == '.');
}
else
cond->req_hits = 0;
*memaddr = str;
}
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which)
{
cheevos_cond_t dummy;
unsigned index = 0;
unsigned count = 0;
for (;;)
{
for (;;)
{
cheevos_cond_parse(&dummy, &memaddr);
if (index == which)
count++;
if (*memaddr != '_')
break;
memaddr++;
}
index++;
if (*memaddr != 'S')
break;
memaddr++;
}
return count;
}
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which)
{
cheevos_cond_t dummy;
unsigned index = 0;
for (;;)
{
for (;;)
{
if (index == which)
{
cheevos_cond_parse(cond, &memaddr);
cond++;
}
else
cheevos_cond_parse(&dummy, &memaddr);
if (*memaddr != '_')
break;
memaddr++;
}
index++;
if (*memaddr != 'S')
break;
memaddr++;
}
}
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "cond.h"
#include "var.h"
#include "../retroarch.h"
#include "../verbosity.h"
/*****************************************************************************
Parsing
*****************************************************************************/
static cheevos_cond_op_t cheevos_cond_parse_operator(const char** memaddr)
{
const char *str = *memaddr;
cheevos_cond_op_t op;
if (*str == '=' && str[1] == '=')
{
op = CHEEVOS_COND_OP_EQUALS;
str += 2;
}
else if (*str == '=')
{
op = CHEEVOS_COND_OP_EQUALS;
str++;
}
else if (*str == '!' && str[1] == '=')
{
op = CHEEVOS_COND_OP_NOT_EQUAL_TO;
str += 2;
}
else if (*str == '<' && str[1] == '=')
{
op = CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL;
str += 2;
}
else if (*str == '<')
{
op = CHEEVOS_COND_OP_LESS_THAN;
str++;
}
else if (*str == '>' && str[1] == '=')
{
op = CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL;
str += 2;
}
else if (*str == '>')
{
op = CHEEVOS_COND_OP_GREATER_THAN;
str++;
}
else
{
CHEEVOS_ERR(CHEEVOS_TAG "unknown operator %c\n.", *str);
op = CHEEVOS_COND_OP_EQUALS;
}
*memaddr = str;
return op;
}
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr)
{
const char* str = *memaddr;
cond->type = CHEEVOS_COND_TYPE_STANDARD;
if (*str != 0 && str[1] == ':')
{
int skip = 2;
switch (*str)
{
case 'R':
cond->type = CHEEVOS_COND_TYPE_RESET_IF;
break;
case 'P':
cond->type = CHEEVOS_COND_TYPE_PAUSE_IF;
break;
case 'A':
cond->type = CHEEVOS_COND_TYPE_ADD_SOURCE;
break;
case 'B':
cond->type = CHEEVOS_COND_TYPE_SUB_SOURCE;
break;
case 'C':
cond->type = CHEEVOS_COND_TYPE_ADD_HITS;
break;
default:
skip = 0;
break;
}
str += skip;
}
cheevos_var_parse(&cond->source, &str);
cond->op = cheevos_cond_parse_operator(&str);
cheevos_var_parse(&cond->target, &str);
cond->curr_hits = 0;
if (*str == '(' || *str == '.')
{
char* end;
cond->req_hits = (unsigned)strtol(str + 1, &end, 10);
str = end + (*end == ')' || *end == '.');
}
else
cond->req_hits = 0;
*memaddr = str;
}
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which)
{
cheevos_cond_t dummy;
unsigned index = 0;
unsigned count = 0;
for (;;)
{
for (;;)
{
cheevos_cond_parse(&dummy, &memaddr);
if (index == which)
count++;
if (*memaddr != '_')
break;
memaddr++;
}
index++;
if (*memaddr != 'S')
break;
memaddr++;
}
return count;
}
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which)
{
cheevos_cond_t dummy;
unsigned index = 0;
for (;;)
{
for (;;)
{
if (index == which)
{
cheevos_cond_parse(cond, &memaddr);
cond++;
}
else
cheevos_cond_parse(&dummy, &memaddr);
if (*memaddr != '_')
break;
memaddr++;
}
index++;
if (*memaddr != 'S')
break;
memaddr++;
}
}

View File

@ -1,63 +1,63 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_COND_H
#define __RARCH_CHEEVOS_COND_H
#include "var.h"
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef enum
{
CHEEVOS_COND_TYPE_STANDARD,
CHEEVOS_COND_TYPE_PAUSE_IF,
CHEEVOS_COND_TYPE_RESET_IF,
CHEEVOS_COND_TYPE_ADD_SOURCE,
CHEEVOS_COND_TYPE_SUB_SOURCE,
CHEEVOS_COND_TYPE_ADD_HITS
} cheevos_cond_type_t;
typedef enum
{
CHEEVOS_COND_OP_EQUALS,
CHEEVOS_COND_OP_LESS_THAN,
CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL,
CHEEVOS_COND_OP_GREATER_THAN,
CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL,
CHEEVOS_COND_OP_NOT_EQUAL_TO
} cheevos_cond_op_t;
typedef struct
{
cheevos_cond_type_t type;
unsigned req_hits;
unsigned curr_hits;
char pause;
cheevos_var_t source;
cheevos_cond_op_t op;
cheevos_var_t target;
} cheevos_cond_t;
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr);
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which);
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which);
RETRO_END_DECLS
#endif /* __RARCH_CHEEVOS_COND_H */
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_COND_H
#define __RARCH_CHEEVOS_COND_H
#include "var.h"
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef enum
{
CHEEVOS_COND_TYPE_STANDARD,
CHEEVOS_COND_TYPE_PAUSE_IF,
CHEEVOS_COND_TYPE_RESET_IF,
CHEEVOS_COND_TYPE_ADD_SOURCE,
CHEEVOS_COND_TYPE_SUB_SOURCE,
CHEEVOS_COND_TYPE_ADD_HITS
} cheevos_cond_type_t;
typedef enum
{
CHEEVOS_COND_OP_EQUALS,
CHEEVOS_COND_OP_LESS_THAN,
CHEEVOS_COND_OP_LESS_THAN_OR_EQUAL,
CHEEVOS_COND_OP_GREATER_THAN,
CHEEVOS_COND_OP_GREATER_THAN_OR_EQUAL,
CHEEVOS_COND_OP_NOT_EQUAL_TO
} cheevos_cond_op_t;
typedef struct
{
cheevos_cond_type_t type;
unsigned req_hits;
unsigned curr_hits;
char pause;
cheevos_var_t source;
cheevos_cond_op_t op;
cheevos_var_t target;
} cheevos_cond_t;
void cheevos_cond_parse(cheevos_cond_t* cond, const char** memaddr);
unsigned cheevos_cond_count_in_set(const char* memaddr, unsigned which);
void cheevos_cond_parse_in_set(cheevos_cond_t* cond, const char* memaddr, unsigned which);
RETRO_END_DECLS
#endif /* __RARCH_CHEEVOS_COND_H */

View File

@ -1,75 +1,75 @@
#ifndef CORO_H
#define CORO_H
/*
Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
*/
/* Use at the beginning of the coroutine, you must have declared a variable coro_t* coro */
#define CORO_ENTER() \
{ \
CORO_again: ; \
switch ( coro->step ) { \
case CORO_BEGIN: ;
/* Use to define labels which are targets to GOTO and GOSUB */
#define CORO_SUB( x ) \
case x: ;
/* Use at the end of the coroutine */
#define CORO_LEAVE() \
} } \
do { return 0; } while ( 0 )
/* Go to the x label */
#define CORO_GOTO( x ) \
do { \
coro->step = ( x ); \
goto CORO_again; \
} while ( 0 )
/* Go to a subroutine, execution continues until the subroutine returns via RET */
#define CORO_GOSUB( x ) \
do { \
coro->stack[ coro->sp++ ] = __LINE__; \
coro->step = ( x ); \
goto CORO_again; \
case __LINE__: ; \
} while ( 0 )
/* Returns from a subroutine */
#define CORO_RET() \
do { \
coro->step = coro->stack[ --coro->sp ]; \
goto CORO_again; \
} while ( 0 )
/* Yields to the caller, execution continues from this point when the coroutine is resumed */
#define CORO_YIELD() \
do { \
coro->step = __LINE__; \
return 1; \
case __LINE__: ; \
} while ( 0 )
/* The coroutine entry point, never use 0 as a label */
#define CORO_BEGIN 0
/* Sets up the coroutine */
#define CORO_SETUP() \
do { \
coro->step = CORO_BEGIN; \
coro->sp = 0; \
} while ( 0 )
#define CORO_STOP() \
do { \
return 0; \
} while ( 0 )
/* Add this macro to your coro_t structure containing the variables for the coroutine */
#define CORO_FIELDS \
int step, sp; \
int stack[ 8 ];
#endif /* CORO_H */
#ifndef CORO_H
#define CORO_H
/*
Released under the CC0: https://creativecommons.org/publicdomain/zero/1.0/
*/
/* Use at the beginning of the coroutine, you must have declared a variable coro_t* coro */
#define CORO_ENTER() \
{ \
CORO_again: ; \
switch ( coro->step ) { \
case CORO_BEGIN: ;
/* Use to define labels which are targets to GOTO and GOSUB */
#define CORO_SUB( x ) \
case x: ;
/* Use at the end of the coroutine */
#define CORO_LEAVE() \
} } \
do { return 0; } while ( 0 )
/* Go to the x label */
#define CORO_GOTO( x ) \
do { \
coro->step = ( x ); \
goto CORO_again; \
} while ( 0 )
/* Go to a subroutine, execution continues until the subroutine returns via RET */
#define CORO_GOSUB( x ) \
do { \
coro->stack[ coro->sp++ ] = __LINE__; \
coro->step = ( x ); \
goto CORO_again; \
case __LINE__: ; \
} while ( 0 )
/* Returns from a subroutine */
#define CORO_RET() \
do { \
coro->step = coro->stack[ --coro->sp ]; \
goto CORO_again; \
} while ( 0 )
/* Yields to the caller, execution continues from this point when the coroutine is resumed */
#define CORO_YIELD() \
do { \
coro->step = __LINE__; \
return 1; \
case __LINE__: ; \
} while ( 0 )
/* The coroutine entry point, never use 0 as a label */
#define CORO_BEGIN 0
/* Sets up the coroutine */
#define CORO_SETUP() \
do { \
coro->step = CORO_BEGIN; \
coro->sp = 0; \
} while ( 0 )
#define CORO_STOP() \
do { \
return 0; \
} while ( 0 )
/* Add this macro to your coro_t structure containing the variables for the coroutine */
#define CORO_FIELDS \
int step, sp; \
int stack[ 8 ];
#endif /* CORO_H */

View File

@ -1,415 +1,415 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <stdint.h>
#include <libretro.h>
#include "var.h"
#include "../retroarch.h"
#include "../core.h"
#include "../verbosity.h"
/*****************************************************************************
Parsing
*****************************************************************************/
static cheevos_var_size_t cheevos_var_parse_prefix(const char** memaddr)
{
/* Careful not to use ABCDEF here, this denotes part of an actual variable! */
const char* str = *memaddr;
cheevos_var_size_t size;
switch (toupper((unsigned char)*str++))
{
case 'M':
size = CHEEVOS_VAR_SIZE_BIT_0;
break;
case 'N':
size = CHEEVOS_VAR_SIZE_BIT_1;
break;
case 'O':
size = CHEEVOS_VAR_SIZE_BIT_2;
break;
case 'P':
size = CHEEVOS_VAR_SIZE_BIT_3;
break;
case 'Q':
size = CHEEVOS_VAR_SIZE_BIT_4;
break;
case 'R':
size = CHEEVOS_VAR_SIZE_BIT_5;
break;
case 'S':
size = CHEEVOS_VAR_SIZE_BIT_6;
break;
case 'T':
size = CHEEVOS_VAR_SIZE_BIT_7;
break;
case 'L':
size = CHEEVOS_VAR_SIZE_NIBBLE_LOWER;
break;
case 'U':
size = CHEEVOS_VAR_SIZE_NIBBLE_UPPER;
break;
case 'H':
size = CHEEVOS_VAR_SIZE_EIGHT_BITS;
break;
case 'X':
size = CHEEVOS_VAR_SIZE_THIRTYTWO_BITS;
break;
default:
str--;
/* fall through */
case ' ':
size = CHEEVOS_VAR_SIZE_SIXTEEN_BITS;
break;
}
*memaddr = str;
return size;
}
static size_t cheevos_var_reduce(size_t addr, size_t mask)
{
while (mask)
{
size_t tmp = (mask - 1) & ~mask;
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
mask = (mask & (mask - 1)) >> 1;
}
return addr;
}
static size_t cheevos_var_highest_bit(size_t n)
{
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return n ^ (n >> 1);
}
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr)
{
char *end = NULL;
const char *str = *memaddr;
unsigned base = 16;
var->is_bcd = false;
if (toupper((unsigned char)*str) == 'D' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
{
/* d0x + 4 hex digits */
str += 3;
var->type = CHEEVOS_VAR_TYPE_DELTA_MEM;
}
else if (toupper((unsigned char)*str) == 'B' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
{
/* b0x (binary-coded decimal) */
str += 3;
var->is_bcd = true;
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
}
else if (*str == '0' && toupper((unsigned char)str[1]) == 'X')
{
/* 0x + 4 hex digits */
str += 2;
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
}
else
{
var->type = CHEEVOS_VAR_TYPE_VALUE_COMP;
if (toupper((unsigned char)*str) == 'H')
str++;
else
{
if (toupper((unsigned char)*str) == 'V')
str++;
base = 10;
}
}
if (var->type != CHEEVOS_VAR_TYPE_VALUE_COMP)
{
var->size = cheevos_var_parse_prefix(&str);
}
var->value = (unsigned)strtol(str, &end, base);
*memaddr = end;
}
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console)
{
rarch_system_info_t *system = runloop_get_system_info();
var->bank_id = -1;
if (console == CHEEVOS_CONSOLE_NINTENDO)
{
if (var->value >= 0x0800 && var->value < 0x2000)
{
CHEEVOS_LOG(CHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", var->value, var->value & 0x07ff);
var->value &= 0x07ff;
}
}
else if (console == CHEEVOS_CONSOLE_GAMEBOY_COLOR)
{
if (var->value >= 0xe000 && var->value <= 0xfdff)
{
CHEEVOS_LOG(CHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", var->value, var->value - 0x2000);
var->value -= 0x2000;
}
}
if (system->mmaps.num_descriptors != 0)
{
const rarch_memory_descriptor_t *desc = NULL;
const rarch_memory_descriptor_t *end = NULL;
/* Patch the address to correctly map it to the mmaps */
if (console == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE)
{
if (var->value < 0x8000) /* Internal RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x3000000);
var->value += 0x3000000;
}
else /* Work RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x2000000 - 0x8000);
var->value += 0x2000000 - 0x8000;
}
}
else if (console == CHEEVOS_CONSOLE_PC_ENGINE)
{
CHEEVOS_LOG(CHEEVOS_TAG "PCE memory address %X adjusted to %X\n", var->value, var->value + 0x1f0000);
var->value += 0x1f0000;
}
else if (console == CHEEVOS_CONSOLE_SUPER_NINTENDO)
{
if (var->value < 0x020000) /* Work RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x7e0000);
var->value += 0x7e0000;
}
else /* Save RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x006000 - 0x020000);
var->value += 0x006000 - 0x020000;
}
}
desc = system->mmaps.descriptors;
end = desc + system->mmaps.num_descriptors;
for (; desc < end; desc++)
{
if (((desc->core.start ^ var->value) & desc->core.select) == 0)
{
unsigned addr = var->value;
var->bank_id = (int)(desc - system->mmaps.descriptors);
var->value = (unsigned)cheevos_var_reduce(
(addr - desc->core.start) & desc->disconnect_mask,
desc->core.disconnect);
if (var->value >= desc->core.len)
var->value -= cheevos_var_highest_bit(var->value);
var->value += desc->core.offset;
CHEEVOS_LOG(CHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, var->bank_id + 1, var->value);
break;
}
}
}
else
{
unsigned i;
for (i = 0; i < 4; i++)
{
retro_ctx_memory_info_t meminfo;
switch (i)
{
case 0:
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
break;
case 1:
meminfo.id = RETRO_MEMORY_SAVE_RAM;
break;
case 2:
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
break;
case 3:
meminfo.id = RETRO_MEMORY_RTC;
break;
}
core_get_memory(&meminfo);
if (var->value < meminfo.size)
{
var->bank_id = i;
break;
}
/* HACK subtract the correct amount of bytes to reach the save RAM */
if (i == 0 && console == CHEEVOS_CONSOLE_NINTENDO)
var->value -= 0x6000;
else
var->value -= meminfo.size;
}
}
}
/*****************************************************************************
Testing
*****************************************************************************/
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var)
{
uint8_t* memory = NULL;
if (var->bank_id >= 0)
{
rarch_system_info_t* system = runloop_get_system_info();
if (system->mmaps.num_descriptors != 0)
memory = (uint8_t*)system->mmaps.descriptors[var->bank_id].core.ptr;
else
{
retro_ctx_memory_info_t meminfo = {NULL, 0, 0};
switch (var->bank_id)
{
case 0:
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
break;
case 1:
meminfo.id = RETRO_MEMORY_SAVE_RAM;
break;
case 2:
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
break;
case 3:
meminfo.id = RETRO_MEMORY_RTC;
break;
default:
CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
break;
}
core_get_memory(&meminfo);
memory = (uint8_t*)meminfo.data;
}
if (memory)
memory += var->value;
}
return memory;
}
unsigned cheevos_var_get_value(cheevos_var_t* var)
{
const uint8_t* memory = NULL;
unsigned value = 0;
switch (var->type)
{
case CHEEVOS_VAR_TYPE_VALUE_COMP:
value = var->value;
break;
case CHEEVOS_VAR_TYPE_ADDRESS:
case CHEEVOS_VAR_TYPE_DELTA_MEM:
memory = cheevos_var_get_memory(var);
if (memory)
{
value = memory[0];
switch (var->size)
{
case CHEEVOS_VAR_SIZE_BIT_0:
value &= 1;
break;
case CHEEVOS_VAR_SIZE_BIT_1:
value = (value >> 1) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_2:
value = (value >> 2) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_3:
value = (value >> 3) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_4:
value = (value >> 4) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_5:
value = (value >> 5) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_6:
value = (value >> 6) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_7:
value = (value >> 7) & 1;
break;
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
value &= 0x0f;
break;
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
value = (value >> 4) & 0x0f;
break;
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
break;
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
value |= memory[1] << 8;
break;
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
value |= memory[1] << 8;
value |= memory[2] << 16;
value |= memory[3] << 24;
break;
}
}
if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
{
unsigned previous = var->previous;
var->previous = value;
value = previous;
}
break;
case CHEEVOS_VAR_TYPE_DYNAMIC_VAR:
/* We shouldn't get here... */
break;
}
if(var->is_bcd)
return (((value >> 4) & 0xf) * 10) + (value & 0xf);
return value;
}
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2017 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <stdint.h>
#include <libretro.h>
#include "var.h"
#include "../retroarch.h"
#include "../core.h"
#include "../verbosity.h"
/*****************************************************************************
Parsing
*****************************************************************************/
static cheevos_var_size_t cheevos_var_parse_prefix(const char** memaddr)
{
/* Careful not to use ABCDEF here, this denotes part of an actual variable! */
const char* str = *memaddr;
cheevos_var_size_t size;
switch (toupper((unsigned char)*str++))
{
case 'M':
size = CHEEVOS_VAR_SIZE_BIT_0;
break;
case 'N':
size = CHEEVOS_VAR_SIZE_BIT_1;
break;
case 'O':
size = CHEEVOS_VAR_SIZE_BIT_2;
break;
case 'P':
size = CHEEVOS_VAR_SIZE_BIT_3;
break;
case 'Q':
size = CHEEVOS_VAR_SIZE_BIT_4;
break;
case 'R':
size = CHEEVOS_VAR_SIZE_BIT_5;
break;
case 'S':
size = CHEEVOS_VAR_SIZE_BIT_6;
break;
case 'T':
size = CHEEVOS_VAR_SIZE_BIT_7;
break;
case 'L':
size = CHEEVOS_VAR_SIZE_NIBBLE_LOWER;
break;
case 'U':
size = CHEEVOS_VAR_SIZE_NIBBLE_UPPER;
break;
case 'H':
size = CHEEVOS_VAR_SIZE_EIGHT_BITS;
break;
case 'X':
size = CHEEVOS_VAR_SIZE_THIRTYTWO_BITS;
break;
default:
str--;
/* fall through */
case ' ':
size = CHEEVOS_VAR_SIZE_SIXTEEN_BITS;
break;
}
*memaddr = str;
return size;
}
static size_t cheevos_var_reduce(size_t addr, size_t mask)
{
while (mask)
{
size_t tmp = (mask - 1) & ~mask;
addr = (addr & tmp) | ((addr >> 1) & ~tmp);
mask = (mask & (mask - 1)) >> 1;
}
return addr;
}
static size_t cheevos_var_highest_bit(size_t n)
{
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
return n ^ (n >> 1);
}
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr)
{
char *end = NULL;
const char *str = *memaddr;
unsigned base = 16;
var->is_bcd = false;
if (toupper((unsigned char)*str) == 'D' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
{
/* d0x + 4 hex digits */
str += 3;
var->type = CHEEVOS_VAR_TYPE_DELTA_MEM;
}
else if (toupper((unsigned char)*str) == 'B' && str[1] == '0' && toupper((unsigned char)str[2]) == 'X')
{
/* b0x (binary-coded decimal) */
str += 3;
var->is_bcd = true;
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
}
else if (*str == '0' && toupper((unsigned char)str[1]) == 'X')
{
/* 0x + 4 hex digits */
str += 2;
var->type = CHEEVOS_VAR_TYPE_ADDRESS;
}
else
{
var->type = CHEEVOS_VAR_TYPE_VALUE_COMP;
if (toupper((unsigned char)*str) == 'H')
str++;
else
{
if (toupper((unsigned char)*str) == 'V')
str++;
base = 10;
}
}
if (var->type != CHEEVOS_VAR_TYPE_VALUE_COMP)
{
var->size = cheevos_var_parse_prefix(&str);
}
var->value = (unsigned)strtol(str, &end, base);
*memaddr = end;
}
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console)
{
rarch_system_info_t *system = runloop_get_system_info();
var->bank_id = -1;
if (console == CHEEVOS_CONSOLE_NINTENDO)
{
if (var->value >= 0x0800 && var->value < 0x2000)
{
CHEEVOS_LOG(CHEEVOS_TAG "NES memory address in mirrorred RAM %X, adjusted to %X\n", var->value, var->value & 0x07ff);
var->value &= 0x07ff;
}
}
else if (console == CHEEVOS_CONSOLE_GAMEBOY_COLOR)
{
if (var->value >= 0xe000 && var->value <= 0xfdff)
{
CHEEVOS_LOG(CHEEVOS_TAG "GBC memory address in echo RAM %X, adjusted to %X\n", var->value, var->value - 0x2000);
var->value -= 0x2000;
}
}
if (system->mmaps.num_descriptors != 0)
{
const rarch_memory_descriptor_t *desc = NULL;
const rarch_memory_descriptor_t *end = NULL;
/* Patch the address to correctly map it to the mmaps */
if (console == CHEEVOS_CONSOLE_GAMEBOY_ADVANCE)
{
if (var->value < 0x8000) /* Internal RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x3000000);
var->value += 0x3000000;
}
else /* Work RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "GBA memory address %X adjusted to %X\n", var->value, var->value + 0x2000000 - 0x8000);
var->value += 0x2000000 - 0x8000;
}
}
else if (console == CHEEVOS_CONSOLE_PC_ENGINE)
{
CHEEVOS_LOG(CHEEVOS_TAG "PCE memory address %X adjusted to %X\n", var->value, var->value + 0x1f0000);
var->value += 0x1f0000;
}
else if (console == CHEEVOS_CONSOLE_SUPER_NINTENDO)
{
if (var->value < 0x020000) /* Work RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x7e0000);
var->value += 0x7e0000;
}
else /* Save RAM */
{
CHEEVOS_LOG(CHEEVOS_TAG "SNES memory address %X adjusted to %X\n", var->value, var->value + 0x006000 - 0x020000);
var->value += 0x006000 - 0x020000;
}
}
desc = system->mmaps.descriptors;
end = desc + system->mmaps.num_descriptors;
for (; desc < end; desc++)
{
if (((desc->core.start ^ var->value) & desc->core.select) == 0)
{
unsigned addr = var->value;
var->bank_id = (int)(desc - system->mmaps.descriptors);
var->value = (unsigned)cheevos_var_reduce(
(addr - desc->core.start) & desc->disconnect_mask,
desc->core.disconnect);
if (var->value >= desc->core.len)
var->value -= cheevos_var_highest_bit(var->value);
var->value += desc->core.offset;
CHEEVOS_LOG(CHEEVOS_TAG "address %X set to descriptor %d at offset %X\n", addr, var->bank_id + 1, var->value);
break;
}
}
}
else
{
unsigned i;
for (i = 0; i < 4; i++)
{
retro_ctx_memory_info_t meminfo;
switch (i)
{
case 0:
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
break;
case 1:
meminfo.id = RETRO_MEMORY_SAVE_RAM;
break;
case 2:
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
break;
case 3:
meminfo.id = RETRO_MEMORY_RTC;
break;
}
core_get_memory(&meminfo);
if (var->value < meminfo.size)
{
var->bank_id = i;
break;
}
/* HACK subtract the correct amount of bytes to reach the save RAM */
if (i == 0 && console == CHEEVOS_CONSOLE_NINTENDO)
var->value -= 0x6000;
else
var->value -= meminfo.size;
}
}
}
/*****************************************************************************
Testing
*****************************************************************************/
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var)
{
uint8_t* memory = NULL;
if (var->bank_id >= 0)
{
rarch_system_info_t* system = runloop_get_system_info();
if (system->mmaps.num_descriptors != 0)
memory = (uint8_t*)system->mmaps.descriptors[var->bank_id].core.ptr;
else
{
retro_ctx_memory_info_t meminfo = {NULL, 0, 0};
switch (var->bank_id)
{
case 0:
meminfo.id = RETRO_MEMORY_SYSTEM_RAM;
break;
case 1:
meminfo.id = RETRO_MEMORY_SAVE_RAM;
break;
case 2:
meminfo.id = RETRO_MEMORY_VIDEO_RAM;
break;
case 3:
meminfo.id = RETRO_MEMORY_RTC;
break;
default:
CHEEVOS_ERR(CHEEVOS_TAG "invalid bank id: %s\n", var->bank_id);
break;
}
core_get_memory(&meminfo);
memory = (uint8_t*)meminfo.data;
}
if (memory)
memory += var->value;
}
return memory;
}
unsigned cheevos_var_get_value(cheevos_var_t* var)
{
const uint8_t* memory = NULL;
unsigned value = 0;
switch (var->type)
{
case CHEEVOS_VAR_TYPE_VALUE_COMP:
value = var->value;
break;
case CHEEVOS_VAR_TYPE_ADDRESS:
case CHEEVOS_VAR_TYPE_DELTA_MEM:
memory = cheevos_var_get_memory(var);
if (memory)
{
value = memory[0];
switch (var->size)
{
case CHEEVOS_VAR_SIZE_BIT_0:
value &= 1;
break;
case CHEEVOS_VAR_SIZE_BIT_1:
value = (value >> 1) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_2:
value = (value >> 2) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_3:
value = (value >> 3) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_4:
value = (value >> 4) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_5:
value = (value >> 5) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_6:
value = (value >> 6) & 1;
break;
case CHEEVOS_VAR_SIZE_BIT_7:
value = (value >> 7) & 1;
break;
case CHEEVOS_VAR_SIZE_NIBBLE_LOWER:
value &= 0x0f;
break;
case CHEEVOS_VAR_SIZE_NIBBLE_UPPER:
value = (value >> 4) & 0x0f;
break;
case CHEEVOS_VAR_SIZE_EIGHT_BITS:
break;
case CHEEVOS_VAR_SIZE_SIXTEEN_BITS:
value |= memory[1] << 8;
break;
case CHEEVOS_VAR_SIZE_THIRTYTWO_BITS:
value |= memory[1] << 8;
value |= memory[2] << 16;
value |= memory[3] << 24;
break;
}
}
if (var->type == CHEEVOS_VAR_TYPE_DELTA_MEM)
{
unsigned previous = var->previous;
var->previous = value;
value = previous;
}
break;
case CHEEVOS_VAR_TYPE_DYNAMIC_VAR:
/* We shouldn't get here... */
break;
}
if(var->is_bcd)
return (((value >> 4) & 0xf) * 10) + (value & 0xf);
return value;
}

View File

@ -1,78 +1,78 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2018 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_VAR_H
#define __RARCH_CHEEVOS_VAR_H
#include <stdint.h>
#include "cheevos.h"
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef enum
{
CHEEVOS_VAR_SIZE_BIT_0 = 0,
CHEEVOS_VAR_SIZE_BIT_1,
CHEEVOS_VAR_SIZE_BIT_2,
CHEEVOS_VAR_SIZE_BIT_3,
CHEEVOS_VAR_SIZE_BIT_4,
CHEEVOS_VAR_SIZE_BIT_5,
CHEEVOS_VAR_SIZE_BIT_6,
CHEEVOS_VAR_SIZE_BIT_7,
CHEEVOS_VAR_SIZE_NIBBLE_LOWER,
CHEEVOS_VAR_SIZE_NIBBLE_UPPER,
/* Byte, */
CHEEVOS_VAR_SIZE_EIGHT_BITS, /* =Byte, */
CHEEVOS_VAR_SIZE_SIXTEEN_BITS,
CHEEVOS_VAR_SIZE_THIRTYTWO_BITS
} cheevos_var_size_t;
typedef enum
{
/* compare to the value of a live address in RAM */
CHEEVOS_VAR_TYPE_ADDRESS = 0,
/* a number. assume 32 bit */
CHEEVOS_VAR_TYPE_VALUE_COMP,
/* the value last known at this address. */
CHEEVOS_VAR_TYPE_DELTA_MEM,
/* a custom user-set variable */
CHEEVOS_VAR_TYPE_DYNAMIC_VAR
} cheevos_var_type_t;
typedef struct
{
cheevos_var_size_t size;
cheevos_var_type_t type;
int bank_id;
bool is_bcd;
unsigned value;
unsigned previous;
} cheevos_var_t;
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr);
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console);
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var);
unsigned cheevos_var_get_value(cheevos_var_t* var);
RETRO_END_DECLS
#endif /* __RARCH_CHEEVOS_VAR_H */
/* RetroArch - A frontend for libretro.
* Copyright (C) 2015-2018 - Andre Leiradella
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RARCH_CHEEVOS_VAR_H
#define __RARCH_CHEEVOS_VAR_H
#include <stdint.h>
#include "cheevos.h"
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef enum
{
CHEEVOS_VAR_SIZE_BIT_0 = 0,
CHEEVOS_VAR_SIZE_BIT_1,
CHEEVOS_VAR_SIZE_BIT_2,
CHEEVOS_VAR_SIZE_BIT_3,
CHEEVOS_VAR_SIZE_BIT_4,
CHEEVOS_VAR_SIZE_BIT_5,
CHEEVOS_VAR_SIZE_BIT_6,
CHEEVOS_VAR_SIZE_BIT_7,
CHEEVOS_VAR_SIZE_NIBBLE_LOWER,
CHEEVOS_VAR_SIZE_NIBBLE_UPPER,
/* Byte, */
CHEEVOS_VAR_SIZE_EIGHT_BITS, /* =Byte, */
CHEEVOS_VAR_SIZE_SIXTEEN_BITS,
CHEEVOS_VAR_SIZE_THIRTYTWO_BITS
} cheevos_var_size_t;
typedef enum
{
/* compare to the value of a live address in RAM */
CHEEVOS_VAR_TYPE_ADDRESS = 0,
/* a number. assume 32 bit */
CHEEVOS_VAR_TYPE_VALUE_COMP,
/* the value last known at this address. */
CHEEVOS_VAR_TYPE_DELTA_MEM,
/* a custom user-set variable */
CHEEVOS_VAR_TYPE_DYNAMIC_VAR
} cheevos_var_type_t;
typedef struct
{
cheevos_var_size_t size;
cheevos_var_type_t type;
int bank_id;
bool is_bcd;
unsigned value;
unsigned previous;
} cheevos_var_t;
void cheevos_var_parse(cheevos_var_t* var, const char** memaddr);
void cheevos_var_patch_addr(cheevos_var_t* var, cheevos_console_t console);
uint8_t* cheevos_var_get_memory(const cheevos_var_t* var);
unsigned cheevos_var_get_value(cheevos_var_t* var);
RETRO_END_DECLS
#endif /* __RARCH_CHEEVOS_VAR_H */

View File

@ -1,9 +1,9 @@
#ifndef EXEC_3DSX_H
#define EXEC_3DSX_H
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
int exec_3dsx_no_path_in_args(const char* path, const char** args);
int exec_3dsx(const char* path, const char** args);
#ifndef EXEC_3DSX_H
#define EXEC_3DSX_H
//since 3dsx programs are not guaranteed access to the OS, the 3dsx bootloader run by the exploit must run the next program
//your program must have no extra threads running when this is called, these limits do not apply to exec_cia
int exec_3dsx_no_path_in_args(const char* path, const char** args);
int exec_3dsx(const char* path, const char** args);
#endif

View File

@ -1,6 +1,6 @@
#ifndef EXEC_CIA_H
#define EXEC_CIA_H
int exec_cia(const char* path, const char** args);
#ifndef EXEC_CIA_H
#define EXEC_CIA_H
int exec_cia(const char* path, const char** args);
#endif

View File

@ -1,95 +1,95 @@
#pragma once
// C stdlib includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
// 3DS includes
#include <3ds.h>
#define ENTRY_ARGBUFSIZE 0x400
#define NUM_SERVICESTHATMATTER 5
typedef enum
{
StrId_Loading = 0,
StrId_Directory,
StrId_DefaultLongTitle,
StrId_DefaultPublisher,
StrId_IOError,
StrId_CouldNotOpenFile,
StrId_NoAppsFound_Title,
StrId_NoAppsFound_Msg,
StrId_Reboot,
StrId_ReturnToHome,
StrId_TitleSelector,
StrId_ErrorReadingTitleMetadata,
StrId_NoTitlesFound,
StrId_SelectTitle,
StrId_NoTargetTitleSupport,
StrId_MissingTargetTitle,
StrId_NetLoader,
StrId_NetLoaderUnavailable,
StrId_NetLoaderOffline,
StrId_NetLoaderError,
StrId_NetLoaderActive,
StrId_NetLoaderTransferring,
StrId_Max,
} StrId;
typedef struct
{
char* dst;
u32 buf[ENTRY_ARGBUFSIZE/sizeof(u32)];
} argData_s;
typedef struct
{
bool scanned;
u32 sectionSizes[3];
bool servicesThatMatter[NUM_SERVICESTHATMATTER];
} executableMetadata_s;
typedef struct
{
u32 num;
u32 text_end;
u32 data_address;
u32 data_size;
u32 processLinearOffset;
u32 processHookAddress;
u32 processAppCodeAddress;
u32 processHookTidLow, processHookTidHigh;
u32 mediatype;
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
} memmap_header_t;
typedef struct
{
u32 src, dst, size;
} memmap_entry_t;
typedef struct
{
memmap_header_t header;
memmap_entry_t map[];
} memmap_t;
#define memmapSize(m) (sizeof(memmap_header_t) + sizeof(memmap_entry_t)*(m)->header.num)
#include "launch.h"
#pragma once
// C stdlib includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
// 3DS includes
#include <3ds.h>
#define ENTRY_ARGBUFSIZE 0x400
#define NUM_SERVICESTHATMATTER 5
typedef enum
{
StrId_Loading = 0,
StrId_Directory,
StrId_DefaultLongTitle,
StrId_DefaultPublisher,
StrId_IOError,
StrId_CouldNotOpenFile,
StrId_NoAppsFound_Title,
StrId_NoAppsFound_Msg,
StrId_Reboot,
StrId_ReturnToHome,
StrId_TitleSelector,
StrId_ErrorReadingTitleMetadata,
StrId_NoTitlesFound,
StrId_SelectTitle,
StrId_NoTargetTitleSupport,
StrId_MissingTargetTitle,
StrId_NetLoader,
StrId_NetLoaderUnavailable,
StrId_NetLoaderOffline,
StrId_NetLoaderError,
StrId_NetLoaderActive,
StrId_NetLoaderTransferring,
StrId_Max,
} StrId;
typedef struct
{
char* dst;
u32 buf[ENTRY_ARGBUFSIZE/sizeof(u32)];
} argData_s;
typedef struct
{
bool scanned;
u32 sectionSizes[3];
bool servicesThatMatter[NUM_SERVICESTHATMATTER];
} executableMetadata_s;
typedef struct
{
u32 num;
u32 text_end;
u32 data_address;
u32 data_size;
u32 processLinearOffset;
u32 processHookAddress;
u32 processAppCodeAddress;
u32 processHookTidLow, processHookTidHigh;
u32 mediatype;
bool capabilities[0x10]; // {socuAccess, csndAccess, qtmAccess, nfcAccess, httpcAccess, reserved...}
} memmap_header_t;
typedef struct
{
u32 src, dst, size;
} memmap_entry_t;
typedef struct
{
memmap_header_t header;
memmap_entry_t map[];
} memmap_t;
#define memmapSize(m) (sizeof(memmap_header_t) + sizeof(memmap_entry_t)*(m)->header.num)
#include "launch.h"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,86 +1,86 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2019 - Hans-Kristian Arntzen
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SLANG_REFLECTION_HPP_
#define SLANG_REFLECTION_HPP_
#include <string>
#include <unordered_map>
#include <stdint.h>
#include <spirv_cross.hpp>
struct slang_texture_semantic_meta
{
size_t ubo_offset = 0;
size_t push_constant_offset = 0;
unsigned binding = 0;
uint32_t stage_mask = 0;
bool texture = false;
bool uniform = false;
bool push_constant = false;
};
struct slang_semantic_meta
{
size_t ubo_offset = 0;
size_t push_constant_offset = 0;
unsigned num_components = 0;
bool uniform = false;
bool push_constant = false;
};
struct slang_texture_semantic_map
{
slang_texture_semantic semantic;
unsigned index;
};
struct slang_semantic_map
{
slang_semantic semantic;
unsigned index;
};
struct slang_reflection
{
slang_reflection();
size_t ubo_size = 0;
size_t push_constant_size = 0;
unsigned ubo_binding = 0;
uint32_t ubo_stage_mask = 0;
uint32_t push_constant_stage_mask = 0;
std::vector<slang_texture_semantic_meta> semantic_textures[SLANG_NUM_TEXTURE_SEMANTICS];
slang_semantic_meta semantics[SLANG_NUM_SEMANTICS];
std::vector<slang_semantic_meta> semantic_float_parameters;
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_map = nullptr;
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_uniform_map = nullptr;
const std::unordered_map<std::string, slang_semantic_map> *semantic_map = nullptr;
unsigned pass_number = 0;
};
bool slang_reflect_spirv(const std::vector<uint32_t> &vertex,
const std::vector<uint32_t> &fragment,
slang_reflection *reflection);
bool slang_reflect(const spirv_cross::Compiler &vertex_compiler, const spirv_cross::Compiler &fragment_compiler,
const spirv_cross::ShaderResources &vertex, const spirv_cross::ShaderResources &fragment,
slang_reflection *reflection);
#endif
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2019 - Hans-Kristian Arntzen
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SLANG_REFLECTION_HPP_
#define SLANG_REFLECTION_HPP_
#include <string>
#include <unordered_map>
#include <stdint.h>
#include <spirv_cross.hpp>
struct slang_texture_semantic_meta
{
size_t ubo_offset = 0;
size_t push_constant_offset = 0;
unsigned binding = 0;
uint32_t stage_mask = 0;
bool texture = false;
bool uniform = false;
bool push_constant = false;
};
struct slang_semantic_meta
{
size_t ubo_offset = 0;
size_t push_constant_offset = 0;
unsigned num_components = 0;
bool uniform = false;
bool push_constant = false;
};
struct slang_texture_semantic_map
{
slang_texture_semantic semantic;
unsigned index;
};
struct slang_semantic_map
{
slang_semantic semantic;
unsigned index;
};
struct slang_reflection
{
slang_reflection();
size_t ubo_size = 0;
size_t push_constant_size = 0;
unsigned ubo_binding = 0;
uint32_t ubo_stage_mask = 0;
uint32_t push_constant_stage_mask = 0;
std::vector<slang_texture_semantic_meta> semantic_textures[SLANG_NUM_TEXTURE_SEMANTICS];
slang_semantic_meta semantics[SLANG_NUM_SEMANTICS];
std::vector<slang_semantic_meta> semantic_float_parameters;
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_map = nullptr;
const std::unordered_map<std::string, slang_texture_semantic_map> *texture_semantic_uniform_map = nullptr;
const std::unordered_map<std::string, slang_semantic_map> *semantic_map = nullptr;
unsigned pass_number = 0;
};
bool slang_reflect_spirv(const std::vector<uint32_t> &vertex,
const std::vector<uint32_t> &fragment,
slang_reflection *reflection);
bool slang_reflect(const spirv_cross::Compiler &vertex_compiler, const spirv_cross::Compiler &fragment_compiler,
const spirv_cross::ShaderResources &vertex, const spirv_cross::ShaderResources &fragment,
slang_reflection *reflection);
#endif

View File

@ -1,326 +1,326 @@
/*==========================================================================;
*
* Copyright (C) Microsoft Corporation. All Rights Reserved.
*
* File: d3d8caps.h
* Content: Direct3D capabilities include file
*
***************************************************************************/
#ifndef _D3D8CAPS_H
#define _D3D8CAPS_H
#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION 0x0800
#endif /* DIRECT3D_VERSION */
/* include this file content only if compiling for DX8 interfaces */
#if(DIRECT3D_VERSION >= 0x0800)
#if defined(_X86_) || defined(_IA64_)
#pragma pack(4)
#endif
typedef struct _D3DCAPS8
{
/* Device Info */
D3DDEVTYPE DeviceType;
UINT AdapterOrdinal;
/* Caps from DX7 Draw */
DWORD Caps;
DWORD Caps2;
DWORD Caps3;
DWORD PresentationIntervals;
/* Cursor Caps */
DWORD CursorCaps;
/* 3D Device Caps */
DWORD DevCaps;
DWORD PrimitiveMiscCaps;
DWORD RasterCaps;
DWORD ZCmpCaps;
DWORD SrcBlendCaps;
DWORD DestBlendCaps;
DWORD AlphaCmpCaps;
DWORD ShadeCaps;
DWORD TextureCaps;
DWORD TextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DTexture8's */
DWORD CubeTextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DCubeTexture8's */
DWORD VolumeTextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DVolumeTexture8's */
DWORD TextureAddressCaps; /* D3DPTADDRESSCAPS for IDirect3DTexture8's */
DWORD VolumeTextureAddressCaps; /* D3DPTADDRESSCAPS for IDirect3DVolumeTexture8's */
DWORD LineCaps; /* D3DLINECAPS */
DWORD MaxTextureWidth, MaxTextureHeight;
DWORD MaxVolumeExtent;
DWORD MaxTextureRepeat;
DWORD MaxTextureAspectRatio;
DWORD MaxAnisotropy;
float MaxVertexW;
float GuardBandLeft;
float GuardBandTop;
float GuardBandRight;
float GuardBandBottom;
float ExtentsAdjust;
DWORD StencilCaps;
DWORD FVFCaps;
DWORD TextureOpCaps;
DWORD MaxTextureBlendStages;
DWORD MaxSimultaneousTextures;
DWORD VertexProcessingCaps;
DWORD MaxActiveLights;
DWORD MaxUserClipPlanes;
DWORD MaxVertexBlendMatrices;
DWORD MaxVertexBlendMatrixIndex;
float MaxPointSize;
DWORD MaxPrimitiveCount; /* max number of primitives per DrawPrimitive call */
DWORD MaxVertexIndex;
DWORD MaxStreams;
DWORD MaxStreamStride; /* max stride for SetStreamSource */
DWORD VertexShaderVersion;
DWORD MaxVertexShaderConst; /* number of vertex shader constant registers */
DWORD PixelShaderVersion;
float MaxPixelShaderValue; /* max value of pixel shader arithmetic component */
} D3DCAPS8;
/* BIT DEFINES FOR D3DCAPS8 DWORD MEMBERS */
/* Caps */
#define D3DCAPS_READ_SCANLINE 0x00020000L
/* Caps2 */
#define D3DCAPS2_NO2DDURING3DSCENE 0x00000002L
#define D3DCAPS2_FULLSCREENGAMMA 0x00020000L
#define D3DCAPS2_CANRENDERWINDOWED 0x00080000L
#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L
#define D3DCAPS2_RESERVED 0x02000000L
#define D3DCAPS2_CANMANAGERESOURCE 0x10000000L
#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L
/* Caps3 */
#define D3DCAPS3_RESERVED 0x8000001fL
/* Indicates that the device can respect the ALPHABLENDENABLE render state
* when fullscreen while using the FLIP or DISCARD swap effect.
* COPY and COPYVSYNC swap effects work whether or not this flag is set.
*/
#define D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD 0x00000020L
/* PresentationIntervals */
#define D3DPRESENT_INTERVAL_DEFAULT 0x00000000L
#define D3DPRESENT_INTERVAL_ONE 0x00000001L
#define D3DPRESENT_INTERVAL_TWO 0x00000002L
#define D3DPRESENT_INTERVAL_THREE 0x00000004L
#define D3DPRESENT_INTERVAL_FOUR 0x00000008L
#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L
/* CursorCaps */
/* Driver supports HW color cursor in at least hi-res modes(height >=400) */
#define D3DCURSORCAPS_COLOR 0x00000001L
/* Driver supports HW cursor also in low-res modes(height < 400) */
#define D3DCURSORCAPS_LOWRES 0x00000002L
/* DevCaps */
#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */
#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */
#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */
#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */
#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */
#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */
#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */
#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */
#define D3DDEVCAPS_DRAWPRIMITIVES2 0x00002000L /* Device can support DrawPrimitives2 */
#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */
#define D3DDEVCAPS_DRAWPRIMITIVES2EX 0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/
#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */
#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */
#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */
#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */
#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */
#define D3DDEVCAPS_RTPATCHES 0x00400000L /* Device supports Rect and Tri patches */
#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */
#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */
/* PrimitiveMiscCaps */
#define D3DPMISCCAPS_MASKZ 0x00000002L
#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L
#define D3DPMISCCAPS_CULLNONE 0x00000010L
#define D3DPMISCCAPS_CULLCW 0x00000020L
#define D3DPMISCCAPS_CULLCCW 0x00000040L
#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L
#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */
#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */
#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */
#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */
#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */
/* LineCaps */
#define D3DLINECAPS_TEXTURE 0x00000001L
#define D3DLINECAPS_ZTEST 0x00000002L
#define D3DLINECAPS_BLEND 0x00000004L
#define D3DLINECAPS_ALPHACMP 0x00000008L
#define D3DLINECAPS_FOG 0x00000010L
/* RasterCaps */
#define D3DPRASTERCAPS_DITHER 0x00000001L
#define D3DPRASTERCAPS_PAT 0x00000008L
#define D3DPRASTERCAPS_ZTEST 0x00000010L
#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L
#define D3DPRASTERCAPS_FOGTABLE 0x00000100L
#define D3DPRASTERCAPS_ANTIALIASEDGES 0x00001000L
#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L
#define D3DPRASTERCAPS_ZBIAS 0x00004000L
#define D3DPRASTERCAPS_ZBUFFERLESSHSR 0x00008000L
#define D3DPRASTERCAPS_FOGRANGE 0x00010000L
#define D3DPRASTERCAPS_ANISOTROPY 0x00020000L
#define D3DPRASTERCAPS_WBUFFER 0x00040000L
#define D3DPRASTERCAPS_WFOG 0x00100000L
#define D3DPRASTERCAPS_ZFOG 0x00200000L
#define D3DPRASTERCAPS_COLORPERSPECTIVE 0x00400000L /* Device iterates colors perspective correct */
#define D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE 0x00800000L
/* ZCmpCaps, AlphaCmpCaps */
#define D3DPCMPCAPS_NEVER 0x00000001L
#define D3DPCMPCAPS_LESS 0x00000002L
#define D3DPCMPCAPS_EQUAL 0x00000004L
#define D3DPCMPCAPS_LESSEQUAL 0x00000008L
#define D3DPCMPCAPS_GREATER 0x00000010L
#define D3DPCMPCAPS_NOTEQUAL 0x00000020L
#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L
#define D3DPCMPCAPS_ALWAYS 0x00000080L
/* SourceBlendCaps, DestBlendCaps */
#define D3DPBLENDCAPS_ZERO 0x00000001L
#define D3DPBLENDCAPS_ONE 0x00000002L
#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L
#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L
#define D3DPBLENDCAPS_SRCALPHA 0x00000010L
#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L
#define D3DPBLENDCAPS_DESTALPHA 0x00000040L
#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L
#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L
#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L
#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L
#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L
#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L
/* ShadeCaps */
#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L
#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L
#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L
#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L
/* TextureCaps */
#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L /* Perspective-correct texturing is supported */
#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */
#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */
#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */
#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L /* Texture indices are not scaled by the texture size prior to interpolation */
#define D3DPTEXTURECAPS_ALPHAPALETTE 0x00000080L /* Device can draw alpha from texture palettes */
/* Device can use non-POW2 textures if:
* 1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage
* 2) D3DRS_WRAP(N) is zero for this texture's coordinates
* 3) mip mapping is not enabled (use magnification filter only)
*/
#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L
#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */
#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */
#define D3DPTEXTURECAPS_VOLUMEMAP 0x00002000L /* Device can do volume textures */
#define D3DPTEXTURECAPS_MIPMAP 0x00004000L /* Device can do mipmapped textures */
#define D3DPTEXTURECAPS_MIPVOLUMEMAP 0x00008000L /* Device can do mipmapped volume textures */
#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */
#define D3DPTEXTURECAPS_CUBEMAP_POW2 0x00020000L /* Device requires that cubemaps be power-of-2 dimension */
#define D3DPTEXTURECAPS_VOLUMEMAP_POW2 0x00040000L /* Device requires that volume maps be power-of-2 dimension */
/* TextureFilterCaps */
#define D3DPTFILTERCAPS_MINFPOINT 0x00000100L /* Min Filter */
#define D3DPTFILTERCAPS_MINFLINEAR 0x00000200L
#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L
#define D3DPTFILTERCAPS_MIPFPOINT 0x00010000L /* Mip Filter */
#define D3DPTFILTERCAPS_MIPFLINEAR 0x00020000L
#define D3DPTFILTERCAPS_MAGFPOINT 0x01000000L /* Mag Filter */
#define D3DPTFILTERCAPS_MAGFLINEAR 0x02000000L
#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L
#define D3DPTFILTERCAPS_MAGFAFLATCUBIC 0x08000000L
#define D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC 0x10000000L
/* TextureAddressCaps */
#define D3DPTADDRESSCAPS_WRAP 0x00000001L
#define D3DPTADDRESSCAPS_MIRROR 0x00000002L
#define D3DPTADDRESSCAPS_CLAMP 0x00000004L
#define D3DPTADDRESSCAPS_BORDER 0x00000008L
#define D3DPTADDRESSCAPS_INDEPENDENTUV 0x00000010L
#define D3DPTADDRESSCAPS_MIRRORONCE 0x00000020L
/* StencilCaps */
#define D3DSTENCILCAPS_KEEP 0x00000001L
#define D3DSTENCILCAPS_ZERO 0x00000002L
#define D3DSTENCILCAPS_REPLACE 0x00000004L
#define D3DSTENCILCAPS_INCRSAT 0x00000008L
#define D3DSTENCILCAPS_DECRSAT 0x00000010L
#define D3DSTENCILCAPS_INVERT 0x00000020L
#define D3DSTENCILCAPS_INCR 0x00000040L
#define D3DSTENCILCAPS_DECR 0x00000080L
/* TextureOpCaps */
#define D3DTEXOPCAPS_DISABLE 0x00000001L
#define D3DTEXOPCAPS_SELECTARG1 0x00000002L
#define D3DTEXOPCAPS_SELECTARG2 0x00000004L
#define D3DTEXOPCAPS_MODULATE 0x00000008L
#define D3DTEXOPCAPS_MODULATE2X 0x00000010L
#define D3DTEXOPCAPS_MODULATE4X 0x00000020L
#define D3DTEXOPCAPS_ADD 0x00000040L
#define D3DTEXOPCAPS_ADDSIGNED 0x00000080L
#define D3DTEXOPCAPS_ADDSIGNED2X 0x00000100L
#define D3DTEXOPCAPS_SUBTRACT 0x00000200L
#define D3DTEXOPCAPS_ADDSMOOTH 0x00000400L
#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA 0x00000800L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHA 0x00001000L
#define D3DTEXOPCAPS_BLENDFACTORALPHA 0x00002000L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 0x00004000L
#define D3DTEXOPCAPS_BLENDCURRENTALPHA 0x00008000L
#define D3DTEXOPCAPS_PREMODULATE 0x00010000L
#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 0x00020000L
#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 0x00040000L
#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 0x00080000L
#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 0x00100000L
#define D3DTEXOPCAPS_BUMPENVMAP 0x00200000L
#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 0x00400000L
#define D3DTEXOPCAPS_DOTPRODUCT3 0x00800000L
#define D3DTEXOPCAPS_MULTIPLYADD 0x01000000L
#define D3DTEXOPCAPS_LERP 0x02000000L
/* FVFCaps */
#define D3DFVFCAPS_TEXCOORDCOUNTMASK 0x0000ffffL /* mask for texture coordinate count field */
#define D3DFVFCAPS_DONOTSTRIPELEMENTS 0x00080000L /* Device prefers that vertex elements not be stripped */
#define D3DFVFCAPS_PSIZE 0x00100000L /* Device can receive point size */
/* VertexProcessingCaps */
#define D3DVTXPCAPS_TEXGEN 0x00000001L /* device can do texgen */
#define D3DVTXPCAPS_MATERIALSOURCE7 0x00000002L /* device can do DX7-level colormaterialsource ops */
#define D3DVTXPCAPS_DIRECTIONALLIGHTS 0x00000008L /* device can do directional lights */
#define D3DVTXPCAPS_POSITIONALLIGHTS 0x00000010L /* device can do positional lights (includes point and spot) */
#define D3DVTXPCAPS_LOCALVIEWER 0x00000020L /* device can do local viewer */
#define D3DVTXPCAPS_TWEENING 0x00000040L /* device can do vertex tweening */
#define D3DVTXPCAPS_NO_VSDT_UBYTE4 0x00000080L /* device does not support D3DVSDT_UBYTE4 */
#pragma pack()
#endif /* (DIRECT3D_VERSION >= 0x0800) */
#endif /* _D3D8CAPS_H_ */
/*==========================================================================;
*
* Copyright (C) Microsoft Corporation. All Rights Reserved.
*
* File: d3d8caps.h
* Content: Direct3D capabilities include file
*
***************************************************************************/
#ifndef _D3D8CAPS_H
#define _D3D8CAPS_H
#ifndef DIRECT3D_VERSION
#define DIRECT3D_VERSION 0x0800
#endif /* DIRECT3D_VERSION */
/* include this file content only if compiling for DX8 interfaces */
#if(DIRECT3D_VERSION >= 0x0800)
#if defined(_X86_) || defined(_IA64_)
#pragma pack(4)
#endif
typedef struct _D3DCAPS8
{
/* Device Info */
D3DDEVTYPE DeviceType;
UINT AdapterOrdinal;
/* Caps from DX7 Draw */
DWORD Caps;
DWORD Caps2;
DWORD Caps3;
DWORD PresentationIntervals;
/* Cursor Caps */
DWORD CursorCaps;
/* 3D Device Caps */
DWORD DevCaps;
DWORD PrimitiveMiscCaps;
DWORD RasterCaps;
DWORD ZCmpCaps;
DWORD SrcBlendCaps;
DWORD DestBlendCaps;
DWORD AlphaCmpCaps;
DWORD ShadeCaps;
DWORD TextureCaps;
DWORD TextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DTexture8's */
DWORD CubeTextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DCubeTexture8's */
DWORD VolumeTextureFilterCaps; /* D3DPTFILTERCAPS for IDirect3DVolumeTexture8's */
DWORD TextureAddressCaps; /* D3DPTADDRESSCAPS for IDirect3DTexture8's */
DWORD VolumeTextureAddressCaps; /* D3DPTADDRESSCAPS for IDirect3DVolumeTexture8's */
DWORD LineCaps; /* D3DLINECAPS */
DWORD MaxTextureWidth, MaxTextureHeight;
DWORD MaxVolumeExtent;
DWORD MaxTextureRepeat;
DWORD MaxTextureAspectRatio;
DWORD MaxAnisotropy;
float MaxVertexW;
float GuardBandLeft;
float GuardBandTop;
float GuardBandRight;
float GuardBandBottom;
float ExtentsAdjust;
DWORD StencilCaps;
DWORD FVFCaps;
DWORD TextureOpCaps;
DWORD MaxTextureBlendStages;
DWORD MaxSimultaneousTextures;
DWORD VertexProcessingCaps;
DWORD MaxActiveLights;
DWORD MaxUserClipPlanes;
DWORD MaxVertexBlendMatrices;
DWORD MaxVertexBlendMatrixIndex;
float MaxPointSize;
DWORD MaxPrimitiveCount; /* max number of primitives per DrawPrimitive call */
DWORD MaxVertexIndex;
DWORD MaxStreams;
DWORD MaxStreamStride; /* max stride for SetStreamSource */
DWORD VertexShaderVersion;
DWORD MaxVertexShaderConst; /* number of vertex shader constant registers */
DWORD PixelShaderVersion;
float MaxPixelShaderValue; /* max value of pixel shader arithmetic component */
} D3DCAPS8;
/* BIT DEFINES FOR D3DCAPS8 DWORD MEMBERS */
/* Caps */
#define D3DCAPS_READ_SCANLINE 0x00020000L
/* Caps2 */
#define D3DCAPS2_NO2DDURING3DSCENE 0x00000002L
#define D3DCAPS2_FULLSCREENGAMMA 0x00020000L
#define D3DCAPS2_CANRENDERWINDOWED 0x00080000L
#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L
#define D3DCAPS2_RESERVED 0x02000000L
#define D3DCAPS2_CANMANAGERESOURCE 0x10000000L
#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L
/* Caps3 */
#define D3DCAPS3_RESERVED 0x8000001fL
/* Indicates that the device can respect the ALPHABLENDENABLE render state
* when fullscreen while using the FLIP or DISCARD swap effect.
* COPY and COPYVSYNC swap effects work whether or not this flag is set.
*/
#define D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD 0x00000020L
/* PresentationIntervals */
#define D3DPRESENT_INTERVAL_DEFAULT 0x00000000L
#define D3DPRESENT_INTERVAL_ONE 0x00000001L
#define D3DPRESENT_INTERVAL_TWO 0x00000002L
#define D3DPRESENT_INTERVAL_THREE 0x00000004L
#define D3DPRESENT_INTERVAL_FOUR 0x00000008L
#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L
/* CursorCaps */
/* Driver supports HW color cursor in at least hi-res modes(height >=400) */
#define D3DCURSORCAPS_COLOR 0x00000001L
/* Driver supports HW cursor also in low-res modes(height < 400) */
#define D3DCURSORCAPS_LOWRES 0x00000002L
/* DevCaps */
#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */
#define D3DDEVCAPS_EXECUTEVIDEOMEMORY 0x00000020L /* Device can use execute buffers from video memory */
#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */
#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */
#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */
#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */
#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */
#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */
#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */
#define D3DDEVCAPS_DRAWPRIMITIVES2 0x00002000L /* Device can support DrawPrimitives2 */
#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */
#define D3DDEVCAPS_DRAWPRIMITIVES2EX 0x00008000L /* Device can support Extended DrawPrimitives2 i.e. DX7 compliant driver*/
#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */
#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */
#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */
#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */
#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */
#define D3DDEVCAPS_RTPATCHES 0x00400000L /* Device supports Rect and Tri patches */
#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */
#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */
/* PrimitiveMiscCaps */
#define D3DPMISCCAPS_MASKZ 0x00000002L
#define D3DPMISCCAPS_LINEPATTERNREP 0x00000004L
#define D3DPMISCCAPS_CULLNONE 0x00000010L
#define D3DPMISCCAPS_CULLCW 0x00000020L
#define D3DPMISCCAPS_CULLCCW 0x00000040L
#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L
#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */
#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */
#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */
#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */
#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */
/* LineCaps */
#define D3DLINECAPS_TEXTURE 0x00000001L
#define D3DLINECAPS_ZTEST 0x00000002L
#define D3DLINECAPS_BLEND 0x00000004L
#define D3DLINECAPS_ALPHACMP 0x00000008L
#define D3DLINECAPS_FOG 0x00000010L
/* RasterCaps */
#define D3DPRASTERCAPS_DITHER 0x00000001L
#define D3DPRASTERCAPS_PAT 0x00000008L
#define D3DPRASTERCAPS_ZTEST 0x00000010L
#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L
#define D3DPRASTERCAPS_FOGTABLE 0x00000100L
#define D3DPRASTERCAPS_ANTIALIASEDGES 0x00001000L
#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L
#define D3DPRASTERCAPS_ZBIAS 0x00004000L
#define D3DPRASTERCAPS_ZBUFFERLESSHSR 0x00008000L
#define D3DPRASTERCAPS_FOGRANGE 0x00010000L
#define D3DPRASTERCAPS_ANISOTROPY 0x00020000L
#define D3DPRASTERCAPS_WBUFFER 0x00040000L
#define D3DPRASTERCAPS_WFOG 0x00100000L
#define D3DPRASTERCAPS_ZFOG 0x00200000L
#define D3DPRASTERCAPS_COLORPERSPECTIVE 0x00400000L /* Device iterates colors perspective correct */
#define D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE 0x00800000L
/* ZCmpCaps, AlphaCmpCaps */
#define D3DPCMPCAPS_NEVER 0x00000001L
#define D3DPCMPCAPS_LESS 0x00000002L
#define D3DPCMPCAPS_EQUAL 0x00000004L
#define D3DPCMPCAPS_LESSEQUAL 0x00000008L
#define D3DPCMPCAPS_GREATER 0x00000010L
#define D3DPCMPCAPS_NOTEQUAL 0x00000020L
#define D3DPCMPCAPS_GREATEREQUAL 0x00000040L
#define D3DPCMPCAPS_ALWAYS 0x00000080L
/* SourceBlendCaps, DestBlendCaps */
#define D3DPBLENDCAPS_ZERO 0x00000001L
#define D3DPBLENDCAPS_ONE 0x00000002L
#define D3DPBLENDCAPS_SRCCOLOR 0x00000004L
#define D3DPBLENDCAPS_INVSRCCOLOR 0x00000008L
#define D3DPBLENDCAPS_SRCALPHA 0x00000010L
#define D3DPBLENDCAPS_INVSRCALPHA 0x00000020L
#define D3DPBLENDCAPS_DESTALPHA 0x00000040L
#define D3DPBLENDCAPS_INVDESTALPHA 0x00000080L
#define D3DPBLENDCAPS_DESTCOLOR 0x00000100L
#define D3DPBLENDCAPS_INVDESTCOLOR 0x00000200L
#define D3DPBLENDCAPS_SRCALPHASAT 0x00000400L
#define D3DPBLENDCAPS_BOTHSRCALPHA 0x00000800L
#define D3DPBLENDCAPS_BOTHINVSRCALPHA 0x00001000L
/* ShadeCaps */
#define D3DPSHADECAPS_COLORGOURAUDRGB 0x00000008L
#define D3DPSHADECAPS_SPECULARGOURAUDRGB 0x00000200L
#define D3DPSHADECAPS_ALPHAGOURAUDBLEND 0x00004000L
#define D3DPSHADECAPS_FOGGOURAUD 0x00080000L
/* TextureCaps */
#define D3DPTEXTURECAPS_PERSPECTIVE 0x00000001L /* Perspective-correct texturing is supported */
#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */
#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */
#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */
#define D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE 0x00000040L /* Texture indices are not scaled by the texture size prior to interpolation */
#define D3DPTEXTURECAPS_ALPHAPALETTE 0x00000080L /* Device can draw alpha from texture palettes */
/* Device can use non-POW2 textures if:
* 1) D3DTEXTURE_ADDRESS is set to CLAMP for this texture's stage
* 2) D3DRS_WRAP(N) is zero for this texture's coordinates
* 3) mip mapping is not enabled (use magnification filter only)
*/
#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L
#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */
#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */
#define D3DPTEXTURECAPS_VOLUMEMAP 0x00002000L /* Device can do volume textures */
#define D3DPTEXTURECAPS_MIPMAP 0x00004000L /* Device can do mipmapped textures */
#define D3DPTEXTURECAPS_MIPVOLUMEMAP 0x00008000L /* Device can do mipmapped volume textures */
#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */
#define D3DPTEXTURECAPS_CUBEMAP_POW2 0x00020000L /* Device requires that cubemaps be power-of-2 dimension */
#define D3DPTEXTURECAPS_VOLUMEMAP_POW2 0x00040000L /* Device requires that volume maps be power-of-2 dimension */
/* TextureFilterCaps */
#define D3DPTFILTERCAPS_MINFPOINT 0x00000100L /* Min Filter */
#define D3DPTFILTERCAPS_MINFLINEAR 0x00000200L
#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L
#define D3DPTFILTERCAPS_MIPFPOINT 0x00010000L /* Mip Filter */
#define D3DPTFILTERCAPS_MIPFLINEAR 0x00020000L
#define D3DPTFILTERCAPS_MAGFPOINT 0x01000000L /* Mag Filter */
#define D3DPTFILTERCAPS_MAGFLINEAR 0x02000000L
#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L
#define D3DPTFILTERCAPS_MAGFAFLATCUBIC 0x08000000L
#define D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC 0x10000000L
/* TextureAddressCaps */
#define D3DPTADDRESSCAPS_WRAP 0x00000001L
#define D3DPTADDRESSCAPS_MIRROR 0x00000002L
#define D3DPTADDRESSCAPS_CLAMP 0x00000004L
#define D3DPTADDRESSCAPS_BORDER 0x00000008L
#define D3DPTADDRESSCAPS_INDEPENDENTUV 0x00000010L
#define D3DPTADDRESSCAPS_MIRRORONCE 0x00000020L
/* StencilCaps */
#define D3DSTENCILCAPS_KEEP 0x00000001L
#define D3DSTENCILCAPS_ZERO 0x00000002L
#define D3DSTENCILCAPS_REPLACE 0x00000004L
#define D3DSTENCILCAPS_INCRSAT 0x00000008L
#define D3DSTENCILCAPS_DECRSAT 0x00000010L
#define D3DSTENCILCAPS_INVERT 0x00000020L
#define D3DSTENCILCAPS_INCR 0x00000040L
#define D3DSTENCILCAPS_DECR 0x00000080L
/* TextureOpCaps */
#define D3DTEXOPCAPS_DISABLE 0x00000001L
#define D3DTEXOPCAPS_SELECTARG1 0x00000002L
#define D3DTEXOPCAPS_SELECTARG2 0x00000004L
#define D3DTEXOPCAPS_MODULATE 0x00000008L
#define D3DTEXOPCAPS_MODULATE2X 0x00000010L
#define D3DTEXOPCAPS_MODULATE4X 0x00000020L
#define D3DTEXOPCAPS_ADD 0x00000040L
#define D3DTEXOPCAPS_ADDSIGNED 0x00000080L
#define D3DTEXOPCAPS_ADDSIGNED2X 0x00000100L
#define D3DTEXOPCAPS_SUBTRACT 0x00000200L
#define D3DTEXOPCAPS_ADDSMOOTH 0x00000400L
#define D3DTEXOPCAPS_BLENDDIFFUSEALPHA 0x00000800L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHA 0x00001000L
#define D3DTEXOPCAPS_BLENDFACTORALPHA 0x00002000L
#define D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 0x00004000L
#define D3DTEXOPCAPS_BLENDCURRENTALPHA 0x00008000L
#define D3DTEXOPCAPS_PREMODULATE 0x00010000L
#define D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 0x00020000L
#define D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 0x00040000L
#define D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 0x00080000L
#define D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA 0x00100000L
#define D3DTEXOPCAPS_BUMPENVMAP 0x00200000L
#define D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 0x00400000L
#define D3DTEXOPCAPS_DOTPRODUCT3 0x00800000L
#define D3DTEXOPCAPS_MULTIPLYADD 0x01000000L
#define D3DTEXOPCAPS_LERP 0x02000000L
/* FVFCaps */
#define D3DFVFCAPS_TEXCOORDCOUNTMASK 0x0000ffffL /* mask for texture coordinate count field */
#define D3DFVFCAPS_DONOTSTRIPELEMENTS 0x00080000L /* Device prefers that vertex elements not be stripped */
#define D3DFVFCAPS_PSIZE 0x00100000L /* Device can receive point size */
/* VertexProcessingCaps */
#define D3DVTXPCAPS_TEXGEN 0x00000001L /* device can do texgen */
#define D3DVTXPCAPS_MATERIALSOURCE7 0x00000002L /* device can do DX7-level colormaterialsource ops */
#define D3DVTXPCAPS_DIRECTIONALLIGHTS 0x00000008L /* device can do directional lights */
#define D3DVTXPCAPS_POSITIONALLIGHTS 0x00000010L /* device can do positional lights (includes point and spot) */
#define D3DVTXPCAPS_LOCALVIEWER 0x00000020L /* device can do local viewer */
#define D3DVTXPCAPS_TWEENING 0x00000040L /* device can do vertex tweening */
#define D3DVTXPCAPS_NO_VSDT_UBYTE4 0x00000080L /* device does not support D3DVSDT_UBYTE4 */
#pragma pack()
#endif /* (DIRECT3D_VERSION >= 0x0800) */
#endif /* _D3D8CAPS_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,364 +1,364 @@
/* CRT SwitchRes Core
* Copyright (C) 2018 Alphanu / Ben Templeman.
*
* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "video_driver.h"
#include "video_crt_switch.h"
#include "video_display_server.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#if defined(HAVE_VIDEOCORE)
#include "include/userland/interface/vmcs_host/vc_vchi_gencmd.h"
static void crt_rpi_switch(int width, int height, float hz);
#endif
static unsigned ra_core_width = 0;
static unsigned ra_core_height = 0;
static unsigned ra_tmp_width = 0;
static unsigned ra_tmp_height = 0;
static unsigned ra_set_core_hz = 0;
static unsigned orig_width = 0;
static unsigned orig_height = 0;
static int crt_center_adjust = 0;
static bool first_run = true;
static float ra_tmp_core_hz = 0.0f;
static float fly_aspect = 0.0f;
static float ra_core_hz = 0.0f;
static unsigned crt_index = 0;
static void crt_check_first_run(void)
{
if (!first_run)
return;
first_run = false;
}
static void switch_crt_hz(void)
{
if (ra_core_hz == ra_tmp_core_hz)
return;
/* set hz float to an int for windows switching */
if (ra_core_hz < 100)
{
if (ra_core_hz < 53)
ra_set_core_hz = 50;
if (ra_core_hz >= 53 && ra_core_hz < 57)
ra_set_core_hz = 55;
if (ra_core_hz >= 57)
ra_set_core_hz = 60;
}
if (ra_core_hz > 100)
{
if (ra_core_hz < 106)
ra_set_core_hz = 120;
if (ra_core_hz >= 106 && ra_core_hz < 114)
ra_set_core_hz = 110;
if (ra_core_hz >= 114)
ra_set_core_hz = 120;
}
video_monitor_set_refresh_rate(ra_set_core_hz);
ra_tmp_core_hz = ra_core_hz;
}
void crt_aspect_ratio_switch(unsigned width, unsigned height)
{
/* send aspect float to videeo_driver */
fly_aspect = (float)width / height;
video_driver_set_aspect_ratio_value((float)fly_aspect);
}
static void switch_res_crt(unsigned width, unsigned height)
{
video_display_server_set_resolution(width, height,
ra_set_core_hz, ra_core_hz, crt_center_adjust, crt_index);
#if defined(HAVE_VIDEOCORE)
crt_rpi_switch(width, height, ra_core_hz);
video_monitor_set_refresh_rate(ra_core_hz);
crt_switch_driver_reinit();
#endif
video_driver_apply_state_changes();
}
/* Create correct aspect to fit video if resolution does not exist */
static void crt_screen_setup_aspect(unsigned width, unsigned height)
{
#if defined(HAVE_VIDEOCORE)
if (height > 300)
height = height/2;
#endif
switch_crt_hz();
/* get original resolution of core */
if (height == 4)
{
/* detect menu only */
if (width < 1920)
width = 320;
height = 240;
crt_aspect_ratio_switch(width, height);
}
if (height < 200 && height != 144)
{
crt_aspect_ratio_switch(width, height);
height = 200;
}
if (height > 200)
crt_aspect_ratio_switch(width, height);
if (height == 144 && ra_set_core_hz == 50)
{
height = 288;
crt_aspect_ratio_switch(width, height);
}
if (height > 200 && height < 224)
{
crt_aspect_ratio_switch(width, height);
height = 224;
}
if (height > 224 && height < 240)
{
crt_aspect_ratio_switch(width, height);
height = 240;
}
if (height > 240 && height < 255)
{
crt_aspect_ratio_switch(width, height);
height = 254;
}
if (height == 528 && ra_set_core_hz == 60)
{
crt_aspect_ratio_switch(width, height);
height = 480;
}
if (height >= 240 && height < 255 && ra_set_core_hz == 55)
{
crt_aspect_ratio_switch(width, height);
height = 254;
}
switch_res_crt(width, height);
}
void crt_switch_res_core(unsigned width, unsigned height,
float hz, unsigned crt_mode,
int crt_switch_center_adjust, int monitor_index)
{
/* ra_core_hz float passed from within
* void video_driver_monitor_adjust_system_rates(void) */
ra_core_width = width;
ra_core_height = height;
ra_core_hz = hz;
crt_center_adjust = crt_switch_center_adjust;
crt_index = monitor_index;
if (crt_mode == 2)
{
if (hz > 53)
ra_core_hz = hz * 2;
if (hz <= 53)
ra_core_hz = 120.0f;
}
crt_check_first_run();
/* Detect resolution change and switch */
if (
(ra_tmp_height != ra_core_height) ||
(ra_core_width != ra_tmp_width)
)
crt_screen_setup_aspect(width, height);
ra_tmp_height = ra_core_height;
ra_tmp_width = ra_core_width;
/* Check if aspect is correct, if notchange */
if (video_driver_get_aspect_ratio() != fly_aspect)
{
video_driver_set_aspect_ratio_value((float)fly_aspect);
video_driver_apply_state_changes();
}
}
void crt_video_restore(void)
{
if (first_run)
return;
first_run = true;
}
#if defined(HAVE_VIDEOCORE)
static void crt_rpi_switch(int width, int height, float hz)
{
char buffer[1024];
VCHI_INSTANCE_T vchi_instance;
VCHI_CONNECTION_T *vchi_connection = NULL;
static char output[250] = {0};
static char output1[250] = {0};
static char output2[250] = {0};
static char set_hdmi[250] = {0};
static char set_hdmi_timing[250] = {0};
int i = 0;
int hfp = 0;
int hsp = 0;
int hbp = 0;
int vfp = 0;
int vsp = 0;
int vbp = 0;
int hmax = 0;
int vmax = 0;
int pdefault = 8;
int pwidth = 0;
float roundw = 0.0f;
float roundh = 0.0f;
float pixel_clock = 0;
int ip_flag = 0;
/* set core refresh from hz */
video_monitor_set_refresh_rate(hz);
/* following code is the mode line generator */
pwidth = width;
if (height < 400 && width > 400)
pwidth = width / 2;
roundw = roundf((float)pwidth / (float)height * 100) / 100;
if (height > width)
roundw = roundf((float)height / (float)width * 100) / 100;
if (roundw > 1.35)
roundw = 1.25;
if (roundw < 1.20)
roundw = 1.34;
hfp = width * 0.065;
hsp = width * 0.1433-hfp;
hbp = width * 0.3-hsp-hfp;
if (height < 241)
vmax = 261;
if (height < 241 && hz > 56 && hz < 58)
vmax = 280;
if (height < 241 && hz < 55)
vmax = 313;
if (height > 250 && height < 260 && hz > 54)
vmax = 296;
if (height > 250 && height < 260 && hz > 52 && hz < 54)
vmax = 285;
if (height > 250 && height < 260 && hz < 52)
vmax = 313;
if (height > 260 && height < 300)
vmax = 318;
if (height > 400 && hz > 56)
vmax = 533;
if (height > 520 && hz < 57)
vmax = 580;
if (height > 300 && hz < 56)
vmax = 615;
if (height > 500 && hz < 56)
vmax = 624;
if (height > 300)
pdefault = pdefault * 2;
vfp = (height + ((vmax - height) / 2) - pdefault) - height;
if (height < 300)
vsp = vfp + 3; /* needs to be 3 for progressive */
if (height > 300)
vsp = vfp + 6; /* needs to be 6 for interlaced */
vsp = 3;
vbp = (vmax-height)-vsp-vfp;
hmax = width+hfp+hsp+hbp;
if (height < 300)
{
pixel_clock = (hmax * vmax * hz) ;
ip_flag = 0;
}
if (height > 300)
{
pixel_clock = (hmax * vmax * (hz/2)) /2 ;
ip_flag = 1;
}
/* above code is the modeline generator */
snprintf(set_hdmi_timing, sizeof(set_hdmi_timing),
"hdmi_timings %d 1 %d %d %d %d 1 %d %d %d 0 0 0 %f %d %f 1 ",
width, hfp, hsp, hbp, height, vfp,vsp, vbp,
hz, ip_flag, pixel_clock);
vcos_init ();
vchi_initialise (&vchi_instance);
vchi_connect (NULL, 0, vchi_instance);
vc_vchi_gencmd_init (vchi_instance, &vchi_connection, 1);
vc_gencmd (buffer, sizeof (buffer), set_hdmi_timing);
vc_gencmd_stop ();
vchi_disconnect (vchi_instance);
snprintf(output1, sizeof(output1),
"tvservice -e \"DMT 87\" > /dev/null");
system(output1);
snprintf(output2, sizeof(output1),
"fbset -g %d %d %d %d 24 > /dev/null",
width, height, width, height);
system(output2);
}
#endif
/* CRT SwitchRes Core
* Copyright (C) 2018 Alphanu / Ben Templeman.
*
* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "video_driver.h"
#include "video_crt_switch.h"
#include "video_display_server.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#if defined(HAVE_VIDEOCORE)
#include "include/userland/interface/vmcs_host/vc_vchi_gencmd.h"
static void crt_rpi_switch(int width, int height, float hz);
#endif
static unsigned ra_core_width = 0;
static unsigned ra_core_height = 0;
static unsigned ra_tmp_width = 0;
static unsigned ra_tmp_height = 0;
static unsigned ra_set_core_hz = 0;
static unsigned orig_width = 0;
static unsigned orig_height = 0;
static int crt_center_adjust = 0;
static bool first_run = true;
static float ra_tmp_core_hz = 0.0f;
static float fly_aspect = 0.0f;
static float ra_core_hz = 0.0f;
static unsigned crt_index = 0;
static void crt_check_first_run(void)
{
if (!first_run)
return;
first_run = false;
}
static void switch_crt_hz(void)
{
if (ra_core_hz == ra_tmp_core_hz)
return;
/* set hz float to an int for windows switching */
if (ra_core_hz < 100)
{
if (ra_core_hz < 53)
ra_set_core_hz = 50;
if (ra_core_hz >= 53 && ra_core_hz < 57)
ra_set_core_hz = 55;
if (ra_core_hz >= 57)
ra_set_core_hz = 60;
}
if (ra_core_hz > 100)
{
if (ra_core_hz < 106)
ra_set_core_hz = 120;
if (ra_core_hz >= 106 && ra_core_hz < 114)
ra_set_core_hz = 110;
if (ra_core_hz >= 114)
ra_set_core_hz = 120;
}
video_monitor_set_refresh_rate(ra_set_core_hz);
ra_tmp_core_hz = ra_core_hz;
}
void crt_aspect_ratio_switch(unsigned width, unsigned height)
{
/* send aspect float to videeo_driver */
fly_aspect = (float)width / height;
video_driver_set_aspect_ratio_value((float)fly_aspect);
}
static void switch_res_crt(unsigned width, unsigned height)
{
video_display_server_set_resolution(width, height,
ra_set_core_hz, ra_core_hz, crt_center_adjust, crt_index);
#if defined(HAVE_VIDEOCORE)
crt_rpi_switch(width, height, ra_core_hz);
video_monitor_set_refresh_rate(ra_core_hz);
crt_switch_driver_reinit();
#endif
video_driver_apply_state_changes();
}
/* Create correct aspect to fit video if resolution does not exist */
static void crt_screen_setup_aspect(unsigned width, unsigned height)
{
#if defined(HAVE_VIDEOCORE)
if (height > 300)
height = height/2;
#endif
switch_crt_hz();
/* get original resolution of core */
if (height == 4)
{
/* detect menu only */
if (width < 1920)
width = 320;
height = 240;
crt_aspect_ratio_switch(width, height);
}
if (height < 200 && height != 144)
{
crt_aspect_ratio_switch(width, height);
height = 200;
}
if (height > 200)
crt_aspect_ratio_switch(width, height);
if (height == 144 && ra_set_core_hz == 50)
{
height = 288;
crt_aspect_ratio_switch(width, height);
}
if (height > 200 && height < 224)
{
crt_aspect_ratio_switch(width, height);
height = 224;
}
if (height > 224 && height < 240)
{
crt_aspect_ratio_switch(width, height);
height = 240;
}
if (height > 240 && height < 255)
{
crt_aspect_ratio_switch(width, height);
height = 254;
}
if (height == 528 && ra_set_core_hz == 60)
{
crt_aspect_ratio_switch(width, height);
height = 480;
}
if (height >= 240 && height < 255 && ra_set_core_hz == 55)
{
crt_aspect_ratio_switch(width, height);
height = 254;
}
switch_res_crt(width, height);
}
void crt_switch_res_core(unsigned width, unsigned height,
float hz, unsigned crt_mode,
int crt_switch_center_adjust, int monitor_index)
{
/* ra_core_hz float passed from within
* void video_driver_monitor_adjust_system_rates(void) */
ra_core_width = width;
ra_core_height = height;
ra_core_hz = hz;
crt_center_adjust = crt_switch_center_adjust;
crt_index = monitor_index;
if (crt_mode == 2)
{
if (hz > 53)
ra_core_hz = hz * 2;
if (hz <= 53)
ra_core_hz = 120.0f;
}
crt_check_first_run();
/* Detect resolution change and switch */
if (
(ra_tmp_height != ra_core_height) ||
(ra_core_width != ra_tmp_width)
)
crt_screen_setup_aspect(width, height);
ra_tmp_height = ra_core_height;
ra_tmp_width = ra_core_width;
/* Check if aspect is correct, if notchange */
if (video_driver_get_aspect_ratio() != fly_aspect)
{
video_driver_set_aspect_ratio_value((float)fly_aspect);
video_driver_apply_state_changes();
}
}
void crt_video_restore(void)
{
if (first_run)
return;
first_run = true;
}
#if defined(HAVE_VIDEOCORE)
static void crt_rpi_switch(int width, int height, float hz)
{
char buffer[1024];
VCHI_INSTANCE_T vchi_instance;
VCHI_CONNECTION_T *vchi_connection = NULL;
static char output[250] = {0};
static char output1[250] = {0};
static char output2[250] = {0};
static char set_hdmi[250] = {0};
static char set_hdmi_timing[250] = {0};
int i = 0;
int hfp = 0;
int hsp = 0;
int hbp = 0;
int vfp = 0;
int vsp = 0;
int vbp = 0;
int hmax = 0;
int vmax = 0;
int pdefault = 8;
int pwidth = 0;
float roundw = 0.0f;
float roundh = 0.0f;
float pixel_clock = 0;
int ip_flag = 0;
/* set core refresh from hz */
video_monitor_set_refresh_rate(hz);
/* following code is the mode line generator */
pwidth = width;
if (height < 400 && width > 400)
pwidth = width / 2;
roundw = roundf((float)pwidth / (float)height * 100) / 100;
if (height > width)
roundw = roundf((float)height / (float)width * 100) / 100;
if (roundw > 1.35)
roundw = 1.25;
if (roundw < 1.20)
roundw = 1.34;
hfp = width * 0.065;
hsp = width * 0.1433-hfp;
hbp = width * 0.3-hsp-hfp;
if (height < 241)
vmax = 261;
if (height < 241 && hz > 56 && hz < 58)
vmax = 280;
if (height < 241 && hz < 55)
vmax = 313;
if (height > 250 && height < 260 && hz > 54)
vmax = 296;
if (height > 250 && height < 260 && hz > 52 && hz < 54)
vmax = 285;
if (height > 250 && height < 260 && hz < 52)
vmax = 313;
if (height > 260 && height < 300)
vmax = 318;
if (height > 400 && hz > 56)
vmax = 533;
if (height > 520 && hz < 57)
vmax = 580;
if (height > 300 && hz < 56)
vmax = 615;
if (height > 500 && hz < 56)
vmax = 624;
if (height > 300)
pdefault = pdefault * 2;
vfp = (height + ((vmax - height) / 2) - pdefault) - height;
if (height < 300)
vsp = vfp + 3; /* needs to be 3 for progressive */
if (height > 300)
vsp = vfp + 6; /* needs to be 6 for interlaced */
vsp = 3;
vbp = (vmax-height)-vsp-vfp;
hmax = width+hfp+hsp+hbp;
if (height < 300)
{
pixel_clock = (hmax * vmax * hz) ;
ip_flag = 0;
}
if (height > 300)
{
pixel_clock = (hmax * vmax * (hz/2)) /2 ;
ip_flag = 1;
}
/* above code is the modeline generator */
snprintf(set_hdmi_timing, sizeof(set_hdmi_timing),
"hdmi_timings %d 1 %d %d %d %d 1 %d %d %d 0 0 0 %f %d %f 1 ",
width, hfp, hsp, hbp, height, vfp,vsp, vbp,
hz, ip_flag, pixel_clock);
vcos_init ();
vchi_initialise (&vchi_instance);
vchi_connect (NULL, 0, vchi_instance);
vc_vchi_gencmd_init (vchi_instance, &vchi_connection, 1);
vc_gencmd (buffer, sizeof (buffer), set_hdmi_timing);
vc_gencmd_stop ();
vchi_disconnect (vchi_instance);
snprintf(output1, sizeof(output1),
"tvservice -e \"DMT 87\" > /dev/null");
system(output1);
snprintf(output2, sizeof(output1),
"fbset -g %d %d %d %d 24 > /dev/null",
width, height, width, height);
system(output2);
}
#endif

View File

@ -1,38 +1,38 @@
/* CRT SwitchRes Core
* Copyright (C) 2018 Alphanu / Ben Templeman.
*
* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __VIDEO_CRT_SWITCH_H__
#define __VIDEO_CRT_SWITCH_H__
#include <stdint.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust, int monitor_index);
void crt_aspect_ratio_switch(unsigned width, unsigned height);
void crt_video_restore(void);
RETRO_END_DECLS
#endif
/* CRT SwitchRes Core
* Copyright (C) 2018 Alphanu / Ben Templeman.
*
* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __VIDEO_CRT_SWITCH_H__
#define __VIDEO_CRT_SWITCH_H__
#include <stdint.h>
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust, int monitor_index);
void crt_aspect_ratio_switch(unsigned width, unsigned height);
void crt_video_restore(void);
RETRO_END_DECLS
#endif

View File

@ -1,112 +1,112 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "video_display_server.h"
#include "video_driver.h"
#include "../verbosity.h"
static const video_display_server_t *current_display_server = &dispserv_null;
static void *current_display_server_data = NULL;
const char *video_display_server_get_ident(void)
{
if (!current_display_server)
return "null";
return current_display_server->ident;
}
void* video_display_server_init(void)
{
enum rarch_display_type type = video_driver_display_type_get();
video_display_server_destroy();
switch (type)
{
case RARCH_DISPLAY_WIN32:
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
current_display_server = &dispserv_win32;
#endif
break;
case RARCH_DISPLAY_X11:
#if defined(HAVE_X11)
current_display_server = &dispserv_x11;
#endif
break;
default:
current_display_server = &dispserv_null;
break;
}
current_display_server_data = current_display_server->init();
RARCH_LOG("[Video]: Found display server: %s\n",
current_display_server->ident);
return current_display_server_data;
}
void video_display_server_destroy(void)
{
if (current_display_server && current_display_server->destroy)
if (current_display_server_data)
current_display_server->destroy(current_display_server_data);
}
bool video_display_server_set_window_opacity(unsigned opacity)
{
if (current_display_server && current_display_server->set_window_opacity)
return current_display_server->set_window_opacity(current_display_server_data, opacity);
return false;
}
bool video_display_server_set_window_progress(int progress, bool finished)
{
if (current_display_server && current_display_server->set_window_progress)
return current_display_server->set_window_progress(current_display_server_data, progress, finished);
return false;
}
bool video_display_server_set_window_decorations(bool on)
{
if (current_display_server && current_display_server->set_window_decorations)
return current_display_server->set_window_decorations(current_display_server_data, on);
return false;
}
bool video_display_server_set_resolution(unsigned width, unsigned height,
int int_hz, float hz, int center, int monitor_index)
{
if (current_display_server && current_display_server->set_resolution)
return current_display_server->set_resolution(current_display_server_data, width, height, int_hz, hz, center, monitor_index);
return false;
}
void *video_display_server_get_resolution_list(unsigned *size)
{
if (current_display_server && current_display_server->get_resolution_list)
return current_display_server->get_resolution_list(current_display_server_data, size);
return NULL;
}
const char *video_display_server_get_output_options(void)
{
if (current_display_server && current_display_server->get_output_options)
return current_display_server->get_output_options(current_display_server_data);
return NULL;
}
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "video_display_server.h"
#include "video_driver.h"
#include "../verbosity.h"
static const video_display_server_t *current_display_server = &dispserv_null;
static void *current_display_server_data = NULL;
const char *video_display_server_get_ident(void)
{
if (!current_display_server)
return "null";
return current_display_server->ident;
}
void* video_display_server_init(void)
{
enum rarch_display_type type = video_driver_display_type_get();
video_display_server_destroy();
switch (type)
{
case RARCH_DISPLAY_WIN32:
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
current_display_server = &dispserv_win32;
#endif
break;
case RARCH_DISPLAY_X11:
#if defined(HAVE_X11)
current_display_server = &dispserv_x11;
#endif
break;
default:
current_display_server = &dispserv_null;
break;
}
current_display_server_data = current_display_server->init();
RARCH_LOG("[Video]: Found display server: %s\n",
current_display_server->ident);
return current_display_server_data;
}
void video_display_server_destroy(void)
{
if (current_display_server && current_display_server->destroy)
if (current_display_server_data)
current_display_server->destroy(current_display_server_data);
}
bool video_display_server_set_window_opacity(unsigned opacity)
{
if (current_display_server && current_display_server->set_window_opacity)
return current_display_server->set_window_opacity(current_display_server_data, opacity);
return false;
}
bool video_display_server_set_window_progress(int progress, bool finished)
{
if (current_display_server && current_display_server->set_window_progress)
return current_display_server->set_window_progress(current_display_server_data, progress, finished);
return false;
}
bool video_display_server_set_window_decorations(bool on)
{
if (current_display_server && current_display_server->set_window_decorations)
return current_display_server->set_window_decorations(current_display_server_data, on);
return false;
}
bool video_display_server_set_resolution(unsigned width, unsigned height,
int int_hz, float hz, int center, int monitor_index)
{
if (current_display_server && current_display_server->set_resolution)
return current_display_server->set_resolution(current_display_server_data, width, height, int_hz, hz, center, monitor_index);
return false;
}
void *video_display_server_get_resolution_list(unsigned *size)
{
if (current_display_server && current_display_server->get_resolution_list)
return current_display_server->get_resolution_list(current_display_server_data, size);
return NULL;
}
const char *video_display_server_get_output_options(void)
{
if (current_display_server && current_display_server->get_output_options)
return current_display_server->get_output_options(current_display_server_data);
return NULL;
}

View File

@ -1,77 +1,77 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __VIDEO_DISPLAY_SERVER__H
#define __VIDEO_DISPLAY_SERVER__H
#include <retro_common_api.h>
#include <boolean.h>
RETRO_BEGIN_DECLS
typedef struct video_display_config
{
unsigned width;
unsigned height;
unsigned bpp;
unsigned refreshrate;
unsigned idx;
bool current;
} video_display_config_t;
typedef struct video_display_server
{
void *(*init)(void);
void (*destroy)(void *data);
bool (*set_window_opacity)(void *data, unsigned opacity);
bool (*set_window_progress)(void *data, int progress, bool finished);
bool (*set_window_decorations)(void *data, bool on);
bool (*set_resolution)(void *data, unsigned width,
unsigned height, int int_hz, float hz, int center, int monitor_index);
void *(*get_resolution_list)(void *data,
unsigned *size);
const char *(*get_output_options)(void *data);
const char *ident;
} video_display_server_t;
void* video_display_server_init(void);
void video_display_server_destroy(void);
bool video_display_server_set_window_opacity(unsigned opacity);
bool video_display_server_set_window_progress(int progress, bool finished);
bool video_display_server_set_window_decorations(bool on);
bool video_display_server_set_resolution(
unsigned width, unsigned height,
int int_hz, float hz, int center, int monitor_index);
void *video_display_server_get_resolution_list(unsigned *size);
const char *video_display_server_get_output_options(void);
const char *video_display_server_get_ident(void);
extern const video_display_server_t dispserv_win32;
extern const video_display_server_t dispserv_x11;
extern const video_display_server_t dispserv_null;
RETRO_END_DECLS
#endif
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __VIDEO_DISPLAY_SERVER__H
#define __VIDEO_DISPLAY_SERVER__H
#include <retro_common_api.h>
#include <boolean.h>
RETRO_BEGIN_DECLS
typedef struct video_display_config
{
unsigned width;
unsigned height;
unsigned bpp;
unsigned refreshrate;
unsigned idx;
bool current;
} video_display_config_t;
typedef struct video_display_server
{
void *(*init)(void);
void (*destroy)(void *data);
bool (*set_window_opacity)(void *data, unsigned opacity);
bool (*set_window_progress)(void *data, int progress, bool finished);
bool (*set_window_decorations)(void *data, bool on);
bool (*set_resolution)(void *data, unsigned width,
unsigned height, int int_hz, float hz, int center, int monitor_index);
void *(*get_resolution_list)(void *data,
unsigned *size);
const char *(*get_output_options)(void *data);
const char *ident;
} video_display_server_t;
void* video_display_server_init(void);
void video_display_server_destroy(void);
bool video_display_server_set_window_opacity(unsigned opacity);
bool video_display_server_set_window_progress(int progress, bool finished);
bool video_display_server_set_window_decorations(bool on);
bool video_display_server_set_resolution(
unsigned width, unsigned height,
int int_hz, float hz, int center, int monitor_index);
void *video_display_server_get_resolution_list(unsigned *size);
const char *video_display_server_get_output_options(void);
const char *video_display_server_get_ident(void);
extern const video_display_server_t dispserv_win32;
extern const video_display_server_t dispserv_x11;
extern const video_display_server_t dispserv_null;
RETRO_END_DECLS
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
filter = normal2x
filter = normal2x

View File

@ -1,68 +1,68 @@

#ifdef WANT_GLSLANG
#ifdef _MSC_VER
#include <compat/msvc.h>
#ifdef strtoull
#undef strtoull
#endif
#endif
#include "../deps/glslang/glslang.cpp"
#include "../deps/glslang/glslang/SPIRV/disassemble.cpp"
#include "../deps/glslang/glslang/SPIRV/doc.cpp"
#include "../deps/glslang/glslang/SPIRV/GlslangToSpv.cpp"
#include "../deps/glslang/glslang/SPIRV/InReadableOrder.cpp"
#include "../deps/glslang/glslang/SPIRV/Logger.cpp"
#include "../deps/glslang/glslang/SPIRV/SpvBuilder.cpp"
#include "../deps/glslang/glslang/SPIRV/SPVRemapper.cpp"
#include "../deps/glslang/glslang/glslang/GenericCodeGen/CodeGen.cpp"
#include "../deps/glslang/glslang/glslang/GenericCodeGen/Link.cpp"
#include "../deps/glslang/glslang/OGLCompilersDLL/InitializeDll.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/attribute.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Constant.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/glslang_tab.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/InfoSink.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Initialize.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Intermediate.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/intermOut.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/IntermTraverse.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/iomapper.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/limits.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/linkValidate.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/parseConst.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ParseContextBase.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ParseHelper.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/PoolAlloc.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/propagateNoContraction.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/reflection.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/RemoveTree.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Scan.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ShaderLang.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/SymbolTable.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Versions.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp"
#ifdef __APPLE__
#include "../deps/glslang/glslang/glslang/OSDependent/Unix/ossource.cpp"
#endif
#if defined(ENABLE_HLSL)
#include "../deps/glslang/glslang/hlsl/hlslAttributes.cpp"
#include "../deps/glslang/glslang/hlsl/hlslGrammar.cpp"
#include "../deps/glslang/glslang/hlsl/hlslOpMap.cpp"
#include "../deps/glslang/glslang/hlsl/hlslParseables.cpp"
#include "../deps/glslang/glslang/hlsl/hlslParseHelper.cpp"
#include "../deps/glslang/glslang/hlsl/hlslScanContext.cpp"
#include "../deps/glslang/glslang/hlsl/hlslTokenStream.cpp"
#endif
#endif

#ifdef WANT_GLSLANG
#ifdef _MSC_VER
#include <compat/msvc.h>
#ifdef strtoull
#undef strtoull
#endif
#endif
#include "../deps/glslang/glslang.cpp"
#include "../deps/glslang/glslang/SPIRV/disassemble.cpp"
#include "../deps/glslang/glslang/SPIRV/doc.cpp"
#include "../deps/glslang/glslang/SPIRV/GlslangToSpv.cpp"
#include "../deps/glslang/glslang/SPIRV/InReadableOrder.cpp"
#include "../deps/glslang/glslang/SPIRV/Logger.cpp"
#include "../deps/glslang/glslang/SPIRV/SpvBuilder.cpp"
#include "../deps/glslang/glslang/SPIRV/SPVRemapper.cpp"
#include "../deps/glslang/glslang/glslang/GenericCodeGen/CodeGen.cpp"
#include "../deps/glslang/glslang/glslang/GenericCodeGen/Link.cpp"
#include "../deps/glslang/glslang/OGLCompilersDLL/InitializeDll.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/attribute.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Constant.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/glslang_tab.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/InfoSink.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Initialize.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Intermediate.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/intermOut.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/IntermTraverse.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/iomapper.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/limits.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/linkValidate.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/parseConst.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ParseContextBase.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ParseHelper.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/PoolAlloc.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/propagateNoContraction.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/reflection.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/RemoveTree.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Scan.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/ShaderLang.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/SymbolTable.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/Versions.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp"
#include "../deps/glslang/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp"
#ifdef __APPLE__
#include "../deps/glslang/glslang/glslang/OSDependent/Unix/ossource.cpp"
#endif
#if defined(ENABLE_HLSL)
#include "../deps/glslang/glslang/hlsl/hlslAttributes.cpp"
#include "../deps/glslang/glslang/hlsl/hlslGrammar.cpp"
#include "../deps/glslang/glslang/hlsl/hlslOpMap.cpp"
#include "../deps/glslang/glslang/hlsl/hlslParseables.cpp"
#include "../deps/glslang/glslang/hlsl/hlslParseHelper.cpp"
#include "../deps/glslang/glslang/hlsl/hlslScanContext.cpp"
#include "../deps/glslang/glslang/hlsl/hlslTokenStream.cpp"
#endif
#endif

View File

@ -1,163 +1,163 @@
/***************************************************************************
libchdr_flac_codec.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/flac.h>
#include <libchdr/huffman.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/***************************************************************************
* CD FLAC DECOMPRESSOR
***************************************************************************
*/
/*------------------------------------------------------
* cdfl_codec_blocksize - return the optimal block size
*------------------------------------------------------
*/
static uint32_t cdfl_codec_blocksize(uint32_t bytes)
{
/* determine FLAC block size, which must be 16-65535
* clamp to 2k since that's supposed to be the sweet spot */
uint32_t hunkbytes = bytes / 4;
while (hunkbytes > 2048)
hunkbytes /= 2;
return hunkbytes;
}
chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
{
#ifdef WANT_SUBCODE
chd_error ret;
#endif
uint16_t native_endian = 0;
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
/* make sure the CHD's hunk size is an even multiple of the frame size */
if (hunkbytes % CD_FRAME_SIZE != 0)
return CHDERR_CODEC_ERROR;
cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdfl->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
/* determine whether we want native or swapped samples */
*(uint8_t *)(&native_endian) = 1;
cdfl->swap_endian = (native_endian & 1);
#ifdef WANT_SUBCODE
/* init zlib inflater */
ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
/* flac decoder init */
flac_decoder_init(&cdfl->decoder);
if (cdfl->decoder.decoder == NULL)
return CHDERR_OUT_OF_MEMORY;
return CHDERR_NONE;
}
void cdfl_codec_free(void *codec)
{
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
flac_decoder_free(&cdfl->decoder);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdfl->subcode_decompressor);
#endif
if (cdfl->buffer)
free(cdfl->buffer);
}
chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
uint32_t framenum;
uint8_t *buffer;
#ifdef WANT_SUBCODE
uint32_t offset;
chd_error ret;
#endif
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
/* reset and decode */
uint32_t frames = destlen / CD_FRAME_SIZE;
if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
return CHDERR_DECOMPRESSION_ERROR;
buffer = &cdfl->buffer[0];
if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
return CHDERR_DECOMPRESSION_ERROR;
#ifdef WANT_SUBCODE
/* inflate the subcode data */
offset = flac_decoder_finish(&cdfl->decoder);
ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
if (ret != CHDERR_NONE)
return ret;
#else
flac_decoder_finish(&cdfl->decoder);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
}
return CHDERR_NONE;
}
/***************************************************************************
libchdr_flac_codec.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/flac.h>
#include <libchdr/huffman.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/***************************************************************************
* CD FLAC DECOMPRESSOR
***************************************************************************
*/
/*------------------------------------------------------
* cdfl_codec_blocksize - return the optimal block size
*------------------------------------------------------
*/
static uint32_t cdfl_codec_blocksize(uint32_t bytes)
{
/* determine FLAC block size, which must be 16-65535
* clamp to 2k since that's supposed to be the sweet spot */
uint32_t hunkbytes = bytes / 4;
while (hunkbytes > 2048)
hunkbytes /= 2;
return hunkbytes;
}
chd_error cdfl_codec_init(void *codec, uint32_t hunkbytes)
{
#ifdef WANT_SUBCODE
chd_error ret;
#endif
uint16_t native_endian = 0;
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
/* make sure the CHD's hunk size is an even multiple of the frame size */
if (hunkbytes % CD_FRAME_SIZE != 0)
return CHDERR_CODEC_ERROR;
cdfl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdfl->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
/* determine whether we want native or swapped samples */
*(uint8_t *)(&native_endian) = 1;
cdfl->swap_endian = (native_endian & 1);
#ifdef WANT_SUBCODE
/* init zlib inflater */
ret = zlib_codec_init(&cdfl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
/* flac decoder init */
flac_decoder_init(&cdfl->decoder);
if (cdfl->decoder.decoder == NULL)
return CHDERR_OUT_OF_MEMORY;
return CHDERR_NONE;
}
void cdfl_codec_free(void *codec)
{
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
flac_decoder_free(&cdfl->decoder);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdfl->subcode_decompressor);
#endif
if (cdfl->buffer)
free(cdfl->buffer);
}
chd_error cdfl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
uint32_t framenum;
uint8_t *buffer;
#ifdef WANT_SUBCODE
uint32_t offset;
chd_error ret;
#endif
cdfl_codec_data *cdfl = (cdfl_codec_data*)codec;
/* reset and decode */
uint32_t frames = destlen / CD_FRAME_SIZE;
if (!flac_decoder_reset(&cdfl->decoder, 44100, 2, cdfl_codec_blocksize(frames * CD_MAX_SECTOR_DATA), src, complen))
return CHDERR_DECOMPRESSION_ERROR;
buffer = &cdfl->buffer[0];
if (!flac_decoder_decode_interleaved(&cdfl->decoder, (int16_t *)(buffer), frames * CD_MAX_SECTOR_DATA/4, cdfl->swap_endian))
return CHDERR_DECOMPRESSION_ERROR;
#ifdef WANT_SUBCODE
/* inflate the subcode data */
offset = flac_decoder_finish(&cdfl->decoder);
ret = zlib_codec_decompress(&cdfl->subcode_decompressor, src + offset, complen - offset, &cdfl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
if (ret != CHDERR_NONE)
return ret;
#else
flac_decoder_finish(&cdfl->decoder);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdfl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdfl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
}
return CHDERR_NONE;
}

View File

@ -1,354 +1,354 @@
/***************************************************************************
libchdr_lzma_codec.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/lzma.h>
#include <libchdr/huffman.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/***************************************************************************
* LZMA ALLOCATOR HELPER
***************************************************************************
*/
/*-------------------------------------------------
* lzma_fast_alloc - fast malloc for lzma, which
* allocates and frees memory frequently
*-------------------------------------------------
*/
static void *lzma_fast_alloc(void *p, size_t size)
{
int scan;
uint32_t *addr = NULL;
lzma_allocator *codec = (lzma_allocator *)(p);
/* compute the size, rounding to the nearest 1k */
size = (size + 0x3ff) & ~0x3ff;
/* reuse a hunk if we can */
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
uint32_t *ptr = codec->allocptr[scan];
if (ptr != NULL && size == *ptr)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
}
}
/* alloc a new one and put it into the list */
addr = (uint32_t *)malloc(sizeof(uint32_t) * (size + sizeof(uint32_t)));
if (!addr)
return NULL;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (codec->allocptr[scan] == NULL)
{
codec->allocptr[scan] = addr;
break;
}
}
/* set the low bit of the size so we don't match next time */
*addr = size | 1;
return addr + 1;
}
/*-------------------------------------------------
* lzma_fast_free - fast free for lzma, which
* allocates and frees memory frequently
*-------------------------------------------------
*/
static void lzma_fast_free(void *p, void *address)
{
int scan;
uint32_t *ptr;
lzma_allocator *codec;
if (address == NULL)
return;
codec = (lzma_allocator *)(p);
/* find the hunk */
ptr = (uint32_t *)(address) - 1;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (ptr == codec->allocptr[scan])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
return;
}
}
}
/*-------------------------------------------------
* lzma_allocator_init
*-------------------------------------------------
*/
void lzma_allocator_init(void* p)
{
lzma_allocator *codec = (lzma_allocator *)(p);
/* reset pointer list */
memset(codec->allocptr, 0, sizeof(codec->allocptr));
codec->Alloc = lzma_fast_alloc;
codec->Free = lzma_fast_free;
}
/*-------------------------------------------------
* lzma_allocator_free
*-------------------------------------------------
*/
void lzma_allocator_free(void* p )
{
lzma_allocator *codec = (lzma_allocator *)(p);
/* free our memory */
int i;
for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
{
if (codec->allocptr[i] != NULL)
free(codec->allocptr[i]);
}
}
/***************************************************************************
* LZMA DECOMPRESSOR
***************************************************************************
*/
/*-------------------------------------------------
* lzma_codec_init - constructor
*-------------------------------------------------
*/
chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
{
CLzmaEncProps encoder_props;
CLzmaEncHandle enc;
uint8_t decoder_props[LZMA_PROPS_SIZE];
lzma_allocator* alloc;
size_t props_size;
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
/* construct the decoder */
LzmaDec_Construct(&lzma_codec->decoder);
/* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
* This code assumes that the current version of the encoder imposes the same requirements on the
* decoder as the encoder used to produce the file. This is not necessarily true. The format
* needs to be changed so the encoder properties are written to the file.
* configure the properties like the compressor did */
LzmaEncProps_Init(&encoder_props);
encoder_props.level = 9;
encoder_props.reduceSize = hunkbytes;
LzmaEncProps_Normalize(&encoder_props);
/* convert to decoder properties */
alloc = &lzma_codec->allocator;
lzma_allocator_init(alloc);
enc = LzmaEnc_Create((ISzAlloc*)alloc);
if (!enc)
return CHDERR_DECOMPRESSION_ERROR;
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
{
LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
return CHDERR_DECOMPRESSION_ERROR;
}
props_size = sizeof(decoder_props);
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
{
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
return CHDERR_DECOMPRESSION_ERROR;
}
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
/* do memory allocations */
if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
return CHDERR_DECOMPRESSION_ERROR;
/* Okay */
return CHDERR_NONE;
}
/*-------------------------------------------------
* lzma_codec_free
*-------------------------------------------------
*/
void lzma_codec_free(void* codec)
{
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
lzma_allocator* alloc = &lzma_codec->allocator;
/* free memory */
lzma_allocator_free(alloc);
LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
}
/*-------------------------------------------------
* decompress - decompress data using the LZMA
* codec
*-------------------------------------------------
*/
chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
ELzmaStatus status;
SRes res;
size_t consumedlen, decodedlen;
/* initialize */
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
LzmaDec_Init(&lzma_codec->decoder);
/* decode */
consumedlen = complen;
decodedlen = destlen;
res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
}
/* cdlz */
chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
{
chd_error ret;
cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
/* allocate buffer */
cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdlz->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#ifdef WANT_SUBCODE
ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
return CHDERR_NONE;
}
void cdlz_codec_free(void* codec)
{
cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
lzma_codec_free(&cdlz->base_decompressor);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdlz->subcode_decompressor);
#endif
if (cdlz->buffer)
free(cdlz->buffer);
}
chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
#ifdef WANT_RAW_DATA_SECTOR
uint8_t *sector;
#endif
uint32_t framenum;
cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
/* determine header bytes */
uint32_t frames = destlen / CD_FRAME_SIZE;
uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
uint32_t header_bytes = ecc_bytes + complen_bytes;
/* extract compressed length of base */
uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
if (complen_bytes > 2)
complen_base = (complen_base << 8) | src[ecc_bytes + 2];
/* reset and decode */
lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
if (header_bytes + complen_base >= complen)
return CHDERR_DECOMPRESSION_ERROR;
zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
#ifdef WANT_RAW_DATA_SECTOR
/* reconstitute the ECC data and sync header */
sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
ecc_generate(sector);
}
#endif
}
return CHDERR_NONE;
}
/***************************************************************************
libchdr_lzma_codec.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/lzma.h>
#include <libchdr/huffman.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/***************************************************************************
* LZMA ALLOCATOR HELPER
***************************************************************************
*/
/*-------------------------------------------------
* lzma_fast_alloc - fast malloc for lzma, which
* allocates and frees memory frequently
*-------------------------------------------------
*/
static void *lzma_fast_alloc(void *p, size_t size)
{
int scan;
uint32_t *addr = NULL;
lzma_allocator *codec = (lzma_allocator *)(p);
/* compute the size, rounding to the nearest 1k */
size = (size + 0x3ff) & ~0x3ff;
/* reuse a hunk if we can */
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
uint32_t *ptr = codec->allocptr[scan];
if (ptr != NULL && size == *ptr)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
}
}
/* alloc a new one and put it into the list */
addr = (uint32_t *)malloc(sizeof(uint32_t) * (size + sizeof(uint32_t)));
if (!addr)
return NULL;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (codec->allocptr[scan] == NULL)
{
codec->allocptr[scan] = addr;
break;
}
}
/* set the low bit of the size so we don't match next time */
*addr = size | 1;
return addr + 1;
}
/*-------------------------------------------------
* lzma_fast_free - fast free for lzma, which
* allocates and frees memory frequently
*-------------------------------------------------
*/
static void lzma_fast_free(void *p, void *address)
{
int scan;
uint32_t *ptr;
lzma_allocator *codec;
if (address == NULL)
return;
codec = (lzma_allocator *)(p);
/* find the hunk */
ptr = (uint32_t *)(address) - 1;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (ptr == codec->allocptr[scan])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
return;
}
}
}
/*-------------------------------------------------
* lzma_allocator_init
*-------------------------------------------------
*/
void lzma_allocator_init(void* p)
{
lzma_allocator *codec = (lzma_allocator *)(p);
/* reset pointer list */
memset(codec->allocptr, 0, sizeof(codec->allocptr));
codec->Alloc = lzma_fast_alloc;
codec->Free = lzma_fast_free;
}
/*-------------------------------------------------
* lzma_allocator_free
*-------------------------------------------------
*/
void lzma_allocator_free(void* p )
{
lzma_allocator *codec = (lzma_allocator *)(p);
/* free our memory */
int i;
for (i = 0 ; i < MAX_LZMA_ALLOCS ; i++)
{
if (codec->allocptr[i] != NULL)
free(codec->allocptr[i]);
}
}
/***************************************************************************
* LZMA DECOMPRESSOR
***************************************************************************
*/
/*-------------------------------------------------
* lzma_codec_init - constructor
*-------------------------------------------------
*/
chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
{
CLzmaEncProps encoder_props;
CLzmaEncHandle enc;
uint8_t decoder_props[LZMA_PROPS_SIZE];
lzma_allocator* alloc;
size_t props_size;
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
/* construct the decoder */
LzmaDec_Construct(&lzma_codec->decoder);
/* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
* This code assumes that the current version of the encoder imposes the same requirements on the
* decoder as the encoder used to produce the file. This is not necessarily true. The format
* needs to be changed so the encoder properties are written to the file.
* configure the properties like the compressor did */
LzmaEncProps_Init(&encoder_props);
encoder_props.level = 9;
encoder_props.reduceSize = hunkbytes;
LzmaEncProps_Normalize(&encoder_props);
/* convert to decoder properties */
alloc = &lzma_codec->allocator;
lzma_allocator_init(alloc);
enc = LzmaEnc_Create((ISzAlloc*)alloc);
if (!enc)
return CHDERR_DECOMPRESSION_ERROR;
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
{
LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
return CHDERR_DECOMPRESSION_ERROR;
}
props_size = sizeof(decoder_props);
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
{
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
return CHDERR_DECOMPRESSION_ERROR;
}
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
/* do memory allocations */
if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
return CHDERR_DECOMPRESSION_ERROR;
/* Okay */
return CHDERR_NONE;
}
/*-------------------------------------------------
* lzma_codec_free
*-------------------------------------------------
*/
void lzma_codec_free(void* codec)
{
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
lzma_allocator* alloc = &lzma_codec->allocator;
/* free memory */
lzma_allocator_free(alloc);
LzmaDec_Free(&lzma_codec->decoder, (ISzAlloc*)&lzma_codec->allocator);
}
/*-------------------------------------------------
* decompress - decompress data using the LZMA
* codec
*-------------------------------------------------
*/
chd_error lzma_codec_decompress(void* codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
ELzmaStatus status;
SRes res;
size_t consumedlen, decodedlen;
/* initialize */
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
LzmaDec_Init(&lzma_codec->decoder);
/* decode */
consumedlen = complen;
decodedlen = destlen;
res = LzmaDec_DecodeToBuf(&lzma_codec->decoder, dest, &decodedlen, src, &consumedlen, LZMA_FINISH_END, &status);
if ((res != SZ_OK && res != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) || consumedlen != complen || decodedlen != destlen)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
}
/* cdlz */
chd_error cdlz_codec_init(void* codec, uint32_t hunkbytes)
{
chd_error ret;
cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
/* allocate buffer */
cdlz->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdlz->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
ret = lzma_codec_init(&cdlz->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#ifdef WANT_SUBCODE
ret = zlib_codec_init(&cdlz->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
return CHDERR_NONE;
}
void cdlz_codec_free(void* codec)
{
cdlz_codec_data* cdlz = (cdlz_codec_data*) codec;
lzma_codec_free(&cdlz->base_decompressor);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdlz->subcode_decompressor);
#endif
if (cdlz->buffer)
free(cdlz->buffer);
}
chd_error cdlz_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
#ifdef WANT_RAW_DATA_SECTOR
uint8_t *sector;
#endif
uint32_t framenum;
cdlz_codec_data* cdlz = (cdlz_codec_data*)codec;
/* determine header bytes */
uint32_t frames = destlen / CD_FRAME_SIZE;
uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
uint32_t header_bytes = ecc_bytes + complen_bytes;
/* extract compressed length of base */
uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
if (complen_bytes > 2)
complen_base = (complen_base << 8) | src[ecc_bytes + 2];
/* reset and decode */
lzma_codec_decompress(&cdlz->base_decompressor, &src[header_bytes], complen_base, &cdlz->buffer[0], frames * CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
if (header_bytes + complen_base >= complen)
return CHDERR_DECOMPRESSION_ERROR;
zlib_codec_decompress(&cdlz->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdlz->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdlz->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdlz->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
#ifdef WANT_RAW_DATA_SECTOR
/* reconstitute the ECC data and sync header */
sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
ecc_generate(sector);
}
#endif
}
return CHDERR_NONE;
}

View File

@ -1,298 +1,298 @@
/***************************************************************************
libchdr_zlib.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/huffman.h>
#include <libchdr/libchdr_zlib.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/* cdzl */
chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
{
chd_error ret;
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
/* make sure the CHD's hunk size is an even multiple of the frame size */
if (hunkbytes % CD_FRAME_SIZE != 0)
return CHDERR_CODEC_ERROR;
cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdzl->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#ifdef WANT_SUBCODE
ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
return CHDERR_NONE;
}
void cdzl_codec_free(void *codec)
{
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
zlib_codec_free(&cdzl->base_decompressor);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdzl->subcode_decompressor);
#endif
if (cdzl->buffer)
free(cdzl->buffer);
}
chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
#ifdef WANT_RAW_DATA_SECTOR
uint8_t *sector;
#endif
uint32_t framenum;
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
/* determine header bytes */
uint32_t frames = destlen / CD_FRAME_SIZE;
uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
uint32_t header_bytes = ecc_bytes + complen_bytes;
/* extract compressed length of base */
uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
if (complen_bytes > 2)
complen_base = (complen_base << 8) | src[ecc_bytes + 2];
/* reset and decode */
zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
#ifdef WANT_RAW_DATA_SECTOR
/* reconstitute the ECC data and sync header */
sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
ecc_generate(sector);
}
#endif
}
return CHDERR_NONE;
}
/***************************************************************************
ZLIB COMPRESSION CODEC
***************************************************************************/
/*-------------------------------------------------
zlib_codec_init - initialize the ZLIB codec
-------------------------------------------------*/
chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
{
int zerr;
chd_error err;
zlib_codec_data *data = (zlib_codec_data*)codec;
/* clear the buffers */
memset(data, 0, sizeof(zlib_codec_data));
/* init the inflater first */
data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
data->inflater.avail_in = 0;
data->inflater.zalloc = zlib_fast_alloc;
data->inflater.zfree = zlib_fast_free;
data->inflater.opaque = &data->allocator;
zerr = inflateInit2(&data->inflater, -MAX_WBITS);
/* convert errors */
if (zerr == Z_MEM_ERROR)
err = CHDERR_OUT_OF_MEMORY;
else if (zerr != Z_OK)
err = CHDERR_CODEC_ERROR;
else
err = CHDERR_NONE;
return err;
}
/*-------------------------------------------------
zlib_codec_free - free data for the ZLIB
codec
-------------------------------------------------*/
void zlib_codec_free(void *codec)
{
zlib_codec_data *data = (zlib_codec_data *)codec;
/* deinit the streams */
if (data != NULL)
{
int i;
zlib_allocator alloc;
inflateEnd(&data->inflater);
/* free our fast memory */
alloc = data->allocator;
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (alloc.allocptr[i])
free(alloc.allocptr[i]);
}
}
/*-------------------------------------------------
zlib_codec_decompress - decomrpess data using
the ZLIB codec
-------------------------------------------------*/
chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
zlib_codec_data *data = (zlib_codec_data *)codec;
int zerr;
/* reset the decompressor */
data->inflater.next_in = (Bytef *)src;
data->inflater.avail_in = complen;
data->inflater.total_in = 0;
data->inflater.next_out = (Bytef *)dest;
data->inflater.avail_out = destlen;
data->inflater.total_out = 0;
zerr = inflateReset(&data->inflater);
if (zerr != Z_OK)
return CHDERR_DECOMPRESSION_ERROR;
/* do it */
zerr = inflate(&data->inflater, Z_FINISH);
(void)zerr;
if (data->inflater.total_out != destlen)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
}
/*-------------------------------------------------
zlib_fast_alloc - fast malloc for ZLIB, which
allocates and frees memory frequently
-------------------------------------------------*/
voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr;
int i;
/* compute the size, rounding to the nearest 1k */
size = (size * items + 0x3ff) & ~0x3ff;
/* reuse a hunk if we can */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
{
ptr = alloc->allocptr[i];
if (ptr && size == *ptr)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
}
}
/* alloc a new one */
ptr = (UINT32 *)malloc(size + sizeof(UINT32));
if (!ptr)
return NULL;
/* put it into the list */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (!alloc->allocptr[i])
{
alloc->allocptr[i] = ptr;
break;
}
/* set the low bit of the size so we don't match next time */
*ptr = size | 1;
return ptr + 1;
}
/*-------------------------------------------------
zlib_fast_free - fast free for ZLIB, which
allocates and frees memory frequently
-------------------------------------------------*/
void zlib_fast_free(voidpf opaque, voidpf address)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr = (UINT32 *)address - 1;
int i;
/* find the hunk */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (ptr == alloc->allocptr[i])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
return;
}
}
/***************************************************************************
libchdr_zlib.c
MAME Compressed Hunks of Data file format
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''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 AARON GILES 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 <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libchdr/chd.h>
#include <libchdr/minmax.h>
#include <libchdr/cdrom.h>
#include <libchdr/huffman.h>
#include <libchdr/libchdr_zlib.h>
#include <zlib.h>
#include <retro_inline.h>
#include <streams/file_stream.h>
#define TRUE 1
#define FALSE 0
/* cdzl */
chd_error cdzl_codec_init(void *codec, uint32_t hunkbytes)
{
chd_error ret;
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
/* make sure the CHD's hunk size is an even multiple of the frame size */
if (hunkbytes % CD_FRAME_SIZE != 0)
return CHDERR_CODEC_ERROR;
cdzl->buffer = (uint8_t*)malloc(sizeof(uint8_t) * hunkbytes);
if (cdzl->buffer == NULL)
return CHDERR_OUT_OF_MEMORY;
ret = zlib_codec_init(&cdzl->base_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#ifdef WANT_SUBCODE
ret = zlib_codec_init(&cdzl->subcode_decompressor, (hunkbytes / CD_FRAME_SIZE) * CD_MAX_SECTOR_DATA);
if (ret != CHDERR_NONE)
return ret;
#endif
return CHDERR_NONE;
}
void cdzl_codec_free(void *codec)
{
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
zlib_codec_free(&cdzl->base_decompressor);
#ifdef WANT_SUBCODE
zlib_codec_free(&cdzl->subcode_decompressor);
#endif
if (cdzl->buffer)
free(cdzl->buffer);
}
chd_error cdzl_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
#ifdef WANT_RAW_DATA_SECTOR
uint8_t *sector;
#endif
uint32_t framenum;
cdzl_codec_data* cdzl = (cdzl_codec_data*)codec;
/* determine header bytes */
uint32_t frames = destlen / CD_FRAME_SIZE;
uint32_t complen_bytes = (destlen < 65536) ? 2 : 3;
uint32_t ecc_bytes = (frames + 7) / 8;
uint32_t header_bytes = ecc_bytes + complen_bytes;
/* extract compressed length of base */
uint32_t complen_base = (src[ecc_bytes + 0] << 8) | src[ecc_bytes + 1];
if (complen_bytes > 2)
complen_base = (complen_base << 8) | src[ecc_bytes + 2];
/* reset and decode */
zlib_codec_decompress(&cdzl->base_decompressor, &src[header_bytes], complen_base, &cdzl->buffer[0], frames * CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
zlib_codec_decompress(&cdzl->subcode_decompressor, &src[header_bytes + complen_base], complen - complen_base - header_bytes, &cdzl->buffer[frames * CD_MAX_SECTOR_DATA], frames * CD_MAX_SUBCODE_DATA);
#endif
/* reassemble the data */
for (framenum = 0; framenum < frames; framenum++)
{
memcpy(&dest[framenum * CD_FRAME_SIZE], &cdzl->buffer[framenum * CD_MAX_SECTOR_DATA], CD_MAX_SECTOR_DATA);
#ifdef WANT_SUBCODE
memcpy(&dest[framenum * CD_FRAME_SIZE + CD_MAX_SECTOR_DATA], &cdzl->buffer[frames * CD_MAX_SECTOR_DATA + framenum * CD_MAX_SUBCODE_DATA], CD_MAX_SUBCODE_DATA);
#endif
#ifdef WANT_RAW_DATA_SECTOR
/* reconstitute the ECC data and sync header */
sector = (uint8_t *)&dest[framenum * CD_FRAME_SIZE];
if ((src[framenum / 8] & (1 << (framenum % 8))) != 0)
{
memcpy(sector, s_cd_sync_header, sizeof(s_cd_sync_header));
ecc_generate(sector);
}
#endif
}
return CHDERR_NONE;
}
/***************************************************************************
ZLIB COMPRESSION CODEC
***************************************************************************/
/*-------------------------------------------------
zlib_codec_init - initialize the ZLIB codec
-------------------------------------------------*/
chd_error zlib_codec_init(void *codec, uint32_t hunkbytes)
{
int zerr;
chd_error err;
zlib_codec_data *data = (zlib_codec_data*)codec;
/* clear the buffers */
memset(data, 0, sizeof(zlib_codec_data));
/* init the inflater first */
data->inflater.next_in = (Bytef *)data; /* bogus, but that's ok */
data->inflater.avail_in = 0;
data->inflater.zalloc = zlib_fast_alloc;
data->inflater.zfree = zlib_fast_free;
data->inflater.opaque = &data->allocator;
zerr = inflateInit2(&data->inflater, -MAX_WBITS);
/* convert errors */
if (zerr == Z_MEM_ERROR)
err = CHDERR_OUT_OF_MEMORY;
else if (zerr != Z_OK)
err = CHDERR_CODEC_ERROR;
else
err = CHDERR_NONE;
return err;
}
/*-------------------------------------------------
zlib_codec_free - free data for the ZLIB
codec
-------------------------------------------------*/
void zlib_codec_free(void *codec)
{
zlib_codec_data *data = (zlib_codec_data *)codec;
/* deinit the streams */
if (data != NULL)
{
int i;
zlib_allocator alloc;
inflateEnd(&data->inflater);
/* free our fast memory */
alloc = data->allocator;
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (alloc.allocptr[i])
free(alloc.allocptr[i]);
}
}
/*-------------------------------------------------
zlib_codec_decompress - decomrpess data using
the ZLIB codec
-------------------------------------------------*/
chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
zlib_codec_data *data = (zlib_codec_data *)codec;
int zerr;
/* reset the decompressor */
data->inflater.next_in = (Bytef *)src;
data->inflater.avail_in = complen;
data->inflater.total_in = 0;
data->inflater.next_out = (Bytef *)dest;
data->inflater.avail_out = destlen;
data->inflater.total_out = 0;
zerr = inflateReset(&data->inflater);
if (zerr != Z_OK)
return CHDERR_DECOMPRESSION_ERROR;
/* do it */
zerr = inflate(&data->inflater, Z_FINISH);
(void)zerr;
if (data->inflater.total_out != destlen)
return CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
}
/*-------------------------------------------------
zlib_fast_alloc - fast malloc for ZLIB, which
allocates and frees memory frequently
-------------------------------------------------*/
voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr;
int i;
/* compute the size, rounding to the nearest 1k */
size = (size * items + 0x3ff) & ~0x3ff;
/* reuse a hunk if we can */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
{
ptr = alloc->allocptr[i];
if (ptr && size == *ptr)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
}
}
/* alloc a new one */
ptr = (UINT32 *)malloc(size + sizeof(UINT32));
if (!ptr)
return NULL;
/* put it into the list */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (!alloc->allocptr[i])
{
alloc->allocptr[i] = ptr;
break;
}
/* set the low bit of the size so we don't match next time */
*ptr = size | 1;
return ptr + 1;
}
/*-------------------------------------------------
zlib_fast_free - fast free for ZLIB, which
allocates and frees memory frequently
-------------------------------------------------*/
void zlib_fast_free(voidpf opaque, voidpf address)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr = (UINT32 *)address - 1;
int i;
/* find the hunk */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (ptr == alloc->allocptr[i])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
return;
}
}

View File

@ -1,293 +1,293 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2014-2017 - Jean-André Santoni
* Copyright (C) 2015-2017 - Andrés Suárez
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <retro_miscellaneous.h>
#include <lists/file_list.h>
#include <lists/string_list.h>
#include <file/file_path.h>
#include <compat/strl.h>
#include <streams/file_stream.h>
#include <string/stdstring.h>
#ifdef HAVE_NETWORKING
#include <net/net_http_parse.h>
#endif
#include "menu_driver.h"
#include "menu_networking.h"
#include "menu_cbs.h"
#include "menu_entries.h"
#include "../core_info.h"
#include "../configuration.h"
#include "../file_path_special.h"
#include "../msg_hash.h"
#include "../tasks/task_file_transfer.h"
#include "../tasks/tasks_internal.h"
void print_buf_lines(file_list_t *list, char *buf,
const char *label, int buf_size,
enum msg_file_type type, bool append, bool extended)
{
char c;
int i, j = 0;
char *line_start = buf;
if (!buf || !buf_size)
{
menu_entries_append_enum(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
FILE_TYPE_NONE, 0, 0);
return;
}
for (i = 0; i < buf_size; i++)
{
size_t ln;
const char *core_date = NULL;
const char *core_crc = NULL;
const char *core_pathname = NULL;
struct string_list *str_list = NULL;
/* The end of the buffer, print the last bit */
if (*(buf + i) == '\0')
break;
if (*(buf + i) != '\n')
continue;
/* Found a line ending, print the line and compute new line_start */
/* Save the next char */
c = *(buf + i + 1);
/* replace with \0 */
*(buf + i + 1) = '\0';
/* We need to strip the newline. */
ln = strlen(line_start) - 1;
if (line_start[ln] == '\n')
line_start[ln] = '\0';
str_list = string_split(line_start, " ");
if (str_list->elems[0].data)
core_date = str_list->elems[0].data;
if (str_list->elems[1].data)
core_crc = str_list->elems[1].data;
if (str_list->elems[2].data)
core_pathname = str_list->elems[2].data;
(void)core_date;
(void)core_crc;
if (extended)
{
if (append)
menu_entries_append_enum(list, core_pathname, "",
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
else
menu_entries_prepend(list, core_pathname, "",
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
}
else
{
if (append)
menu_entries_append_enum(list, line_start, label,
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
else
menu_entries_prepend(list, line_start, label,
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
}
switch (type)
{
case FILE_TYPE_DOWNLOAD_CORE:
{
settings_t *settings = config_get_ptr();
if (settings)
{
char display_name[255];
char core_path[PATH_MAX_LENGTH];
char *last = NULL;
display_name[0] = core_path[0] = '\0';
fill_pathname_join_noext(
core_path,
settings->paths.path_libretro_info,
(extended && !string_is_empty(core_pathname))
? core_pathname : line_start,
sizeof(core_path));
path_remove_extension(core_path);
last = (char*)strrchr(core_path, '_');
if (!string_is_empty(last))
{
if (string_is_not_equal_fast(last, "_libretro", 9))
*last = '\0';
}
strlcat(core_path,
file_path_str(FILE_PATH_CORE_INFO_EXTENSION),
sizeof(core_path));
if (
filestream_exists(core_path)
&& core_info_get_display_name(
core_path, display_name, sizeof(display_name)))
file_list_set_alt_at_offset(list, j, display_name);
}
}
break;
default:
case FILE_TYPE_NONE:
break;
}
j++;
string_list_free(str_list);
/* Restore the saved char */
*(buf + i + 1) = c;
line_start = buf + i + 1;
}
if (append)
file_list_sort_on_alt(list);
/* If the buffer was completely full, and didn't end
* with a newline, just ignore the partial last line. */
}
void cb_net_generic_subdir(void *task_data, void *user_data, const char *err)
{
#ifdef HAVE_NETWORKING
char subdir_path[PATH_MAX_LENGTH];
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
file_transfer_t *state = (file_transfer_t*)user_data;
subdir_path[0] = '\0';
if (!data || err)
goto finish;
if (!string_is_empty(data->data))
memcpy(subdir_path, data->data, data->len * sizeof(char));
subdir_path[data->len] = '\0';
finish:
if (!err && !strstr(subdir_path, file_path_str(FILE_PATH_INDEX_DIRS_URL)))
{
char parent_dir[PATH_MAX_LENGTH];
parent_dir[0] = '\0';
fill_pathname_parent_dir(parent_dir,
state->path, sizeof(parent_dir));
/*generic_action_ok_displaylist_push(parent_dir, NULL,
subdir_path, 0, 0, 0, ACTION_OK_DL_CORE_CONTENT_DIRS_SUBDIR_LIST);*/
}
if (data)
{
if (data->data)
free(data->data);
free(data);
}
if (user_data)
free(user_data);
#endif
}
void cb_net_generic(void *task_data, void *user_data, const char *err)
{
#ifdef HAVE_NETWORKING
bool refresh = false;
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
file_transfer_t *state = (file_transfer_t*)user_data;
menu_handle_t *menu = NULL;
if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
goto finish;
if (menu->core_buf)
free(menu->core_buf);
menu->core_buf = NULL;
menu->core_len = 0;
if (!data || err)
goto finish;
menu->core_buf = (char*)malloc((data->len+1) * sizeof(char));
if (!menu->core_buf)
goto finish;
if (!string_is_empty(data->data))
memcpy(menu->core_buf, data->data, data->len * sizeof(char));
menu->core_buf[data->len] = '\0';
menu->core_len = data->len;
finish:
refresh = true;
menu_entries_ctl(MENU_ENTRIES_CTL_UNSET_REFRESH, &refresh);
if (data)
{
if (data->data)
free(data->data);
free(data);
}
if (!err && !strstr(state->path, file_path_str(FILE_PATH_INDEX_DIRS_URL)))
{
char *parent_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
file_transfer_t *transf = NULL;
parent_dir[0] = '\0';
fill_pathname_parent_dir(parent_dir,
state->path, PATH_MAX_LENGTH * sizeof(char));
strlcat(parent_dir,
file_path_str(FILE_PATH_INDEX_DIRS_URL),
PATH_MAX_LENGTH * sizeof(char));
transf = (file_transfer_t*)malloc(sizeof(*transf));
transf->enum_idx = MSG_UNKNOWN;
strlcpy(transf->path, parent_dir, sizeof(transf->path));
task_push_http_transfer(parent_dir, true,
"index_dirs", cb_net_generic_subdir, transf);
free(parent_dir);
}
if (state)
free(state);
#endif
}
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2014-2017 - Jean-André Santoni
* Copyright (C) 2015-2017 - Andrés Suárez
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <retro_miscellaneous.h>
#include <lists/file_list.h>
#include <lists/string_list.h>
#include <file/file_path.h>
#include <compat/strl.h>
#include <streams/file_stream.h>
#include <string/stdstring.h>
#ifdef HAVE_NETWORKING
#include <net/net_http_parse.h>
#endif
#include "menu_driver.h"
#include "menu_networking.h"
#include "menu_cbs.h"
#include "menu_entries.h"
#include "../core_info.h"
#include "../configuration.h"
#include "../file_path_special.h"
#include "../msg_hash.h"
#include "../tasks/task_file_transfer.h"
#include "../tasks/tasks_internal.h"
void print_buf_lines(file_list_t *list, char *buf,
const char *label, int buf_size,
enum msg_file_type type, bool append, bool extended)
{
char c;
int i, j = 0;
char *line_start = buf;
if (!buf || !buf_size)
{
menu_entries_append_enum(list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ENTRIES_TO_DISPLAY),
msg_hash_to_str(MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY),
MENU_ENUM_LABEL_NO_ENTRIES_TO_DISPLAY,
FILE_TYPE_NONE, 0, 0);
return;
}
for (i = 0; i < buf_size; i++)
{
size_t ln;
const char *core_date = NULL;
const char *core_crc = NULL;
const char *core_pathname = NULL;
struct string_list *str_list = NULL;
/* The end of the buffer, print the last bit */
if (*(buf + i) == '\0')
break;
if (*(buf + i) != '\n')
continue;
/* Found a line ending, print the line and compute new line_start */
/* Save the next char */
c = *(buf + i + 1);
/* replace with \0 */
*(buf + i + 1) = '\0';
/* We need to strip the newline. */
ln = strlen(line_start) - 1;
if (line_start[ln] == '\n')
line_start[ln] = '\0';
str_list = string_split(line_start, " ");
if (str_list->elems[0].data)
core_date = str_list->elems[0].data;
if (str_list->elems[1].data)
core_crc = str_list->elems[1].data;
if (str_list->elems[2].data)
core_pathname = str_list->elems[2].data;
(void)core_date;
(void)core_crc;
if (extended)
{
if (append)
menu_entries_append_enum(list, core_pathname, "",
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
else
menu_entries_prepend(list, core_pathname, "",
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
}
else
{
if (append)
menu_entries_append_enum(list, line_start, label,
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
else
menu_entries_prepend(list, line_start, label,
MENU_ENUM_LABEL_URL_ENTRY, type, 0, 0);
}
switch (type)
{
case FILE_TYPE_DOWNLOAD_CORE:
{
settings_t *settings = config_get_ptr();
if (settings)
{
char display_name[255];
char core_path[PATH_MAX_LENGTH];
char *last = NULL;
display_name[0] = core_path[0] = '\0';
fill_pathname_join_noext(
core_path,
settings->paths.path_libretro_info,
(extended && !string_is_empty(core_pathname))
? core_pathname : line_start,
sizeof(core_path));
path_remove_extension(core_path);
last = (char*)strrchr(core_path, '_');
if (!string_is_empty(last))
{
if (string_is_not_equal_fast(last, "_libretro", 9))
*last = '\0';
}
strlcat(core_path,
file_path_str(FILE_PATH_CORE_INFO_EXTENSION),
sizeof(core_path));
if (
filestream_exists(core_path)
&& core_info_get_display_name(
core_path, display_name, sizeof(display_name)))
file_list_set_alt_at_offset(list, j, display_name);
}
}
break;
default:
case FILE_TYPE_NONE:
break;
}
j++;
string_list_free(str_list);
/* Restore the saved char */
*(buf + i + 1) = c;
line_start = buf + i + 1;
}
if (append)
file_list_sort_on_alt(list);
/* If the buffer was completely full, and didn't end
* with a newline, just ignore the partial last line. */
}
void cb_net_generic_subdir(void *task_data, void *user_data, const char *err)
{
#ifdef HAVE_NETWORKING
char subdir_path[PATH_MAX_LENGTH];
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
file_transfer_t *state = (file_transfer_t*)user_data;
subdir_path[0] = '\0';
if (!data || err)
goto finish;
if (!string_is_empty(data->data))
memcpy(subdir_path, data->data, data->len * sizeof(char));
subdir_path[data->len] = '\0';
finish:
if (!err && !strstr(subdir_path, file_path_str(FILE_PATH_INDEX_DIRS_URL)))
{
char parent_dir[PATH_MAX_LENGTH];
parent_dir[0] = '\0';
fill_pathname_parent_dir(parent_dir,
state->path, sizeof(parent_dir));
/*generic_action_ok_displaylist_push(parent_dir, NULL,
subdir_path, 0, 0, 0, ACTION_OK_DL_CORE_CONTENT_DIRS_SUBDIR_LIST);*/
}
if (data)
{
if (data->data)
free(data->data);
free(data);
}
if (user_data)
free(user_data);
#endif
}
void cb_net_generic(void *task_data, void *user_data, const char *err)
{
#ifdef HAVE_NETWORKING
bool refresh = false;
http_transfer_data_t *data = (http_transfer_data_t*)task_data;
file_transfer_t *state = (file_transfer_t*)user_data;
menu_handle_t *menu = NULL;
if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
goto finish;
if (menu->core_buf)
free(menu->core_buf);
menu->core_buf = NULL;
menu->core_len = 0;
if (!data || err)
goto finish;
menu->core_buf = (char*)malloc((data->len+1) * sizeof(char));
if (!menu->core_buf)
goto finish;
if (!string_is_empty(data->data))
memcpy(menu->core_buf, data->data, data->len * sizeof(char));
menu->core_buf[data->len] = '\0';
menu->core_len = data->len;
finish:
refresh = true;
menu_entries_ctl(MENU_ENTRIES_CTL_UNSET_REFRESH, &refresh);
if (data)
{
if (data->data)
free(data->data);
free(data);
}
if (!err && !strstr(state->path, file_path_str(FILE_PATH_INDEX_DIRS_URL)))
{
char *parent_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
file_transfer_t *transf = NULL;
parent_dir[0] = '\0';
fill_pathname_parent_dir(parent_dir,
state->path, PATH_MAX_LENGTH * sizeof(char));
strlcat(parent_dir,
file_path_str(FILE_PATH_INDEX_DIRS_URL),
PATH_MAX_LENGTH * sizeof(char));
transf = (file_transfer_t*)malloc(sizeof(*transf));
transf->enum_idx = MSG_UNKNOWN;
strlcpy(transf->path, parent_dir, sizeof(transf->path));
task_push_http_transfer(parent_dir, true,
"index_dirs", cb_net_generic_subdir, transf);
free(parent_dir);
}
if (state)
free(state);
#endif
}

View File

@ -1,43 +1,43 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MENU_NETWORKING_H
#define _MENU_NETWORKING_H
#include <stdint.h>
#include <retro_common_api.h>
#include <retro_environment.h>
#include <lists/file_list.h>
#include "../msg_hash.h"
RETRO_BEGIN_DECLS
void print_buf_lines(file_list_t *list, char *buf,
const char *label, int buf_size,
enum msg_file_type type, bool append, bool extended);
void cb_net_generic_subdir(void *task_data, void *user_data,
const char *err);
void cb_net_generic(void *task_data, void *user_data, const char *err);
RETRO_END_DECLS
#endif
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2016-2017 - Brad Parker
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MENU_NETWORKING_H
#define _MENU_NETWORKING_H
#include <stdint.h>
#include <retro_common_api.h>
#include <retro_environment.h>
#include <lists/file_list.h>
#include "../msg_hash.h"
RETRO_BEGIN_DECLS
void print_buf_lines(file_list_t *list, char *buf,
const char *label, int buf_size,
enum msg_file_type type, bool append, bool extended);
void cb_net_generic_subdir(void *task_data, void *user_data,
const char *err);
void cb_net_generic(void *task_data, void *user_data, const char *err);
RETRO_END_DECLS
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +1,81 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TASKS_FILE_TRANSFER_H
#define TASKS_FILE_TRANSFER_H
#include <boolean.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
#include <queues/message_queue.h>
#include "../msg_hash.h"
RETRO_BEGIN_DECLS
enum nbio_status_enum
{
NBIO_STATUS_INIT = 0,
NBIO_STATUS_TRANSFER,
NBIO_STATUS_TRANSFER_PARSE,
NBIO_STATUS_TRANSFER_FINISHED
};
enum nbio_type
{
NBIO_TYPE_NONE = 0,
NBIO_TYPE_JPEG,
NBIO_TYPE_PNG,
NBIO_TYPE_TGA,
NBIO_TYPE_BMP,
NBIO_TYPE_OGG,
NBIO_TYPE_FLAC,
NBIO_TYPE_MP3,
NBIO_TYPE_MOD,
NBIO_TYPE_WAV
};
enum nbio_status_flags
{
NBIO_FLAG_NONE = 0,
NBIO_FLAG_IMAGE_SUPPORTS_RGBA
};
typedef int (*transfer_cb_t)(void *data, size_t len);
typedef struct nbio_handle
{
enum nbio_type type;
bool is_finished;
unsigned status;
unsigned pos_increment;
uint32_t status_flags;
void *data;
char *path;
struct nbio_t *handle;
msg_queue_t *msg_queue;
transfer_cb_t cb;
} nbio_handle_t;
typedef struct
{
enum msg_hash_enums enum_idx;
char path[PATH_MAX_LENGTH];
} file_transfer_t;
RETRO_END_DECLS
#endif
/* RetroArch - A frontend for libretro.
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch 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 Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch 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 RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TASKS_FILE_TRANSFER_H
#define TASKS_FILE_TRANSFER_H
#include <boolean.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
#include <queues/message_queue.h>
#include "../msg_hash.h"
RETRO_BEGIN_DECLS
enum nbio_status_enum
{
NBIO_STATUS_INIT = 0,
NBIO_STATUS_TRANSFER,
NBIO_STATUS_TRANSFER_PARSE,
NBIO_STATUS_TRANSFER_FINISHED
};
enum nbio_type
{
NBIO_TYPE_NONE = 0,
NBIO_TYPE_JPEG,
NBIO_TYPE_PNG,
NBIO_TYPE_TGA,
NBIO_TYPE_BMP,
NBIO_TYPE_OGG,
NBIO_TYPE_FLAC,
NBIO_TYPE_MP3,
NBIO_TYPE_MOD,
NBIO_TYPE_WAV
};
enum nbio_status_flags
{
NBIO_FLAG_NONE = 0,
NBIO_FLAG_IMAGE_SUPPORTS_RGBA
};
typedef int (*transfer_cb_t)(void *data, size_t len);
typedef struct nbio_handle
{
enum nbio_type type;
bool is_finished;
unsigned status;
unsigned pos_increment;
uint32_t status_flags;
void *data;
char *path;
struct nbio_t *handle;
msg_queue_t *msg_queue;
transfer_cb_t cb;
} nbio_handle_t;
typedef struct
{
enum msg_hash_enums enum_idx;
char path[PATH_MAX_LENGTH];
} file_transfer_t;
RETRO_END_DECLS
#endif

View File

@ -1,19 +1,19 @@
Copyright (c) 2011 PSL1GHT Development Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Copyright (c) 2011 PSL1GHT Development Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,46 +1,46 @@
#include <boolean.h>
#include <tesseract/baseapi.h>
#include "tess_get_text.h"
#define ERROR_BUFFER_LENGTH 1000
static tesseract::TessBaseAPI *api;
static char* one_time_return_pointer = NULL;
char tess_last_error[ERROR_BUFFER_LENGTH];
bool tess_init(const char* lang_data_dir, const char* language)
{
api = new tesseract::TessBaseAPI();
snprintf(tess_last_error, ERROR_BUFFER_LENGTH, "No errors!\n");
if (api->Init(lang_data_dir, language))
{
snprintf(tess_last_error, ERROR_BUFFER_LENGTH,
"Could not initialize tesseract.\n");
return false;
}
return true;
}
void tess_deinit(void)
{
if (one_time_return_pointer)
delete [] one_time_return_pointer;
if (api)
api->End();
}
char* tess_get_text(tess_image image)
{
if (one_time_return_pointer)
delete [] one_time_return_pointer;
api->SetImage(image.data, image.width, image.height,
image.bytes_per_pixel, image.width * image.bytes_per_pixel);
one_time_return_pointer = api->GetUTF8Text();
return one_time_return_pointer;
}
#include <boolean.h>
#include <tesseract/baseapi.h>
#include "tess_get_text.h"
#define ERROR_BUFFER_LENGTH 1000
static tesseract::TessBaseAPI *api;
static char* one_time_return_pointer = NULL;
char tess_last_error[ERROR_BUFFER_LENGTH];
bool tess_init(const char* lang_data_dir, const char* language)
{
api = new tesseract::TessBaseAPI();
snprintf(tess_last_error, ERROR_BUFFER_LENGTH, "No errors!\n");
if (api->Init(lang_data_dir, language))
{
snprintf(tess_last_error, ERROR_BUFFER_LENGTH,
"Could not initialize tesseract.\n");
return false;
}
return true;
}
void tess_deinit(void)
{
if (one_time_return_pointer)
delete [] one_time_return_pointer;
if (api)
api->End();
}
char* tess_get_text(tess_image image)
{
if (one_time_return_pointer)
delete [] one_time_return_pointer;
api->SetImage(image.data, image.width, image.height,
image.bytes_per_pixel, image.width * image.bytes_per_pixel);
one_time_return_pointer = api->GetUTF8Text();
return one_time_return_pointer;
}

View File

@ -1,26 +1,26 @@
#ifndef TESS_GET_TEXT
#define TESS_GET_TEXT
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef struct
{
unsigned width;
unsigned height;
unsigned bytes_per_pixel;
void* data;
} tess_image;
/* if running in RetroArch language should be "eng" or "jpn" */
bool tess_init(const char* lang_data_dir, const char* language);
void tess_deinit(void);
char* tess_get_text(tess_image image);
extern char tess_last_error[];
RETRO_END_DECLS
#endif
#ifndef TESS_GET_TEXT
#define TESS_GET_TEXT
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
typedef struct
{
unsigned width;
unsigned height;
unsigned bytes_per_pixel;
void* data;
} tess_image;
/* if running in RetroArch language should be "eng" or "jpn" */
bool tess_init(const char* lang_data_dir, const char* language);
void tess_deinit(void);
char* tess_get_text(tess_image image);
extern char tess_last_error[];
RETRO_END_DECLS
#endif

View File

@ -1,58 +1,58 @@
#include <string/stdstring.h>
#include <libretro.h>
#include "ocr_driver.h"
#include "../configuration.h"
static const ocr_driver_t *ocr_backends[] = {
#ifdef HAVE_TESSERACT
&ocr_tesseract,
#endif
&ocr_null,
NULL
};
static const ocr_driver_t *current_ocr_backend = NULL;
static void *ocr_data = NULL;
static const ocr_driver_t *ocr_find_backend(const char* ident)
{
unsigned i;
for (i = 0; ocr_backends[i]; i++)
{
if (string_is_equal(ocr_backends[i]->ident, ident))
return ocr_backends[i];
}
return NULL;
}
bool ocr_driver_init(void)
{
settings_t *settings = config_get_ptr();
int game_char_set = RETRO_LANGUAGE_DUMMY;
current_ocr_backend = ocr_find_backend(settings->arrays.ocr_driver);
ocr_data = NULL;
/* TODO: get game language */
if (current_ocr_backend)
ocr_data = (*current_ocr_backend->init)(game_char_set);
return ocr_data != NULL;
}
void ocr_driver_free(void)
{
if (current_ocr_backend && ocr_data)
(*current_ocr_backend->free)(ocr_data);
}
char* ocr_driver_get_text(struct ocr_image_info image)
{
char* image_string = NULL;
if (current_ocr_backend && ocr_data)
image_string = (*current_ocr_backend->get_text)(ocr_data, image);
return image_string;
#include <string/stdstring.h>
#include <libretro.h>
#include "ocr_driver.h"
#include "../configuration.h"
static const ocr_driver_t *ocr_backends[] = {
#ifdef HAVE_TESSERACT
&ocr_tesseract,
#endif
&ocr_null,
NULL
};
static const ocr_driver_t *current_ocr_backend = NULL;
static void *ocr_data = NULL;
static const ocr_driver_t *ocr_find_backend(const char* ident)
{
unsigned i;
for (i = 0; ocr_backends[i]; i++)
{
if (string_is_equal(ocr_backends[i]->ident, ident))
return ocr_backends[i];
}
return NULL;
}
bool ocr_driver_init(void)
{
settings_t *settings = config_get_ptr();
int game_char_set = RETRO_LANGUAGE_DUMMY;
current_ocr_backend = ocr_find_backend(settings->arrays.ocr_driver);
ocr_data = NULL;
/* TODO: get game language */
if (current_ocr_backend)
ocr_data = (*current_ocr_backend->init)(game_char_set);
return ocr_data != NULL;
}
void ocr_driver_free(void)
{
if (current_ocr_backend && ocr_data)
(*current_ocr_backend->free)(ocr_data);
}
char* ocr_driver_get_text(struct ocr_image_info image)
{
char* image_string = NULL;
if (current_ocr_backend && ocr_data)
image_string = (*current_ocr_backend->get_text)(ocr_data, image);
return image_string;
}

View File

@ -1,41 +1,41 @@
#ifndef __OCR_DRIVER__H
#define __OCR_DRIVER__H
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
struct ocr_image_info
{
unsigned width;
unsigned height;
unsigned pixel_format;
void* data;
};
typedef struct ocr_driver
{
void* (*init)(int game_character_set);
void (*free)(void* data);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to get_text */
char* (*get_text)(void* data, struct ocr_image_info image);
const char *ident;
} ocr_driver_t;
#ifdef HAVE_TESSERACT
extern const ocr_driver_t ocr_tesseract;
#endif
extern const ocr_driver_t ocr_null;
bool ocr_driver_init(void);
void ocr_driver_free(void);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to ocr_driver_get_text */
char* ocr_driver_get_text(struct ocr_image_info image);
RETRO_END_DECLS
#ifndef __OCR_DRIVER__H
#define __OCR_DRIVER__H
#include <boolean.h>
#include <retro_common_api.h>
RETRO_BEGIN_DECLS
struct ocr_image_info
{
unsigned width;
unsigned height;
unsigned pixel_format;
void* data;
};
typedef struct ocr_driver
{
void* (*init)(int game_character_set);
void (*free)(void* data);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to get_text */
char* (*get_text)(void* data, struct ocr_image_info image);
const char *ident;
} ocr_driver_t;
#ifdef HAVE_TESSERACT
extern const ocr_driver_t ocr_tesseract;
#endif
extern const ocr_driver_t ocr_null;
bool ocr_driver_init(void);
void ocr_driver_free(void);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to ocr_driver_get_text */
char* ocr_driver_get_text(struct ocr_image_info image);
RETRO_END_DECLS
#endif

View File

@ -1,67 +1,67 @@
#include <string/stdstring.h>
#include "translation_driver.h"
#include "ocr_driver.h"
#include "../configuration.h"
static const translation_driver_t *translation_backends[] = {
&translation_cached_google,
&ocr_null,
NULL
};
static const translation_driver_t *current_translation_backend = NULL;
static void *translation_data = NULL;
static const translation_driver_t *translation_find_backend(
const char* ident)
{
unsigned i;
for (i = 0; translation_backends[i]; i++)
{
if (string_is_equal(translation_backends[i]->ident, ident))
return translation_backends[i];
}
return NULL;
}
bool translation_driver_init(void)
{
settings_t *settings = config_get_ptr();
if (!settings)
return false;
current_translation_backend = translation_find_backend(
settings->arrays.translation_driver);
translation_data = NULL;
if (current_translation_backend)
translation_data = (*current_translation_backend->init)();
return translation_data != NULL;
}
void translation_driver_free(void)
{
if (current_translation_backend && translation_data)
(*current_translation_backend->free)(translation_data);
}
char* translation_driver_translate_image(struct ocr_image_info image)
{
char* translated_text = NULL;
if (current_translation_backend && translation_data)
{
if (current_translation_backend->translate_image)
translated_text = (*current_translation_backend->translate_image)
(translation_data, image);
else
translated_text = (*current_translation_backend->translate_text)
(translation_data, ocr_driver_get_text(image));
}
return translated_text;
}
#include <string/stdstring.h>
#include "translation_driver.h"
#include "ocr_driver.h"
#include "../configuration.h"
static const translation_driver_t *translation_backends[] = {
&translation_cached_google,
&ocr_null,
NULL
};
static const translation_driver_t *current_translation_backend = NULL;
static void *translation_data = NULL;
static const translation_driver_t *translation_find_backend(
const char* ident)
{
unsigned i;
for (i = 0; translation_backends[i]; i++)
{
if (string_is_equal(translation_backends[i]->ident, ident))
return translation_backends[i];
}
return NULL;
}
bool translation_driver_init(void)
{
settings_t *settings = config_get_ptr();
if (!settings)
return false;
current_translation_backend = translation_find_backend(
settings->arrays.translation_driver);
translation_data = NULL;
if (current_translation_backend)
translation_data = (*current_translation_backend->init)();
return translation_data != NULL;
}
void translation_driver_free(void)
{
if (current_translation_backend && translation_data)
(*current_translation_backend->free)(translation_data);
}
char* translation_driver_translate_image(struct ocr_image_info image)
{
char* translated_text = NULL;
if (current_translation_backend && translation_data)
{
if (current_translation_backend->translate_image)
translated_text = (*current_translation_backend->translate_image)
(translation_data, image);
else
translated_text = (*current_translation_backend->translate_text)
(translation_data, ocr_driver_get_text(image));
}
return translated_text;
}

View File

@ -1,51 +1,51 @@
#ifndef __TRANSLATION_DRIVER__H
#define __TRANSLATION_DRIVER__H
#include <boolean.h>
#include <retro_common_api.h>
#include "ocr_driver.h"
RETRO_BEGIN_DECLS
enum translation_init_errors
{
TRANSLATION_INIT_SUCCESS = 0,
TRANSLATION_INIT_UNSUPPORTED_DEVICE_LANGUAGE,
TRANSLATION_INIT_UNSUPPORTED_GAME_LANGUAGE,
TRANSLATION_INIT_UNKNOWN_DEVICE_LANGUAGE,
TRANSLATION_INIT_UNKNOWN_GAME_LANGUAGE
};
struct translation_driver_info
{
int device_language;
int game_language;
};
typedef struct translation_driver
{
void* (*init)(const struct translation_driver_info *params);
void (*free)(void* data);
/* use translate_image if non NULL else run image through ocr driver then run translate_text */
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to translate_image/text */
/* NOTE: translate_image is allowed to call the ocr driver itself if it wants */
char* (*translate_text)(void* data, const char* game_text);
char* (*translate_image)(void* data, struct ocr_image_info image);
const char *ident;
} translation_driver_t;
extern const translation_driver_t translation_cached_google;
extern const translation_driver_t translation_null;
bool translation_driver_init(void);
void translation_driver_free(void);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to translation_driver_translate_image */
char* translation_driver_translate_image(struct ocr_image_info image);
RETRO_END_DECLS
#ifndef __TRANSLATION_DRIVER__H
#define __TRANSLATION_DRIVER__H
#include <boolean.h>
#include <retro_common_api.h>
#include "ocr_driver.h"
RETRO_BEGIN_DECLS
enum translation_init_errors
{
TRANSLATION_INIT_SUCCESS = 0,
TRANSLATION_INIT_UNSUPPORTED_DEVICE_LANGUAGE,
TRANSLATION_INIT_UNSUPPORTED_GAME_LANGUAGE,
TRANSLATION_INIT_UNKNOWN_DEVICE_LANGUAGE,
TRANSLATION_INIT_UNKNOWN_GAME_LANGUAGE
};
struct translation_driver_info
{
int device_language;
int game_language;
};
typedef struct translation_driver
{
void* (*init)(const struct translation_driver_info *params);
void (*free)(void* data);
/* use translate_image if non NULL else run image through ocr driver then run translate_text */
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to translate_image/text */
/* NOTE: translate_image is allowed to call the ocr driver itself if it wants */
char* (*translate_text)(void* data, const char* game_text);
char* (*translate_image)(void* data, struct ocr_image_info image);
const char *ident;
} translation_driver_t;
extern const translation_driver_t translation_cached_google;
extern const translation_driver_t translation_null;
bool translation_driver_init(void);
void translation_driver_free(void);
/* returned char pointers do not need to be freed but are 1 time use, they may be destroyed on the next call to translation_driver_translate_image */
char* translation_driver_translate_image(struct ocr_image_info image);
RETRO_END_DECLS
#endif

View File

@ -1 +1 @@
<!ENTITY version "1.7.6">
<!ENTITY version "1.7.6">