mirror of
https://github.com/libretro/mgba.git
synced 2024-11-24 08:30:30 +00:00
Merge branch 'master' into port/wii
This commit is contained in:
commit
ddab7a7e44
9
CHANGES
9
CHANGES
@ -30,6 +30,8 @@ Features:
|
||||
- Libretro now supports BIOS, rumble and solar sensor
|
||||
- Implement BIOS call Stop, for sleep mode
|
||||
- Automatically load patches, if found
|
||||
- Improved video synchronization
|
||||
- Configurable audio output sample rate
|
||||
Bugfixes:
|
||||
- ARM7: Fix SWI and IRQ timings
|
||||
- GBA Audio: Force audio FIFOs to 32-bit
|
||||
@ -67,6 +69,10 @@ Bugfixes:
|
||||
- Qt: Fix analog buttons not getting unmapped
|
||||
- GBA Video: Prevent tiles < 512 from being used in modes 3 - 5
|
||||
- Qt: Fix passing command line options
|
||||
- Qt: Fix crashes on Windows by using using QMetaObject to do cross-thread calls
|
||||
- GBA Video: Fix timing on first scanline
|
||||
- GBA: Ensure cycles never go negative
|
||||
- Util: Fix formatting of floats
|
||||
Misc:
|
||||
- Qt: Handle saving input settings better
|
||||
- Debugger: Free watchpoints in addition to breakpoints
|
||||
@ -115,6 +121,9 @@ Misc:
|
||||
- Qt: Increase usability of key mapper
|
||||
- Qt: Show checkmark for window sizes
|
||||
- Qt: Set window path to loaded ROM
|
||||
- GBA Memory: Run multiple DMAs in a tight loop if they all occur before present
|
||||
- GBA Audio: Process multiple audio events at once, if necessary
|
||||
- GBA: Process multiple timer events at once, if necessary
|
||||
|
||||
0.2.1: (2015-05-13)
|
||||
Bugfixes:
|
||||
|
@ -45,13 +45,17 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (e.g. Release or Debug)" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if (NOT DEFINED LIBDIR)
|
||||
set(LIBDIR "lib")
|
||||
endif()
|
||||
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBDIR}")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
if (NOT DEFINED MANDIR)
|
||||
set(MANDIR ${CMAKE_INSTALL_MANDIR})
|
||||
endif()
|
||||
|
||||
# Function definitions
|
||||
include(FindPkgConfig)
|
||||
|
@ -30,13 +30,12 @@ The ports are vaguely usable, but by no means should be considered stable.
|
||||
|
||||
### PS Vita (port/psp2)
|
||||
* Add menu
|
||||
* Add audio
|
||||
* Fix audio
|
||||
* Make it faster
|
||||
* Threaded renderer shim
|
||||
* Hardware acceleration
|
||||
|
||||
### Wii (port/wii)
|
||||
* Add menu
|
||||
* Add audio
|
||||
* Thread support
|
||||
* Clean up video detection
|
||||
|
118
doc/mgba-qt.6
Normal file
118
doc/mgba-qt.6
Normal file
@ -0,0 +1,118 @@
|
||||
.\" Copyright (c) 2015 Anthony J. Bentley <anthony@anjbe.name>
|
||||
.\"
|
||||
.\" This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.\" License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.\" file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
.Dd July 29, 2015
|
||||
.Dt MGBA-QT 6
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mgba-qt
|
||||
.Nd Game Boy Advance emulator
|
||||
.Sh SYNOPSIS
|
||||
.Nm mgba-qt
|
||||
.Op Fl b Ar biosfile
|
||||
.Op Fl l Ar loglevel
|
||||
.Op Fl p Ar patchfile
|
||||
.Op Fl s Ar n
|
||||
.Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a Game Boy Advance emulator.
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl b Ar biosfile , Fl -bios Ar biosfile
|
||||
Specify a BIOS file to use during boot.
|
||||
If this flag is omitted,
|
||||
.Nm
|
||||
will use the BIOS specified in the configuration file,
|
||||
or a high\(hylevel emulated BIOS if none is specified.
|
||||
.It Fl l Ar loglevel
|
||||
Log messages during emulation.
|
||||
.Ar loglevel
|
||||
is a bitmask defining which types of messages to log:
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
1 \(en fatal errors
|
||||
.It
|
||||
2 \(en errors
|
||||
.It
|
||||
4 \(en warnings
|
||||
.It
|
||||
8 \(en informative messages
|
||||
.It
|
||||
16 \(en debugging messages
|
||||
.It
|
||||
32 \(en stub messages for unimplemented features
|
||||
.It
|
||||
256 \(en in\(hygame errors
|
||||
.It
|
||||
512 \(en software interrupts
|
||||
.It
|
||||
1024 \(en emulator status messages
|
||||
.It
|
||||
2048 \(en serial I/O messages
|
||||
.El
|
||||
The default is to log warnings, errors, fatal errors, and status messages.
|
||||
.It Fl p Ar patchfile , Fl -patch Ar patchfile
|
||||
Specify a patch file in BPS, IPS, or UPS format.
|
||||
.It Fl s Ar n , Fl -frameskip Ar n
|
||||
Skip every
|
||||
.Ar n
|
||||
frames.
|
||||
.El
|
||||
.Sh CONTROLS
|
||||
The default controls are as follows:
|
||||
.Bl -hang -width "Frame advance" -compact
|
||||
.It A
|
||||
.Cm x
|
||||
.It B
|
||||
.Cm z
|
||||
.It L
|
||||
.Cm a
|
||||
.It R
|
||||
.Cm s
|
||||
.It Start
|
||||
.Aq Cm Enter
|
||||
.It Select
|
||||
.Aq Cm Backspace
|
||||
.It Load state
|
||||
.Cm F1 Ns \(en Ns Cm F9
|
||||
.It Save state
|
||||
.Ao Cm Shift Ac Ns \(hy Ns Cm F1 Ns \(en Ns Cm F9
|
||||
.It Frame advance
|
||||
.Ao Cm Ctrl Ac Ns \(hy Ns Cm n
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width ~/.config/mgba/config.ini -compact
|
||||
.It Pa ~/.config/mgba/config.ini
|
||||
Default
|
||||
.Xr mgba 6
|
||||
configuration file.
|
||||
.It Pa ~/.config/mgba/qt.ini
|
||||
Default
|
||||
.Nm mgba-qt
|
||||
configuration file.
|
||||
.It Pa portable.ini
|
||||
If this file exists in the current directory,
|
||||
.Nm
|
||||
will read
|
||||
.Pa config.ini
|
||||
and
|
||||
.Pa qt.ini
|
||||
from the current directory instead of
|
||||
.Pa ~/.config/mgba .
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.An Jeffrey Pfau Aq Mt jeffrey@endrift.com
|
||||
.Sh HOMEPAGE
|
||||
.Bl -bullet
|
||||
.It
|
||||
.Lk https://mgba.io/ "mGBA homepage"
|
||||
.It
|
||||
.Lk https://github.com/mgba-emu/mgba "Development repository"
|
||||
.It
|
||||
.Lk https://github.com/mgba-emu/mgba/issues "Bug tracker"
|
||||
.It
|
||||
.Lk https://forums.mgba.io/ "Message board"
|
||||
.El
|
259
doc/mgba.6
Normal file
259
doc/mgba.6
Normal file
@ -0,0 +1,259 @@
|
||||
.\" Copyright (c) 2015 Anthony J. Bentley <anthony@anjbe.name>
|
||||
.\"
|
||||
.\" This Source Code Form is subject to the terms of the Mozilla Public
|
||||
.\" License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
.\" file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
.Dd July 29, 2015
|
||||
.Dt MGBA 6
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mgba
|
||||
.Nd Game Boy Advance emulator
|
||||
.Sh SYNOPSIS
|
||||
.Nm mgba
|
||||
.Op Fl 123456dfg
|
||||
.Op Fl b Ar biosfile
|
||||
.Op Fl c Ar cheatfile
|
||||
.Op Fl l Ar loglevel
|
||||
.Op Fl p Ar patchfile
|
||||
.Op Fl s Ar n
|
||||
.Op Fl v Ar moviefile
|
||||
.Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a Game Boy Advance emulator.
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl 1
|
||||
Scale the window 1\(mu.
|
||||
.It Fl 2
|
||||
Scale the window 2\(mu.
|
||||
.It Fl 3
|
||||
Scale the window 3\(mu.
|
||||
.It Fl 4
|
||||
Scale the window 4\(mu.
|
||||
.It Fl 5
|
||||
Scale the window 5\(mu.
|
||||
.It Fl 6
|
||||
Scale the window 6\(mu.
|
||||
.It Fl b Ar biosfile , Fl -bios Ar biosfile
|
||||
Specify a BIOS file to use during boot.
|
||||
If this flag is omitted,
|
||||
.Nm
|
||||
will use the BIOS specified in the configuration file,
|
||||
or a high\(hylevel emulated BIOS if none is specified.
|
||||
.It Fl c Ar cheatfile , Fl -cheats Ar cheatfile
|
||||
Apply cheat codes from
|
||||
.Ar cheatfile .
|
||||
.It Fl d
|
||||
Start emulating via the command\(hyline debugger.
|
||||
.It Fl f
|
||||
Start the emulator full\(hyscreen.
|
||||
.It Fl g
|
||||
Start a
|
||||
.Xr gdb 1
|
||||
session.
|
||||
By default the session starts on port 2345.
|
||||
.It Fl l Ar loglevel
|
||||
Log messages during emulation to
|
||||
.Dv stdout .
|
||||
.Ar loglevel
|
||||
is a bitmask defining which types of messages to log:
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
1 \(en fatal errors
|
||||
.It
|
||||
2 \(en errors
|
||||
.It
|
||||
4 \(en warnings
|
||||
.It
|
||||
8 \(en informative messages
|
||||
.It
|
||||
16 \(en debugging messages
|
||||
.It
|
||||
32 \(en stub messages for unimplemented features
|
||||
.It
|
||||
256 \(en in\(hygame errors
|
||||
.It
|
||||
512 \(en software interrupts
|
||||
.It
|
||||
1024 \(en emulator status messages
|
||||
.It
|
||||
2048 \(en serial I/O messages
|
||||
.El
|
||||
The default is to log warnings, errors, fatal errors, and status messages.
|
||||
.It Fl p Ar patchfile , Fl -patch Ar patchfile
|
||||
Specify a patch file in BPS, IPS, or UPS format.
|
||||
.It Fl s Ar n , Fl -frameskip Ar n
|
||||
Skip every
|
||||
.Ar n
|
||||
frames.
|
||||
.It Fl v Ar moviefile , Fl -movie Ar moviefile
|
||||
Play back a movie of recording input from
|
||||
.Ar moviefile .
|
||||
.El
|
||||
.Sh CONTROLS
|
||||
The default controls are as follows:
|
||||
.Bl -hang -width "Frame advance" -compact
|
||||
.It A
|
||||
.Cm x
|
||||
.It B
|
||||
.Cm z
|
||||
.It L
|
||||
.Cm a
|
||||
.It R
|
||||
.Cm s
|
||||
.It Start
|
||||
.Aq Cm Enter
|
||||
.It Select
|
||||
.Aq Cm Backspace
|
||||
.It Load state
|
||||
.Cm F1 Ns \(en Ns Cm F9
|
||||
.It Save state
|
||||
.Ao Cm Shift Ac Ns \(hy Ns Cm F1 Ns \(en Ns Cm F9
|
||||
.It Frame advance
|
||||
.Ao Cm Ctrl Ac Ns \(hy Ns Cm n
|
||||
.El
|
||||
.Sh DEBUGGER
|
||||
When
|
||||
.Nm
|
||||
is run with the
|
||||
.Fl d
|
||||
option, the command\(hyline debugger is enabled.
|
||||
It supports the following commands:
|
||||
.Pp
|
||||
.Bl -tag -compact -width 1
|
||||
.It Cm b Ns Oo Cm reak Oc Ar address
|
||||
.It Cm b Ns Oo Cm reak Oc Ns Cm /a Ar address
|
||||
.It Cm b Ns Oo Cm reak Oc Ns Cm /t Ar address
|
||||
Set a breakpoint \(en ARM
|
||||
.Pq Ql /a ,
|
||||
Thumb
|
||||
.Pq Ql /t ,
|
||||
or the current CPU mode \(en at
|
||||
.Ar address .
|
||||
.It Cm c Ns Op Cm ontinue
|
||||
Continue execution.
|
||||
.It Cm d Ns Oo Cm elete Oc Ar address
|
||||
Delete a breakpoint at
|
||||
.Ar address .
|
||||
.It Cm dis Ns Oo Cm asm Oc Op Ar address Op Ar count
|
||||
.It Cm dis Ns Oo Cm asm Oc Ns Cm /a Op Ar address Op Ar count
|
||||
.It Cm dis Ns Oo Cm asm Oc Ns Cm /t Op Ar address Op Ar count
|
||||
.It Cm dis Ns Oo Cm assemble Oc Op Ar address Op Ar count
|
||||
.It Cm dis Ns Oo Cm assemble Oc Ns Cm /a Op Ar address Op Ar count
|
||||
.It Cm dis Ns Oo Cm assemble Oc Ns Cm /t Op Ar address Op Ar count
|
||||
Disassemble
|
||||
.Ar count
|
||||
instructions starting at
|
||||
.Ar address ,
|
||||
as ARM
|
||||
.Pq Ql /a ,
|
||||
Thumb
|
||||
.Pq Ql /t ,
|
||||
or the current CPU mode.
|
||||
If
|
||||
.Ar count
|
||||
is not specified, only disassemble the instruction at
|
||||
.Ar address .
|
||||
If
|
||||
.Ar address
|
||||
is not specified, only disassemble the current address.
|
||||
.It Cm h Ns Op Cm elp
|
||||
Print help.
|
||||
.It Cm i Ns Op Cm nfo
|
||||
.It Cm status
|
||||
Print the current contents of general\(hypurpose registers and the current
|
||||
program state register, and disassemble the current instruction.
|
||||
.It Cm n Ns Op Cm ext
|
||||
Execute the next instruction.
|
||||
.It Cm p Ns Oo Cm rint Oc Ar value ...
|
||||
.It Cm p Ns Oo Cm rint Oc Ns Cm /t Ar value ...
|
||||
.It Cm p Ns Oo Cm rint Oc Ns Cm /x Ar value ...
|
||||
Print one or more
|
||||
.Ar value Ns s
|
||||
as binary
|
||||
.Pq Ql /t ,
|
||||
hexadecimal
|
||||
.Pq Ql /x ,
|
||||
or decimal.
|
||||
.It Cm q Ns Op Cm uit
|
||||
Quit the emulator.
|
||||
.It Cm reset
|
||||
Reset the emulation.
|
||||
.It Cm r/1 Ar address
|
||||
.It Cm r/2 Ar address
|
||||
.It Cm r/4 Ar address
|
||||
Read a byte
|
||||
.Pq Ql /1 ,
|
||||
halfword
|
||||
.Pq Ql /2 ,
|
||||
or word
|
||||
.Pq Ql /4
|
||||
from
|
||||
.Ar address .
|
||||
.It Cm w Ns Oo Cm atch Oc Ar address
|
||||
Set a watchpoint at
|
||||
.Ar address .
|
||||
.It Cm w/1 Ar address data
|
||||
.It Cm w/2 Ar address data
|
||||
.It Cm w/4 Ar address data
|
||||
Write
|
||||
.Ar data
|
||||
as a byte
|
||||
.Pq Ql /1 ,
|
||||
halfword
|
||||
.Pq Ql /2 ,
|
||||
or word
|
||||
.Pq Ql /4
|
||||
to
|
||||
.Ar address .
|
||||
.It Cm w/r Ar register data
|
||||
Write
|
||||
.Ar data
|
||||
as a word to
|
||||
.Ar register .
|
||||
.It Cm x/1 Ar address Op Ar count
|
||||
.It Cm x/2 Ar address Op Ar count
|
||||
.It Cm x/4 Ar address Op Ar count
|
||||
Examine
|
||||
.Ar count
|
||||
bytes
|
||||
.Pq Ql /1 ,
|
||||
halfwords
|
||||
.Pq Ql /2 ,
|
||||
or words
|
||||
.Pq Ql /4
|
||||
from
|
||||
.Ar address .
|
||||
If
|
||||
.Ar count
|
||||
is not specified, examine 16 bytes, 8 halfwords, or 4 words.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width ~/.config/mgba/config.ini -compact
|
||||
.It Pa ~/.config/mgba/config.ini
|
||||
Default
|
||||
.Nm
|
||||
configuration file.
|
||||
.It Pa portable.ini
|
||||
If this file exists in the current directory,
|
||||
.Nm
|
||||
will read
|
||||
.Pa config.ini
|
||||
from the current directory instead of
|
||||
.Pa ~/.config/mgba .
|
||||
.El
|
||||
.Sh AUTHORS
|
||||
.An Jeffrey Pfau Aq Mt jeffrey@endrift.com
|
||||
.Sh HOMEPAGE
|
||||
.Bl -bullet
|
||||
.It
|
||||
.Lk https://mgba.io/ "mGBA homepage"
|
||||
.It
|
||||
.Lk https://github.com/mgba-emu/mgba "Development repository"
|
||||
.It
|
||||
.Lk https://github.com/mgba-emu/mgba/issues "Bug tracker"
|
||||
.It
|
||||
.Lk https://forums.mgba.io/ "Message board"
|
||||
.El
|
@ -31,7 +31,7 @@
|
||||
DEFINE_THUMB_DECODER(NAME, MNEMONIC, \
|
||||
info->op1.reg = opcode & 0x0007; \
|
||||
info->memory.baseReg = (opcode >> 3) & 0x0007; \
|
||||
info->memory.offset.immediate = ((opcode >> 6) & 0x0007) * WIDTH; \
|
||||
info->memory.offset.immediate = ((opcode >> 6) & 0x001F) * WIDTH; \
|
||||
info->memory.width = (enum ARMMemoryAccessType) WIDTH; \
|
||||
info->operandFormat = ARM_OPERAND_REGISTER_1 | \
|
||||
ARM_OPERAND_AFFECTED_1 | \
|
||||
|
@ -18,7 +18,9 @@ static const char* ERROR_OVERFLOW = "Arguments overflow";
|
||||
|
||||
static struct CLIDebugger* _activeDebugger;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
#endif
|
||||
static void _continue(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _disassemble(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
static void _disassembleArm(struct CLIDebugger*, struct CLIDebugVector*);
|
||||
@ -99,7 +101,9 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = {
|
||||
{ "x/1", _dumpByte, CLIDVParse, "Examine bytes at a specified offset" },
|
||||
{ "x/2", _dumpHalfword, CLIDVParse, "Examine halfwords at a specified offset" },
|
||||
{ "x/4", _dumpWord, CLIDVParse, "Examine words at a specified offset" },
|
||||
#ifndef NDEBUG
|
||||
{ "!", _breakInto, 0, "Break into attached debugger (for developers)" },
|
||||
#endif
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@ -114,6 +118,7 @@ static inline void _printPSR(union PSR psr) {
|
||||
psr.t ? 'T' : '-');
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void _handleDeath(int sig) {
|
||||
UNUSED(sig);
|
||||
printf("No debugger attached!\n");
|
||||
@ -135,6 +140,7 @@ static void _breakInto(struct CLIDebugger* debugger, struct CLIDebugVector* dv)
|
||||
#endif
|
||||
sigaction(SIGTRAP, &osa, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _continue(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {
|
||||
UNUSED(dv);
|
||||
|
@ -167,7 +167,7 @@ void GBAAudioResizeBuffer(struct GBAAudio* audio, size_t samples) {
|
||||
int32_t GBAAudioProcessEvents(struct GBAAudio* audio, int32_t cycles) {
|
||||
audio->nextEvent -= cycles;
|
||||
audio->eventDiff += cycles;
|
||||
if (audio->nextEvent <= 0) {
|
||||
while (audio->nextEvent <= 0) {
|
||||
audio->nextEvent = INT_MAX;
|
||||
if (audio->enable) {
|
||||
if (audio->playingCh1 && !audio->ch1.envelope.dead) {
|
||||
|
@ -184,6 +184,11 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
|
||||
int32_t cycles = cpu->nextEvent;
|
||||
int32_t nextEvent = INT_MAX;
|
||||
int32_t testEvent;
|
||||
#ifndef NDEBUG
|
||||
if (cycles < 0) {
|
||||
GBALog(gba, GBA_LOG_FATAL, "Negative cycles passed: %i", cycles);
|
||||
}
|
||||
#endif
|
||||
|
||||
gba->bus = cpu->prefetch[1];
|
||||
if (cpu->executionMode == MODE_THUMB) {
|
||||
@ -239,7 +244,7 @@ static int32_t GBATimersProcessEvents(struct GBA* gba, int32_t cycles) {
|
||||
if (timer->enable) {
|
||||
timer->nextEvent -= cycles;
|
||||
timer->lastEvent -= cycles;
|
||||
if (timer->nextEvent <= 0) {
|
||||
while (timer->nextEvent <= 0) {
|
||||
timer->lastEvent = timer->nextEvent;
|
||||
timer->nextEvent += timer->overflowInterval;
|
||||
gba->memory.io[REG_TM0CNT_LO >> 1] = timer->reload;
|
||||
|
@ -612,6 +612,7 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
|
||||
hw->readWrite = state->hw.readWrite;
|
||||
hw->pinState = state->hw.pinState;
|
||||
hw->direction = state->hw.pinDirection;
|
||||
hw->devices = state->hw.devices;
|
||||
hw->rtc = state->hw.rtc;
|
||||
hw->gyroSample = state->hw.gyroSample;
|
||||
hw->gyroEdge = state->hw.gyroEdge;
|
||||
@ -624,4 +625,7 @@ void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASer
|
||||
hw->gbpInputsPosted = state->hw.gbpInputsPosted;
|
||||
hw->gbpTxPosition = state->hw.gbpTxPosition;
|
||||
hw->gbpNextEvent = state->hw.gbpNextEvent;
|
||||
if (hw->devices & HW_GB_PLAYER) {
|
||||
GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
|
||||
}
|
||||
}
|
||||
|
@ -446,8 +446,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||
} else {
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||
LOAD_BAD;
|
||||
uint32_t v2 = value;
|
||||
LOAD_16(value, address & 2, &v2);
|
||||
value = (value >> ((address & 2) * 8)) & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
case REGION_WORKING_RAM:
|
||||
@ -506,8 +505,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||
default:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||
LOAD_BAD;
|
||||
uint32_t v2 = value;
|
||||
LOAD_16(value, address & 2, &v2);
|
||||
value = (value >> ((address & 2) * 8)) & 0xFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1405,7 +1403,7 @@ int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
|
||||
}
|
||||
memory->nextDMA -= cycles;
|
||||
memory->eventDiff += cycles;
|
||||
if (memory->nextDMA <= 0) {
|
||||
while (memory->nextDMA <= 0) {
|
||||
struct GBADMA* dma = &memory->dma[memory->activeDMA];
|
||||
GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
|
||||
GBAMemoryUpdateDMAs(gba, memory->eventDiff);
|
||||
|
@ -87,6 +87,10 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: CPU cycles are negative");
|
||||
error = true;
|
||||
}
|
||||
if (state->cpu.nextEvent < 0) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: Next event is negative");
|
||||
error = true;
|
||||
}
|
||||
if (state->video.eventDiff < 0) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: video eventDiff is negative");
|
||||
error = true;
|
||||
@ -99,6 +103,10 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: overflowInterval is negative");
|
||||
error = true;
|
||||
}
|
||||
if (state->timers[0].nextEvent < 0 || state->timers[1].nextEvent < 0 || state->timers[2].nextEvent < 0 || state->timers[3].nextEvent < 0) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: timer nextEvent is negative");
|
||||
error = true;
|
||||
}
|
||||
if (state->audio.eventDiff < 0) {
|
||||
GBALog(gba, GBA_LOG_WARN, "Savestate is corrupted: audio eventDiff is negative");
|
||||
error = true;
|
||||
|
@ -247,6 +247,7 @@ void GBAConfigMap(const struct GBAConfig* config, struct GBAOptions* opts) {
|
||||
if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) {
|
||||
opts->audioBuffers = audioBuffers;
|
||||
}
|
||||
_lookupUIntValue(config, "sampleRate", &opts->sampleRate);
|
||||
|
||||
int fakeBool;
|
||||
if (_lookupIntValue(config, "useBios", &fakeBool)) {
|
||||
@ -305,6 +306,7 @@ void GBAConfigLoadDefaults(struct GBAConfig* config, const struct GBAOptions* op
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferInterval", opts->rewindBufferInterval);
|
||||
ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget);
|
||||
ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers);
|
||||
ConfigurationSetUIntValue(&config->defaultsTable, 0, "sampleRate", opts->sampleRate);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "audioSync", opts->audioSync);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "videoSync", opts->videoSync);
|
||||
ConfigurationSetIntValue(&config->defaultsTable, 0, "fullscreen", opts->fullscreen);
|
||||
|
@ -29,6 +29,7 @@ struct GBAOptions {
|
||||
int rewindBufferInterval;
|
||||
float fpsTarget;
|
||||
size_t audioBuffers;
|
||||
unsigned sampleRate;
|
||||
|
||||
int fullscreen;
|
||||
int width;
|
||||
|
@ -67,7 +67,7 @@ void GBAVideoReset(struct GBAVideo* video) {
|
||||
video->lastHblank = 0;
|
||||
video->nextHblank = VIDEO_HDRAW_LENGTH;
|
||||
video->nextEvent = video->nextHblank;
|
||||
video->eventDiff = video->nextEvent;
|
||||
video->eventDiff = 0;
|
||||
|
||||
video->nextHblankIRQ = 0;
|
||||
video->nextVblankIRQ = 0;
|
||||
|
@ -145,7 +145,7 @@
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="extraLinks">
|
||||
<property name="text">
|
||||
<string><a href="http://mgba.io/">Website</a> • <a href="https://forumsmgba.io/">Forums / Support</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> • <a href="https://github.com/mgba-emu/mgba/blob/{gitBranch}/LICENSE">License</a></string>
|
||||
<string><a href="http://mgba.io/">Website</a> • <a href="https://forums.mgba.io/">Forums / Support</a> • <a href="https://github.com/mgba-emu/mgba/tree/{gitBranch}">Source</a> • <a href="https://github.com/mgba-emu/mgba/blob/{gitBranch}/LICENSE">License</a></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
virtual void setInput(GBAThread* input);
|
||||
int getBufferSamples() const { return m_samples; }
|
||||
virtual unsigned sampleRate() const = 0;
|
||||
|
||||
public slots:
|
||||
virtual void start() = 0;
|
||||
@ -39,7 +40,7 @@ public slots:
|
||||
virtual void setBufferSamples(int samples) = 0;
|
||||
virtual void inputParametersChanged() = 0;
|
||||
|
||||
virtual unsigned sampleRate() const = 0;
|
||||
virtual void requestSampleRate(unsigned) = 0;
|
||||
|
||||
protected:
|
||||
GBAThread* input() { return m_context; }
|
||||
|
@ -20,6 +20,7 @@ AudioProcessorQt::AudioProcessorQt(QObject* parent)
|
||||
: AudioProcessor(parent)
|
||||
, m_audioOutput(nullptr)
|
||||
, m_device(nullptr)
|
||||
, m_sampleRate(44100)
|
||||
{
|
||||
}
|
||||
|
||||
@ -45,7 +46,7 @@ void AudioProcessorQt::start() {
|
||||
|
||||
if (!m_audioOutput) {
|
||||
QAudioFormat format;
|
||||
format.setSampleRate(44100);
|
||||
format.setSampleRate(m_sampleRate);
|
||||
format.setChannelCount(2);
|
||||
format.setSampleSize(16);
|
||||
format.setCodec("audio/pcm");
|
||||
@ -84,6 +85,15 @@ void AudioProcessorQt::inputParametersChanged() {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorQt::requestSampleRate(unsigned rate) {
|
||||
m_sampleRate = rate;
|
||||
if (m_device) {
|
||||
QAudioFormat format(m_audioOutput->format());
|
||||
format.setSampleRate(rate);
|
||||
m_device->setFormat(format);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned AudioProcessorQt::sampleRate() const {
|
||||
if (!m_audioOutput) {
|
||||
return 0;
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
AudioProcessorQt(QObject* parent = nullptr);
|
||||
|
||||
virtual void setInput(GBAThread* input);
|
||||
virtual unsigned sampleRate() const override;
|
||||
|
||||
public slots:
|
||||
virtual void start();
|
||||
@ -28,11 +29,12 @@ public slots:
|
||||
virtual void setBufferSamples(int samples);
|
||||
virtual void inputParametersChanged();
|
||||
|
||||
virtual unsigned sampleRate() const override;
|
||||
virtual void requestSampleRate(unsigned) override;
|
||||
|
||||
private:
|
||||
QAudioOutput* m_audioOutput;
|
||||
AudioDevice* m_device;
|
||||
unsigned m_sampleRate;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ using namespace QGBA;
|
||||
|
||||
AudioProcessorSDL::AudioProcessorSDL(QObject* parent)
|
||||
: AudioProcessor(parent)
|
||||
, m_audio()
|
||||
, m_audio{ 2048, 44100 }
|
||||
{
|
||||
}
|
||||
|
||||
@ -55,6 +55,18 @@ void AudioProcessorSDL::setBufferSamples(int samples) {
|
||||
void AudioProcessorSDL::inputParametersChanged() {
|
||||
}
|
||||
|
||||
unsigned AudioProcessorSDL::sampleRate() const {
|
||||
return m_audio.obtainedSpec.freq;
|
||||
void AudioProcessorSDL::requestSampleRate(unsigned rate) {
|
||||
m_audio.sampleRate = rate;
|
||||
if (m_audio.thread) {
|
||||
GBASDLDeinitAudio(&m_audio);
|
||||
GBASDLInitAudio(&m_audio, input());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned AudioProcessorSDL::sampleRate() const {
|
||||
if (m_audio.thread) {
|
||||
return m_audio.obtainedSpec.freq;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ public:
|
||||
AudioProcessorSDL(QObject* parent = nullptr);
|
||||
~AudioProcessorSDL();
|
||||
|
||||
virtual unsigned sampleRate() const override;
|
||||
|
||||
public slots:
|
||||
virtual void start();
|
||||
virtual void pause();
|
||||
@ -29,7 +31,7 @@ public slots:
|
||||
virtual void setBufferSamples(int samples);
|
||||
virtual void inputParametersChanged();
|
||||
|
||||
virtual unsigned sampleRate() const override;
|
||||
virtual void requestSampleRate(unsigned) override;
|
||||
|
||||
private:
|
||||
GBASDLAudio m_audio;
|
||||
|
@ -170,6 +170,9 @@ if(UNIX AND NOT APPLE)
|
||||
install(CODE "execute_process(COMMAND ${DESKTOP_FILE_INSTALL} \"${CMAKE_SOURCE_DIR}/res/mgba-qt.desktop\" --dir \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/share/applications/\")")
|
||||
endif()
|
||||
endif()
|
||||
if(UNIX)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba-qt.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-qt)
|
||||
endif()
|
||||
if(APPLE OR WIN32)
|
||||
set_target_properties(${BINARY_NAME}-qt PROPERTIES OUTPUT_NAME ${PROJECT_NAME})
|
||||
endif()
|
||||
|
@ -99,19 +99,29 @@ void CheatsView::removeSet() {
|
||||
}
|
||||
|
||||
void CheatsView::enterCheat(std::function<bool(GBACheatSet*, const char*)> callback) {
|
||||
GBACheatSet* set;
|
||||
GBACheatSet* set = nullptr;
|
||||
QModelIndexList selection = m_ui.cheatList->selectionModel()->selectedIndexes();
|
||||
if (selection.count() != 1) {
|
||||
return;
|
||||
QModelIndex index;
|
||||
if (selection.count() == 0) {
|
||||
set = new GBACheatSet;
|
||||
GBACheatSetInit(set, nullptr);
|
||||
} else if (selection.count() == 1) {
|
||||
index = selection[0];
|
||||
set = m_model.itemAt(index);
|
||||
}
|
||||
set = m_model.itemAt(selection[0]);
|
||||
|
||||
if (!set) {
|
||||
return;
|
||||
}
|
||||
m_controller->threadInterrupt();
|
||||
if (selection.count() == 0) {
|
||||
m_model.addSet(set);
|
||||
index = m_model.index(m_model.rowCount() - 1, 0, QModelIndex());
|
||||
m_ui.cheatList->selectionModel()->select(index, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
|
||||
}
|
||||
QStringList cheats = m_ui.codeEntry->toPlainText().split('\n', QString::SkipEmptyParts);
|
||||
for (const QString& string : cheats) {
|
||||
m_model.beginAppendRow(selection[0]);
|
||||
m_model.beginAppendRow(index);
|
||||
callback(set, string.toUtf8().constData());
|
||||
m_model.endAppendRow();
|
||||
}
|
||||
|
@ -107,7 +107,8 @@ ConfigController::ConfigController(QObject* parent)
|
||||
m_opts.audioSync = GameController::AUDIO_SYNC;
|
||||
m_opts.videoSync = GameController::VIDEO_SYNC;
|
||||
m_opts.fpsTarget = 60;
|
||||
m_opts.audioBuffers = 2048;
|
||||
m_opts.audioBuffers = 1536;
|
||||
m_opts.sampleRate = 44100;
|
||||
m_opts.volume = GBA_AUDIO_VOLUME_MAX;
|
||||
m_opts.logLevel = GBA_LOG_WARN | GBA_LOG_ERROR | GBA_LOG_FATAL | GBA_LOG_STATUS;
|
||||
m_opts.rewindEnable = false;
|
||||
|
@ -22,7 +22,7 @@ Display::Driver Display::s_driver = Display::Driver::QT;
|
||||
|
||||
Display* Display::create(QWidget* parent) {
|
||||
#ifdef BUILD_GL
|
||||
QGLFormat format(QGLFormat(QGL::Rgba | QGL::DoubleBuffer));
|
||||
QGLFormat format(QGLFormat(QGL::Rgba | QGL::SingleBuffer));
|
||||
format.setSwapInterval(1);
|
||||
#endif
|
||||
|
||||
|
@ -118,7 +118,8 @@ void DisplayGL::filter(bool filter) {
|
||||
|
||||
void DisplayGL::framePosted(const uint32_t* buffer) {
|
||||
if (m_drawThread && buffer) {
|
||||
QMetaObject::invokeMethod(m_painter, "setBacking", Q_ARG(const uint32_t*, buffer));
|
||||
m_painter->enqueue(buffer);
|
||||
QMetaObject::invokeMethod(m_painter, "draw");
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +153,19 @@ PainterGL::PainterGL(QGLWidget* parent)
|
||||
m_backend.d.user = this;
|
||||
m_backend.d.filter = false;
|
||||
m_backend.d.lockAspectRatio = false;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
m_free.append(new uint32_t[256 * 256]);
|
||||
}
|
||||
}
|
||||
|
||||
PainterGL::~PainterGL() {
|
||||
while (!m_queue.isEmpty()) {
|
||||
delete[] m_queue.dequeue();
|
||||
}
|
||||
for (auto item : m_free) {
|
||||
delete[] item;
|
||||
}
|
||||
}
|
||||
|
||||
void PainterGL::setContext(GBAThread* context) {
|
||||
@ -162,15 +176,6 @@ void PainterGL::setMessagePainter(MessagePainter* messagePainter) {
|
||||
m_messagePainter = messagePainter;
|
||||
}
|
||||
|
||||
void PainterGL::setBacking(const uint32_t* backing) {
|
||||
m_gl->makeCurrent();
|
||||
m_backend.d.postFrame(&m_backend.d, backing);
|
||||
if (m_active) {
|
||||
draw();
|
||||
}
|
||||
m_gl->doneCurrent();
|
||||
}
|
||||
|
||||
void PainterGL::resize(const QSize& size) {
|
||||
m_size = size;
|
||||
if (m_active) {
|
||||
@ -200,7 +205,11 @@ void PainterGL::start() {
|
||||
}
|
||||
|
||||
void PainterGL::draw() {
|
||||
if (GBASyncWaitFrameStart(&m_context->sync, m_context->frameskip)) {
|
||||
if (m_queue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (GBASyncWaitFrameStart(&m_context->sync, m_context->frameskip) || !m_queue.isEmpty()) {
|
||||
dequeue();
|
||||
m_painter.begin(m_gl->context()->device());
|
||||
performDraw();
|
||||
m_painter.end();
|
||||
@ -209,6 +218,9 @@ void PainterGL::draw() {
|
||||
} else {
|
||||
GBASyncWaitFrameEnd(&m_context->sync);
|
||||
}
|
||||
if (!m_queue.isEmpty()) {
|
||||
QMetaObject::invokeMethod(this, "draw", Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void PainterGL::forceDraw() {
|
||||
@ -221,6 +233,7 @@ void PainterGL::forceDraw() {
|
||||
void PainterGL::stop() {
|
||||
m_active = false;
|
||||
m_gl->makeCurrent();
|
||||
dequeueAll();
|
||||
m_backend.d.clear(&m_backend.d);
|
||||
m_backend.d.swap(&m_backend.d);
|
||||
m_backend.d.deinit(&m_backend.d);
|
||||
@ -231,9 +244,6 @@ void PainterGL::stop() {
|
||||
|
||||
void PainterGL::pause() {
|
||||
m_active = false;
|
||||
// Make sure both buffers are filled
|
||||
forceDraw();
|
||||
forceDraw();
|
||||
}
|
||||
|
||||
void PainterGL::unpause() {
|
||||
@ -250,3 +260,41 @@ void PainterGL::performDraw() {
|
||||
m_messagePainter->paint(&m_painter);
|
||||
}
|
||||
}
|
||||
|
||||
void PainterGL::enqueue(const uint32_t* backing) {
|
||||
m_mutex.lock();
|
||||
uint32_t* buffer;
|
||||
if (m_free.isEmpty()) {
|
||||
buffer = m_queue.dequeue();
|
||||
} else {
|
||||
buffer = m_free.takeLast();
|
||||
}
|
||||
memcpy(buffer, backing, 256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
||||
m_queue.enqueue(buffer);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
void PainterGL::dequeue() {
|
||||
m_mutex.lock();
|
||||
if (m_queue.isEmpty()) {
|
||||
m_mutex.unlock();
|
||||
return;
|
||||
}
|
||||
uint32_t* buffer = m_queue.dequeue();
|
||||
m_backend.d.postFrame(&m_backend.d, buffer);
|
||||
m_free.append(buffer);
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
void PainterGL::dequeueAll() {
|
||||
uint32_t* buffer = 0;
|
||||
m_mutex.lock();
|
||||
while (!m_queue.isEmpty()) {
|
||||
buffer = m_queue.dequeue();
|
||||
m_free.append(buffer);
|
||||
}
|
||||
if (buffer) {
|
||||
m_backend.d.postFrame(&m_backend.d, buffer);
|
||||
}
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include "Display.h"
|
||||
|
||||
#include <QGLWidget>
|
||||
#include <QList>
|
||||
#include <QMouseEvent>
|
||||
#include <QQueue>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
@ -74,12 +76,13 @@ Q_OBJECT
|
||||
|
||||
public:
|
||||
PainterGL(QGLWidget* parent);
|
||||
~PainterGL();
|
||||
|
||||
void setContext(GBAThread*);
|
||||
void setMessagePainter(MessagePainter*);
|
||||
void enqueue(const uint32_t* backing);
|
||||
|
||||
public slots:
|
||||
void setBacking(const uint32_t*);
|
||||
void forceDraw();
|
||||
void draw();
|
||||
void start();
|
||||
@ -92,8 +95,13 @@ public slots:
|
||||
|
||||
private:
|
||||
void performDraw();
|
||||
void dequeue();
|
||||
void dequeueAll();
|
||||
|
||||
QList<uint32_t*> m_free;
|
||||
QQueue<uint32_t*> m_queue;
|
||||
QPainter m_painter;
|
||||
QMutex m_mutex;
|
||||
QGLWidget* m_gl;
|
||||
bool m_active;
|
||||
GBAThread* m_context;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <QIcon>
|
||||
|
||||
extern "C" {
|
||||
#include "gba/supervisor/thread.h"
|
||||
#include "platform/commandline.h"
|
||||
#include "util/socket.h"
|
||||
}
|
||||
@ -33,10 +34,13 @@ GBAApp::GBAApp(int& argc, char* argv[])
|
||||
SDL_Init(SDL_INIT_NOPARACHUTE);
|
||||
#endif
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
setWindowIcon(QIcon(":/res/mgba-1024.png"));
|
||||
#endif
|
||||
|
||||
SocketSubsystemInit();
|
||||
qRegisterMetaType<const uint32_t*>("const uint32_t*");
|
||||
qRegisterMetaType<GBAThread*>("GBAThread*");
|
||||
|
||||
QApplication::setApplicationName(projectName);
|
||||
QApplication::setApplicationVersion(projectVersion);
|
||||
@ -53,6 +57,7 @@ GBAApp::GBAApp(int& argc, char* argv[])
|
||||
return;
|
||||
}
|
||||
|
||||
AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
|
||||
Window* w = new Window(&m_configController);
|
||||
connect(w, &Window::destroyed, [this]() {
|
||||
m_windows[0] = nullptr;
|
||||
@ -67,9 +72,6 @@ GBAApp::GBAApp(int& argc, char* argv[])
|
||||
freeArguments(&args);
|
||||
w->show();
|
||||
|
||||
AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
|
||||
w->controller()->reloadAudioDriver();
|
||||
|
||||
w->controller()->setMultiplayerController(&m_multiplayer);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
using namespace QGBA;
|
||||
|
||||
GDBWindow::GDBWindow(GDBController* controller, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
: QDialog(parent)
|
||||
, m_gdbController(controller)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowFullscreenButtonHint);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#ifndef QGBA_GDB_WINDOW
|
||||
#define QGBA_GDB_WINDOW
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
@ -15,7 +15,7 @@ namespace QGBA {
|
||||
|
||||
class GDBController;
|
||||
|
||||
class GDBWindow : public QWidget {
|
||||
class GDBWindow : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -31,7 +31,8 @@ using namespace std;
|
||||
|
||||
GameController::GameController(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_drawContext(new uint32_t[256 * 256])
|
||||
, m_drawContext(new uint32_t[256 * VIDEO_HORIZONTAL_PIXELS])
|
||||
, m_frontBuffer(new uint32_t[256 * 256])
|
||||
, m_threadContext()
|
||||
, m_activeKeys(0)
|
||||
, m_inactiveKeys(0)
|
||||
@ -86,7 +87,9 @@ GameController::GameController(QObject* parent)
|
||||
|
||||
m_threadContext.startCallback = [](GBAThread* context) {
|
||||
GameController* controller = static_cast<GameController*>(context->userData);
|
||||
controller->m_audioProcessor->setInput(context);
|
||||
if (controller->m_audioProcessor) {
|
||||
controller->m_audioProcessor->setInput(context);
|
||||
}
|
||||
context->gba->luminanceSource = &controller->m_lux;
|
||||
GBARTCGenericSourceInit(&controller->m_rtc, context->gba);
|
||||
context->gba->rtcSource = &controller->m_rtc.d;
|
||||
@ -111,24 +114,25 @@ GameController::GameController(QObject* parent)
|
||||
vf->truncate(vf, 0);
|
||||
}
|
||||
}
|
||||
controller->gameStarted(context);
|
||||
QMetaObject::invokeMethod(controller, "gameStarted", Q_ARG(GBAThread*, context));
|
||||
};
|
||||
|
||||
m_threadContext.cleanCallback = [](GBAThread* context) {
|
||||
GameController* controller = static_cast<GameController*>(context->userData);
|
||||
controller->gameStopped(context);
|
||||
QMetaObject::invokeMethod(controller, "gameStopped", Q_ARG(GBAThread*, context));
|
||||
};
|
||||
|
||||
m_threadContext.frameCallback = [](GBAThread* context) {
|
||||
GameController* controller = static_cast<GameController*>(context->userData);
|
||||
if (GBASyncDrawingFrame(&controller->m_threadContext.sync)) {
|
||||
controller->frameAvailable(controller->m_drawContext);
|
||||
memcpy(controller->m_frontBuffer, controller->m_drawContext, 256 * VIDEO_HORIZONTAL_PIXELS * BYTES_PER_PIXEL);
|
||||
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, controller->m_frontBuffer));
|
||||
} else {
|
||||
controller->frameAvailable(nullptr);
|
||||
QMetaObject::invokeMethod(controller, "frameAvailable", Q_ARG(const uint32_t*, nullptr));
|
||||
}
|
||||
if (controller->m_pauseAfterFrame.testAndSetAcquire(true, false)) {
|
||||
GBAThreadPauseFromThread(context);
|
||||
controller->gamePaused(&controller->m_threadContext);
|
||||
QMetaObject::invokeMethod(controller, "gamePaused", Q_ARG(GBAThread*, context));
|
||||
}
|
||||
};
|
||||
|
||||
@ -157,7 +161,7 @@ GameController::GameController(QObject* parent)
|
||||
va_copy(argc, args);
|
||||
int immediate = va_arg(argc, int);
|
||||
va_end(argc);
|
||||
controller->unimplementedBiosCall(immediate);
|
||||
QMetaObject::invokeMethod(controller, "unimplementedBiosCall", Q_ARG(int, immediate));
|
||||
} else if (level == GBA_LOG_STATUS) {
|
||||
// Slot 0 is reserved for suspend points
|
||||
if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) {
|
||||
@ -185,9 +189,9 @@ GameController::GameController(QObject* parent)
|
||||
}
|
||||
QString message(QString().vsprintf(format, args));
|
||||
if (level == GBA_LOG_STATUS) {
|
||||
controller->statusPosted(message);
|
||||
QMetaObject::invokeMethod(controller, "statusPosted", Q_ARG(const QString&, message));
|
||||
}
|
||||
controller->postLog(level, message);
|
||||
QMetaObject::invokeMethod(controller, "postLog", Q_ARG(int, level), Q_ARG(const QString&, message));
|
||||
};
|
||||
|
||||
connect(&m_rewindTimer, &QTimer::timeout, [this]() {
|
||||
@ -216,6 +220,7 @@ GameController::~GameController() {
|
||||
GBACheatDeviceDestroy(&m_cheatDevice);
|
||||
delete m_renderer;
|
||||
delete[] m_drawContext;
|
||||
delete[] m_frontBuffer;
|
||||
delete m_backupLoadState;
|
||||
}
|
||||
|
||||
@ -339,7 +344,7 @@ void GameController::openGame(bool biosOnly) {
|
||||
}
|
||||
|
||||
m_inputController->recalibrateAxes();
|
||||
memset(m_drawContext, 0xF8, 1024 * 256);
|
||||
memset(m_drawContext, 0xF8, 1024 * VIDEO_HORIZONTAL_PIXELS);
|
||||
|
||||
if (!GBAThreadStart(&m_threadContext)) {
|
||||
m_gameOpen = false;
|
||||
@ -530,9 +535,9 @@ void GameController::startRewinding() {
|
||||
return;
|
||||
}
|
||||
m_wasPaused = isPaused();
|
||||
bool signalsBlocked = blockSignals(true);
|
||||
setPaused(true);
|
||||
blockSignals(signalsBlocked);
|
||||
if (!GBAThreadIsPaused(&m_threadContext)) {
|
||||
GBAThreadPause(&m_threadContext);
|
||||
}
|
||||
m_rewindTimer.start();
|
||||
}
|
||||
|
||||
@ -585,10 +590,24 @@ void GameController::clearKeys() {
|
||||
}
|
||||
|
||||
void GameController::setAudioBufferSamples(int samples) {
|
||||
threadInterrupt();
|
||||
redoSamples(samples);
|
||||
threadContinue();
|
||||
QMetaObject::invokeMethod(m_audioProcessor, "setBufferSamples", Q_ARG(int, samples));
|
||||
if (m_audioProcessor) {
|
||||
threadInterrupt();
|
||||
redoSamples(samples);
|
||||
threadContinue();
|
||||
QMetaObject::invokeMethod(m_audioProcessor, "setBufferSamples", Q_ARG(int, samples));
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::setAudioSampleRate(unsigned rate) {
|
||||
if (!rate) {
|
||||
return;
|
||||
}
|
||||
if (m_audioProcessor) {
|
||||
threadInterrupt();
|
||||
redoSamples(m_audioProcessor->getBufferSamples());
|
||||
threadContinue();
|
||||
QMetaObject::invokeMethod(m_audioProcessor, "requestSampleRate", Q_ARG(unsigned, rate));
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::setAudioChannelEnabled(int channel, bool enable) {
|
||||
@ -641,7 +660,9 @@ void GameController::setFPSTarget(float fps) {
|
||||
if (m_turbo && m_turboSpeed > 0) {
|
||||
m_threadContext.fpsTarget *= m_turboSpeed;
|
||||
}
|
||||
redoSamples(m_audioProcessor->getBufferSamples());
|
||||
if (m_audioProcessor) {
|
||||
redoSamples(m_audioProcessor->getBufferSamples());
|
||||
}
|
||||
threadContinue();
|
||||
}
|
||||
|
||||
@ -652,9 +673,14 @@ void GameController::setSkipBIOS(bool set) {
|
||||
}
|
||||
|
||||
void GameController::setUseBIOS(bool use) {
|
||||
threadInterrupt();
|
||||
if (use == m_useBios) {
|
||||
return;
|
||||
}
|
||||
m_useBios = use;
|
||||
threadContinue();
|
||||
if (m_gameOpen) {
|
||||
closeGame();
|
||||
openGame();
|
||||
}
|
||||
}
|
||||
|
||||
void GameController::loadState(int slot) {
|
||||
@ -798,7 +824,9 @@ void GameController::enableTurbo() {
|
||||
m_threadContext.sync.audioWait = true;
|
||||
m_threadContext.sync.videoFrameWait = false;
|
||||
}
|
||||
redoSamples(m_audioProcessor->getBufferSamples());
|
||||
if (m_audioProcessor) {
|
||||
redoSamples(m_audioProcessor->getBufferSamples());
|
||||
}
|
||||
threadContinue();
|
||||
}
|
||||
|
||||
@ -827,11 +855,21 @@ void GameController::screenshot() {
|
||||
#endif
|
||||
|
||||
void GameController::reloadAudioDriver() {
|
||||
QMetaObject::invokeMethod(m_audioProcessor, "pause", Qt::BlockingQueuedConnection);
|
||||
int samples = m_audioProcessor->getBufferSamples();
|
||||
delete m_audioProcessor;
|
||||
int samples = 0;
|
||||
unsigned sampleRate = 0;
|
||||
if (m_audioProcessor) {
|
||||
QMetaObject::invokeMethod(m_audioProcessor, "pause", Qt::BlockingQueuedConnection);
|
||||
samples = m_audioProcessor->getBufferSamples();
|
||||
sampleRate = m_audioProcessor->sampleRate();
|
||||
delete m_audioProcessor;
|
||||
}
|
||||
m_audioProcessor = AudioProcessor::create();
|
||||
m_audioProcessor->setBufferSamples(samples);
|
||||
if (samples) {
|
||||
m_audioProcessor->setBufferSamples(samples);
|
||||
}
|
||||
if (sampleRate) {
|
||||
m_audioProcessor->requestSampleRate(sampleRate);
|
||||
}
|
||||
m_audioProcessor->moveToThread(m_audioThread);
|
||||
connect(this, SIGNAL(gameStarted(GBAThread*)), m_audioProcessor, SLOT(start()));
|
||||
connect(this, SIGNAL(gameStopped(GBAThread*)), m_audioProcessor, SLOT(pause()));
|
||||
|
@ -119,6 +119,7 @@ public slots:
|
||||
void keyReleased(int key);
|
||||
void clearKeys();
|
||||
void setAudioBufferSamples(int samples);
|
||||
void setAudioSampleRate(unsigned rate);
|
||||
void setAudioChannelEnabled(int channel, bool enable = true);
|
||||
void setVideoLayerEnabled(int layer, bool enable = true);
|
||||
void setFPSTarget(float fps);
|
||||
@ -167,6 +168,7 @@ private:
|
||||
void enableTurbo();
|
||||
|
||||
uint32_t* m_drawContext;
|
||||
uint32_t* m_frontBuffer;
|
||||
GBAThread m_threadContext;
|
||||
GBAVideoSoftwareRenderer* m_renderer;
|
||||
GBACheatDevice m_cheatDevice;
|
||||
|
@ -26,6 +26,7 @@ LoadSaveState::LoadSaveState(GameController* controller, QWidget* parent)
|
||||
, m_currentFocus(controller->stateSlot() - 1)
|
||||
, m_mode(LoadSave::LOAD)
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_slots[0] = m_ui.state1;
|
||||
@ -208,6 +209,5 @@ void LoadSaveState::showEvent(QShowEvent* event) {
|
||||
void LoadSaveState::paintEvent(QPaintEvent*) {
|
||||
QPainter painter(this);
|
||||
QRect full(QPoint(), size());
|
||||
painter.drawPixmap(full, m_currentImage);
|
||||
painter.fillRect(full, QColor(0, 0, 0, 128));
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ extern "C" {
|
||||
using namespace QGBA;
|
||||
|
||||
OverrideView::OverrideView(GameController* controller, ConfigController* config, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
: QDialog(parent)
|
||||
, m_controller(controller)
|
||||
, m_config(config)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@
|
||||
#ifndef QGBA_OVERRIDE_VIEW
|
||||
#define QGBA_OVERRIDE_VIEW
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_OverrideView.h"
|
||||
|
||||
@ -21,7 +21,7 @@ namespace QGBA {
|
||||
class ConfigController;
|
||||
class GameController;
|
||||
|
||||
class OverrideView : public QWidget {
|
||||
class OverrideView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -13,7 +13,7 @@ using namespace QGBA;
|
||||
SavestateButton::SavestateButton(QWidget* parent)
|
||||
: QAbstractButton(parent)
|
||||
{
|
||||
// Nothing to do
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
}
|
||||
|
||||
void SavestateButton::paintEvent(QPaintEvent*) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
using namespace QGBA;
|
||||
|
||||
SensorView::SensorView(GameController* controller, InputController* input, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
: QDialog(parent)
|
||||
, m_controller(controller)
|
||||
, m_input(input)
|
||||
, m_rotation(input->rotationSource())
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define QGBA_SENSOR_VIEW
|
||||
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
|
||||
#include <functional>
|
||||
|
||||
@ -22,7 +22,7 @@ class GameController;
|
||||
class GamepadAxisEvent;
|
||||
class InputController;
|
||||
|
||||
class SensorView : public QWidget {
|
||||
class SensorView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -13,8 +13,8 @@
|
||||
using namespace QGBA;
|
||||
|
||||
SettingsView::SettingsView(ConfigController* controller, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_controller(controller)
|
||||
: QDialog(parent)
|
||||
, m_controller(controller)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
@ -22,6 +22,7 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent)
|
||||
loadSetting("useBios", m_ui.useBios);
|
||||
loadSetting("skipBios", m_ui.skipBios);
|
||||
loadSetting("audioBuffers", m_ui.audioBufferSize);
|
||||
loadSetting("sampleRate", m_ui.sampleRate);
|
||||
loadSetting("videoSync", m_ui.videoSync);
|
||||
loadSetting("audioSync", m_ui.audioSync);
|
||||
loadSetting("frameskip", m_ui.frameskip);
|
||||
@ -102,6 +103,7 @@ void SettingsView::updateConfig() {
|
||||
saveSetting("useBios", m_ui.useBios);
|
||||
saveSetting("skipBios", m_ui.skipBios);
|
||||
saveSetting("audioBuffers", m_ui.audioBufferSize);
|
||||
saveSetting("sampleRate", m_ui.sampleRate);
|
||||
saveSetting("videoSync", m_ui.videoSync);
|
||||
saveSetting("audioSync", m_ui.audioSync);
|
||||
saveSetting("frameskip", m_ui.frameskip);
|
||||
|
@ -6,7 +6,7 @@
|
||||
#ifndef QGBA_SETTINGS_VIEW
|
||||
#define QGBA_SETTINGS_VIEW
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDialog>
|
||||
|
||||
#include "ui_SettingsView.h"
|
||||
|
||||
@ -14,7 +14,7 @@ namespace QGBA {
|
||||
|
||||
class ConfigController;
|
||||
|
||||
class SettingsView : public QWidget {
|
||||
class SettingsView : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -62,26 +62,41 @@
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string>2048</string>
|
||||
<string>1536</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>512</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>768</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1024</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1536</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2048</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3072</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4096</string>
|
||||
@ -99,13 +114,20 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Sample rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Volume:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QSlider" name="volume">
|
||||
@ -132,28 +154,38 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Display driver:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="displayDriver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Frameskip:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="6" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_12">
|
||||
@ -174,14 +206,14 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>FPS target:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="7" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="fpsTarget">
|
||||
@ -205,21 +237,21 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Sync:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="9" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="videoSync">
|
||||
@ -237,29 +269,63 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="lockAspectRatio">
|
||||
<property name="text">
|
||||
<string>Lock aspect ratio</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="resampleVideo">
|
||||
<property name="text">
|
||||
<string>Resample video</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="displayDriver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
||||
<item>
|
||||
<widget class="QComboBox" name="sampleRate">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string>44100</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>22050</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32000</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>44100</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>48000</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Hz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
|
@ -100,6 +100,14 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
|
||||
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), &m_inputController, SLOT(resumeScreensaver()));
|
||||
connect(m_controller, SIGNAL(stateLoaded(GBAThread*)), m_display, SLOT(forceDraw()));
|
||||
connect(m_controller, SIGNAL(rewound(GBAThread*)), m_display, SLOT(forceDraw()));
|
||||
connect(m_controller, &GameController::gamePaused, [this]() {
|
||||
QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), VIDEO_HORIZONTAL_PIXELS,
|
||||
VIDEO_VERTICAL_PIXELS, 1024, QImage::Format_RGBX8888);
|
||||
QPixmap pixmap;
|
||||
pixmap.convertFromImage(currentImage);
|
||||
m_screenWidget->setPixmap(pixmap);
|
||||
m_screenWidget->setLockAspectRatio(3, 2);
|
||||
});
|
||||
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), m_display, SLOT(pauseDrawing()));
|
||||
#ifndef Q_OS_MAC
|
||||
connect(m_controller, SIGNAL(gamePaused(GBAThread*)), menuBar(), SLOT(show()));
|
||||
@ -127,6 +135,7 @@ Window::Window(ConfigController* config, int playerId, QWidget* parent)
|
||||
connect(this, SIGNAL(shutdown()), m_controller, SLOT(closeGame()));
|
||||
connect(this, SIGNAL(shutdown()), m_logView, SLOT(hide()));
|
||||
connect(this, SIGNAL(audioBufferSamplesChanged(int)), m_controller, SLOT(setAudioBufferSamples(int)));
|
||||
connect(this, SIGNAL(sampleRateChanged(unsigned)), m_controller, SLOT(setAudioSampleRate(unsigned)));
|
||||
connect(this, SIGNAL(fpsTargetChanged(float)), m_controller, SLOT(setFPSTarget(float)));
|
||||
connect(&m_fpsTimer, SIGNAL(timeout()), this, SLOT(showFPS()));
|
||||
connect(m_display, &Display::hideCursor, [this]() {
|
||||
@ -195,6 +204,7 @@ void Window::loadConfig() {
|
||||
m_controller->loadBIOS(opts->bios);
|
||||
}
|
||||
|
||||
// TODO: Move these to ConfigController
|
||||
if (opts->fpsTarget) {
|
||||
emit fpsTargetChanged(opts->fpsTarget);
|
||||
}
|
||||
@ -203,6 +213,10 @@ void Window::loadConfig() {
|
||||
emit audioBufferSamplesChanged(opts->audioBuffers);
|
||||
}
|
||||
|
||||
if (opts->sampleRate) {
|
||||
emit sampleRateChanged(opts->sampleRate);
|
||||
}
|
||||
|
||||
if (opts->width && opts->height) {
|
||||
resizeFrame(opts->width, opts->height);
|
||||
}
|
||||
@ -393,9 +407,7 @@ void Window::gdbOpen() {
|
||||
m_gdbController = new GDBController(m_controller, this);
|
||||
}
|
||||
GDBWindow* window = new GDBWindow(m_gdbController);
|
||||
connect(this, SIGNAL(shutdown()), window, SLOT(close()));
|
||||
window->setAttribute(Qt::WA_DeleteOnClose);
|
||||
window->show();
|
||||
openView(window);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -673,7 +685,7 @@ void Window::openStateWindow(LoadSave ls) {
|
||||
connect(this, SIGNAL(shutdown()), m_stateWindow, SLOT(close()));
|
||||
connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_stateWindow, SLOT(close()));
|
||||
connect(m_stateWindow, &LoadSaveState::closed, [this]() {
|
||||
m_screenWidget->layout()->removeWidget(m_stateWindow);
|
||||
detachWidget(m_stateWindow);
|
||||
m_stateWindow = nullptr;
|
||||
QMetaObject::invokeMethod(this, "setFocus", Qt::QueuedConnection);
|
||||
});
|
||||
@ -823,13 +835,6 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
connect(pause, SIGNAL(triggered(bool)), m_controller, SLOT(setPaused(bool)));
|
||||
connect(m_controller, &GameController::gamePaused, [this, pause]() {
|
||||
pause->setChecked(true);
|
||||
|
||||
QImage currentImage(reinterpret_cast<const uchar*>(m_controller->drawContext()), VIDEO_HORIZONTAL_PIXELS,
|
||||
VIDEO_VERTICAL_PIXELS, 1024, QImage::Format_RGB32);
|
||||
QPixmap pixmap;
|
||||
pixmap.convertFromImage(currentImage.rgbSwapped());
|
||||
m_screenWidget->setPixmap(pixmap);
|
||||
m_screenWidget->setLockAspectRatio(3, 2);
|
||||
});
|
||||
connect(m_controller, &GameController::gameUnpaused, [pause]() { pause->setChecked(false); });
|
||||
m_gameActions.append(pause);
|
||||
@ -939,9 +944,12 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
for (int i = 1; i <= 6; ++i) {
|
||||
QAction* setSize = new QAction(tr("%1x").arg(QString::number(i)), avMenu);
|
||||
setSize->setCheckable(true);
|
||||
connect(setSize, &QAction::triggered, [this, i]() {
|
||||
connect(setSize, &QAction::triggered, [this, i, setSize]() {
|
||||
showNormal();
|
||||
resizeFrame(VIDEO_HORIZONTAL_PIXELS * i, VIDEO_VERTICAL_PIXELS * i);
|
||||
bool enableSignals = setSize->blockSignals(true);
|
||||
setSize->setChecked(true);
|
||||
setSize->blockSignals(enableSignals);
|
||||
});
|
||||
m_frameSizes[i] = setSize;
|
||||
addControlledAction(frameMenu, setSize, QString("frame%1x").arg(QString::number(i)));
|
||||
@ -980,20 +988,6 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
|
||||
avMenu->addSeparator();
|
||||
|
||||
QMenu* buffersMenu = avMenu->addMenu(tr("Audio buffer &size"));
|
||||
ConfigOption* buffers = m_config->addOption("audioBuffers");
|
||||
buffers->connect([this](const QVariant& value) {
|
||||
emit audioBufferSamplesChanged(value.toInt());
|
||||
}, this);
|
||||
buffers->addValue(tr("512"), 512, buffersMenu);
|
||||
buffers->addValue(tr("768"), 768, buffersMenu);
|
||||
buffers->addValue(tr("1024"), 1024, buffersMenu);
|
||||
buffers->addValue(tr("2048"), 2048, buffersMenu);
|
||||
buffers->addValue(tr("4096"), 4096, buffersMenu);
|
||||
m_config->updateOption("audioBuffers");
|
||||
|
||||
avMenu->addSeparator();
|
||||
|
||||
QMenu* target = avMenu->addMenu(tr("FPS target"));
|
||||
ConfigOption* fpsTargetOption = m_config->addOption("fpsTarget");
|
||||
fpsTargetOption->connect([this](const QVariant& value) {
|
||||
@ -1129,6 +1123,21 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
m_controller->setSkipBIOS(value.toBool());
|
||||
}, this);
|
||||
|
||||
ConfigOption* useBios = m_config->addOption("useBios");
|
||||
useBios->connect([this](const QVariant& value) {
|
||||
m_controller->setUseBIOS(value.toBool());
|
||||
}, this);
|
||||
|
||||
ConfigOption* buffers = m_config->addOption("audioBuffers");
|
||||
buffers->connect([this](const QVariant& value) {
|
||||
emit audioBufferSamplesChanged(value.toInt());
|
||||
}, this);
|
||||
|
||||
ConfigOption* sampleRate = m_config->addOption("sampleRate");
|
||||
sampleRate->connect([this](const QVariant& value) {
|
||||
emit sampleRateChanged(value.toUInt());
|
||||
}, this);
|
||||
|
||||
ConfigOption* volume = m_config->addOption("volume");
|
||||
volume->connect([this](const QVariant& value) {
|
||||
m_controller->setVolume(value.toInt());
|
||||
@ -1171,7 +1180,7 @@ void Window::setupMenu(QMenuBar* menubar) {
|
||||
|
||||
void Window::attachWidget(QWidget* widget) {
|
||||
m_screenWidget->layout()->addWidget(widget);
|
||||
unsetCursor();
|
||||
m_screenWidget->unsetCursor();
|
||||
static_cast<QStackedLayout*>(m_screenWidget->layout())->setCurrentWidget(widget);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,7 @@ signals:
|
||||
void startDrawing(GBAThread*);
|
||||
void shutdown();
|
||||
void audioBufferSamplesChanged(int samples);
|
||||
void sampleRateChanged(unsigned samples);
|
||||
void fpsTargetChanged(float target);
|
||||
|
||||
public slots:
|
||||
|
@ -84,3 +84,6 @@ set_target_properties(${BINARY_NAME}-sdl PROPERTIES COMPILE_DEFINITIONS "${FEATU
|
||||
target_link_libraries(${BINARY_NAME}-sdl ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY})
|
||||
set_target_properties(${BINARY_NAME}-sdl PROPERTIES OUTPUT_NAME ${BINARY_NAME})
|
||||
install(TARGETS ${BINARY_NAME}-sdl DESTINATION bin COMPONENT ${BINARY_NAME}-sdl)
|
||||
if(UNIX)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/doc/mgba.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-sdl)
|
||||
endif()
|
||||
|
@ -112,6 +112,10 @@ int main(int argc, char** argv) {
|
||||
bool didFail = false;
|
||||
|
||||
renderer.audio.samples = context.audioBuffers;
|
||||
renderer.audio.sampleRate = 44100;
|
||||
if (opts.sampleRate) {
|
||||
renderer.audio.sampleRate = opts.sampleRate;
|
||||
}
|
||||
if (!GBASDLInitAudio(&renderer.audio, &context)) {
|
||||
didFail = true;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ bool GBASDLInitAudio(struct GBASDLAudio* context, struct GBAThread* threadContex
|
||||
return false;
|
||||
}
|
||||
|
||||
context->desiredSpec.freq = 44100;
|
||||
context->desiredSpec.freq = context->sampleRate;
|
||||
context->desiredSpec.format = AUDIO_S16SYS;
|
||||
context->desiredSpec.channels = 2;
|
||||
context->desiredSpec.samples = context->samples;
|
||||
|
@ -15,6 +15,7 @@
|
||||
struct GBASDLAudio {
|
||||
// Input
|
||||
size_t samples;
|
||||
unsigned sampleRate;
|
||||
|
||||
// State
|
||||
SDL_AudioSpec desiredSpec;
|
||||
|
@ -9,20 +9,20 @@
|
||||
|
||||
int ftostr_l(char* restrict str, size_t size, float f, locale_t locale) {
|
||||
#ifdef HAVE_SNPRINTF_L
|
||||
return snprintf_l(str, size, locale, "%*.g", FLT_DIG, f);
|
||||
return snprintf_l(str, size, locale, "%.*g", FLT_DIG, f);
|
||||
#elif defined(HAVE_LOCALE)
|
||||
locale_t old = uselocale(locale);
|
||||
int res = snprintf(str, size, "%*.g", FLT_DIG, f);
|
||||
int res = snprintf(str, size, "%.*g", FLT_DIG, f);
|
||||
uselocale(old);
|
||||
return res;
|
||||
#elif defined(HAVE_SETLOCALE)
|
||||
char* old = setlocale(LC_NUMERIC, locale);
|
||||
int res = snprintf(str, size, "%*.g", FLT_DIG, f);
|
||||
int res = snprintf(str, size, "%.*g", FLT_DIG, f);
|
||||
setlocale(LC_NUMERIC, old);
|
||||
return res;
|
||||
#else
|
||||
UNUSED(locale);
|
||||
return snprintf(str, size, "%*.g", FLT_DIG, f);
|
||||
return snprintf(str, size, "%.*g", FLT_DIG, f);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
5
tools/debian/changelog
Normal file
5
tools/debian/changelog
Normal file
@ -0,0 +1,5 @@
|
||||
mgba (0.3.0-1) UNRELEASED; urgency=low
|
||||
|
||||
* Initial release (closes: Bug#787470).
|
||||
|
||||
-- Sérgio Benjamim <sergio_br2@yahoo.com.br> Mon, 17 Aug 2015 18:40:00 -0300
|
2
tools/debian/clean
Normal file
2
tools/debian/clean
Normal file
@ -0,0 +1,2 @@
|
||||
debian/libmgba.install
|
||||
debian/libretro-mgba.install
|
1
tools/debian/compat
Normal file
1
tools/debian/compat
Normal file
@ -0,0 +1 @@
|
||||
9
|
78
tools/debian/control
Normal file
78
tools/debian/control
Normal file
@ -0,0 +1,78 @@
|
||||
Source: mgba
|
||||
Section: otherosfs
|
||||
Priority: extra
|
||||
Maintainer: Sérgio Benjamim <sergio_br2@yahoo.com.br>
|
||||
Build-Depends: cmake (>= 2.8.11),
|
||||
debhelper (>= 9),
|
||||
libavcodec-dev,
|
||||
libavformat-dev,
|
||||
libavresample-dev,
|
||||
libavutil-dev,
|
||||
libedit-dev,
|
||||
libmagickwand-dev,
|
||||
libpng-dev,
|
||||
libqt5opengl5-dev,
|
||||
libsdl2-dev,
|
||||
libswscale-dev,
|
||||
libzip-dev,
|
||||
pkg-config,
|
||||
qtbase5-dev,
|
||||
qtmultimedia5-dev,
|
||||
zlib1g-dev
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: http://mgba.io/
|
||||
|
||||
Package: libmgba
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Game Boy Advance emulator (common library for mGBA)
|
||||
mGBA is a new emulator for running Game Boy Advance games. It aims to be faster
|
||||
and more accurate than many existing Game Boy Advance emulators, as well as
|
||||
adding features that other emulators lack.
|
||||
.
|
||||
This package provides the common library for mGBA.
|
||||
.
|
||||
Game Boy Advance is a registered trademark of Nintendo of America Inc. mGBA is
|
||||
not affiliated with or endorsed by any of the companies mentioned.
|
||||
|
||||
Package: mgba-qt
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Game Boy Advance emulator (Qt frontend for mGBA)
|
||||
mGBA is a new emulator for running Game Boy Advance games. It aims to be faster
|
||||
and more accurate than many existing Game Boy Advance emulators, as well as
|
||||
adding features that other emulators lack.
|
||||
.
|
||||
This package provides the Qt GUI frontend for mGBA.
|
||||
.
|
||||
Game Boy Advance is a registered trademark of Nintendo of America Inc. mGBA is
|
||||
not affiliated with or endorsed by any of the companies mentioned.
|
||||
|
||||
Package: mgba-sdl
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Game Boy Advance emulator (SDL frontend for mGBA)
|
||||
mGBA is a new emulator for running Game Boy Advance games. It aims to be faster
|
||||
and more accurate than many existing Game Boy Advance emulators, as well as
|
||||
adding features that other emulators lack.
|
||||
.
|
||||
This package provides the SDL UI console for mGBA.
|
||||
.
|
||||
Game Boy Advance is a registered trademark of Nintendo of America Inc. mGBA is
|
||||
not affiliated with or endorsed by any of the companies mentioned.
|
||||
|
||||
Package: libretro-mgba
|
||||
Architecture: any
|
||||
Multi-Arch: same
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Description: Libretro wrapper for mGBA
|
||||
This wrapper makes mGBA API compatible with libretro, thus allowing its use
|
||||
with libretro frontends, such as RetroArch.
|
||||
.
|
||||
mGBA is a new emulator for running Game Boy Advance games. It aims to be faster
|
||||
and more accurate than many existing Game Boy Advance emulators, as well as
|
||||
adding features that other emulators lack.
|
||||
.
|
||||
Game Boy Advance is a registered trademark of Nintendo of America Inc. mGBA is
|
||||
not affiliated with or endorsed by any of the companies mentioned.
|
472
tools/debian/copyright
Normal file
472
tools/debian/copyright
Normal file
@ -0,0 +1,472 @@
|
||||
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: mGBA
|
||||
Upstream-Contact: Jeffrey Pfau (aka endrift) <jeffrey@endrift.com>
|
||||
Source: https://github.com/mgba-emu/mgba
|
||||
Comment: This package was debianized by
|
||||
Sergio Benjamim (sergio-br2) <sergio_br2@yahoo.com.br> on Mon, 01 Jun 2015 18:40:00 -0300
|
||||
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2015 Jeffrey Pfau
|
||||
License: MPL-2.0
|
||||
|
||||
Files: src/third-party/blip_buf/*
|
||||
Copyright: 2003-2009 Shay Green
|
||||
License: LGPL-2.1+
|
||||
|
||||
Files: src/third-party/inih/*
|
||||
Copyright: 2009 Brush Technology. All rights reserved.
|
||||
License: BSD-3-clause-Brush-Technology
|
||||
|
||||
Files: src/third-party/lzma/*
|
||||
Copyright: 2008-2015 Igor Pavlov
|
||||
License: public-domain
|
||||
These files have been put in the public domain by their author
|
||||
|
||||
Files: src/platform/libretro/libretro.h
|
||||
Copyright: 2010-2015 The RetroArch Team
|
||||
License: Expat
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2015 Sergio Benjamim (sergio-br2) <sergio_br2@yahoo.com.br>
|
||||
License: MPL-2.0
|
||||
|
||||
|
||||
License: MPL-2.0
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
.
|
||||
1. Definitions
|
||||
--------------
|
||||
.
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
.
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
.
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
.
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
.
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
.
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
.
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
.
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
.
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
.
|
||||
1.8. "License"
|
||||
means this document.
|
||||
.
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
.
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
.
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
.
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
.
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
.
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
.
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
.
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
.
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
.
|
||||
2.1. Grants
|
||||
.
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
.
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
.
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
.
|
||||
2.2. Effective Date
|
||||
.
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
.
|
||||
2.3. Limitations on Grant Scope
|
||||
.
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
.
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
.
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
.
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
.
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
.
|
||||
2.4. Subsequent Licenses
|
||||
.
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
.
|
||||
2.5. Representation
|
||||
.
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
.
|
||||
2.6. Fair Use
|
||||
.
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
.
|
||||
2.7. Conditions
|
||||
.
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
.
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
.
|
||||
3.1. Distribution of Source Form
|
||||
.
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
.
|
||||
3.2. Distribution of Executable Form
|
||||
.
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
.
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
.
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
.
|
||||
3.3. Distribution of a Larger Work
|
||||
.
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
.
|
||||
3.4. Notices
|
||||
.
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
.
|
||||
3.5. Application of Additional Terms
|
||||
.
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
.
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
.
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
.
|
||||
5. Termination
|
||||
--------------
|
||||
.
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
.
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
.
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
.
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
.
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
.
|
||||
8. Litigation
|
||||
-------------
|
||||
.
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
.
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
.
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
.
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
.
|
||||
10.1. New Versions
|
||||
.
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
.
|
||||
10.2. Effect of New Versions
|
||||
.
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
.
|
||||
10.3. Modified Versions
|
||||
.
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
.
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
.
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
.
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
.
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
.
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
.
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
.
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
.
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
||||
|
||||
|
||||
License: BSD-3-clause-Brush-Technology
|
||||
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 of Brush Technology 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 BRUSH TECHNOLOGY ''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 BRUSH TECHNOLOGY 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.
|
||||
|
||||
|
||||
License: Expat
|
||||
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.
|
||||
|
||||
|
||||
License: LGPL-2.1+
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
.
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
.
|
||||
On Debian systems, the full text of the GNU Lesser General Public
|
||||
License version 2.1 can be found in the file
|
||||
`/usr/share/common-licenses/LGPL-2.1'.
|
2
tools/debian/docs
Normal file
2
tools/debian/docs
Normal file
@ -0,0 +1,2 @@
|
||||
README.md
|
||||
CHANGES
|
1
tools/debian/libmgba.install.in
Normal file
1
tools/debian/libmgba.install.in
Normal file
@ -0,0 +1 @@
|
||||
obj/libmgba.so* usr/lib/@DEB_HOST_MULTIARCH@/
|
1
tools/debian/libretro-mgba.install.in
Normal file
1
tools/debian/libretro-mgba.install.in
Normal file
@ -0,0 +1 @@
|
||||
obj/mgba_libretro.so usr/lib/@DEB_HOST_MULTIARCH@/libretro
|
3
tools/debian/mgba-qt.install
Normal file
3
tools/debian/mgba-qt.install
Normal file
@ -0,0 +1,3 @@
|
||||
usr/bin/mgba-qt
|
||||
res/mgba-qt.desktop usr/share/applications
|
||||
usr/share/icons
|
1
tools/debian/mgba-qt.manpages
Normal file
1
tools/debian/mgba-qt.manpages
Normal file
@ -0,0 +1 @@
|
||||
doc/mgba-qt.6
|
1
tools/debian/mgba-sdl.install
Normal file
1
tools/debian/mgba-sdl.install
Normal file
@ -0,0 +1 @@
|
||||
usr/bin/mgba
|
1
tools/debian/mgba-sdl.manpages
Normal file
1
tools/debian/mgba-sdl.manpages
Normal file
@ -0,0 +1 @@
|
||||
doc/mgba.6
|
27
tools/debian/rules
Executable file
27
tools/debian/rules
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
# Copyright (C) 2015 Sergio Benjamim
|
||||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
|
||||
ARCH=$(shell dpkg-architecture -qDEB_HOST_ARCH)
|
||||
|
||||
ifeq ($(ARCH),armhf)
|
||||
ARM=-DBUILD_GL=OFF -DBUILD_GLES2=ON
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@ --buildsystem=cmake --builddirectory=obj --parallel
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_SKIP_RPATH=ON -DBUILD_LIBRETRO=ON $(ARM)
|
||||
sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
|
||||
debian/libretro-mgba.install.in > debian/libretro-mgba.install
|
||||
sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
|
||||
debian/libmgba.install.in > debian/libmgba.install
|
||||
|
||||
override_dh_installchangelogs:
|
||||
dh_installchangelogs -k CHANGES
|
1
tools/debian/source/format
Normal file
1
tools/debian/source/format
Normal file
@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
3
tools/debian/watch
Normal file
3
tools/debian/watch
Normal file
@ -0,0 +1,3 @@
|
||||
version=3
|
||||
opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/mgba-$1\.tar\.gz/ \
|
||||
https://github.com/mgba-emu/mgba/tags .*/v?(\d\S*)\.tar\.gz
|
@ -32,6 +32,16 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT GIT_COMMIT)
|
||||
set(GIT_COMMIT "(unknown)")
|
||||
endif()
|
||||
if(NOT GIT_COMMIT_SHORT)
|
||||
set(GIT_COMMIT_SHORT "(unknown)")
|
||||
endif()
|
||||
if(NOT GIT_BRANCH)
|
||||
set(GIT_BRANCH "(unknown)")
|
||||
endif()
|
||||
|
||||
if(CONFIG_FILE AND OUT_FILE)
|
||||
configure_file("${CONFIG_FILE}" "${OUT_FILE}")
|
||||
endif()
|
||||
|
Loading…
Reference in New Issue
Block a user