Cocoa Port:
- Do a bunch of code refactoring and cleanup. - Add some new UI for an upcoming new feature.
This commit is contained in:
parent
c024a78a43
commit
932cdd6366
|
@ -0,0 +1,563 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ClientAVCaptureObject.h"
|
||||
|
||||
#include "../../common.h"
|
||||
#include "../../NDSSystem.h"
|
||||
#include "../../GPU.h"
|
||||
|
||||
|
||||
static void* RunConvertVideoSlice555XTo888(void *arg)
|
||||
{
|
||||
VideoConvertParam *convertParam = (VideoConvertParam *)arg;
|
||||
convertParam->captureObj->ConvertVideoSlice555Xto888(*convertParam);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* RunConvertVideoSlice888XTo888(void *arg)
|
||||
{
|
||||
VideoConvertParam *convertParam = (VideoConvertParam *)arg;
|
||||
convertParam->captureObj->ConvertVideoSlice888Xto888(*convertParam);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* RunAviFileWrite(void *arg)
|
||||
{
|
||||
ClientAVCaptureFileStream *fs = (ClientAVCaptureFileStream *)arg;
|
||||
fs->WriteAllFrames();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ClientAVCaptureFileStream::ClientAVCaptureFileStream()
|
||||
{
|
||||
_videoWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH;
|
||||
_videoHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT;
|
||||
|
||||
_fileTypeID = AVFileTypeID_mp4_H264_AAC;
|
||||
_fileTypeContainerID = (AVFileTypeContainerID)(_fileTypeID & AVFILETYPEID_CONTAINERMASK);
|
||||
_fileTypeVideoCodecID = (AVFileTypeVideoCodecID)(_fileTypeID & AVFILETYPEID_VIDEOCODECMASK);
|
||||
_fileTypeAudioCodecID = (AVFileTypeAudioCodecID)(_fileTypeID & AVFILETYPEID_AUDIOCODECMASK);
|
||||
|
||||
_baseFileName = "untitled";
|
||||
_baseFileNameExt = "mp4";
|
||||
_segmentNumber = 0;
|
||||
|
||||
_maxSegmentSize = (4ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL); // Default to 4TB segments.
|
||||
_expectedMaxFrameSize = 0;
|
||||
_writtenVideoFrameCount = 0;
|
||||
_writtenAudioSampleCount = 0;
|
||||
_writtenBytes = 0;
|
||||
|
||||
_semQueue = NULL;
|
||||
_mutexQueue = slock_new();
|
||||
}
|
||||
|
||||
ClientAVCaptureFileStream::~ClientAVCaptureFileStream()
|
||||
{
|
||||
slock_free(this->_mutexQueue);
|
||||
ssem_free(this->_semQueue);
|
||||
}
|
||||
|
||||
void ClientAVCaptureFileStream::InitBaseProperties(const AVFileTypeID fileTypeID, const std::string &fileName,
|
||||
const size_t videoWidth, const size_t videoHeight,
|
||||
size_t pendingFrameCount)
|
||||
{
|
||||
// Set up the stream formats that will be used for all AVI segments.
|
||||
this->_fileTypeID = fileTypeID;
|
||||
this->_fileTypeContainerID = (AVFileTypeContainerID)(fileTypeID & AVFILETYPEID_CONTAINERMASK);
|
||||
this->_fileTypeVideoCodecID = (AVFileTypeVideoCodecID)(fileTypeID & AVFILETYPEID_VIDEOCODECMASK);
|
||||
this->_fileTypeAudioCodecID = (AVFileTypeAudioCodecID)(fileTypeID & AVFILETYPEID_AUDIOCODECMASK);
|
||||
|
||||
switch (this->_fileTypeContainerID)
|
||||
{
|
||||
case AVFileTypeContainerID_mp4:
|
||||
this->_baseFileNameExt = "mp4";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_avi:
|
||||
this->_baseFileNameExt = "avi";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_mkv:
|
||||
this->_baseFileNameExt = "mkv";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_mov:
|
||||
this->_baseFileNameExt = "mov";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_m4a:
|
||||
this->_baseFileNameExt = "m4a";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_aiff:
|
||||
this->_baseFileNameExt = "aiff";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_flac:
|
||||
this->_baseFileNameExt = "flac";
|
||||
break;
|
||||
|
||||
case AVFileTypeContainerID_wav:
|
||||
this->_baseFileNameExt = "wav";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this->_baseFileName = fileName;
|
||||
this->_videoWidth = videoWidth;
|
||||
this->_videoHeight = videoHeight;
|
||||
|
||||
const size_t videoFrameSize = videoWidth * videoHeight * 3; // The video frame will always be in the RGB888 colorspace.
|
||||
const size_t audioBlockSize = sizeof(int16_t) * 2;
|
||||
const size_t audioFrameSize = ((DESMUME_SAMPLE_RATE * audioBlockSize) / 30);
|
||||
|
||||
this->_expectedMaxFrameSize = videoFrameSize + audioFrameSize;
|
||||
|
||||
_semQueue = ssem_new(pendingFrameCount);
|
||||
}
|
||||
|
||||
AVFileTypeVideoCodecID ClientAVCaptureFileStream::GetVideoCodecID()
|
||||
{
|
||||
return this->_fileTypeVideoCodecID;
|
||||
}
|
||||
|
||||
AVFileTypeAudioCodecID ClientAVCaptureFileStream::GetAudioCodecID()
|
||||
{
|
||||
return this->_fileTypeAudioCodecID;
|
||||
}
|
||||
|
||||
bool ClientAVCaptureFileStream::IsValid()
|
||||
{
|
||||
// Implementations need to override this method.
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientAVCaptureFileStream::QueueAdd(uint8_t *srcVideo, const size_t videoBufferSize, uint8_t *srcAudio, const size_t audioBufferSize)
|
||||
{
|
||||
AVStreamWriteParam newParam;
|
||||
newParam.srcVideo = srcVideo;
|
||||
newParam.videoBufferSize = videoBufferSize;
|
||||
newParam.srcAudio = srcAudio;
|
||||
newParam.audioBufferSize = audioBufferSize;
|
||||
|
||||
ssem_wait(this->_semQueue);
|
||||
|
||||
slock_lock(this->_mutexQueue);
|
||||
this->_writeQueue.push(newParam);
|
||||
slock_unlock(this->_mutexQueue);
|
||||
}
|
||||
|
||||
void ClientAVCaptureFileStream::QueueWait()
|
||||
{
|
||||
// If the queue if full, the ssem_wait() will force a wait until the current frame is finished writing.
|
||||
ssem_wait(this->_semQueue);
|
||||
ssem_signal(this->_semQueue);
|
||||
}
|
||||
|
||||
size_t ClientAVCaptureFileStream::GetQueueSize()
|
||||
{
|
||||
slock_lock(this->_mutexQueue);
|
||||
const size_t queueSize = this->_writeQueue.size();
|
||||
slock_unlock(this->_mutexQueue);
|
||||
|
||||
return queueSize;
|
||||
}
|
||||
|
||||
ClientAVCaptureError ClientAVCaptureFileStream::FlushVideo(uint8_t *srcBuffer, const size_t bufferSize)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
return ClientAVCaptureError_None;
|
||||
}
|
||||
|
||||
ClientAVCaptureError ClientAVCaptureFileStream::FlushAudio(uint8_t *srcBuffer, const size_t bufferSize)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
return ClientAVCaptureError_None;
|
||||
}
|
||||
|
||||
ClientAVCaptureError ClientAVCaptureFileStream::WriteOneFrame(const AVStreamWriteParam ¶m)
|
||||
{
|
||||
// Do nothing. This is implementation dependent.
|
||||
return ClientAVCaptureError_None;
|
||||
}
|
||||
|
||||
ClientAVCaptureError ClientAVCaptureFileStream::WriteAllFrames()
|
||||
{
|
||||
ClientAVCaptureError error = ClientAVCaptureError_None;
|
||||
|
||||
do
|
||||
{
|
||||
slock_lock(this->_mutexQueue);
|
||||
if (this->_writeQueue.empty())
|
||||
{
|
||||
slock_unlock(this->_mutexQueue);
|
||||
break;
|
||||
}
|
||||
|
||||
const AVStreamWriteParam param = this->_writeQueue.front();
|
||||
slock_unlock(this->_mutexQueue);
|
||||
|
||||
error = this->WriteOneFrame(param);
|
||||
|
||||
slock_lock(this->_mutexQueue);
|
||||
this->_writeQueue.pop();
|
||||
slock_unlock(this->_mutexQueue);
|
||||
|
||||
ssem_signal(this->_semQueue);
|
||||
|
||||
if (error)
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
} while (true);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
ClientAVCaptureObject::ClientAVCaptureObject()
|
||||
{
|
||||
__InstanceInit(0, 0);
|
||||
}
|
||||
|
||||
ClientAVCaptureObject::ClientAVCaptureObject(size_t videoFrameWidth, size_t videoFrameHeight)
|
||||
{
|
||||
__InstanceInit(videoFrameWidth, videoFrameHeight);
|
||||
|
||||
_pendingVideoBuffer = (u8 *)malloc_alignedCacheLine(_videoFrameSize * _pendingBufferCount);
|
||||
_pendingAudioBuffer = (u8 *)malloc_alignedCacheLine(_audioFrameSize * _pendingBufferCount);
|
||||
_pendingAudioWriteSize = (size_t *)calloc(_pendingBufferCount, sizeof(size_t));
|
||||
|
||||
const size_t linesPerThread = (_numThreads > 0) ? videoFrameHeight / _numThreads : videoFrameHeight;
|
||||
|
||||
if (_numThreads == 0)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_CONVERT_THREADS; i++)
|
||||
{
|
||||
_convertParam[i].firstLineIndex = 0;
|
||||
_convertParam[i].lastLineIndex = linesPerThread - 1;
|
||||
_convertParam[i].srcOffset = 0;
|
||||
_convertParam[i].dstOffset = (videoFrameWidth * (videoFrameHeight - 1) * 3);
|
||||
_convertParam[i].frameWidth = videoFrameWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < _numThreads; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
_convertParam[i].firstLineIndex = 0;
|
||||
_convertParam[i].lastLineIndex = linesPerThread - 1;
|
||||
}
|
||||
else if (i == (_numThreads - 1))
|
||||
{
|
||||
_convertParam[i].firstLineIndex = _convertParam[i - 1].lastLineIndex + 1;
|
||||
_convertParam[i].lastLineIndex = videoFrameHeight - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_convertParam[i].firstLineIndex = _convertParam[i - 1].lastLineIndex + 1;
|
||||
_convertParam[i].lastLineIndex = _convertParam[i].firstLineIndex + linesPerThread - 1;
|
||||
}
|
||||
|
||||
_convertParam[i].srcOffset = (videoFrameWidth * _convertParam[i].firstLineIndex);
|
||||
_convertParam[i].dstOffset = (videoFrameWidth * (videoFrameHeight - (_convertParam[i].firstLineIndex + 1)) * 3);
|
||||
_convertParam[i].frameWidth = videoFrameWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::__InstanceInit(size_t videoFrameWidth, size_t videoFrameHeight)
|
||||
{
|
||||
_fs = NULL;
|
||||
_isCapturingVideo = false;
|
||||
_isCapturingAudio = false;
|
||||
|
||||
_mutexCaptureFlags = slock_new();
|
||||
|
||||
_videoFrameWidth = videoFrameWidth;
|
||||
_videoFrameHeight = videoFrameHeight;
|
||||
_videoFrameSize = videoFrameWidth * videoFrameHeight * 3; // The video frame will always be in the RGB888 colorspace.
|
||||
_audioBlockSize = sizeof(int16_t) * 2;
|
||||
_audioFrameSize = ((DESMUME_SAMPLE_RATE * _audioBlockSize) / 30);
|
||||
|
||||
_pendingVideoBuffer = NULL;
|
||||
_pendingAudioBuffer = NULL;
|
||||
_pendingAudioWriteSize = NULL;
|
||||
_currentBufferIndex = 0;
|
||||
|
||||
_pendingBufferCount = MAX_PENDING_BUFFER_SIZE / (_videoFrameSize + _audioFrameSize);
|
||||
if (_pendingBufferCount > MAX_PENDING_FRAME_COUNT)
|
||||
{
|
||||
_pendingBufferCount = MAX_PENDING_FRAME_COUNT;
|
||||
}
|
||||
|
||||
// Create the colorspace conversion threads.
|
||||
_numThreads = CommonSettings.num_cores;
|
||||
|
||||
if (_numThreads > MAX_CONVERT_THREADS)
|
||||
{
|
||||
_numThreads = MAX_CONVERT_THREADS;
|
||||
}
|
||||
else if (_numThreads < 2)
|
||||
{
|
||||
_numThreads = 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _numThreads; i++)
|
||||
{
|
||||
memset(&_convertParam[i], 0, sizeof(VideoConvertParam));
|
||||
_convertParam[i].captureObj = this;
|
||||
|
||||
_convertThread[i] = new Task();
|
||||
_convertThread[i]->start(false);
|
||||
}
|
||||
|
||||
_fileWriteThread = new Task();
|
||||
_fileWriteThread->start(false);
|
||||
}
|
||||
|
||||
ClientAVCaptureObject::~ClientAVCaptureObject()
|
||||
{
|
||||
this->_fileWriteThread->finish();
|
||||
delete this->_fileWriteThread;
|
||||
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
delete this->_convertThread[i];
|
||||
}
|
||||
|
||||
free_aligned(this->_pendingVideoBuffer);
|
||||
free_aligned(this->_pendingAudioBuffer);
|
||||
free(this->_pendingAudioWriteSize);
|
||||
|
||||
slock_free(this->_mutexCaptureFlags);
|
||||
}
|
||||
|
||||
ClientAVCaptureFileStream* ClientAVCaptureObject::GetOutputFileStream()
|
||||
{
|
||||
return this->_fs;
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::SetOutputFileStream(ClientAVCaptureFileStream *fs)
|
||||
{
|
||||
if (fs == NULL)
|
||||
{
|
||||
slock_lock(this->_mutexCaptureFlags);
|
||||
this->_isCapturingVideo = false;
|
||||
this->_isCapturingAudio = false;
|
||||
slock_unlock(this->_mutexCaptureFlags);
|
||||
}
|
||||
|
||||
this->_fs = fs;
|
||||
|
||||
if (fs != NULL)
|
||||
{
|
||||
slock_lock(this->_mutexCaptureFlags);
|
||||
this->_isCapturingVideo = (fs->GetVideoCodecID() != AVFileTypeVideoCodecID_None);
|
||||
this->_isCapturingAudio = (fs->GetAudioCodecID() != AVFileTypeAudioCodecID_None);
|
||||
slock_unlock(this->_mutexCaptureFlags);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientAVCaptureObject::IsFileStreamValid()
|
||||
{
|
||||
if (this->_fs == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->_fs->IsValid();
|
||||
}
|
||||
|
||||
bool ClientAVCaptureObject::IsCapturingVideo()
|
||||
{
|
||||
slock_lock(this->_mutexCaptureFlags);
|
||||
const bool isCapturingVideo = this->_isCapturingVideo;
|
||||
slock_unlock(this->_mutexCaptureFlags);
|
||||
|
||||
return isCapturingVideo;
|
||||
}
|
||||
|
||||
bool ClientAVCaptureObject::IsCapturingAudio()
|
||||
{
|
||||
slock_lock(this->_mutexCaptureFlags);
|
||||
const bool isCapturingAudio = this->_isCapturingAudio;
|
||||
slock_unlock(this->_mutexCaptureFlags);
|
||||
|
||||
return isCapturingAudio;
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::StartFrame()
|
||||
{
|
||||
if (!this->IsFileStreamValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the queue is full, then we need to wait for some frames to finish writing
|
||||
// before we continue adding new frames to the queue.
|
||||
this->_fs->QueueWait();
|
||||
|
||||
this->_currentBufferIndex = ((this->_currentBufferIndex + 1) % this->_pendingBufferCount);
|
||||
this->_pendingAudioWriteSize[this->_currentBufferIndex] = 0;
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::StreamWriteStart()
|
||||
{
|
||||
if (!this->IsFileStreamValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t bufferIndex = this->_currentBufferIndex;
|
||||
const size_t queueSize = this->_fs->GetQueueSize();
|
||||
const bool isQueueEmpty = (queueSize == 0);
|
||||
|
||||
// If there are no frames in the current write queue, then we know that the current
|
||||
// pending video frame will be written immediately. If this is the case, then we
|
||||
// need to force the video conversion to finish so that we can write out the frame.
|
||||
if (isQueueEmpty)
|
||||
{
|
||||
if (this->_videoFrameSize > 0)
|
||||
{
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->_fs->QueueAdd(this->_pendingVideoBuffer + (this->_videoFrameSize * bufferIndex), this->_videoFrameSize,
|
||||
this->_pendingAudioBuffer + (AUDIO_STREAM_BUFFER_SIZE * bufferIndex), this->_pendingAudioWriteSize[bufferIndex]);
|
||||
|
||||
if (isQueueEmpty)
|
||||
{
|
||||
this->_fileWriteThread->execute(&RunAviFileWrite, this->_fs);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::StreamWriteFinish()
|
||||
{
|
||||
this->_fileWriteThread->finish();
|
||||
}
|
||||
|
||||
//converts 16bpp to 24bpp and flips
|
||||
void ClientAVCaptureObject::ConvertVideoSlice555Xto888(const VideoConvertParam ¶m)
|
||||
{
|
||||
const u16 *__restrict src = (const u16 *__restrict)param.src;
|
||||
u8 *__restrict dst = param.dst;
|
||||
|
||||
for (size_t y = param.firstLineIndex; y <= param.lastLineIndex; y++)
|
||||
{
|
||||
ColorspaceConvertBuffer555XTo888<true, false>(src, dst, param.frameWidth);
|
||||
src += param.frameWidth;
|
||||
dst -= param.frameWidth * 3;
|
||||
}
|
||||
}
|
||||
|
||||
//converts 32bpp to 24bpp and flips
|
||||
void ClientAVCaptureObject::ConvertVideoSlice888Xto888(const VideoConvertParam ¶m)
|
||||
{
|
||||
const u32 *__restrict src = (const u32 *__restrict)param.src;
|
||||
u8 *__restrict dst = param.dst;
|
||||
|
||||
for (size_t y = param.firstLineIndex; y <= param.lastLineIndex; y++)
|
||||
{
|
||||
ColorspaceConvertBuffer888XTo888<true, false>(src, dst, param.frameWidth);
|
||||
src += param.frameWidth;
|
||||
dst -= param.frameWidth * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::ReadVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat)
|
||||
{
|
||||
//dont do anything if prescale has changed, it's just going to be garbage
|
||||
if (!this->_isCapturingVideo ||
|
||||
(srcVideoFrame == NULL) ||
|
||||
(this->_videoFrameSize == 0) ||
|
||||
(this->_videoFrameWidth != inFrameWidth) ||
|
||||
(this->_videoFrameHeight != (inFrameHeight * 2)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t bufferIndex = this->_currentBufferIndex;
|
||||
u8 *convertBufferHead = this->_pendingVideoBuffer + (this->_videoFrameSize * bufferIndex);
|
||||
|
||||
if (colorFormat == NDSColorFormat_BGR555_Rev)
|
||||
{
|
||||
if (this->_numThreads == 0)
|
||||
{
|
||||
this->_convertParam[0].src = (u16 *)srcVideoFrame;
|
||||
this->_convertParam[0].dst = convertBufferHead + this->_convertParam[0].dstOffset;
|
||||
this->ConvertVideoSlice555Xto888(this->_convertParam[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
this->_convertParam[i].src = (u16 *)srcVideoFrame + this->_convertParam[i].srcOffset;
|
||||
this->_convertParam[i].dst = convertBufferHead + this->_convertParam[i].dstOffset;
|
||||
this->_convertThread[i]->execute(&RunConvertVideoSlice555XTo888, &this->_convertParam[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->_numThreads == 0)
|
||||
{
|
||||
this->_convertParam[0].src = (u32 *)srcVideoFrame;
|
||||
this->_convertParam[0].dst = convertBufferHead + this->_convertParam[0].dstOffset;
|
||||
this->ConvertVideoSlice888Xto888(this->_convertParam[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < this->_numThreads; i++)
|
||||
{
|
||||
this->_convertThread[i]->finish();
|
||||
this->_convertParam[i].src = (u32 *)srcVideoFrame + this->_convertParam[i].srcOffset;
|
||||
this->_convertParam[i].dst = convertBufferHead + this->_convertParam[i].dstOffset;
|
||||
this->_convertThread[i]->execute(&RunConvertVideoSlice888XTo888, &this->_convertParam[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientAVCaptureObject::ReadAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount)
|
||||
{
|
||||
if (!this->_isCapturingAudio || (srcAudioBuffer == NULL))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t bufferIndex = this->_currentBufferIndex;
|
||||
const size_t soundSize = inSampleCount * this->_audioBlockSize;
|
||||
|
||||
memcpy(this->_pendingAudioBuffer + (AUDIO_STREAM_BUFFER_SIZE * bufferIndex) + this->_pendingAudioWriteSize[bufferIndex], srcAudioBuffer, soundSize);
|
||||
this->_pendingAudioWriteSize[bufferIndex] += soundSize;
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CLIENT_AV_CAPTURE_OBJECT_H_
|
||||
#define _CLIENT_AV_CAPTURE_OBJECT_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
|
||||
#include <rthreads/rthreads.h>
|
||||
#include <rthreads/rsemaphore.h>
|
||||
|
||||
#include "utils/colorspacehandler/colorspacehandler.h"
|
||||
#include "utils/task.h"
|
||||
#include "../../SPU.h"
|
||||
|
||||
#define VIDEO_STREAM 0
|
||||
#define AUDIO_STREAM 1
|
||||
#define MAX_CONVERT_THREADS 32
|
||||
|
||||
#define AUDIO_STREAM_BUFFER_SIZE ((DESMUME_SAMPLE_RATE * sizeof(int16_t) * 2) / 30) // 16-bit samples, 2 channels, 2 frames (need only 1 frame's worth, but have 2 frame's worth for safety)
|
||||
#define MAX_AVI_FILE_SIZE (2ULL * 1024ULL * 1024ULL * 1024ULL) // Max file size should be 2 GB due to the Video for Windows AVI limit.
|
||||
#define MAX_PENDING_BUFFER_SIZE (1536ULL * 1024ULL * 1024ULL) // Max pending buffer size should not exceed 1.5 GB.
|
||||
#define MAX_PENDING_FRAME_COUNT 180 // Maintain up to 180 frames in memory for current and future file writes. This is equivalent to 3 seconds worth of frames.
|
||||
|
||||
|
||||
enum AVFileTypeContainerID
|
||||
{
|
||||
AVFileTypeContainerID_mp4 = 0x000000,
|
||||
AVFileTypeContainerID_avi = 0x010000,
|
||||
AVFileTypeContainerID_mkv = 0x020000,
|
||||
AVFileTypeContainerID_mov = 0x030000,
|
||||
|
||||
AVFileTypeContainerID_m4a = 0x800000,
|
||||
AVFileTypeContainerID_aiff = 0x810000,
|
||||
AVFileTypeContainerID_flac = 0x820000,
|
||||
AVFileTypeContainerID_wav = 0x830000
|
||||
};
|
||||
|
||||
enum AVFileTypeVideoCodecID
|
||||
{
|
||||
AVFileTypeVideoCodecID_H264 = 0x000000,
|
||||
AVFileTypeVideoCodecID_HVEC = 0x001000,
|
||||
AVFileTypeVideoCodecID_HuffYUV = 0x002000,
|
||||
AVFileTypeVideoCodecID_FFV1 = 0x003000,
|
||||
AVFileTypeVideoCodecID_ProRes = 0x004000,
|
||||
|
||||
AVFileTypeVideoCodecID_None = 0x00FF00
|
||||
};
|
||||
|
||||
enum AVFileTypeAudioCodecID
|
||||
{
|
||||
AVFileTypeAudioCodecID_AAC = 0x000000,
|
||||
AVFileTypeAudioCodecID_PCMs16LE = 0x000010,
|
||||
AVFileTypeAudioCodecID_PCMs16BE = 0x000020,
|
||||
AVFileTypeAudioCodecID_ALAC = 0x000030,
|
||||
AVFileTypeAudioCodecID_FLAC = 0x000040,
|
||||
|
||||
AVFileTypeAudioCodecID_None = 0x0000FF
|
||||
};
|
||||
|
||||
enum AVFileTypeID
|
||||
{
|
||||
AVFileTypeID_mp4_H264_AAC = (AVFileTypeContainerID_mp4 | AVFileTypeVideoCodecID_H264 | AVFileTypeAudioCodecID_AAC), // dec = 0
|
||||
AVFileTypeID_mp4_HVEC_AAC = (AVFileTypeContainerID_mp4 | AVFileTypeVideoCodecID_HVEC | AVFileTypeAudioCodecID_AAC), // dec = 4096
|
||||
AVFileTypeID_avi_HuffYUV_PCMs16LE = (AVFileTypeContainerID_avi | AVFileTypeVideoCodecID_HuffYUV | AVFileTypeAudioCodecID_PCMs16LE), // dec = 73744
|
||||
AVFileTypeID_mkv_FFV1_FLAC = (AVFileTypeContainerID_mkv | AVFileTypeVideoCodecID_FFV1 | AVFileTypeAudioCodecID_FLAC), // dec = 143424
|
||||
AVFileTypeID_mov_H264_ALAC = (AVFileTypeContainerID_mov | AVFileTypeVideoCodecID_H264 | AVFileTypeAudioCodecID_ALAC), // dec = 196656
|
||||
AVFileTypeID_mov_ProRes_ALAC = (AVFileTypeContainerID_mov | AVFileTypeVideoCodecID_ProRes | AVFileTypeAudioCodecID_ALAC), // dec = 213040
|
||||
|
||||
AVFileTypeID_m4a_AAC = (AVFileTypeContainerID_m4a | AVFileTypeVideoCodecID_None | AVFileTypeAudioCodecID_AAC), // dec = 8453888
|
||||
AVFileTypeID_m4a_ALAC = (AVFileTypeContainerID_m4a | AVFileTypeVideoCodecID_None | AVFileTypeAudioCodecID_ALAC), // dec = 8453936
|
||||
AVFileTypeID_aiff_PCMs16BE = (AVFileTypeContainerID_aiff | AVFileTypeVideoCodecID_None | AVFileTypeAudioCodecID_PCMs16BE), // dec = 8519456
|
||||
AVFileTypeID_flac_FLAC = (AVFileTypeContainerID_flac | AVFileTypeVideoCodecID_None | AVFileTypeAudioCodecID_FLAC), // dec = 8585024
|
||||
AVFileTypeID_wav_PCMs16LE = (AVFileTypeContainerID_wav | AVFileTypeVideoCodecID_None | AVFileTypeAudioCodecID_PCMs16LE), // dec = 8650512
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
AVFILETYPEID_CONTAINERMASK = 0xFF0000,
|
||||
AVFILETYPEID_VIDEOCODECMASK = 0x00F000,
|
||||
AVFILETYPEID_VIDEOCODECOPTMASK = 0x000F00,
|
||||
AVFILETYPEID_AUDIOCODECMASK = 0x0000F0,
|
||||
AVFILETYPEID_AUDIOCODECOPTMASK = 0x00000F
|
||||
};
|
||||
|
||||
enum FileStreamCloseAction
|
||||
{
|
||||
FSCA_DoNothing = 0,
|
||||
FSCA_PurgeQueue = 1,
|
||||
FSCA_WriteRemainingInQueue = 2
|
||||
};
|
||||
|
||||
enum ClientAVCaptureError
|
||||
{
|
||||
ClientAVCaptureError_None = 0,
|
||||
ClientAVCaptureError_GenericError = 1,
|
||||
ClientAVCaptureError_FileOpenError = 1000,
|
||||
ClientAVCaptureError_GenericFormatCodecError = 2000,
|
||||
ClientAVCaptureError_InvalidContainerFormat = 2000,
|
||||
ClientAVCaptureError_InvalidVideoCodec = 2000,
|
||||
ClientAVCaptureError_InvalidAudioCodec = 2000,
|
||||
ClientAVCaptureError_VideoStreamError = 2000,
|
||||
ClientAVCaptureError_VideoFrameCreationError = 2000,
|
||||
ClientAVCaptureError_AudioStreamError = 2000,
|
||||
ClientAVCaptureError_AudioFrameCreationError = 2000,
|
||||
ClientAVCaptureError_FrameEncodeError = 2000,
|
||||
ClientAVCaptureError_FrameWriteError = 2000
|
||||
};
|
||||
|
||||
class ClientAVCaptureObject;
|
||||
|
||||
struct VideoConvertParam
|
||||
{
|
||||
ClientAVCaptureObject *captureObj;
|
||||
|
||||
const void *src;
|
||||
uint8_t *dst;
|
||||
|
||||
size_t srcOffset;
|
||||
size_t dstOffset;
|
||||
|
||||
size_t firstLineIndex;
|
||||
size_t lastLineIndex;
|
||||
size_t frameWidth;
|
||||
};
|
||||
typedef struct VideoConvertParam VideoConvertParam;
|
||||
|
||||
struct AVStreamWriteParam
|
||||
{
|
||||
u8 *srcVideo;
|
||||
u8 *srcAudio;
|
||||
size_t videoBufferSize;
|
||||
size_t audioBufferSize;
|
||||
};
|
||||
typedef struct AVStreamWriteParam AVStreamWriteParam;
|
||||
|
||||
typedef std::queue<AVStreamWriteParam> AVStreamWriteQueue;
|
||||
|
||||
class ClientAVCaptureFileStream
|
||||
{
|
||||
protected:
|
||||
size_t _videoWidth;
|
||||
size_t _videoHeight;
|
||||
|
||||
std::string _baseFileName;
|
||||
std::string _baseFileNameExt;
|
||||
size_t _segmentNumber;
|
||||
|
||||
AVFileTypeID _fileTypeID;
|
||||
AVFileTypeContainerID _fileTypeContainerID;
|
||||
AVFileTypeVideoCodecID _fileTypeVideoCodecID;
|
||||
AVFileTypeAudioCodecID _fileTypeAudioCodecID;
|
||||
|
||||
uint64_t _maxSegmentSize;
|
||||
uint64_t _expectedMaxFrameSize;
|
||||
uint64_t _writtenBytes;
|
||||
size_t _writtenVideoFrameCount;
|
||||
size_t _writtenAudioSampleCount;
|
||||
|
||||
ssem_t *_semQueue;
|
||||
slock_t *_mutexQueue;
|
||||
AVStreamWriteQueue _writeQueue;
|
||||
|
||||
public:
|
||||
ClientAVCaptureFileStream();
|
||||
virtual ~ClientAVCaptureFileStream();
|
||||
|
||||
void InitBaseProperties(const AVFileTypeID fileTypeID, const std::string &fileName,
|
||||
const size_t videoWidth, const size_t videoHeight,
|
||||
size_t pendingFrameCount);
|
||||
|
||||
AVFileTypeVideoCodecID GetVideoCodecID();
|
||||
AVFileTypeAudioCodecID GetAudioCodecID();
|
||||
|
||||
virtual ClientAVCaptureError Open() = 0;
|
||||
virtual void Close(FileStreamCloseAction theAction) = 0;
|
||||
virtual bool IsValid();
|
||||
|
||||
void QueueAdd(uint8_t *srcVideo, const size_t videoBufferSize, uint8_t *srcAudio, const size_t audioBufferSize);
|
||||
void QueueWait();
|
||||
size_t GetQueueSize();
|
||||
|
||||
virtual ClientAVCaptureError FlushVideo(uint8_t *srcBuffer, const size_t bufferSize);
|
||||
virtual ClientAVCaptureError FlushAudio(uint8_t *srcBuffer, const size_t bufferSize);
|
||||
virtual ClientAVCaptureError WriteOneFrame(const AVStreamWriteParam ¶m);
|
||||
|
||||
ClientAVCaptureError WriteAllFrames();
|
||||
};
|
||||
|
||||
class ClientAVCaptureObject
|
||||
{
|
||||
private:
|
||||
void __InstanceInit(size_t videoFrameWidth, size_t videoFrameHeight);
|
||||
|
||||
protected:
|
||||
ClientAVCaptureFileStream *_fs;
|
||||
|
||||
bool _isCapturingVideo;
|
||||
bool _isCapturingAudio;
|
||||
|
||||
size_t _videoFrameWidth;
|
||||
size_t _videoFrameHeight;
|
||||
size_t _videoFrameSize;
|
||||
size_t _audioBlockSize;
|
||||
size_t _audioFrameSize;
|
||||
|
||||
uint8_t *_pendingVideoBuffer;
|
||||
uint8_t *_pendingAudioBuffer;
|
||||
size_t *_pendingAudioWriteSize;
|
||||
size_t _pendingBufferCount;
|
||||
size_t _currentBufferIndex;
|
||||
|
||||
size_t _numThreads;
|
||||
Task *_fileWriteThread;
|
||||
Task *_convertThread[MAX_CONVERT_THREADS];
|
||||
VideoConvertParam _convertParam[MAX_CONVERT_THREADS];
|
||||
|
||||
slock_t *_mutexCaptureFlags;
|
||||
|
||||
public:
|
||||
ClientAVCaptureObject();
|
||||
ClientAVCaptureObject(size_t videoFrameWidth, size_t videoFrameHeight);
|
||||
~ClientAVCaptureObject();
|
||||
|
||||
ClientAVCaptureFileStream* GetOutputFileStream();
|
||||
void SetOutputFileStream(ClientAVCaptureFileStream *fs);
|
||||
bool IsFileStreamValid();
|
||||
|
||||
bool IsCapturingVideo();
|
||||
bool IsCapturingAudio();
|
||||
|
||||
void StartFrame();
|
||||
void StreamWriteStart();
|
||||
void StreamWriteFinish();
|
||||
|
||||
void ConvertVideoSlice555Xto888(const VideoConvertParam ¶m);
|
||||
void ConvertVideoSlice888Xto888(const VideoConvertParam ¶m);
|
||||
|
||||
void ReadVideoFrame(const void *srcVideoFrame, const size_t inFrameWidth, const size_t inFrameHeight, const NDSColorFormat colorFormat);
|
||||
void ReadAudioFrames(const void *srcAudioBuffer, const size_t inSampleCount);
|
||||
};
|
||||
|
||||
#endif // _CLIENT_AV_CAPTURE_OBJECT_H_
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,13 +18,29 @@
|
|||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#include "../../armcpu.h"
|
||||
#include "../../GPU.h"
|
||||
#include "../../movie.h"
|
||||
#include "../../NDSSystem.h"
|
||||
#include "../../gdbstub.h"
|
||||
#include "../../rtc.h"
|
||||
|
||||
#include "ClientExecutionControl.h"
|
||||
|
||||
// Need to include assert.h this way so that GDB stub will work
|
||||
// with an optimized build.
|
||||
#if defined(GDB_STUB) && defined(NDEBUG)
|
||||
#define TEMP_NDEBUG
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(TEMP_NDEBUG)
|
||||
#undef TEMP_NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
|
||||
|
||||
ClientExecutionControl::ClientExecutionControl()
|
||||
{
|
||||
|
@ -40,6 +56,15 @@ ClientExecutionControl::ClientExecutionControl()
|
|||
_framesToSkip = 0;
|
||||
_prevExecBehavior = ExecutionBehavior_Pause;
|
||||
|
||||
_isGdbStubStarted = false;
|
||||
_enableGdbStubARM9 = false;
|
||||
_enableGdbStubARM7 = false;
|
||||
_gdbStubPortARM9 = 0;
|
||||
_gdbStubPortARM7 = 0;
|
||||
_gdbStubHandleARM9 = NULL;
|
||||
_gdbStubHandleARM7 = NULL;
|
||||
_isInDebugTrap = false;
|
||||
|
||||
_settingsPending.cpuEngineID = CPUEmulationEngineID_Interpreter;
|
||||
_settingsPending.JITMaxBlockSize = 12;
|
||||
_settingsPending.slot1DeviceType = NDS_SLOT1_RETAIL_AUTO;
|
||||
|
@ -71,6 +96,8 @@ ClientExecutionControl::ClientExecutionControl()
|
|||
_settingsPending.execBehavior = ExecutionBehavior_Pause;
|
||||
_settingsPending.jumpBehavior = FrameJumpBehavior_Forward;
|
||||
|
||||
_settingsPending.avCaptureObject = NULL;
|
||||
|
||||
_settingsApplied = _settingsPending;
|
||||
_settingsApplied.filePathARM9BIOS = _settingsPending.filePathARM9BIOS;
|
||||
_settingsApplied.filePathARM7BIOS = _settingsPending.filePathARM7BIOS;
|
||||
|
@ -100,6 +127,29 @@ ClientExecutionControl::~ClientExecutionControl()
|
|||
pthread_mutex_destroy(&this->_mutexOutputPostNDSExec);
|
||||
}
|
||||
|
||||
ClientAVCaptureObject* ClientExecutionControl::GetClientAVCaptureObject()
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
ClientAVCaptureObject *theCaptureObject = this->_settingsPending.avCaptureObject;
|
||||
pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
|
||||
return theCaptureObject;
|
||||
}
|
||||
|
||||
ClientAVCaptureObject* ClientExecutionControl::GetClientAVCaptureObjectApplied()
|
||||
{
|
||||
return this->_settingsApplied.avCaptureObject;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetClientAVCaptureObject(ClientAVCaptureObject *theCaptureObject)
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
this->_settingsPending.avCaptureObject = theCaptureObject;
|
||||
|
||||
this->_newSettingsPendingOnNDSExec = true;
|
||||
pthread_mutex_unlock(&this->_mutexSettingsPendingOnNDSExec);
|
||||
}
|
||||
|
||||
ClientInputHandler* ClientExecutionControl::GetClientInputHandler()
|
||||
{
|
||||
return this->_inputHandler;
|
||||
|
@ -646,6 +696,138 @@ void ClientExecutionControl::SetFrameJumpTarget(uint64_t newJumpTarget)
|
|||
pthread_mutex_unlock(&this->_mutexSettingsPendingOnExecutionLoopStart);
|
||||
}
|
||||
|
||||
bool ClientExecutionControl::IsGDBStubARM9Enabled()
|
||||
{
|
||||
return this->_enableGdbStubARM9;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetGDBStubARM9Enabled(bool theState)
|
||||
{
|
||||
this->_enableGdbStubARM9 = theState;
|
||||
}
|
||||
|
||||
bool ClientExecutionControl::IsGDBStubARM7Enabled()
|
||||
{
|
||||
return this->_enableGdbStubARM7;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetGDBStubARM7Enabled(bool theState)
|
||||
{
|
||||
this->_enableGdbStubARM7 = theState;
|
||||
}
|
||||
|
||||
uint16_t ClientExecutionControl::GetGDBStubARM9Port()
|
||||
{
|
||||
return this->_gdbStubPortARM9;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetGDBStubARM9Port(uint16_t portNumber)
|
||||
{
|
||||
this->_gdbStubPortARM9 = portNumber;
|
||||
}
|
||||
|
||||
uint16_t ClientExecutionControl::GetGDBStubARM7Port()
|
||||
{
|
||||
return this->_gdbStubPortARM7;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetGDBStubARM7Port(uint16_t portNumber)
|
||||
{
|
||||
this->_gdbStubPortARM7 = portNumber;
|
||||
}
|
||||
|
||||
bool ClientExecutionControl::IsGDBStubStarted()
|
||||
{
|
||||
return this->_isGdbStubStarted;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetIsGDBStubStarted(bool theState)
|
||||
{
|
||||
#ifdef GDB_STUB
|
||||
if (theState)
|
||||
{
|
||||
gdbstub_mutex_init();
|
||||
|
||||
if (this->_enableGdbStubARM9)
|
||||
{
|
||||
const uint16_t arm9Port = this->_gdbStubPortARM9;
|
||||
if(arm9Port > 0)
|
||||
{
|
||||
this->_gdbStubHandleARM9 = createStub_gdb(arm9Port, &NDS_ARM9, &arm9_direct_memory_iface);
|
||||
if (this->_gdbStubHandleARM9 == NULL)
|
||||
{
|
||||
printf("Failed to create ARM9 gdbstub on port %d\n", arm9Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
activateStub_gdb(this->_gdbStubHandleARM9);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(this->_gdbStubHandleARM9);
|
||||
this->_gdbStubHandleARM9 = NULL;
|
||||
}
|
||||
|
||||
if (this->_enableGdbStubARM7)
|
||||
{
|
||||
const uint16_t arm7Port = this->_gdbStubPortARM7;
|
||||
if (arm7Port > 0)
|
||||
{
|
||||
this->_gdbStubHandleARM7 = createStub_gdb(arm7Port, &NDS_ARM7, &arm7_base_memory_iface);
|
||||
if (this->_gdbStubHandleARM7 == NULL)
|
||||
{
|
||||
printf("Failed to create ARM7 gdbstub on port %d\n", arm7Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
activateStub_gdb(this->_gdbStubHandleARM7);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(this->_gdbStubHandleARM7);
|
||||
this->_gdbStubHandleARM7 = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(this->_gdbStubHandleARM9);
|
||||
this->_gdbStubHandleARM9 = NULL;
|
||||
|
||||
destroyStub_gdb(this->_gdbStubHandleARM7);
|
||||
this->_gdbStubHandleARM7 = NULL;
|
||||
|
||||
gdbstub_mutex_destroy();
|
||||
}
|
||||
#endif
|
||||
if ( (this->_gdbStubHandleARM9 == NULL) && (this->_gdbStubHandleARM7 == NULL) )
|
||||
{
|
||||
theState = false;
|
||||
}
|
||||
|
||||
this->_isGdbStubStarted = theState;
|
||||
}
|
||||
|
||||
bool ClientExecutionControl::IsInDebugTrap()
|
||||
{
|
||||
return this->_isInDebugTrap;
|
||||
}
|
||||
|
||||
void ClientExecutionControl::SetIsInDebugTrap(bool theState)
|
||||
{
|
||||
// If we're transitioning out of the debug trap, then ignore
|
||||
// frame skipping this time.
|
||||
if (this->_isInDebugTrap && !theState)
|
||||
{
|
||||
this->ResetFramesToSkip();
|
||||
}
|
||||
|
||||
this->_isInDebugTrap = theState;
|
||||
}
|
||||
|
||||
ExecutionBehavior ClientExecutionControl::GetPreviousExecutionBehavior()
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexSettingsPendingOnExecutionLoopStart);
|
||||
|
@ -859,6 +1041,8 @@ void ClientExecutionControl::ApplySettingsOnNDSExec()
|
|||
|
||||
this->_settingsApplied.enableFrameSkip = this->_settingsPending.enableFrameSkip;
|
||||
|
||||
this->_settingsApplied.avCaptureObject = this->_settingsPending.avCaptureObject;
|
||||
|
||||
const bool needResetFramesToSkip = this->_needResetFramesToSkip;
|
||||
|
||||
this->_needResetFramesToSkip = false;
|
||||
|
@ -1067,3 +1251,33 @@ void ClientExecutionControl::WaitUntilAbsoluteTime(double deadlineAbsoluteTime)
|
|||
{
|
||||
mach_wait_until((uint64_t)deadlineAbsoluteTime);
|
||||
}
|
||||
|
||||
void* createThread_gdb(void (*thread_function)(void *data), void *thread_data)
|
||||
{
|
||||
// Create the thread using POSIX routines.
|
||||
pthread_attr_t attr;
|
||||
pthread_t* posixThreadID = (pthread_t*)malloc(sizeof(pthread_t));
|
||||
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
||||
|
||||
int threadError = pthread_create(posixThreadID, &attr, (void* (*)(void *))thread_function, thread_data);
|
||||
|
||||
assert(!pthread_attr_destroy(&attr));
|
||||
|
||||
if (threadError != 0)
|
||||
{
|
||||
// Report an error.
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return posixThreadID;
|
||||
}
|
||||
}
|
||||
|
||||
void joinThread_gdb(void *thread_handle)
|
||||
{
|
||||
pthread_join(*(pthread_t *)thread_handle, NULL);
|
||||
free(thread_handle);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,6 +22,7 @@
|
|||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
#include "../../slot1.h"
|
||||
|
@ -98,6 +99,8 @@ struct ClientExecutionControlSettings
|
|||
|
||||
ExecutionBehavior execBehavior;
|
||||
FrameJumpBehavior jumpBehavior;
|
||||
|
||||
ClientAVCaptureObject *avCaptureObject;
|
||||
};
|
||||
|
||||
struct NDSFrameInfo
|
||||
|
@ -184,6 +187,8 @@ struct NDSFrameInfo
|
|||
}
|
||||
};
|
||||
|
||||
typedef void *gdbstub_handle_t;
|
||||
|
||||
class ClientExecutionControl
|
||||
{
|
||||
protected:
|
||||
|
@ -204,6 +209,15 @@ protected:
|
|||
uint8_t _framesToSkip;
|
||||
ExecutionBehavior _prevExecBehavior;
|
||||
|
||||
bool _isGdbStubStarted;
|
||||
bool _enableGdbStubARM9;
|
||||
bool _enableGdbStubARM7;
|
||||
uint16_t _gdbStubPortARM9;
|
||||
uint16_t _gdbStubPortARM7;
|
||||
volatile gdbstub_handle_t _gdbStubHandleARM9;
|
||||
volatile gdbstub_handle_t _gdbStubHandleARM7;
|
||||
bool _isInDebugTrap;
|
||||
|
||||
std::string _cpuEmulationEngineNameOut;
|
||||
std::string _slot1DeviceNameOut;
|
||||
std::string _rtcStringOut;
|
||||
|
@ -217,6 +231,10 @@ public:
|
|||
ClientExecutionControl();
|
||||
~ClientExecutionControl();
|
||||
|
||||
ClientAVCaptureObject* GetClientAVCaptureObject();
|
||||
ClientAVCaptureObject* GetClientAVCaptureObjectApplied();
|
||||
void SetClientAVCaptureObject(ClientAVCaptureObject *theCaptureObject);
|
||||
|
||||
ClientInputHandler* GetClientInputHandler();
|
||||
void SetClientInputHandler(ClientInputHandler *inputHandler);
|
||||
|
||||
|
@ -297,6 +315,21 @@ public:
|
|||
uint64_t GetFrameJumpTargetApplied();
|
||||
void SetFrameJumpTarget(uint64_t newJumpTarget);
|
||||
|
||||
bool IsGDBStubARM9Enabled();
|
||||
void SetGDBStubARM9Enabled(bool theState);
|
||||
bool IsGDBStubARM7Enabled();
|
||||
void SetGDBStubARM7Enabled(bool theState);
|
||||
|
||||
uint16_t GetGDBStubARM9Port();
|
||||
void SetGDBStubARM9Port(uint16_t portNumber);
|
||||
uint16_t GetGDBStubARM7Port();
|
||||
void SetGDBStubARM7Port(uint16_t portNumber);
|
||||
|
||||
bool IsGDBStubStarted();
|
||||
void SetIsGDBStubStarted(bool theState);
|
||||
bool IsInDebugTrap();
|
||||
void SetIsInDebugTrap(bool theState);
|
||||
|
||||
ExecutionBehavior GetPreviousExecutionBehavior();
|
||||
ExecutionBehavior GetExecutionBehavior();
|
||||
ExecutionBehavior GetExecutionBehaviorApplied();
|
||||
|
|
|
@ -90,6 +90,18 @@
|
|||
AB23567416C2F6F400DA782E /* macosx_10_5_compat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */; };
|
||||
AB23567516C2FAD800DA782E /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; };
|
||||
AB26D87C16B5253D00A2305C /* OGLRender_3_2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB68A0DA16B139BC00DE0546 /* OGLRender_3_2.cpp */; };
|
||||
AB28624F20AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */; };
|
||||
AB28625020AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */; };
|
||||
AB28625120AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */; };
|
||||
AB28625220AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */; };
|
||||
AB28625920AE3E9F00EAED43 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */; };
|
||||
AB28625A20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */; };
|
||||
AB28625B20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */; };
|
||||
AB28625C20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */; };
|
||||
AB28626120AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */; };
|
||||
AB28626220AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */; };
|
||||
AB28626320AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */; };
|
||||
AB28626420AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */; };
|
||||
AB29B16218313AF5009B7982 /* slot2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB29B16118313AF5009B7982 /* slot2.cpp */; };
|
||||
AB29B16318313AF5009B7982 /* slot2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB29B16118313AF5009B7982 /* slot2.cpp */; };
|
||||
AB29B16418313AF5009B7982 /* slot2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB29B16118313AF5009B7982 /* slot2.cpp */; };
|
||||
|
@ -1434,6 +1446,10 @@
|
|||
ABEFCF64141AB82A000CC0CD /* AppIcon_SaveState.icns in Resources */ = {isa = PBXBuildFile; fileRef = ABEFCF60141AB82A000CC0CD /* AppIcon_SaveState.icns */; };
|
||||
ABF2B9FB16904133000FF7C0 /* troubleshootingWindowDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABF2B9FA16904133000FF7C0 /* troubleshootingWindowDelegate.mm */; };
|
||||
ABF2B9FC16904133000FF7C0 /* troubleshootingWindowDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABF2B9FA16904133000FF7C0 /* troubleshootingWindowDelegate.mm */; };
|
||||
ABF3B52220AE6D3C007DE9FF /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */; };
|
||||
ABF3B52320AE6D3C007DE9FF /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */; };
|
||||
ABF3B52420AE6D3D007DE9FF /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */; };
|
||||
ABF3B52520AE6D3E007DE9FF /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */; };
|
||||
ABFE150714C92FF5005D6699 /* 2xsai.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABFE14FA14C92FF5005D6699 /* 2xsai.cpp */; };
|
||||
ABFE150814C92FF5005D6699 /* bilinear.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABFE14FB14C92FF5005D6699 /* bilinear.cpp */; };
|
||||
ABFE150914C92FF5005D6699 /* epx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABFE14FC14C92FF5005D6699 /* epx.cpp */; };
|
||||
|
@ -1579,6 +1595,14 @@
|
|||
AB1B9E611501A78000464647 /* coreaudiosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreaudiosound.h; sourceTree = "<group>"; };
|
||||
AB1B9E621501A78000464647 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; };
|
||||
AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macosx_10_5_compat.cpp; sourceTree = "<group>"; };
|
||||
AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MacAVCaptureTool.mm; sourceTree = "<group>"; };
|
||||
AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MacBaseCaptureTool.mm; sourceTree = "<group>"; };
|
||||
AB28624920AE3E7B00EAED43 /* MacAVCaptureTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacAVCaptureTool.h; sourceTree = "<group>"; };
|
||||
AB28624A20AE3E7B00EAED43 /* MacBaseCaptureTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacBaseCaptureTool.h; sourceTree = "<group>"; };
|
||||
AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macOS_driver.cpp; sourceTree = "<group>"; };
|
||||
AB28625520AE3E9E00EAED43 /* macOS_driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macOS_driver.h; sourceTree = "<group>"; };
|
||||
AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientAVCaptureObject.cpp; sourceTree = "<group>"; };
|
||||
AB28625820AE3E9F00EAED43 /* ClientAVCaptureObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientAVCaptureObject.h; sourceTree = "<group>"; };
|
||||
AB29B15C18313ACD009B7982 /* slot2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = slot2.h; sourceTree = "<group>"; };
|
||||
AB29B16118313AF5009B7982 /* slot2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2.cpp; sourceTree = "<group>"; };
|
||||
AB29B16518313C14009B7982 /* slot2_auto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = slot2_auto.cpp; sourceTree = "<group>"; };
|
||||
|
@ -2386,17 +2410,20 @@
|
|||
AB3ACB6514C2361100D7D192 /* userinterface */,
|
||||
AB82445A1704AE9A00B8EE20 /* utilities.c */,
|
||||
ABD10AE51715FCDD00B5729D /* audiosamplegenerator.cpp */,
|
||||
AB28625720AE3E9F00EAED43 /* ClientAVCaptureObject.cpp */,
|
||||
ABAD07DA1E19CAA6007867CA /* ClientDisplayView.cpp */,
|
||||
ABB1C9461F5281AE0004844F /* ClientExecutionControl.cpp */,
|
||||
AB11AD871F6757F800CB298E /* ClientInputHandler.cpp */,
|
||||
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */,
|
||||
AB28625320AE3E9E00EAED43 /* macOS_driver.cpp */,
|
||||
AB23567216C2F6F400DA782E /* macosx_10_5_compat.cpp */,
|
||||
ABD10AE61715FCDD00B5729D /* mic_ext.cpp */,
|
||||
ABE6840B189E33BC007FD69C /* OGLDisplayOutput.cpp */,
|
||||
ABB24F6B1A81EE92006C1108 /* OGLDisplayOutput_3_2.cpp */,
|
||||
ABE6840B189E33BC007FD69C /* OGLDisplayOutput.cpp */,
|
||||
AB1B9E601501A78000464647 /* ringbuffer.cpp */,
|
||||
ABD104141346652500AF11D1 /* sndOSX.cpp */,
|
||||
ABD10AE31715FCDD00B5729D /* audiosamplegenerator.h */,
|
||||
AB28625820AE3E9F00EAED43 /* ClientAVCaptureObject.h */,
|
||||
ABAD07DB1E19CAA6007867CA /* ClientDisplayView.h */,
|
||||
ABB1C9471F5281AE0004844F /* ClientExecutionControl.h */,
|
||||
AB11AD881F6757F800CB298E /* ClientInputHandler.h */,
|
||||
|
@ -2413,10 +2440,11 @@
|
|||
AB80E050142BC4FA00A52038 /* cocoa_util.h */,
|
||||
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */,
|
||||
AB1B9E611501A78000464647 /* coreaudiosound.h */,
|
||||
AB28625520AE3E9E00EAED43 /* macOS_driver.h */,
|
||||
ABD10AE41715FCDD00B5729D /* mic_ext.h */,
|
||||
AB1B9E621501A78000464647 /* ringbuffer.h */,
|
||||
ABE6840E189E33D5007FD69C /* OGLDisplayOutput.h */,
|
||||
ABB24F6C1A81EE92006C1108 /* OGLDisplayOutput_3_2.h */,
|
||||
ABE6840E189E33D5007FD69C /* OGLDisplayOutput.h */,
|
||||
AB1B9E621501A78000464647 /* ringbuffer.h */,
|
||||
ABD104011346652500AF11D1 /* sndOSX.h */,
|
||||
AB82445E1704AEC400B8EE20 /* utilities.h */,
|
||||
ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */,
|
||||
|
@ -2808,6 +2836,8 @@
|
|||
AB29B32F16D4BEBF000EF671 /* InputManager.h */,
|
||||
AB3ACB6E14C2361100D7D192 /* inputPrefsView.h */,
|
||||
AB01005C170D07AF00D70FBE /* InputProfileController.h */,
|
||||
AB28624920AE3E7B00EAED43 /* MacAVCaptureTool.h */,
|
||||
AB28624A20AE3E7B00EAED43 /* MacBaseCaptureTool.h */,
|
||||
AB3BF43F1E2628B6003E2B24 /* MacMetalDisplayView.h */,
|
||||
AB3BF4051E22FEA8003E2B24 /* MacOGLDisplayView.h */,
|
||||
ABD1FBF41F7B7EA600B4F648 /* MacScreenshotCaptureTool.h */,
|
||||
|
@ -2825,6 +2855,8 @@
|
|||
AB29B33016D4BEBF000EF671 /* InputManager.mm */,
|
||||
AB3ACB6F14C2361100D7D192 /* inputPrefsView.mm */,
|
||||
AB01005D170D07B000D70FBE /* InputProfileController.mm */,
|
||||
AB28624720AE3E7A00EAED43 /* MacAVCaptureTool.mm */,
|
||||
AB28624820AE3E7A00EAED43 /* MacBaseCaptureTool.mm */,
|
||||
AB3BF43B1E26289E003E2B24 /* MacMetalDisplayView.mm */,
|
||||
AB3BF4011E22FE01003E2B24 /* MacOGLDisplayView.mm */,
|
||||
ABD1FBF01F7B7E7E00B4F648 /* MacScreenshotCaptureTool.mm */,
|
||||
|
@ -4345,6 +4377,7 @@
|
|||
ABD1FF571345ACBF00AF11D1 /* header.cpp in Sources */,
|
||||
ABD1FF621345ACBF00AF11D1 /* libfat.cpp in Sources */,
|
||||
ABD1FF631345ACBF00AF11D1 /* libfat_public_api.cpp in Sources */,
|
||||
ABF3B52220AE6D3C007DE9FF /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1FF641345ACBF00AF11D1 /* lock.cpp in Sources */,
|
||||
ABA7315F1BB51E7000B26147 /* pshinter.c in Sources */,
|
||||
ABD1FEE81345AC8400AF11D1 /* matrix.cpp in Sources */,
|
||||
|
@ -4371,6 +4404,7 @@
|
|||
ABD1FF0B1345AC9C00AF11D1 /* slot1_none.cpp in Sources */,
|
||||
ABD1FF0C1345AC9C00AF11D1 /* slot1_r4.cpp in Sources */,
|
||||
ABFEA8861BB4EC1100B08C25 /* cff.c in Sources */,
|
||||
AB28625220AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */,
|
||||
AB6FBEF6139B6258007BB045 /* slot1_retail_nand.cpp in Sources */,
|
||||
ABCFA9F5178BDE920030C8BA /* encrypt.cpp in Sources */,
|
||||
ABD1FF0E1345AC9C00AF11D1 /* slot2_expMemory.cpp in Sources */,
|
||||
|
@ -4466,6 +4500,7 @@
|
|||
AB405634169F5DBB0016AC3E /* compiler.cpp in Sources */,
|
||||
AB405637169F5DBB0016AC3E /* compilercontext.cpp in Sources */,
|
||||
AB2ABA451C9F9CFA00173B15 /* rthreads.c in Sources */,
|
||||
AB28625C20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
|
||||
ABFEA8561BB4EC1100B08C25 /* ftsynth.c in Sources */,
|
||||
AB40563A169F5DBB0016AC3E /* compilerfunc.cpp in Sources */,
|
||||
AB40563D169F5DBB0016AC3E /* compileritem.cpp in Sources */,
|
||||
|
@ -4504,6 +4539,7 @@
|
|||
AB23567516C2FAD800DA782E /* OGLRender_3_2.cpp in Sources */,
|
||||
ABFEA81A1BB4EC1000B08C25 /* ftfntfmt.c in Sources */,
|
||||
AB3A655F16CC5421001F5D4A /* EmuControllerDelegate.mm in Sources */,
|
||||
AB28626420AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
AB3A656216CC5438001F5D4A /* cocoa_GPU.mm in Sources */,
|
||||
AB9038B917C5ED2200F410BD /* slot1comp_rom.cpp in Sources */,
|
||||
AB8967DA16D2ED0700F826F1 /* DisplayWindowController.mm in Sources */,
|
||||
|
@ -4567,6 +4603,7 @@
|
|||
AB796D0815CDCBA200C59155 /* FIFOSampleBuffer.cpp in Sources */,
|
||||
AB796D0915CDCBA200C59155 /* file_allocation_table.cpp in Sources */,
|
||||
AB796D0A15CDCBA200C59155 /* filetime.cpp in Sources */,
|
||||
ABF3B52520AE6D3E007DE9FF /* MacAVCaptureTool.mm in Sources */,
|
||||
AB796D0B15CDCBA200C59155 /* FIRFilter.cpp in Sources */,
|
||||
AB796D0C15CDCBA200C59155 /* firmware.cpp in Sources */,
|
||||
ABFEA8521BB4EC1100B08C25 /* ftstroke.c in Sources */,
|
||||
|
@ -4593,6 +4630,7 @@
|
|||
AB796D1C15CDCBA200C59155 /* movie.cpp in Sources */,
|
||||
AB9038B817C5ED2200F410BD /* slot1comp_rom.cpp in Sources */,
|
||||
AB796D1D15CDCBA200C59155 /* NDSSystem.cpp in Sources */,
|
||||
AB28624F20AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABFEA8401BB4EC1100B08C25 /* ftpatent.c in Sources */,
|
||||
AB796D1E15CDCBA200C59155 /* OGLRender.cpp in Sources */,
|
||||
AB796D1F15CDCBA200C59155 /* partition.cpp in Sources */,
|
||||
|
@ -4688,6 +4726,7 @@
|
|||
AB796D6415CDCBA200C59155 /* arm_jit.cpp in Sources */,
|
||||
ABFEA8CA1BB4EC1100B08C25 /* smooth.c in Sources */,
|
||||
ABF2B9FB16904133000FF7C0 /* troubleshootingWindowDelegate.mm in Sources */,
|
||||
AB28625920AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
|
||||
AB40562A169F5DBB0016AC3E /* assembler.cpp in Sources */,
|
||||
AB40562D169F5DBB0016AC3E /* assert.cpp in Sources */,
|
||||
AB405630169F5DBB0016AC3E /* buffer.cpp in Sources */,
|
||||
|
@ -4726,6 +4765,7 @@
|
|||
ABFEA8551BB4EC1100B08C25 /* ftsynth.c in Sources */,
|
||||
AB405690169F5DCC0016AC3E /* x86operand.cpp in Sources */,
|
||||
AB405693169F5DCC0016AC3E /* x86util.cpp in Sources */,
|
||||
AB28626120AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
AB26D87C16B5253D00A2305C /* OGLRender_3_2.cpp in Sources */,
|
||||
AB3A655E16CC5421001F5D4A /* EmuControllerDelegate.mm in Sources */,
|
||||
AB3A656116CC5438001F5D4A /* cocoa_GPU.mm in Sources */,
|
||||
|
@ -4771,6 +4811,7 @@
|
|||
ABFEA8571BB4EC1100B08C25 /* ftsynth.c in Sources */,
|
||||
ABFEA80C1BB4EC1000B08C25 /* ftbitmap.c in Sources */,
|
||||
ABFEA82A1BB4EC1100B08C25 /* ftgxval.c in Sources */,
|
||||
AB28626220AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
AB8F3C751A53AC2600A80BF6 /* AAFilter.cpp in Sources */,
|
||||
AB8F3C761A53AC2600A80BF6 /* arm_instructions.cpp in Sources */,
|
||||
AB8F3C771A53AC2600A80BF6 /* armcpu.cpp in Sources */,
|
||||
|
@ -4865,9 +4906,11 @@
|
|||
AB8F3CC41A53AC2600A80BF6 /* task.cpp in Sources */,
|
||||
AB8F3CC51A53AC2600A80BF6 /* TDStretch.cpp in Sources */,
|
||||
AB8F3CC61A53AC2600A80BF6 /* texcache.cpp in Sources */,
|
||||
ABF3B52420AE6D3D007DE9FF /* MacAVCaptureTool.mm in Sources */,
|
||||
AB8F3CC71A53AC2600A80BF6 /* thumb_instructions.cpp in Sources */,
|
||||
AB8F3CC81A53AC2600A80BF6 /* Timestretcher.cpp in Sources */,
|
||||
AB35BD901DEBF41800844310 /* encoding_utf.c in Sources */,
|
||||
AB28625A20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
|
||||
AB8F3CC91A53AC2600A80BF6 /* tinystr.cpp in Sources */,
|
||||
AB8F3CCA1A53AC2600A80BF6 /* slot1comp_mc.cpp in Sources */,
|
||||
AB8F3CCB1A53AC2600A80BF6 /* tinyxml.cpp in Sources */,
|
||||
|
@ -4905,6 +4948,7 @@
|
|||
AB8F3CEA1A53AC2600A80BF6 /* hq4x.cpp in Sources */,
|
||||
ABD1FBF21F7B7E7E00B4F648 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
AB8F3CEB1A53AC2600A80BF6 /* advanscene.cpp in Sources */,
|
||||
AB28625020AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */,
|
||||
AB8F3CEC1A53AC2600A80BF6 /* lq2x.cpp in Sources */,
|
||||
AB8F3CED1A53AC2600A80BF6 /* xbrz.cpp in Sources */,
|
||||
ABB24F6F1A81EE92006C1108 /* OGLDisplayOutput_3_2.cpp in Sources */,
|
||||
|
@ -5219,6 +5263,7 @@
|
|||
ABE1451D1FBBA71A0097A4A8 /* slot2_mpcf.cpp in Sources */,
|
||||
ABE1451E1FBBA71A0097A4A8 /* OGLDisplayOutput.cpp in Sources */,
|
||||
ABE1451F1FBBA71A0097A4A8 /* slot2_none.cpp in Sources */,
|
||||
ABF3B52320AE6D3C007DE9FF /* MacAVCaptureTool.mm in Sources */,
|
||||
ABE145201FBBA71A0097A4A8 /* slot2_paddle.cpp in Sources */,
|
||||
ABE145211FBBA71A0097A4A8 /* slot2_piano.cpp in Sources */,
|
||||
ABE145221FBBA71A0097A4A8 /* Database.cpp in Sources */,
|
||||
|
@ -5232,6 +5277,7 @@
|
|||
ABE1452A1FBBA71A0097A4A8 /* slot1_retail_auto.cpp in Sources */,
|
||||
ABE1452B1FBBA71A0097A4A8 /* SPU.cpp in Sources */,
|
||||
ABE1452C1FBBA71A0097A4A8 /* sse_optimized.cpp in Sources */,
|
||||
AB28625120AE3E7B00EAED43 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABE1452D1FBBA71A0097A4A8 /* task.cpp in Sources */,
|
||||
ABE1452E1FBBA71A0097A4A8 /* TDStretch.cpp in Sources */,
|
||||
ABE1452F1FBBA71A0097A4A8 /* texcache.cpp in Sources */,
|
||||
|
@ -5273,6 +5319,7 @@
|
|||
ABE145551FBBA71A0097A4A8 /* cocoa_videofilter.mm in Sources */,
|
||||
ABE145561FBBA71A0097A4A8 /* OGLRender.cpp in Sources */,
|
||||
ABE145571FBBA71A0097A4A8 /* slot1comp_protocol.cpp in Sources */,
|
||||
AB28626320AE3E9F00EAED43 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABE145581FBBA71A0097A4A8 /* appDelegate.mm in Sources */,
|
||||
ABE145591FBBA71A0097A4A8 /* cheatWindowDelegate.mm in Sources */,
|
||||
ABE1455A1FBBA71A0097A4A8 /* retro_stat.c in Sources */,
|
||||
|
@ -5286,6 +5333,7 @@
|
|||
ABE145621FBBA71A0097A4A8 /* advanscene.cpp in Sources */,
|
||||
ABE145631FBBA71A0097A4A8 /* lq2x.cpp in Sources */,
|
||||
ABE145641FBBA71A0097A4A8 /* xbrz.cpp in Sources */,
|
||||
AB28625B20AE3E9F00EAED43 /* macOS_driver.cpp in Sources */,
|
||||
ABE145651FBBA71A0097A4A8 /* scanline.cpp in Sources */,
|
||||
ABE145661FBBA71A0097A4A8 /* coreaudiosound.cpp in Sources */,
|
||||
ABE145671FBBA71A0097A4A8 /* ringbuffer.cpp in Sources */,
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
|
@ -46,12 +45,13 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUFrameCaptureMode = "3"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
|
|
|
@ -1428,6 +1428,26 @@
|
|||
ABC3DEC11A96EA96009EC345 /* RomInfoPanel.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABC3DEBC1A96EA96009EC345 /* RomInfoPanel.mm */; };
|
||||
ABD0A53A1501AA5A0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */; };
|
||||
ABD0A53B1501AA5A0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */; };
|
||||
ABD1266720AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */; };
|
||||
ABD1266820AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */; };
|
||||
ABD1266920AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */; };
|
||||
ABD1266A20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */; };
|
||||
ABD1266B20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */; };
|
||||
ABD1266C20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */; };
|
||||
ABD1266D20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */; };
|
||||
ABD1266E20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */; };
|
||||
ABD1266F20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */; };
|
||||
ABD1267020AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */; };
|
||||
ABD1267520AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */; };
|
||||
ABD1267620AE812900EFE1B2 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */; };
|
||||
ABD1267720AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */; };
|
||||
ABD1267820AE812900EFE1B2 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */; };
|
||||
ABD1267920AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */; };
|
||||
ABD1267A20AE812900EFE1B2 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */; };
|
||||
ABD1267B20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */; };
|
||||
ABD1267C20AE812900EFE1B2 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */; };
|
||||
ABD1267D20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */; };
|
||||
ABD1267E20AE812900EFE1B2 /* macOS_driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */; };
|
||||
ABD21B5B1DE900D3001D2DFA /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD21B5A1DE900D3001D2DFA /* Database.cpp */; };
|
||||
ABD21B5C1DE900D3001D2DFA /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD21B5A1DE900D3001D2DFA /* Database.cpp */; };
|
||||
ABD21B5D1DE900D3001D2DFA /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD21B5A1DE900D3001D2DFA /* Database.cpp */; };
|
||||
|
@ -2047,6 +2067,14 @@
|
|||
ABD104141346652500AF11D1 /* sndOSX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sndOSX.cpp; sourceTree = "<group>"; };
|
||||
ABD104271346653B00AF11D1 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
ABD10452134666DD00AF11D1 /* DeSmuME_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeSmuME_Prefix.pch; sourceTree = "<group>"; };
|
||||
ABD1266320AE80DF00EFE1B2 /* MacAVCaptureTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacAVCaptureTool.h; sourceTree = "<group>"; };
|
||||
ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MacAVCaptureTool.mm; sourceTree = "<group>"; };
|
||||
ABD1266520AE80DF00EFE1B2 /* MacBaseCaptureTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacBaseCaptureTool.h; sourceTree = "<group>"; };
|
||||
ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MacBaseCaptureTool.mm; sourceTree = "<group>"; };
|
||||
ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClientAVCaptureObject.cpp; sourceTree = "<group>"; };
|
||||
ABD1267220AE812900EFE1B2 /* ClientAVCaptureObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClientAVCaptureObject.h; sourceTree = "<group>"; };
|
||||
ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macOS_driver.cpp; sourceTree = "<group>"; };
|
||||
ABD1267420AE812900EFE1B2 /* macOS_driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = macOS_driver.h; sourceTree = "<group>"; };
|
||||
ABD1FE6F1345AC8400AF11D1 /* armcpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = armcpu.h; sourceTree = "<group>"; };
|
||||
ABD1FE701345AC8400AF11D1 /* bios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bios.h; sourceTree = "<group>"; };
|
||||
ABD1FE721345AC8400AF11D1 /* cheatSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cheatSystem.h; sourceTree = "<group>"; };
|
||||
|
@ -2417,16 +2445,19 @@
|
|||
AB3ACB6514C2361100D7D192 /* userinterface */,
|
||||
AB2F56EF1704C86900E28885 /* utilities.c */,
|
||||
AB2145221714DFF4006DDB0F /* audiosamplegenerator.cpp */,
|
||||
ABD1267120AE812900EFE1B2 /* ClientAVCaptureObject.cpp */,
|
||||
AB0F13911E1B7C320075684F /* ClientDisplayView.cpp */,
|
||||
ABD4F2711F54A51000D75A1F /* ClientExecutionControl.cpp */,
|
||||
ABC04DA11F67A20500EA6ED7 /* ClientInputHandler.cpp */,
|
||||
ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */,
|
||||
ABD1267320AE812900EFE1B2 /* macOS_driver.cpp */,
|
||||
ABC04DC91F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp */,
|
||||
ABD9A46413DB99B300777194 /* mic_ext.cpp */,
|
||||
ABECB51318A460910052D52A /* OGLDisplayOutput.cpp */,
|
||||
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */,
|
||||
ABD104141346652500AF11D1 /* sndOSX.cpp */,
|
||||
AB2145211714DFF4006DDB0F /* audiosamplegenerator.h */,
|
||||
ABD1267220AE812900EFE1B2 /* ClientAVCaptureObject.h */,
|
||||
AB0F13901E1B7C320075684F /* ClientDisplayView.h */,
|
||||
ABD4F2721F54A51000D75A1F /* ClientExecutionControl.h */,
|
||||
ABC04DA21F67A20500EA6ED7 /* ClientInputHandler.h */,
|
||||
|
@ -2443,6 +2474,7 @@
|
|||
AB80E050142BC4FA00A52038 /* cocoa_util.h */,
|
||||
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */,
|
||||
ABD0A5361501AA5A0074A094 /* coreaudiosound.h */,
|
||||
ABD1267420AE812900EFE1B2 /* macOS_driver.h */,
|
||||
ABD9A46313DB99B300777194 /* mic_ext.h */,
|
||||
ABECB51218A460910052D52A /* OGLDisplayOutput.h */,
|
||||
ABD0A5371501AA5A0074A094 /* ringbuffer.h */,
|
||||
|
@ -3080,6 +3112,8 @@
|
|||
AB5A795616D5A56000ED84B7 /* InputManager.h */,
|
||||
AB3ACB6E14C2361100D7D192 /* inputPrefsView.h */,
|
||||
AB213D43170CB141006DDB0F /* InputProfileController.h */,
|
||||
ABD1266320AE80DF00EFE1B2 /* MacAVCaptureTool.h */,
|
||||
ABD1266520AE80DF00EFE1B2 /* MacBaseCaptureTool.h */,
|
||||
AB3E690E1E231E9900D4CC75 /* MacOGLDisplayView.h */,
|
||||
ABAB0AFD1F7C1BB70079EFD3 /* MacScreenshotCaptureTool.h */,
|
||||
AB3ACB7014C2361100D7D192 /* preferencesWindowDelegate.h */,
|
||||
|
@ -3095,6 +3129,8 @@
|
|||
AB5A795716D5A56000ED84B7 /* InputManager.mm */,
|
||||
AB3ACB6F14C2361100D7D192 /* inputPrefsView.mm */,
|
||||
AB213D44170CB141006DDB0F /* InputProfileController.mm */,
|
||||
ABD1266420AE80DF00EFE1B2 /* MacAVCaptureTool.mm */,
|
||||
ABD1266620AE80DF00EFE1B2 /* MacBaseCaptureTool.mm */,
|
||||
AB3E690F1E231E9900D4CC75 /* MacOGLDisplayView.mm */,
|
||||
ABAB0AFE1F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm */,
|
||||
AB3ACB7114C2361100D7D192 /* preferencesWindowDelegate.mm */,
|
||||
|
@ -4629,6 +4665,10 @@
|
|||
ABC04DCB1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
|
||||
ABAFD2791F7110E6007705BD /* gdbstub.cpp in Sources */,
|
||||
ABAB0B001F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
ABD1266920AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1266A20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABD1267720AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267820AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -4818,6 +4858,10 @@
|
|||
ABC04DCC1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
|
||||
ABAFD2781F7110E5007705BD /* gdbstub.cpp in Sources */,
|
||||
ABAB0B011F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
ABD1266B20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1266C20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABD1267920AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267A20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5037,6 +5081,10 @@
|
|||
ABC04DCA1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
|
||||
ABAFD2751F7110E4007705BD /* gdbstub.cpp in Sources */,
|
||||
ABAB0AFF1F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
ABD1266720AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1266820AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABD1267520AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267620AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5256,6 +5304,10 @@
|
|||
ABC04DCE1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
|
||||
ABAFD2761F7110E4007705BD /* gdbstub.cpp in Sources */,
|
||||
ABAB0B031F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
ABD1266F20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1267020AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABD1267D20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267E20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -5445,6 +5497,10 @@
|
|||
ABC04DCD1F67A2AC00EA6ED7 /* macosx_10_5_compat.cpp in Sources */,
|
||||
ABAFD2771F7110E5007705BD /* gdbstub.cpp in Sources */,
|
||||
ABAB0B021F7C1BB70079EFD3 /* MacScreenshotCaptureTool.mm in Sources */,
|
||||
ABD1266D20AE80DF00EFE1B2 /* MacAVCaptureTool.mm in Sources */,
|
||||
ABD1266E20AE80DF00EFE1B2 /* MacBaseCaptureTool.mm in Sources */,
|
||||
ABD1267B20AE812900EFE1B2 /* ClientAVCaptureObject.cpp in Sources */,
|
||||
ABD1267C20AE812900EFE1B2 /* macOS_driver.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define HAVE_OPENGL
|
||||
#define HAVE_LIBZ
|
||||
//#define HAVE_LUA
|
||||
//#define HAVE_AV_CONFIG_H
|
||||
|
||||
#define FT2_BUILD_LIBRARY
|
||||
#define DARWIN_NO_CARBON
|
||||
|
|
|
@ -756,6 +756,32 @@
|
|||
<integer>0</integer>
|
||||
<key>RomInfoPanel_SectionViewState</key>
|
||||
<dict/>
|
||||
<key>AVCaptureTool_DirectoryPath</key>
|
||||
<string>~/Movies</string>
|
||||
<key>AVCaptureTool_FileFormat</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_DisplayMode</key>
|
||||
<integer>2</integer>
|
||||
<key>AVCaptureTool_DisplayRotation</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_DisplaySeparation</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_DisplayLayout</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_DisplayOrder</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_Deposterize</key>
|
||||
<false/>
|
||||
<key>AVCaptureTool_OutputFilter</key>
|
||||
<integer>1</integer>
|
||||
<key>AVCaptureTool_PixelScaler</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_VideoSizeOption</key>
|
||||
<integer>0</integer>
|
||||
<key>AVCaptureTool_VideoWidth</key>
|
||||
<integer>256</integer>
|
||||
<key>AVCaptureTool_VideoHeight</key>
|
||||
<integer>384</integer>
|
||||
<key>ScreenshotCaptureTool_DirectoryPath</key>
|
||||
<string>~/Pictures</string>
|
||||
<key>ScreenshotCaptureTool_FileFormat</key>
|
||||
|
|
|
@ -1198,9 +1198,9 @@ public:
|
|||
|
||||
for (CocoaDSOutput *cdsOutput in _cdsOutputList)
|
||||
{
|
||||
if ([cdsOutput isKindOfClass:[CocoaDSDisplayVideo class]])
|
||||
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
|
||||
{
|
||||
[(CocoaDSDisplayVideo *)cdsOutput signalMessage:MESSAGE_RECEIVE_GPU_FRAME];
|
||||
[(CocoaDSDisplay *)cdsOutput signalMessage:MESSAGE_RECEIVE_GPU_FRAME];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2011-2017 DeSmuME team
|
||||
Copyright (C) 2011-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -33,8 +33,6 @@ class ClientExecutionControl;
|
|||
@class CocoaDSGPU;
|
||||
@class CocoaDSOutput;
|
||||
|
||||
typedef void *gdbstub_handle_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CocoaDSCore *cdsCore;
|
||||
|
@ -59,15 +57,6 @@ typedef struct
|
|||
NSTimer *_fpsTimer;
|
||||
BOOL _isTimerAtSecond;
|
||||
|
||||
BOOL isGdbStubStarted;
|
||||
BOOL isInDebugTrap;
|
||||
BOOL enableGdbStubARM9;
|
||||
BOOL enableGdbStubARM7;
|
||||
NSUInteger gdbStubPortARM9;
|
||||
NSUInteger gdbStubPortARM7;
|
||||
volatile gdbstub_handle_t gdbStubHandleARM9;
|
||||
volatile gdbstub_handle_t gdbStubHandleARM7;
|
||||
|
||||
NSString *slot1StatusText;
|
||||
NSString *frameStatus;
|
||||
NSString *executionSpeedStatus;
|
||||
|
@ -96,12 +85,12 @@ typedef struct
|
|||
@property (assign) NSUInteger frameJumpNumberFramesForward;
|
||||
@property (assign) NSUInteger frameJumpToFrameIndex;
|
||||
|
||||
@property (assign) BOOL isGdbStubStarted;
|
||||
@property (assign) BOOL isInDebugTrap;
|
||||
@property (assign) BOOL enableGdbStubARM9;
|
||||
@property (assign) BOOL enableGdbStubARM7;
|
||||
@property (assign) NSUInteger gdbStubPortARM9;
|
||||
@property (assign) NSUInteger gdbStubPortARM7;
|
||||
@property (assign) BOOL isGdbStubStarted;
|
||||
@property (readonly) BOOL isInDebugTrap;
|
||||
|
||||
@property (assign) BOOL emuFlagAdvancedBusLevelTiming;
|
||||
@property (assign) BOOL emuFlagRigorousTiming;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2011 Roger Manuel
|
||||
Copyright (C) 2011-2017 DeSmuME team
|
||||
Copyright (C) 2011-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,53 +25,17 @@
|
|||
#import "cocoa_rom.h"
|
||||
#import "cocoa_util.h"
|
||||
|
||||
#include "macOS_driver.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
#include "../../movie.h"
|
||||
#include "../../NDSSystem.h"
|
||||
#include "../../armcpu.h"
|
||||
#include "../../driver.h"
|
||||
#include "../../gdbstub.h"
|
||||
#include "../../slot1.h"
|
||||
#include "../../slot2.h"
|
||||
#include "../../SPU.h"
|
||||
#undef BOOL
|
||||
|
||||
// Need to include assert.h this way so that GDB stub will work
|
||||
// with an optimized build.
|
||||
#if defined(GDB_STUB) && defined(NDEBUG)
|
||||
#define TEMP_NDEBUG
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(TEMP_NDEBUG)
|
||||
#undef TEMP_NDEBUG
|
||||
#define NDEBUG
|
||||
#endif
|
||||
|
||||
class OSXDriver : public BaseDriver
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t *mutexThreadExecute;
|
||||
pthread_rwlock_t *rwlockCoreExecute;
|
||||
CocoaDSCore *cdsCore;
|
||||
|
||||
public:
|
||||
pthread_mutex_t* GetCoreThreadMutexLock();
|
||||
void SetCoreThreadMutexLock(pthread_mutex_t *theMutex);
|
||||
pthread_rwlock_t* GetCoreExecuteRWLock();
|
||||
void SetCoreExecuteRWLock(pthread_rwlock_t *theRwLock);
|
||||
void SetCore(CocoaDSCore *theCore);
|
||||
|
||||
virtual void EMU_DebugIdleEnter();
|
||||
virtual void EMU_DebugIdleUpdate();
|
||||
virtual void EMU_DebugIdleWakeUp();
|
||||
};
|
||||
|
||||
|
||||
//accessed from other files
|
||||
volatile bool execute = true;
|
||||
|
||||
|
@ -95,12 +59,12 @@ volatile bool execute = true;
|
|||
@dynamic frameJumpNumberFramesForward;
|
||||
@dynamic frameJumpToFrameIndex;
|
||||
|
||||
@dynamic enableGdbStubARM9;
|
||||
@dynamic enableGdbStubARM7;
|
||||
@dynamic gdbStubPortARM9;
|
||||
@dynamic gdbStubPortARM7;
|
||||
@dynamic isGdbStubStarted;
|
||||
@dynamic isInDebugTrap;
|
||||
@synthesize enableGdbStubARM9;
|
||||
@synthesize enableGdbStubARM7;
|
||||
@synthesize gdbStubPortARM9;
|
||||
@synthesize gdbStubPortARM7;
|
||||
|
||||
@dynamic emuFlagAdvancedBusLevelTiming;
|
||||
@dynamic emuFlagRigorousTiming;
|
||||
|
@ -135,15 +99,6 @@ volatile bool execute = true;
|
|||
return self;
|
||||
}
|
||||
|
||||
isGdbStubStarted = NO;
|
||||
isInDebugTrap = NO;
|
||||
enableGdbStubARM9 = NO;
|
||||
enableGdbStubARM7 = NO;
|
||||
gdbStubPortARM9 = 0;
|
||||
gdbStubPortARM7 = 0;
|
||||
gdbStubHandleARM9 = NULL;
|
||||
gdbStubHandleARM7 = NULL;
|
||||
|
||||
int initResult = NDS_Init();
|
||||
if (initResult == -1)
|
||||
{
|
||||
|
@ -200,10 +155,10 @@ volatile bool execute = true;
|
|||
|
||||
[cdsGPU setOutputList:cdsOutputList rwlock:&threadParam.rwlockOutputList];
|
||||
|
||||
OSXDriver *newDriver = new OSXDriver;
|
||||
macOS_driver *newDriver = new macOS_driver;
|
||||
newDriver->SetCoreThreadMutexLock(&threadParam.mutexThreadExecute);
|
||||
newDriver->SetCoreExecuteRWLock(self.rwlockCoreExecute);
|
||||
newDriver->SetCore(self);
|
||||
newDriver->SetExecutionControl(execControl);
|
||||
driver = newDriver;
|
||||
|
||||
frameStatus = @"---";
|
||||
|
@ -381,96 +336,65 @@ volatile bool execute = true;
|
|||
return (enable) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL) enableGdbStubARM9
|
||||
{
|
||||
const bool enable = execControl->IsGDBStubARM9Enabled();
|
||||
return (enable) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setEnableGdbStubARM9:(BOOL)enable
|
||||
{
|
||||
execControl->SetGDBStubARM9Enabled((enable) ? true : false);
|
||||
}
|
||||
|
||||
- (BOOL) enableGdbStubARM7
|
||||
{
|
||||
const bool enable = execControl->IsGDBStubARM7Enabled();
|
||||
return (enable) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setEnableGdbStubARM7:(BOOL)enable
|
||||
{
|
||||
execControl->SetGDBStubARM7Enabled((enable) ? true : false);
|
||||
}
|
||||
|
||||
- (NSUInteger) gdbStubPortARM9
|
||||
{
|
||||
const uint16_t portNumber = execControl->GetGDBStubARM9Port();
|
||||
return (NSUInteger)portNumber;
|
||||
}
|
||||
|
||||
- (void) setGdbStubPortARM9:(NSUInteger)portNumber
|
||||
{
|
||||
execControl->SetGDBStubARM9Port((uint16_t)portNumber);
|
||||
}
|
||||
|
||||
- (NSUInteger) gdbStubPortARM7
|
||||
{
|
||||
const uint16_t portNumber = execControl->GetGDBStubARM7Port();
|
||||
return (NSUInteger)portNumber;
|
||||
}
|
||||
|
||||
- (void) setGdbStubPortARM7:(NSUInteger)portNumber
|
||||
{
|
||||
execControl->SetGDBStubARM7Port((uint16_t)portNumber);
|
||||
}
|
||||
|
||||
- (void) setIsGdbStubStarted:(BOOL)theState
|
||||
{
|
||||
#ifdef GDB_STUB
|
||||
if (theState)
|
||||
{
|
||||
gdbstub_mutex_init();
|
||||
|
||||
if ([self enableGdbStubARM9])
|
||||
{
|
||||
const uint16_t arm9Port = (uint16_t)[self gdbStubPortARM9];
|
||||
if(arm9Port > 0)
|
||||
{
|
||||
gdbStubHandleARM9 = createStub_gdb(arm9Port, &NDS_ARM9, &arm9_direct_memory_iface);
|
||||
if (gdbStubHandleARM9 == NULL)
|
||||
{
|
||||
NSLog(@"Failed to create ARM9 gdbstub on port %d\n", arm9Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
activateStub_gdb(gdbStubHandleARM9);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(gdbStubHandleARM9);
|
||||
gdbStubHandleARM9 = NULL;
|
||||
}
|
||||
|
||||
if ([self enableGdbStubARM7])
|
||||
{
|
||||
const uint16_t arm7Port = (uint16_t)[self gdbStubPortARM7];
|
||||
if (arm7Port > 0)
|
||||
{
|
||||
gdbStubHandleARM7 = createStub_gdb(arm7Port, &NDS_ARM7, &arm7_base_memory_iface);
|
||||
if (gdbStubHandleARM7 == NULL)
|
||||
{
|
||||
NSLog(@"Failed to create ARM7 gdbstub on port %d\n", arm7Port);
|
||||
}
|
||||
else
|
||||
{
|
||||
activateStub_gdb(gdbStubHandleARM7);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(gdbStubHandleARM7);
|
||||
gdbStubHandleARM7 = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
destroyStub_gdb(gdbStubHandleARM9);
|
||||
gdbStubHandleARM9 = NULL;
|
||||
|
||||
destroyStub_gdb(gdbStubHandleARM7);
|
||||
gdbStubHandleARM7 = NULL;
|
||||
|
||||
gdbstub_mutex_destroy();
|
||||
}
|
||||
#endif
|
||||
if (gdbStubHandleARM9 == NULL && gdbStubHandleARM7 == NULL)
|
||||
{
|
||||
theState = NO;
|
||||
}
|
||||
|
||||
isGdbStubStarted = theState;
|
||||
execControl->SetIsGDBStubStarted((theState) ? true : false);
|
||||
}
|
||||
|
||||
- (BOOL) isGdbStubStarted
|
||||
{
|
||||
return isGdbStubStarted;
|
||||
}
|
||||
|
||||
- (void) setIsInDebugTrap:(BOOL)theState
|
||||
{
|
||||
// If we're transitioning out of the debug trap, then ignore
|
||||
// frame skipping this time.
|
||||
if (isInDebugTrap && !theState)
|
||||
{
|
||||
execControl->ResetFramesToSkip();
|
||||
}
|
||||
|
||||
isInDebugTrap = theState;
|
||||
const bool theState = execControl->IsGDBStubStarted();
|
||||
return (theState) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL) isInDebugTrap
|
||||
{
|
||||
return isInDebugTrap;
|
||||
const bool theState = execControl->IsInDebugTrap();
|
||||
return (theState) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setEmuFlagAdvancedBusLevelTiming:(BOOL)enable
|
||||
|
@ -1120,6 +1044,7 @@ static void* RunCoreThread(void *arg)
|
|||
ClientInputHandler *inputHandler = execControl->GetClientInputHandler();
|
||||
NSMutableArray *cdsOutputList = [cdsCore cdsOutputList];
|
||||
const NDSFrameInfo &ndsFrameInfo = execControl->GetNDSFrameInfo();
|
||||
ClientAVCaptureObject *avCaptureObject = NULL;
|
||||
|
||||
double startTime = 0.0;
|
||||
double frameTime = 0.0; // The amount of time that is expected for the frame to run.
|
||||
|
@ -1157,6 +1082,16 @@ static void* RunCoreThread(void *arg)
|
|||
inputHandler->ApplyInputs();
|
||||
execControl->ApplySettingsOnNDSExec();
|
||||
|
||||
avCaptureObject = execControl->GetClientAVCaptureObjectApplied();
|
||||
if ( (avCaptureObject != NULL) && (avCaptureObject->IsCapturingVideo() || avCaptureObject->IsCapturingAudio()) )
|
||||
{
|
||||
avCaptureObject->StartFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
avCaptureObject = NULL;
|
||||
}
|
||||
|
||||
// Execute the frame and increment the frame counter.
|
||||
pthread_rwlock_wrlock(¶m->rwlockCoreExecute);
|
||||
NDS_exec<false>();
|
||||
|
@ -1178,6 +1113,11 @@ static void* RunCoreThread(void *arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (avCaptureObject != NULL)
|
||||
{
|
||||
avCaptureObject->StreamWriteStart();
|
||||
}
|
||||
|
||||
// Make sure that the mic level is updated at least once every 8 frames, regardless
|
||||
// of whether the NDS actually reads the mic or not.
|
||||
if ((ndsFrameInfo.frameIndex & 0x07) == 0x07)
|
||||
|
@ -1221,11 +1161,11 @@ static void* RunCoreThread(void *arg)
|
|||
if ([cdsOutput isKindOfClass:[CocoaDSDisplay class]])
|
||||
{
|
||||
[(CocoaDSDisplay *)cdsOutput setNDSFrameInfo:ndsFrameInfo];
|
||||
}
|
||||
|
||||
if ( ![cdsOutput isKindOfClass:[CocoaDSSpeaker class]] && (![cdsOutput isKindOfClass:[CocoaDSDisplay class]] || (framesToSkip == 0)) )
|
||||
{
|
||||
[cdsOutput doCoreEmuFrame];
|
||||
|
||||
if (framesToSkip == 0)
|
||||
{
|
||||
[cdsOutput doCoreEmuFrame];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1309,83 +1249,10 @@ static void* RunCoreThread(void *arg)
|
|||
|
||||
} while(true);
|
||||
|
||||
if (avCaptureObject != NULL)
|
||||
{
|
||||
avCaptureObject->StreamWriteFinish();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma mark - OSXDriver
|
||||
|
||||
pthread_mutex_t* OSXDriver::GetCoreThreadMutexLock()
|
||||
{
|
||||
return this->mutexThreadExecute;
|
||||
}
|
||||
|
||||
void OSXDriver::SetCoreThreadMutexLock(pthread_mutex_t *theMutex)
|
||||
{
|
||||
this->mutexThreadExecute = theMutex;
|
||||
}
|
||||
|
||||
pthread_rwlock_t* OSXDriver::GetCoreExecuteRWLock()
|
||||
{
|
||||
return this->rwlockCoreExecute;
|
||||
}
|
||||
|
||||
void OSXDriver::SetCoreExecuteRWLock(pthread_rwlock_t *theRwLock)
|
||||
{
|
||||
this->rwlockCoreExecute = theRwLock;
|
||||
}
|
||||
|
||||
void OSXDriver::SetCore(CocoaDSCore *theCore)
|
||||
{
|
||||
this->cdsCore = theCore;
|
||||
}
|
||||
|
||||
void OSXDriver::EMU_DebugIdleEnter()
|
||||
{
|
||||
[this->cdsCore setIsInDebugTrap:YES];
|
||||
pthread_rwlock_unlock(this->rwlockCoreExecute);
|
||||
pthread_mutex_unlock(this->mutexThreadExecute);
|
||||
}
|
||||
|
||||
void OSXDriver::EMU_DebugIdleUpdate()
|
||||
{
|
||||
usleep(50);
|
||||
}
|
||||
|
||||
void OSXDriver::EMU_DebugIdleWakeUp()
|
||||
{
|
||||
pthread_mutex_lock(this->mutexThreadExecute);
|
||||
pthread_rwlock_wrlock(this->rwlockCoreExecute);
|
||||
[this->cdsCore setIsInDebugTrap:NO];
|
||||
}
|
||||
|
||||
#pragma mark - GDB Stub implementation
|
||||
|
||||
void* createThread_gdb(void (*thread_function)(void *data), void *thread_data)
|
||||
{
|
||||
// Create the thread using POSIX routines.
|
||||
pthread_attr_t attr;
|
||||
pthread_t* posixThreadID = (pthread_t*)malloc(sizeof(pthread_t));
|
||||
|
||||
assert(!pthread_attr_init(&attr));
|
||||
assert(!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
|
||||
|
||||
int threadError = pthread_create(posixThreadID, &attr, (void* (*)(void *))thread_function, thread_data);
|
||||
|
||||
assert(!pthread_attr_destroy(&attr));
|
||||
|
||||
if (threadError != 0)
|
||||
{
|
||||
// Report an error.
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return posixThreadID;
|
||||
}
|
||||
}
|
||||
|
||||
void joinThread_gdb(void *thread_handle)
|
||||
{
|
||||
pthread_join(*(pthread_t *)thread_handle, NULL);
|
||||
free(thread_handle);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import "cocoa_util.h"
|
||||
#include "ClientDisplayView.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
#include "ClientAVCaptureObject.h"
|
||||
#undef BOOL
|
||||
|
||||
@class NSImage;
|
||||
|
@ -118,6 +119,17 @@
|
|||
|
||||
@end
|
||||
|
||||
@interface CocoaDSVideoCapture : CocoaDSDisplay
|
||||
{
|
||||
ClientDisplay3DPresenter *_cdp;
|
||||
}
|
||||
|
||||
@property (assign, nonatomic, getter=clientDisplay3DPresenter, setter=setClientDisplay3DPresenter:) ClientDisplay3DPresenter *_cdp;
|
||||
|
||||
- (void) handleReceiveGPUFrame;
|
||||
|
||||
@end
|
||||
|
||||
@interface CocoaDSDisplayVideo : CocoaDSDisplay
|
||||
{
|
||||
ClientDisplay3DView *_cdv;
|
||||
|
|
|
@ -542,6 +542,28 @@
|
|||
|
||||
@end
|
||||
|
||||
@implementation CocoaDSVideoCapture
|
||||
|
||||
@synthesize _cdp;
|
||||
|
||||
- (void) handleReceiveGPUFrame
|
||||
{
|
||||
[super handleReceiveGPUFrame];
|
||||
|
||||
if (_cdp == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_cdp->LoadDisplays();
|
||||
_cdp->ProcessDisplays();
|
||||
_cdp->UpdateLayout();
|
||||
//_cdp->CopyFrameToBuffer((uint32_t *)[newImageRep bitmapData]);
|
||||
//avCaptureObject->ReadVideoFrame(NULL, 0, 0, NDSColorFormat_BGR888_Rev);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CocoaDSDisplayVideo
|
||||
|
||||
@synthesize _cdv;
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "macOS_driver.h"
|
||||
#include "ClientExecutionControl.h"
|
||||
|
||||
pthread_mutex_t* macOS_driver::GetCoreThreadMutexLock()
|
||||
{
|
||||
return this->__mutexThreadExecute;
|
||||
}
|
||||
|
||||
void macOS_driver::SetCoreThreadMutexLock(pthread_mutex_t *theMutex)
|
||||
{
|
||||
this->__mutexThreadExecute = theMutex;
|
||||
}
|
||||
|
||||
pthread_rwlock_t* macOS_driver::GetCoreExecuteRWLock()
|
||||
{
|
||||
return this->__rwlockCoreExecute;
|
||||
}
|
||||
|
||||
void macOS_driver::SetCoreExecuteRWLock(pthread_rwlock_t *theRwLock)
|
||||
{
|
||||
this->__rwlockCoreExecute = theRwLock;
|
||||
}
|
||||
|
||||
void macOS_driver::SetExecutionControl(ClientExecutionControl *execControl)
|
||||
{
|
||||
this->__execControl = execControl;
|
||||
}
|
||||
|
||||
void macOS_driver::AVI_SoundUpdate(void *soundData, int soundLen)
|
||||
{
|
||||
ClientAVCaptureObject *avCaptureObject = this->__execControl->GetClientAVCaptureObjectApplied();
|
||||
|
||||
if ((avCaptureObject == NULL) || !avCaptureObject->IsCapturingAudio())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
avCaptureObject->ReadAudioFrames(soundData, soundLen);
|
||||
}
|
||||
|
||||
bool macOS_driver::AVI_IsRecording()
|
||||
{
|
||||
ClientAVCaptureObject *avCaptureObject = this->__execControl->GetClientAVCaptureObjectApplied();
|
||||
return ((avCaptureObject != NULL) && avCaptureObject->IsCapturingVideo());
|
||||
}
|
||||
|
||||
bool macOS_driver::WAV_IsRecording()
|
||||
{
|
||||
ClientAVCaptureObject *avCaptureObject = this->__execControl->GetClientAVCaptureObjectApplied();
|
||||
return ((avCaptureObject != NULL) && avCaptureObject->IsCapturingAudio());
|
||||
}
|
||||
|
||||
void macOS_driver::EMU_DebugIdleEnter()
|
||||
{
|
||||
this->__execControl->SetIsInDebugTrap(true);
|
||||
pthread_rwlock_unlock(this->__rwlockCoreExecute);
|
||||
pthread_mutex_unlock(this->__mutexThreadExecute);
|
||||
}
|
||||
|
||||
void macOS_driver::EMU_DebugIdleUpdate()
|
||||
{
|
||||
usleep(50);
|
||||
}
|
||||
|
||||
void macOS_driver::EMU_DebugIdleWakeUp()
|
||||
{
|
||||
pthread_mutex_lock(this->__mutexThreadExecute);
|
||||
pthread_rwlock_wrlock(this->__rwlockCoreExecute);
|
||||
this->__execControl->SetIsInDebugTrap(false);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MACOS_DRIVER_H_
|
||||
#define _MACOS_DRIVER_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../../driver.h"
|
||||
|
||||
class ClientExecutionControl;
|
||||
|
||||
class macOS_driver : public BaseDriver
|
||||
{
|
||||
private:
|
||||
pthread_mutex_t *__mutexThreadExecute;
|
||||
pthread_rwlock_t *__rwlockCoreExecute;
|
||||
ClientExecutionControl *__execControl;
|
||||
|
||||
public:
|
||||
pthread_mutex_t* GetCoreThreadMutexLock();
|
||||
void SetCoreThreadMutexLock(pthread_mutex_t *theMutex);
|
||||
pthread_rwlock_t* GetCoreExecuteRWLock();
|
||||
void SetCoreExecuteRWLock(pthread_rwlock_t *theRwLock);
|
||||
void SetExecutionControl(ClientExecutionControl *execControl);
|
||||
|
||||
virtual void AVI_SoundUpdate(void *soundData, int soundLen);
|
||||
virtual bool AVI_IsRecording();
|
||||
virtual bool WAV_IsRecording();
|
||||
|
||||
virtual void EMU_DebugIdleEnter();
|
||||
virtual void EMU_DebugIdleUpdate();
|
||||
virtual void EMU_DebugIdleWakeUp();
|
||||
};
|
||||
|
||||
|
||||
#endif // _MACOS_DRIVER_H_
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -30,6 +30,7 @@
|
|||
@class DisplayWindowController;
|
||||
@class RomInfoPanel;
|
||||
@class MacScreenshotCaptureToolDelegate;
|
||||
@class MacAVCaptureToolDelegate;
|
||||
struct ClientCommandAttributes;
|
||||
class AudioSampleBlockGenerator;
|
||||
|
||||
|
@ -45,6 +46,7 @@ class AudioSampleBlockGenerator;
|
|||
|
||||
CheatWindowDelegate *cheatWindowDelegate;
|
||||
MacScreenshotCaptureToolDelegate *screenshotCaptureToolDelegate;
|
||||
MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
NSObjectController *firmwarePanelController;
|
||||
NSObjectController *romInfoPanelController;
|
||||
NSObjectController *cdsCoreController;
|
||||
|
@ -127,6 +129,7 @@ class AudioSampleBlockGenerator;
|
|||
|
||||
@property (readonly) IBOutlet CheatWindowDelegate *cheatWindowDelegate;
|
||||
@property (readonly) IBOutlet MacScreenshotCaptureToolDelegate *screenshotCaptureToolDelegate;
|
||||
@property (readonly) IBOutlet MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
@property (readonly) IBOutlet NSObjectController *firmwarePanelController;
|
||||
@property (readonly) IBOutlet NSObjectController *romInfoPanelController;
|
||||
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#import "InputManager.h"
|
||||
#import "cheatWindowDelegate.h"
|
||||
#import "Slot2WindowDelegate.h"
|
||||
#import "MacAVCaptureTool.h"
|
||||
#import "MacScreenshotCaptureTool.h"
|
||||
|
||||
#import "cocoa_globals.h"
|
||||
|
@ -44,6 +45,7 @@
|
|||
|
||||
@synthesize cheatWindowDelegate;
|
||||
@synthesize screenshotCaptureToolDelegate;
|
||||
@synthesize avCaptureToolDelegate;
|
||||
@synthesize firmwarePanelController;
|
||||
@synthesize romInfoPanelController;
|
||||
@synthesize cdsCoreController;
|
||||
|
@ -1759,6 +1761,7 @@
|
|||
// Update the UI to indicate that a ROM has indeed been loaded.
|
||||
[self updateAllWindowTitles];
|
||||
[screenshotCaptureToolDelegate setRomName:[currentRom internalName]];
|
||||
[avCaptureToolDelegate setRomName:[currentRom internalName]];
|
||||
|
||||
for (DisplayWindowController *windowController in windowList)
|
||||
{
|
||||
|
@ -1841,6 +1844,7 @@
|
|||
// Update the UI to indicate that the ROM has finished unloading.
|
||||
[self updateAllWindowTitles];
|
||||
[screenshotCaptureToolDelegate setRomName:[currentRom internalName]];
|
||||
[avCaptureToolDelegate setRomName:[currentRom internalName]];
|
||||
|
||||
[[cdsCore cdsGPU] clearWithColor:0x8000];
|
||||
for (DisplayWindowController *windowController in windowList)
|
||||
|
@ -2213,6 +2217,7 @@
|
|||
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
|
||||
[screenshotCaptureToolDelegate setSharedData:[[cdsCore cdsGPU] sharedData]];
|
||||
[avCaptureToolDelegate setSharedData:[[cdsCore cdsGPU] sharedData]];
|
||||
}
|
||||
|
||||
- (void) readUserDefaults
|
||||
|
@ -2270,14 +2275,16 @@
|
|||
// Set up the ROM Info panel.
|
||||
[romInfoPanel setupUserDefaults];
|
||||
|
||||
// Set up the screenshot capture tool defaults.
|
||||
// Set up the capture tool defaults.
|
||||
[screenshotCaptureToolDelegate readUserDefaults];
|
||||
[avCaptureToolDelegate readUserDefaults];
|
||||
}
|
||||
|
||||
- (void) writeUserDefaults
|
||||
{
|
||||
[romInfoPanel writeDefaults];
|
||||
[screenshotCaptureToolDelegate writeUserDefaults];
|
||||
[avCaptureToolDelegate writeUserDefaults];
|
||||
}
|
||||
|
||||
- (void) restoreDisplayWindowStates
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MAC_AVCAPTURETOOL_H_
|
||||
#define _MAC_AVCAPTURETOOL_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#import "MacBaseCaptureTool.h"
|
||||
#include "../ClientAVCaptureObject.h"
|
||||
#include "../ClientExecutionControl.h"
|
||||
|
||||
|
||||
enum VideoSizeOptionID
|
||||
{
|
||||
VideoSizeOption_UseEmulatorSettings = 0,
|
||||
|
||||
VideoSizeOption_NTSC_480p = 1000,
|
||||
VideoSizeOption_PAL_576p = 1001,
|
||||
|
||||
VideoSizeOption_nHD = 2000,
|
||||
VideoSizeOption_qHD = 2001,
|
||||
VideoSizeOption_HD_720p = 2002,
|
||||
VideoSizeOption_HDPlus = 2003,
|
||||
VideoSizeOption_FHD_1080p = 2004,
|
||||
VideoSizeOption_QHD = 2005,
|
||||
VideoSizeOption_4K_UHD = 2006,
|
||||
|
||||
VideoSizeOption_QVGA = 10000,
|
||||
VideoSizeOption_HVGA = 10001,
|
||||
VideoSizeOption_VGA = 10002,
|
||||
VideoSizeOption_SVGA = 10003,
|
||||
VideoSizeOption_XGA = 10004,
|
||||
VideoSizeOption_SXGA = 10005,
|
||||
VideoSizeOption_UXGA = 10006,
|
||||
VideoSizeOption_QXGA = 10007,
|
||||
VideoSizeOption_HXGA = 10008,
|
||||
|
||||
VideoSizeOption_Custom = 32000
|
||||
};
|
||||
|
||||
struct AVStream;
|
||||
struct AVCodec;
|
||||
struct AVCodecContext;
|
||||
struct AVOutputFormat;
|
||||
struct AVFormatContext;
|
||||
struct AVFrame;
|
||||
struct AVPacket;
|
||||
struct AVRational;
|
||||
struct SwsContext;
|
||||
struct SwrContext;
|
||||
class ClientExecutionControl;
|
||||
@class CocoaDSCore;
|
||||
@class CocoaDSVideoCapture;
|
||||
|
||||
// a wrapper around a single output AVStream
|
||||
struct OutputStream
|
||||
{
|
||||
AVStream *stream;
|
||||
AVCodecContext *enc;
|
||||
|
||||
/* pts of the next frame that will be generated */
|
||||
int64_t next_pts;
|
||||
int samples_count;
|
||||
|
||||
AVFrame *frame;
|
||||
AVFrame *tmp_frame;
|
||||
|
||||
size_t inBufferOffset;
|
||||
|
||||
SwsContext *sws_ctx;
|
||||
SwrContext *swr_ctx;
|
||||
};
|
||||
typedef struct OutputStream OutputStream;
|
||||
|
||||
struct VideoSize
|
||||
{
|
||||
size_t width;
|
||||
size_t height;
|
||||
};
|
||||
|
||||
class FFmpegFileStream : public ClientAVCaptureFileStream
|
||||
{
|
||||
private:
|
||||
static bool __needFFmpegLibraryInit;
|
||||
|
||||
protected:
|
||||
OutputStream _videoStream;
|
||||
OutputStream _audioStream;
|
||||
AVOutputFormat *_outputFormat;
|
||||
AVFormatContext *_outputCtx;
|
||||
AVCodec *_audioCodec;
|
||||
AVCodec *_videoCodec;
|
||||
|
||||
AVFrame* _InitVideoFrame(const int pixFormat, const int videoWidth, const int videoHeight);
|
||||
AVFrame* _InitAudioFrame(const int sampleFormat, const uint64_t channelLayout, const uint32_t sampleRate, const uint32_t nbSamples);
|
||||
void _CloseStream(OutputStream *outStream);
|
||||
void _CloseStreams();
|
||||
ClientAVCaptureError _SendStreamFrame(OutputStream *outStream);
|
||||
void _LogPacket(const AVPacket *thePacket);
|
||||
|
||||
public:
|
||||
FFmpegFileStream();
|
||||
virtual ~FFmpegFileStream();
|
||||
|
||||
virtual ClientAVCaptureError Open();
|
||||
virtual void Close(FileStreamCloseAction theAction);
|
||||
virtual bool IsValid();
|
||||
|
||||
virtual ClientAVCaptureError FlushVideo(uint8_t *srcBuffer, const size_t bufferSize);
|
||||
virtual ClientAVCaptureError FlushAudio(uint8_t *srcBuffer, const size_t bufferSize);
|
||||
virtual ClientAVCaptureError WriteOneFrame(const AVStreamWriteParam ¶m);
|
||||
};
|
||||
|
||||
@interface MacAVCaptureToolDelegate : MacBaseCaptureToolDelegate
|
||||
{
|
||||
ClientAVCaptureObject *_captureObject;
|
||||
ClientExecutionControl *execControl;
|
||||
CocoaDSCore *cdsCore;
|
||||
CocoaDSVideoCapture *_videoCaptureOutput;
|
||||
|
||||
NSButton *recordButton;
|
||||
|
||||
NSInteger videoSizeOption;
|
||||
NSInteger videoWidth;
|
||||
NSInteger videoHeight;
|
||||
|
||||
BOOL isUsingCustomSize;
|
||||
BOOL isFileStreamClosing;
|
||||
}
|
||||
|
||||
@property (readonly) IBOutlet NSButton *recordButton;
|
||||
@property (assign) ClientExecutionControl *execControl;
|
||||
@property (assign) CocoaDSCore *cdsCore;
|
||||
@property (assign) NSInteger videoSizeOption;
|
||||
@property (assign) NSInteger videoWidth;
|
||||
@property (assign) NSInteger videoHeight;
|
||||
|
||||
@property (assign) BOOL isUsingCustomSize;
|
||||
@property (assign) BOOL isRecording;
|
||||
@property (assign) BOOL isFileStreamClosing;
|
||||
|
||||
- (void) setVideoSizeUsingEmulatorSettings;
|
||||
- (void) readUserDefaults;
|
||||
- (void) writeUserDefaults;
|
||||
- (void) openFileStream;
|
||||
- (void) closeFileStream;
|
||||
- (void) avFileStreamCloseFinish:(NSNotification *)aNotification;
|
||||
|
||||
- (IBAction) toggleRecordingState:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
static void* RunAVCaptureCloseThread(void *arg);
|
||||
|
||||
#endif // _MAC_AVCAPTURETOOL_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MAC_BASECAPTURETOOL_H_
|
||||
#define _MAC_BASECAPTURETOOL_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <string>
|
||||
#include "../ClientDisplayView.h"
|
||||
#include "../cocoa_util.h"
|
||||
|
||||
#ifdef BOOL
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
@class MacClientSharedObject;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
|
||||
@interface MacBaseCaptureToolDelegate : NSObject <NSWindowDelegate, DirectoryURLDragDestTextFieldProtocol>
|
||||
#else
|
||||
@interface MacBaseCaptureToolDelegate : NSObject <DirectoryURLDragDestTextFieldProtocol>
|
||||
#endif
|
||||
{
|
||||
NSObject *dummyObject;
|
||||
NSWindow *window;
|
||||
DirectoryURLDragDestTextField *saveDirectoryPathTextField;
|
||||
|
||||
MacClientSharedObject *sharedData;
|
||||
|
||||
NSString *saveDirectoryPath;
|
||||
NSString *romName;
|
||||
NSInteger formatID;
|
||||
NSInteger displayMode;
|
||||
NSInteger displayLayout;
|
||||
NSInteger displayOrder;
|
||||
NSInteger displaySeparation;
|
||||
NSInteger displayScale;
|
||||
NSInteger displayRotation;
|
||||
BOOL useDeposterize;
|
||||
NSInteger outputFilterID;
|
||||
NSInteger pixelScalerID;
|
||||
}
|
||||
|
||||
@property (readonly) IBOutlet NSObject *dummyObject;
|
||||
@property (readonly) IBOutlet NSWindow *window;
|
||||
@property (readonly) IBOutlet DirectoryURLDragDestTextField *saveDirectoryPathTextField;
|
||||
|
||||
@property (retain) MacClientSharedObject *sharedData;
|
||||
|
||||
@property (copy) NSString *saveDirectoryPath;
|
||||
@property (copy) NSString *romName;
|
||||
@property (assign) NSInteger formatID;
|
||||
@property (assign) NSInteger displayMode;
|
||||
@property (assign) NSInteger displayLayout;
|
||||
@property (assign) NSInteger displayOrder;
|
||||
@property (assign) NSInteger displaySeparation;
|
||||
@property (assign) NSInteger displayScale;
|
||||
@property (assign) NSInteger displayRotation;
|
||||
@property (assign) BOOL useDeposterize;
|
||||
@property (assign) NSInteger outputFilterID;
|
||||
@property (assign) NSInteger pixelScalerID;
|
||||
|
||||
- (IBAction) chooseDirectoryPath:(id)sender;
|
||||
- (void) chooseDirectoryPathDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||
|
||||
@end
|
||||
|
||||
class MacCaptureToolParams
|
||||
{
|
||||
public:
|
||||
void *refObject;
|
||||
MacClientSharedObject *sharedData;
|
||||
|
||||
NSInteger formatID;
|
||||
std::string savePath;
|
||||
std::string romName;
|
||||
bool useDeposterize;
|
||||
OutputFilterTypeID outputFilterID;
|
||||
VideoFilterTypeID pixelScalerID;
|
||||
ClientDisplayPresenterProperties cdpProperty;
|
||||
};
|
||||
|
||||
#endif // _MAC_BASECAPTURETOOL_H_
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
Copyright (C) 2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This file is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the this software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import "../cocoa_globals.h"
|
||||
#import "MacBaseCaptureTool.h"
|
||||
|
||||
|
||||
@implementation MacBaseCaptureToolDelegate
|
||||
|
||||
@synthesize dummyObject;
|
||||
@synthesize window;
|
||||
@synthesize saveDirectoryPathTextField;
|
||||
@synthesize sharedData;
|
||||
@synthesize saveDirectoryPath;
|
||||
@synthesize romName;
|
||||
@synthesize formatID;
|
||||
@synthesize displayMode;
|
||||
@synthesize displayLayout;
|
||||
@synthesize displayOrder;
|
||||
@synthesize displaySeparation;
|
||||
@synthesize displayScale;
|
||||
@synthesize displayRotation;
|
||||
@synthesize useDeposterize;
|
||||
@synthesize outputFilterID;
|
||||
@synthesize pixelScalerID;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if(self == nil)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
sharedData = nil;
|
||||
saveDirectoryPath = nil;
|
||||
romName = @"No_ROM_loaded";
|
||||
|
||||
formatID = 0;
|
||||
displayMode = ClientDisplayMode_Dual;
|
||||
displayLayout = ClientDisplayLayout_Vertical;
|
||||
displayOrder = ClientDisplayOrder_MainFirst;
|
||||
displaySeparation = 0;
|
||||
displayScale = 0;
|
||||
displayRotation = 0;
|
||||
useDeposterize = NO;
|
||||
outputFilterID = OutputFilterTypeID_Bilinear;
|
||||
pixelScalerID = VideoFilterTypeID_None;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setSharedData:nil];
|
||||
[self setSaveDirectoryPath:nil];
|
||||
[self setRomName:nil];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBAction) chooseDirectoryPath:(id)sender
|
||||
{
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setCanCreateDirectories:YES];
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setCanChooseFiles:NO];
|
||||
[panel setResolvesAliases:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setTitle:NSSTRING_TITLE_SAVE_SCREENSHOT_PANEL];
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
[panel beginSheetModalForWindow:[self window]
|
||||
completionHandler:^(NSInteger result) {
|
||||
[self chooseDirectoryPathDidEnd:panel returnCode:result contextInfo:nil];
|
||||
} ];
|
||||
#else
|
||||
[panel beginSheetForDirectory:nil
|
||||
file:nil
|
||||
types:nil
|
||||
modalForWindow:[self window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(chooseDirectoryPathDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void) chooseDirectoryPathDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
|
||||
if (returnCode == NSCancelButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
|
||||
if(selectedFileURL == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[self setSaveDirectoryPath:[selectedFileURL path]];
|
||||
}
|
||||
|
||||
#pragma mark DirectoryURLDragDestTextFieldProtocol Protocol
|
||||
- (void)assignDirectoryPath:(NSString *)dirPath textField:(NSTextField *)textField
|
||||
{
|
||||
if (textField == saveDirectoryPathTextField)
|
||||
{
|
||||
[self setSaveDirectoryPath:dirPath];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,87 +18,19 @@
|
|||
#ifndef _MAC_SCREENSHOTCAPTURETOOL_H_
|
||||
#define _MAC_SCREENSHOTCAPTURETOOL_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "MacBaseCaptureTool.h"
|
||||
|
||||
#include <string>
|
||||
#include "../ClientDisplayView.h"
|
||||
#include "../cocoa_util.h"
|
||||
|
||||
#ifdef BOOL
|
||||
#undef BOOL
|
||||
#endif
|
||||
|
||||
@class MacClientSharedObject;
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
|
||||
@interface MacScreenshotCaptureToolDelegate : NSObject <NSWindowDelegate, DirectoryURLDragDestTextFieldProtocol>
|
||||
#else
|
||||
@interface MacScreenshotCaptureToolDelegate : NSObject <DirectoryURLDragDestTextFieldProtocol>
|
||||
#endif
|
||||
@interface MacScreenshotCaptureToolDelegate : MacBaseCaptureToolDelegate
|
||||
{
|
||||
NSObject *dummyObject;
|
||||
NSWindow *window;
|
||||
DirectoryURLDragDestTextField *saveDirectoryPathTextField;
|
||||
|
||||
MacClientSharedObject *sharedData;
|
||||
|
||||
NSString *saveDirectoryPath;
|
||||
NSString *romName;
|
||||
NSBitmapFormat fileFormat;
|
||||
NSInteger displayMode;
|
||||
NSInteger displayLayout;
|
||||
NSInteger displayOrder;
|
||||
NSInteger displaySeparation;
|
||||
NSInteger displayScale;
|
||||
NSInteger displayRotation;
|
||||
BOOL useDeposterize;
|
||||
NSInteger outputFilterID;
|
||||
NSInteger pixelScalerID;
|
||||
}
|
||||
|
||||
@property (readonly) IBOutlet NSObject *dummyObject;
|
||||
@property (readonly) IBOutlet NSWindow *window;
|
||||
@property (readonly) IBOutlet DirectoryURLDragDestTextField *saveDirectoryPathTextField;
|
||||
|
||||
@property (retain) MacClientSharedObject *sharedData;
|
||||
|
||||
@property (copy) NSString *saveDirectoryPath;
|
||||
@property (copy) NSString *romName;
|
||||
@property (assign) NSBitmapFormat fileFormat;
|
||||
@property (assign) NSInteger displayMode;
|
||||
@property (assign) NSInteger displayLayout;
|
||||
@property (assign) NSInteger displayOrder;
|
||||
@property (assign) NSInteger displaySeparation;
|
||||
@property (assign) NSInteger displayScale;
|
||||
@property (assign) NSInteger displayRotation;
|
||||
@property (assign) BOOL useDeposterize;
|
||||
@property (assign) NSInteger outputFilterID;
|
||||
@property (assign) NSInteger pixelScalerID;
|
||||
|
||||
- (IBAction) chooseDirectoryPath:(id)sender;
|
||||
- (IBAction) takeScreenshot:(id)sender;
|
||||
|
||||
- (void) chooseDirectoryPathDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
|
||||
|
||||
- (void) readUserDefaults;
|
||||
- (void) writeUserDefaults;
|
||||
|
||||
@end
|
||||
|
||||
class MacScreenshotCaptureToolParams
|
||||
{
|
||||
public:
|
||||
MacClientSharedObject *sharedData;
|
||||
|
||||
NSBitmapImageFileType fileFormat;
|
||||
std::string savePath;
|
||||
std::string romName;
|
||||
bool useDeposterize;
|
||||
OutputFilterTypeID outputFilterID;
|
||||
VideoFilterTypeID pixelScalerID;
|
||||
ClientDisplayPresenterProperties cdpProperty;
|
||||
};
|
||||
|
||||
static void* RunFileWriteThread(void *arg);
|
||||
|
||||
#endif // _MAC_SCREENSHOTCAPTURETOOL_H_
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2017 DeSmuME team
|
||||
Copyright (C) 2017-2018 DeSmuME team
|
||||
|
||||
This file is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -29,23 +29,6 @@
|
|||
|
||||
@implementation MacScreenshotCaptureToolDelegate
|
||||
|
||||
@synthesize dummyObject;
|
||||
@synthesize window;
|
||||
@synthesize saveDirectoryPathTextField;
|
||||
@synthesize sharedData;
|
||||
@synthesize saveDirectoryPath;
|
||||
@synthesize romName;
|
||||
@synthesize fileFormat;
|
||||
@synthesize displayMode;
|
||||
@synthesize displayLayout;
|
||||
@synthesize displayOrder;
|
||||
@synthesize displaySeparation;
|
||||
@synthesize displayScale;
|
||||
@synthesize displayRotation;
|
||||
@synthesize useDeposterize;
|
||||
@synthesize outputFilterID;
|
||||
@synthesize pixelScalerID;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
|
@ -54,59 +37,11 @@
|
|||
return nil;
|
||||
}
|
||||
|
||||
sharedData = nil;
|
||||
saveDirectoryPath = nil;
|
||||
romName = @"No_ROM_loaded";
|
||||
|
||||
fileFormat = NSTIFFFileType;
|
||||
displayMode = ClientDisplayMode_Dual;
|
||||
displayLayout = ClientDisplayLayout_Vertical;
|
||||
displayOrder = ClientDisplayOrder_MainFirst;
|
||||
displaySeparation = 0;
|
||||
displayScale = 0;
|
||||
displayRotation = 0;
|
||||
useDeposterize = NO;
|
||||
outputFilterID = OutputFilterTypeID_Bilinear;
|
||||
pixelScalerID = VideoFilterTypeID_None;
|
||||
formatID = NSTIFFFileType;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self setSharedData:nil];
|
||||
[self setSaveDirectoryPath:nil];
|
||||
[self setRomName:nil];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBAction) chooseDirectoryPath:(id)sender
|
||||
{
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
[panel setCanCreateDirectories:YES];
|
||||
[panel setCanChooseDirectories:YES];
|
||||
[panel setCanChooseFiles:NO];
|
||||
[panel setResolvesAliases:YES];
|
||||
[panel setAllowsMultipleSelection:NO];
|
||||
[panel setTitle:NSSTRING_TITLE_SAVE_SCREENSHOT_PANEL];
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
[panel beginSheetModalForWindow:[self window]
|
||||
completionHandler:^(NSInteger result) {
|
||||
[self chooseDirectoryPathDidEnd:panel returnCode:result contextInfo:nil];
|
||||
} ];
|
||||
#else
|
||||
[panel beginSheetForDirectory:nil
|
||||
file:nil
|
||||
types:nil
|
||||
modalForWindow:[self window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(chooseDirectoryPathDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (IBAction) takeScreenshot:(id)sender
|
||||
{
|
||||
NSString *savePath = [self saveDirectoryPath];
|
||||
|
@ -136,9 +71,10 @@
|
|||
[fileManager release];
|
||||
|
||||
// Note: We're allocating the parameter's memory block here, but we will be freeing it once we copy it in the detached thread.
|
||||
MacScreenshotCaptureToolParams *param = new MacScreenshotCaptureToolParams;
|
||||
MacCaptureToolParams *param = new MacCaptureToolParams;
|
||||
param->refObject = NULL;
|
||||
param->sharedData = [self sharedData];
|
||||
param->fileFormat = (NSBitmapImageFileType)[self fileFormat];
|
||||
param->formatID = [self formatID];
|
||||
param->savePath = std::string([savePath cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
param->romName = std::string([romName cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
param->useDeposterize = [self useDeposterize] ? true : false;
|
||||
|
@ -161,28 +97,10 @@
|
|||
pthread_attr_destroy(&fileWriteThreadAttr);
|
||||
}
|
||||
|
||||
- (void) chooseDirectoryPathDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[sheet orderOut:self];
|
||||
|
||||
if (returnCode == NSCancelButton)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NSURL *selectedFileURL = [[sheet URLs] lastObject]; //hopefully also the first object
|
||||
if(selectedFileURL == nil)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[self setSaveDirectoryPath:[selectedFileURL path]];
|
||||
}
|
||||
|
||||
- (void) readUserDefaults
|
||||
{
|
||||
[self setSaveDirectoryPath:[[NSUserDefaults standardUserDefaults] stringForKey:@"ScreenshotCaptureTool_DirectoryPath"]];
|
||||
[self setFileFormat:[[NSUserDefaults standardUserDefaults] integerForKey:@"ScreenshotCaptureTool_FileFormat"]];
|
||||
[self setFormatID:[[NSUserDefaults standardUserDefaults] integerForKey:@"ScreenshotCaptureTool_FileFormat"]];
|
||||
[self setUseDeposterize:[[NSUserDefaults standardUserDefaults] boolForKey:@"ScreenshotCaptureTool_Deposterize"]];
|
||||
[self setOutputFilterID:[[NSUserDefaults standardUserDefaults] integerForKey:@"ScreenshotCaptureTool_OutputFilter"]];
|
||||
[self setPixelScalerID:[[NSUserDefaults standardUserDefaults] integerForKey:@"ScreenshotCaptureTool_PixelScaler"]];
|
||||
|
@ -197,7 +115,7 @@
|
|||
- (void) writeUserDefaults
|
||||
{
|
||||
[[NSUserDefaults standardUserDefaults] setObject:[self saveDirectoryPath] forKey:@"ScreenshotCaptureTool_DirectoryPath"];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:[self fileFormat] forKey:@"ScreenshotCaptureTool_FileFormat"];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:[self formatID] forKey:@"ScreenshotCaptureTool_FileFormat"];
|
||||
[[NSUserDefaults standardUserDefaults] setBool:[self useDeposterize] forKey:@"ScreenshotCaptureTool_Deposterize"];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:[self outputFilterID] forKey:@"ScreenshotCaptureTool_OutputFilter"];
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:[self pixelScalerID] forKey:@"ScreenshotCaptureTool_PixelScaler"];
|
||||
|
@ -209,25 +127,17 @@
|
|||
[[NSUserDefaults standardUserDefaults] setInteger:[self displayRotation] forKey:@"ScreenshotCaptureTool_DisplayRotation"];
|
||||
}
|
||||
|
||||
#pragma mark DirectoryURLDragDestTextFieldProtocol Protocol
|
||||
- (void)assignDirectoryPath:(NSString *)dirPath textField:(NSTextField *)textField
|
||||
{
|
||||
if (textField == saveDirectoryPathTextField)
|
||||
{
|
||||
[self setSaveDirectoryPath:dirPath];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static void* RunFileWriteThread(void *arg)
|
||||
{
|
||||
// Copy the rendering properties from the calling thread.
|
||||
MacScreenshotCaptureToolParams *inParams = (MacScreenshotCaptureToolParams *)arg;
|
||||
MacScreenshotCaptureToolParams param;
|
||||
MacCaptureToolParams *inParams = (MacCaptureToolParams *)arg;
|
||||
MacCaptureToolParams param;
|
||||
|
||||
param.refObject = inParams->refObject;
|
||||
param.sharedData = inParams->sharedData;
|
||||
param.fileFormat = inParams->fileFormat;
|
||||
param.formatID = inParams->formatID;
|
||||
param.savePath = inParams->savePath;
|
||||
param.romName = inParams->romName;
|
||||
param.useDeposterize = inParams->useDeposterize;
|
||||
|
@ -382,7 +292,7 @@ static void* RunFileWriteThread(void *arg)
|
|||
|
||||
NSString *savePath = [NSString stringWithCString:param.savePath.c_str() encoding:NSUTF8StringEncoding];
|
||||
NSURL *fileURL = [NSURL fileURLWithPath:[savePath stringByAppendingPathComponent:fileName]];
|
||||
[CocoaDSFile saveScreenshot:fileURL bitmapData:newImageRep fileType:param.fileFormat];
|
||||
[CocoaDSFile saveScreenshot:fileURL bitmapData:newImageRep fileType:param.formatID];
|
||||
|
||||
// Clean up.
|
||||
delete cdp;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
@class InputPrefsView;
|
||||
@class FileMigrationDelegate;
|
||||
@class MacAVCaptureToolDelegate;
|
||||
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5
|
||||
|
@ -35,6 +36,7 @@
|
|||
NSObjectController *prefWindowController;
|
||||
NSObjectController *cdsCoreController;
|
||||
FileMigrationDelegate *migrationDelegate;
|
||||
MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
|
||||
NSWindow *prefWindow;
|
||||
NSWindow *troubleshootingWindow;
|
||||
|
@ -54,6 +56,7 @@
|
|||
@property (readonly) IBOutlet NSObjectController *prefWindowController;
|
||||
@property (readonly) IBOutlet NSObjectController *cdsCoreController;
|
||||
@property (readonly) IBOutlet FileMigrationDelegate *migrationDelegate;
|
||||
@property (readonly) IBOutlet MacAVCaptureToolDelegate *avCaptureToolDelegate;
|
||||
@property (readonly) IBOutlet NSWindow *prefWindow;
|
||||
@property (readonly) IBOutlet NSWindow *troubleshootingWindow;
|
||||
@property (readonly) IBOutlet NSMenu *mLoadStateSlot;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#import "DisplayWindowController.h"
|
||||
#import "EmuControllerDelegate.h"
|
||||
#import "FileMigrationDelegate.h"
|
||||
#import "MacAVCaptureTool.h"
|
||||
#import "preferencesWindowDelegate.h"
|
||||
#import "troubleshootingWindowDelegate.h"
|
||||
#import "cheatWindowDelegate.h"
|
||||
|
@ -48,6 +49,7 @@
|
|||
@synthesize emuControlController;
|
||||
@synthesize prefWindowController;
|
||||
@synthesize cdsCoreController;
|
||||
@synthesize avCaptureToolDelegate;
|
||||
@synthesize migrationDelegate;
|
||||
|
||||
@synthesize isAppRunningOnIntel;
|
||||
|
@ -183,6 +185,9 @@
|
|||
[[newCore cdsController] setDelegate:emuControl];
|
||||
[[newCore cdsController] startHardwareMicDevice];
|
||||
|
||||
[avCaptureToolDelegate setCdsCore:newCore];
|
||||
[avCaptureToolDelegate setExecControl:[newCore execControl]];
|
||||
|
||||
// Init the DS speakers.
|
||||
CocoaDSSpeaker *newSpeaker = [[[CocoaDSSpeaker alloc] init] autorelease];
|
||||
[newCore addOutput:newSpeaker];
|
||||
|
|
Loading…
Reference in New Issue