buncha patches by darktjm

sdl fix not applied yet
This commit is contained in:
squall-leonhart 2011-05-24 07:39:29 +00:00
parent 7145f8083d
commit 98215cfb30
18 changed files with 632 additions and 14 deletions

View File

@ -16,6 +16,16 @@ option( ENABLE_ASM_CORE "Enable x86 ASM CPU cores" OFF )
option( ENABLE_ASM_SCALERS "Enable x86 ASM graphic filters" OFF )
option( ENABLE_LINK "Enable GBA linking functionality" OFF )
option( ENABLE_LIRC "Enable LIRC support" OFF )
if(ENABLE_ASM_SCALERS)
option( ENABLE_MMX "Enable MMX" OFF )
endif(ENABLE_ASM_SCALERS)
option( ENABLE_GBA_LOGGING "Enable extended GBA logging" ON )
if( ENABLE_GBA_LOGGING )
ADD_DEFINITIONS (-DGBA_LOGGING )
endif( ENABLE_GBA_LOGGING )
if(ENABLE_MMX)
ADD_DEFINITIONS (-DMMX)
endif(ENABLE_MMX)
# The SDL port can't be built without debugging support
if( NOT ENABLE_DEBUGGER AND ENABLE_SDL )
@ -24,7 +34,13 @@ endif( NOT ENABLE_DEBUGGER AND ENABLE_SDL )
# Set the version number with -DVERSION=X.X.X-uber
IF( NOT VERSION )
SET( VERSION "1.8.0-SVN" )
FIND_PACKAGE(Subversion)
IF(SUBVERSION_FOUND)
Subversion_WC_INFO(${CMAKE_CURRENT_SOURCE_DIR} SVN_INFO)
SET( VERSION "1.8.0-SVN${SVN_INFO_WC_REVISION}" )
ELSE(SUBVERSION_FOUND)
SET( VERSION "1.8.0-SVN" )
ENDIF(SUBVERSION_FOUND)
ENDIF( NOT VERSION )
# Fill in SDLMAIN_LIBRARY on OS X manually to avoid using SDLMain.m
@ -62,6 +78,17 @@ IF( ENABLE_GTK )
PKG_CHECK_MODULES ( GTKGLMM REQUIRED gtkglextmm-x11-1.2 )
ENDIF( ENABLE_GTK )
option( ENABLE_FFMPEG "Enable ffmpeg A/V recording" ON )
if(ENABLE_FFMPEG)
FIND_PACKAGE ( PkgConfig REQUIRED )
PKG_CHECK_MODULES(FFMPEG REQUIRED libavcodec libavformat libswscale libavutil)
endif(ENABLE_FFMPEG)
if(NOT ENABLE_FFMPEG)
ADD_DEFINITIONS(-DNO_FFMPEG)
endif(NOT ENABLE_FFMPEG)
IF( ENABLE_LIRC )
SET( WITHLIRC 1 )
ELSE( ENABLE_LIRC )
@ -157,6 +184,10 @@ SET(SRC_MAIN
src/common/memgzio.c
)
if(ENABLE_FFMPEG)
SET(SRC_MAIN ${SRC_MAIN} src/common/ffmpeg.cpp)
endif(ENABLE_FFMPEG)
SET(SRC_GBA
src/gba/agbprint.cpp
src/gba/bios.cpp

View File

@ -72,13 +72,18 @@ static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
#else
// Mac cross-compile compiler:
// can't find register in class 'BREG' while reloading 'asm'
// so use class 'r' and register var binding
register _b asm("%bx");
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=r" (_b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
*b = _b;
#endif

View File

@ -41,7 +41,7 @@ struct EmulatedSystem {
extern void log(const char *,...);
extern bool systemPauseOnFrame();
extern void systemGbPrint(u8 *,int,int,int,int);
extern void systemGbPrint(u8 *,int,int,int,int,int);
extern void systemScreenCapture(int);
extern void systemDrawScreen();
// updates the joystick data

View File

@ -598,6 +598,7 @@ gzFile utilMemGzOpen(char *memory, int available, const char *mode)
utilGzWriteFunc = memgzwrite;
utilGzReadFunc = memgzread;
utilGzCloseFunc = memgzclose;
utilGzSeekFunc = memgzseek;
return memgzopen(memory, available, mode);
}

View File

@ -29,7 +29,7 @@ int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
Blip_Buffer::Blip_Buffer()
{
factor_ = LONG_MAX;
factor_ = (blip_ulong)LONG_MAX;
buffer_ = 0;
buffer_size_ = 0;
sample_rate_ = 0;

View File

@ -50,6 +50,7 @@ public:
class Gb_Env : public Gb_Osc {
public:
Gb_Env() : env_enabled(false), env_delay(0) {}
int env_delay;
int volume;
bool env_enabled;

468
src/common/ffmpeg.cpp Normal file
View File

@ -0,0 +1,468 @@
// this code has been partially lifted from the output-example.c program in
// libavformat. Not much of that original code remains.
// unlike the rest of the wx code, this has no wx dependency at all, and
// could be used by other front ends as well.
#define __STDC_LIMIT_MACROS // required for ffmpeg
#define __STDC_CONSTANT_MACROS // required for ffmpeg
#include "../gba/Sound.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavcodec/opt.h>
#ifndef AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY PKT_FLAG_KEY
#endif
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,96,0)
// note that there is no sane way to easily free a context w/o free_context()
// so this will probably leak
static void avformat_free_context(AVFormatContext *ctx)
{
if(ctx->pb)
url_fclose(ctx->pb);
for(int i = 0; i < ctx->nb_streams; i++) {
if(ctx->streams[i]->codec)
avcodec_close(ctx->streams[i]->codec);
av_freep(&ctx->streams[i]->codec);
av_freep(&ctx->streams[i]);
}
av_free(ctx);
}
#endif
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,45,0)
#define av_guess_format guess_format
#endif
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,105,0)
#define avio_open url_fopen
#define avio_close url_fclose
#endif
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(52,64,0)
#define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
#define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
#endif
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(50,1,0)
// this will almost definitely fail on big-endian systems
#define PIX_FMT_RGB565LE PIX_FMT_RGB565
#endif
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52,38,0)
#define AV_SAMPLE_FMT_S16 SAMPLE_FMT_S16
#endif
}
#define priv_AVFormatContext AVFormatContext
#define priv_AVStream AVStream
#define priv_AVOutputFormat AVOutputFormat
#define priv_AVFrame AVFrame
#define priv_SwsContext SwsContext
#define priv_PixelFormat PixelFormat
#include "ffmpeg.h"
// I have no idea what size to make these buffers
// I don't see any ffmpeg functions to guess the size, either
// use frame size, or FF_MIN_BUFFER_SIZE (that seems to be what it wants)
#define AUDIO_BUF_LEN (frame_len > FF_MIN_BUFFER_SIZE ? frame_len : FF_MIN_BUFFER_SIZE)
// use maximum frame size * 32 bpp * 2 for good measure
#define VIDEO_BUF_LEN (FF_MIN_BUFFER_SIZE + 256 * 244 * 4 * 2)
bool MediaRecorder::did_init = false;
MediaRecorder::MediaRecorder() : oc(0), vid_st(0), aud_st(0), video_buf(0),
audio_buf(0), audio_buf2(0), converter(0), convpic(0)
{
if(!did_init) {
did_init = true;
av_register_all();
}
pic = avcodec_alloc_frame();
}
MediaRet MediaRecorder::setup_sound_stream(const char *fname, AVOutputFormat *fmt)
{
oc = avformat_alloc_context();
if(!oc)
return MRET_ERR_NOMEM;
oc->oformat = fmt;
strncpy(oc->filename, fname, sizeof(oc->filename) - 1);
oc->filename[sizeof(oc->filename) - 1] = 0;
if(fmt->audio_codec == CODEC_ID_NONE)
return MRET_OK;
AVCodecContext *ctx;
aud_st = av_new_stream(oc, 1);
if(!aud_st) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
ctx = aud_st->codec;
ctx->codec_id = fmt->audio_codec;
ctx->codec_type = AVMEDIA_TYPE_AUDIO;
ctx->sample_fmt = AV_SAMPLE_FMT_S16;
ctx->bit_rate = 128000; // arbitrary; in case we're generating mp3
ctx->sample_rate = soundGetSampleRate();
ctx->channels = 2;
ctx->time_base.den = 60;
ctx->time_base.num = 1;
if(fmt->flags & AVFMT_GLOBALHEADER)
ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
AVCodec *codec = avcodec_find_encoder(fmt->audio_codec);
if(!codec || avcodec_open(ctx, codec)) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOCODEC;
}
return MRET_OK;
}
MediaRet MediaRecorder::setup_video_stream(const char *fname, int w, int h, int d)
{
AVCodecContext *ctx;
vid_st = av_new_stream(oc, 0);
if(!vid_st) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
ctx = vid_st->codec;
ctx->codec_id = oc->oformat->video_codec;
ctx->codec_type = AVMEDIA_TYPE_VIDEO;
ctx->width = w;
ctx->height = h;
ctx->time_base.den = 60;
ctx->time_base.num = 1;
// dunno if any of these help; some output just looks plain crappy
// will have to investigate further
ctx->bit_rate = 400000;
ctx->gop_size = 12;
ctx->max_b_frames = 2;
switch(d) {
case 16:
// FIXME: test & make endian-neutral
pixfmt = PIX_FMT_RGB565LE;
break;
case 24:
pixfmt = PIX_FMT_RGB24;
break;
case 32:
default: // should never be anything else
pixfmt = PIX_FMT_RGBA;
break;
}
ctx->pix_fmt = pixfmt;
pixsize = d >> 3;
linesize = pixsize * w;
ctx->max_b_frames = 2;
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
AVCodec *codec = avcodec_find_encoder(oc->oformat->video_codec);
// make sure RGB is supported (mostly not)
if(codec->pix_fmts) {
const enum PixelFormat *p;
int64_t mask = 0;
for(p = codec->pix_fmts; *p != -1; p++) {
// may get complaints about 1LL; thus the cast
mask |= ((int64_t)1) << *p;
if(*p == pixfmt)
break;
}
if(*p == -1) {
// if not supported, use a converter to the next best format
// this is swscale, the converter used by the output demo
enum PixelFormat dp = (PixelFormat)avcodec_find_best_pix_fmt(mask, pixfmt, 0, NULL);
if(dp == -1)
dp = codec->pix_fmts[0];
if(!(convpic = avcodec_alloc_frame()) ||
avpicture_alloc((AVPicture *)convpic, dp, w, h) < 0) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
#if LIBSWSCALE_VERSION_INT < AV_VERSION_INT(0, 12, 0)
converter = sws_getContext(w, h, pixfmt, w, h, dp, SWS_BICUBIC,
NULL, NULL, NULL);
#else
converter = sws_alloc_context();
// what a convoluted, inefficient way to set options
av_set_int(converter, "sws_flags", SWS_BICUBIC);
av_set_int(converter, "srcw", w);
av_set_int(converter, "srch", h);
av_set_int(converter, "dstw", w);
av_set_int(converter, "dsth", h);
av_set_int(converter, "src_format", pixfmt);
av_set_int(converter, "dst_format", dp);
sws_init_context(converter, NULL, NULL);
#endif
ctx->pix_fmt = dp;
}
}
if(!codec || avcodec_open(ctx, codec)) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOCODEC;
}
return MRET_OK;
}
MediaRet MediaRecorder::finish_setup(const char *fname)
{
if(av_set_parameters(oc, NULL) < 0) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOCODEC;
}
if(audio_buf)
free(audio_buf);
if(audio_buf2)
free(audio_buf2);
audio_buf2 = NULL;
in_audio_buf2 = 0;
if(aud_st) {
frame_len = aud_st->codec->frame_size * 4;
sample_len = soundGetSampleRate() * 4 / 60;
switch(aud_st->codec->codec_id) {
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
case CODEC_ID_PCM_U16BE:
frame_len = sample_len;
}
audio_buf = (u8 *)malloc(AUDIO_BUF_LEN);
if(!audio_buf) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
if(frame_len != sample_len && (frame_len > sample_len || sample_len % frame_len)) {
audio_buf2 = (u16 *)malloc(frame_len);
if(!audio_buf2) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
}
} else
audio_buf = NULL;
if(video_buf)
free(video_buf);
if(vid_st) {
video_buf = (u8 *)malloc(VIDEO_BUF_LEN);
if(!video_buf) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_NOMEM;
}
} else {
video_buf = NULL;
}
if(!(oc->oformat->flags & AVFMT_NOFILE)) {
if(avio_open(&oc->pb, fname, URL_WRONLY) < 0) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_FERR;
}
}
av_write_header(oc);
return MRET_OK;
}
MediaRet MediaRecorder::Record(const char *fname, int width, int height, int depth)
{
if(oc)
return MRET_ERR_RECORDING;
aud_st = vid_st = NULL;
AVOutputFormat *fmt = av_guess_format(NULL, fname, NULL);
if(!fmt)
fmt = av_guess_format("avi", NULL, NULL);
if(!fmt || fmt->video_codec == CODEC_ID_NONE)
return MRET_ERR_FMTGUESS;
MediaRet ret;
if((ret = setup_sound_stream(fname, fmt)) == MRET_OK &&
(ret = setup_video_stream(fname, width, height, depth)) == MRET_OK)
ret = finish_setup(fname);
return ret;
}
MediaRet MediaRecorder::Record(const char *fname)
{
if(oc)
return MRET_ERR_RECORDING;
aud_st = vid_st = NULL;
AVOutputFormat *fmt = av_guess_format(NULL, fname, NULL);
if(!fmt)
fmt = av_guess_format("wav", NULL, NULL);
if(!fmt || fmt->audio_codec == CODEC_ID_NONE)
return MRET_ERR_FMTGUESS;
MediaRet ret;
if((ret = setup_sound_stream(fname, fmt)) == MRET_OK)
ret = finish_setup(fname);
return ret;
}
void MediaRecorder::Stop()
{
if(oc) {
if(in_audio_buf2)
AddFrame((u16 *)0);
av_write_trailer(oc);
avformat_free_context(oc);
oc = NULL;
}
if(audio_buf) {
free(audio_buf);
audio_buf = NULL;
}
if(video_buf) {
free(video_buf);
video_buf = NULL;
}
if(audio_buf2) {
free(audio_buf2);
audio_buf2 = NULL;
}
if(convpic) {
avpicture_free((AVPicture *)convpic);
av_free(convpic);
convpic = NULL;
}
if(converter) {
sws_freeContext(converter);
converter = NULL;
}
}
MediaRecorder::~MediaRecorder()
{
Stop();
}
MediaRet MediaRecorder::AddFrame(const u8 *vid)
{
if(!oc || !vid_st)
return MRET_OK;
AVCodecContext *ctx = vid_st->codec;
AVPacket pkt;
// strip borders. inconsistent between depths for some reason
// but fortunately consistent between gb/gba.
int tbord, rbord;
switch(pixsize) {
case 2:
// 16-bit: 2 @ right, 1 @ top
tbord = 1; rbord = 2; break;
case 3:
// 24-bit: no border
tbord = rbord = 0; break;
case 4:
// 32-bit: 1 @ right, 1 @ top
tbord = 1; rbord = 1; break;
}
avpicture_fill((AVPicture *)pic, (uint8_t *)vid + tbord * (linesize + pixsize * rbord),
(PixelFormat)pixfmt, ctx->width + rbord, ctx->height);
// satisfy stupid sws_scale()'s integrity check
pic->data[1] = pic->data[2] = pic->data[3] = pic->data[0];
pic->linesize[1] = pic->linesize[2] = pic->linesize[3] = pic->linesize[0];
AVFrame *f = pic;
if(converter) {
sws_scale(converter, pic->data, pic->linesize, 0, ctx->height,
convpic->data, convpic->linesize);
f = convpic;
}
av_init_packet(&pkt);
pkt.stream_index = vid_st->index;
if(oc->oformat->flags & AVFMT_RAWPICTURE) {
// this won't work due to border
// not sure what formats set this, anyway
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.data = f->data[0];
pkt.size = linesize * ctx->height;
} else {
pkt.size = avcodec_encode_video(ctx, video_buf, VIDEO_BUF_LEN, f);
if(!pkt.size)
return MRET_OK;
if(ctx->coded_frame && ctx->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(ctx->coded_frame->pts, ctx->time_base, vid_st->time_base);
if(pkt.size > VIDEO_BUF_LEN) {
avformat_free_context(oc);
oc = NULL;
return MRET_ERR_BUFSIZE;
}
if(ctx->coded_frame->key_frame)
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.data = video_buf;
}
if(av_interleaved_write_frame(oc, &pkt) < 0) {
avformat_free_context(oc);
oc = NULL;
// yeah, err might not be a file error, but if it isn't, it's a
// coding error rather than a user-controllable error
// and better resolved using debugging
return MRET_ERR_FERR;
}
return MRET_OK;
}
MediaRet MediaRecorder::AddFrame(const u16 *aud)
{
if(!oc || !aud_st)
return MRET_OK;
// aud == NULL means just flush out last frame
if(!aud && !in_audio_buf2)
return MRET_OK;
AVCodecContext *ctx = aud_st->codec;
AVPacket pkt;
int len = sample_len;
if(in_audio_buf2) {
int ncpy = frame_len - in_audio_buf2;
if(ncpy > len)
ncpy = len;
if(aud) {
memcpy(audio_buf2 + in_audio_buf2/2, aud, ncpy);
len -= ncpy;
aud += ncpy / 2;
} else {
memset(audio_buf2 + in_audio_buf2/2, 0, ncpy);
len = 0;
}
in_audio_buf2 += ncpy;
}
while(len + in_audio_buf2 >= frame_len) {
av_init_packet(&pkt);
pkt.size = avcodec_encode_audio(ctx, audio_buf, frame_len,
(const short *)(in_audio_buf2 ? audio_buf2 : aud));
if(ctx->coded_frame && ctx->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts = av_rescale_q(ctx->coded_frame->pts, ctx->time_base, aud_st->time_base);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = aud_st->index;
pkt.data = audio_buf;
if(av_interleaved_write_frame(oc, &pkt) < 0) {
avformat_free_context(oc);
oc = NULL;
// yeah, err might not be a file error, but if it isn't, it's a
// coding error rather than a user-controllable error
// and better resolved using debugging
return MRET_ERR_FERR;
}
if(in_audio_buf2)
in_audio_buf2 = 0;
else {
aud += frame_len / 2;
len -= frame_len;
}
}
if(len > 0) {
memcpy(audio_buf2, aud, len);
in_audio_buf2 = len;
}
return MRET_OK;
}

79
src/common/ffmpeg.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef WX_FFMPEG_H
#define WX_FFMPEG_H
// simplified interface for recording audio and/or video from emulator
// unlike the rest of the wx code, this has no wx dependency at all, and
// could be used by other front ends as well.
// this only supports selecting output format via file name extensions;
// maybe some future version will support specifying a format. wx-2.9
// has an extra widget for the file selector, but 2.8 doesn't.
// the only missing piece that I couldn't figure out how to do generically
// is the code to find the available formats & associated extensions for
// the file dialog.
#include "../common/Types.h"
// return codes
// probably ought to put in own namespace, but this is good enough
enum MediaRet {
MRET_OK, // no errors
MRET_ERR_NOMEM, // error allocating buffers or structures
MRET_ERR_NOCODEC, // error opening codec
MRET_ERR_FERR, // error writing output file
MRET_ERR_RECORDING, // attempt to start recording when already doing it
MRET_ERR_FMTGUESS, // can't guess format from file name
MRET_ERR_BUFSIZE // buffer overflow (fatal)
};
class MediaRecorder
{
public:
MediaRecorder();
virtual ~MediaRecorder();
// start audio+video (also video-only codecs)
MediaRet Record(const char *fname, int width, int height, int depth);
// start audio only
MediaRet Record(const char *fname);
// stop both
void Stop();
bool IsRecording() { return oc != NULL; }
// add a frame of video; width+height+depth already given
// assumes a 1-pixel border on top & right
// always assumes being passed 1/60th of a second of video
MediaRet AddFrame(const u8 *vid);
// add a frame of audio; uses current sample rate to know length
// always assumes being passed 1/60th of a second of audio.
MediaRet AddFrame(const u16 *aud);
private:
static bool did_init;
// these are to avoid polluting things with avcodec includes
#ifndef priv_AVFormatContext
#define priv_AVFormatContext void
#define priv_AVStream void
#define priv_AVOutputFormat void
#define priv_AVFrame void
#define priv_SwsContext void
#define priv_PixelFormat int
#endif
priv_AVFormatContext *oc;
priv_AVStream *vid_st, *aud_st;
u8 *audio_buf, *video_buf;
u16 *audio_buf2;
int frame_len, sample_len, in_audio_buf2;
int linesize, pixsize;
priv_PixelFormat pixfmt;
priv_AVFrame *pic, *convpic;
priv_SwsContext *converter;
MediaRet setup_sound_stream(const char *fname, priv_AVOutputFormat *fmt);
MediaRet setup_video_stream(const char *fname, int w, int h, int d);
MediaRet finish_setup(const char *fname);
};
#endif /* WX_FFMPEG_H */

View File

@ -697,3 +697,21 @@ long ZEXPORT memtell(file)
return memTell(s->file);
}
long ZEXPORT memgzseek(gzFile file, long off, int whence)
{
if(whence != SEEK_CUR) {
fputs("FIXME: memgzio does not support seeking\n", stderr);
exit(1);
}
// this is inefficient, but the best I can do without actually reading
// the above code
char buf[80];
while(off > 0) {
int r = memgzread(file, buf, off > 80 ? 80 : off);
if(r <= 0)
return -1;
off -= r;
}
return memtell(file);
}

View File

@ -19,5 +19,6 @@ int ZEXPORT memgzread(gzFile file, voidp buf, unsigned len);
int ZEXPORT memgzwrite(gzFile file, const voidp buf, unsigned len);
int ZEXPORT memgzclose(gzFile file);
long ZEXPORT memtell(gzFile file);
long ZEXPORT memgzseek(gzFile file, long offset, int whence);
#endif // MEMGZIO_H

View File

@ -4976,6 +4976,8 @@ void gbEmulate(int ticksToStop)
gbSgbRenderBorder();
//if (gbScreenOn)
systemDrawScreen();
if(systemPauseOnFrame())
ticksToStop = 0;
}
gbFrameSkipCount = 0;
} else
@ -5160,6 +5162,8 @@ void gbEmulate(int ticksToStop)
gbSgbRenderBorder();
//if (gbScreenOn)
systemDrawScreen();
if(systemPauseOnFrame())
ticksToStop = 0;
}
}
if(systemReadJoypads()) {

View File

@ -38,6 +38,7 @@ void gbPrinterReset()
void gbPrinterShowData()
{
systemGbPrint(gbPrinterData,
gbPrinterDataCount,
gbPrinterPacket[6],
gbPrinterPacket[7],
gbPrinterPacket[8],
@ -87,6 +88,7 @@ void gbPrinterShowData()
void gbPrinterReceiveData()
{
int i = gbPrinterDataCount;
if(gbPrinterPacket[3]) { // compressed
u8 *data = &gbPrinterPacket[6];
u8 *dest = &gbPrinterData[gbPrinterDataCount];
@ -97,16 +99,17 @@ void gbPrinterReceiveData()
control &= 0x7f;
control += 2;
memset(dest, *data++, control);
len += control;
len += 2;
dest += control;
} else { // raw data
control++;
memcpy(dest, data, control);
dest += control;
data += control;
len += control;
len += control + 1;
}
}
gbPrinterDataCount = (int)(dest - gbPrinterData);
} else {
memcpy(&gbPrinterData[gbPrinterDataCount],
&gbPrinterPacket[6],

View File

@ -40,7 +40,7 @@ u8 gbSgbScreenBuffer[4160];
inline void gbSgbDraw24Bit(u8 *p, u16 v)
{
*((u32*) p) = systemColorMap32[v];
memcpy(p, &systemColorMap32[v], 3);
}
inline void gbSgbDraw32Bit(u32 *p, u16 v)

View File

@ -5,7 +5,11 @@ extern int armExecute();
extern int thumbExecute();
#ifdef __GNUC__
#ifndef __APPLE__
# define INSN_REGPARM __attribute__((regparm(1)))
#else
# define INSN_REGPARM /*nothing*/
#endif
# define LIKELY(x) __builtin_expect(!!(x),1)
# define UNLIKELY(x) __builtin_expect(!!(x),0)
#else

View File

@ -115,6 +115,7 @@ int systemGetSensorY()
}
void systemGbPrint(u8 * _puiData,
int _iLen,
int _iPages,
int _iFeed,
int _iPalette,

View File

@ -2591,7 +2591,7 @@ u32 systemGetClock()
return SDL_GetTicks();
}
void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast)
void systemGbPrint(u8 *data,int len,int pages,int feed,int palette, int contrast)
{
}

View File

@ -302,26 +302,26 @@ static void debuggerPrintBaseType(Type *t, u32 value, u32 location,
case DW_ATE_signed:
switch(debuggerRadix) {
case 0:
printf("%lld", value);
printf("%lld", (long long)value);
break;
case 1:
printf("0x%llx", value);
printf("0x%llx", (long long)value);
break;
case 2:
printf("0%llo", value);
printf("0%llo", (long long)value);
break;
}
break;
case DW_ATE_unsigned:
switch(debuggerRadix) {
case 0:
printf("%llu", value);
printf("%llu", (unsigned long long)value);
break;
case 1:
printf("0x%llx", value);
printf("0x%llx", (unsigned long long)value);
break;
case 2:
printf("0%llo", value);
printf("0%llo", (unsigned long long)value);
break;
}
break;

View File

@ -467,12 +467,14 @@ void GBPrinterDlg::OnPaint()
}
void systemGbPrint(u8 *data,
int datalen,
int pages,
int feed,
int palette,
int contrast)
{
GBPrinterDlg printer;
memset(data + datalen, 0, 160*144/4 - datalen);
printer.processData(data);
printer.DoModal();
}