Cocoa Port:

- Do a bunch of code refactoring and cleanup.
- Add some new UI for an upcoming new feature.
This commit is contained in:
rogerman 2018-05-17 21:22:51 -07:00
parent c024a78a43
commit 932cdd6366
28 changed files with 83136 additions and 76146 deletions

View File

@ -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 &param)
{
// 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 &param)
{
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 &param)
{
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;
}

View File

@ -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 &param);
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 &param);
void ConvertVideoSlice888Xto888(const VideoConvertParam &param);
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_

View File

@ -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);
}

View File

@ -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();

View File

@ -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 */,

View File

@ -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">

View File

@ -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;
};

View File

@ -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

View File

@ -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>

View File

@ -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];
}
}

View File

@ -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;

View File

@ -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(&param->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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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_

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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

View File

@ -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 &param);
};
@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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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;

View File

@ -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;

View File

@ -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];