This commit is contained in:
Bryan Baraoidan 2017-11-24 08:41:26 -08:00
commit 97b1913ea3
33 changed files with 186168 additions and 301 deletions

View File

@ -7,6 +7,7 @@ include(CheckIncludeFiles)
include(CheckFunctionExists)
include(ExternalProject)
include(SourceGroupByDir)
include(GetGitRevisionDescription)
project(redream)
set(CMAKE_C_STANDARD 11)
@ -54,6 +55,15 @@ if(BUILD_LIBRETRO)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
#--------------------------------------------------
# version file
#--------------------------------------------------
git_describe(GIT_VERSION --tags)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/core/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/core/version.h @ONLY)
#--------------------------------------------------
# config file
#--------------------------------------------------
@ -62,7 +72,9 @@ check_include_files(strings.h HAVE_STRINGS_H)
check_function_exists(strcasecmp HAVE_STRCASECMP)
check_function_exists(strnlen HAVE_STRNLEN)
check_function_exists(strnstr HAVE_STRNSTR)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/core/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/core/config.h)
list(APPEND RELIB_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/src)
list(APPEND RELIB_DEFS HAVE_CONFIG_H)

185505
TAGS Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# git_local_changes(<var>)
#
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
# Uses the return code of "git diff-index --quiet HEAD --".
# Does not regard untracked files.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
function(get_git_head_revision _refspecvar _hashvar)
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
# We have reached the root directory, we are not in git
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
return()
endif()
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
endwhile()
# check if this is a submodule
if(NOT IS_DIRECTORY ${GIT_DIR})
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${GIT_DIR}/HEAD")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake"
@ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(COMMAND
"${GIT_EXECUTABLE}"
describe
${hash}
${ARGN}
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var} "${out}" PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
return()
endif()
execute_process(COMMAND
"${GIT_EXECUTABLE}"
diff-index --quiet HEAD --
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE
res
OUTPUT_VARIABLE
out
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var} "CLEAN" PARENT_SCOPE)
else()
set(${_var} "DIRTY" PARENT_SCOPE)
endif()
endfunction()

View File

@ -0,0 +1,41 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright Iowa State University 2009-2010.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
else()
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
set(HEAD_HASH "${CMAKE_MATCH_1}")
endif()
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

6
src/core/version.h.in Normal file
View File

@ -0,0 +1,6 @@
#ifndef REDREAM_VERSION_H
#define REDREAM_VERSION_H
#define GIT_VERSION "@GIT_VERSION@"
#endif

View File

@ -50,10 +50,15 @@ enum {
};
enum {
EMU_DRAW_INVALID,
EMU_DRAW_PIXELS,
EMU_DRAW_CONTEXT,
EMU_DRAW_DISABLED,
EMU_SOURCE_NONE,
EMU_SOURCE_CTX,
EMU_SOURCE_PXL,
};
struct emu_framebuffer {
uint8_t data[PVR_FRAMEBUFFER_SIZE];
int width;
int height;
};
struct emu_texture {
@ -92,13 +97,10 @@ struct emu {
cond_t res_cond;
/* latest video state pushed by the dreamcast */
volatile int latest;
struct {
uint8_t pixels[PVR_FRAMEBUFFER_SIZE];
int width;
int height;
} latest_fb;
struct tr_context latest_rc;
volatile int vid_disabled;
volatile int vid_source;
struct tr_context vid_rc;
struct emu_framebuffer vid_fb;
/* latest context submitted to emu_start_render */
struct ta_context *pending_ctx;
@ -350,18 +352,15 @@ static void emu_start_tracing(struct emu *emu) {
/*
* dreamcast guest interface
*/
static void emu_vblank_in(void *userdata, int video_disabled) {
static void emu_vblank_in(void *userdata, int vid_disabled) {
struct emu *emu = userdata;
if (emu->multi_threaded) {
mutex_lock(emu->res_mutex);
}
if (video_disabled) {
emu->latest = EMU_DRAW_DISABLED;
}
emu->state = EMU_DRAWFRAME;
emu->vid_disabled = vid_disabled;
if (emu->multi_threaded) {
cond_signal(emu->res_cond);
@ -431,11 +430,11 @@ static void emu_start_render(void *userdata, struct ta_context *ctx) {
static void emu_push_pixels(void *userdata, const uint8_t *data, int w, int h) {
struct emu *emu = userdata;
emu->latest = EMU_DRAW_PIXELS;
memcpy(emu->vid_fb.data, data, w * h * 4);
emu->vid_fb.width = w;
emu->vid_fb.height = h;
memcpy(emu->latest_fb.pixels, data, w * h * 4);
emu->latest_fb.width = w;
emu->latest_fb.height = h;
emu->vid_source = EMU_SOURCE_PXL;
}
static void emu_push_audio(void *userdata, const int16_t *data, int frames) {
@ -600,11 +599,11 @@ void emu_render_frame(struct emu *emu) {
}
if (emu->pending_ctx) {
emu->latest = EMU_DRAW_CONTEXT;
tr_convert_context(emu->r, emu, &emu_find_texture, emu->pending_ctx,
&emu->latest_rc);
&emu->vid_rc);
emu->pending_ctx = NULL;
emu->vid_source = EMU_SOURCE_CTX;
}
if (emu->multi_threaded) {
@ -622,12 +621,14 @@ void emu_render_frame(struct emu *emu) {
mutex_unlock(emu->res_mutex);
}
/* render the latest framebuffer or context */
if (emu->latest == EMU_DRAW_PIXELS) {
r_draw_pixels(emu->r, emu->latest_fb.pixels, 0, 0, emu->latest_fb.width,
emu->latest_fb.height);
} else if (emu->latest == EMU_DRAW_CONTEXT) {
tr_render_context(emu->r, &emu->latest_rc);
/* render the latest video source */
if (!emu->vid_disabled) {
if (emu->vid_source == EMU_SOURCE_PXL) {
r_draw_pixels(emu->r, emu->vid_fb.data, 0, 0, emu->vid_fb.width,
emu->vid_fb.height);
} else if (emu->vid_source == EMU_SOURCE_CTX) {
tr_render_context(emu->r, &emu->vid_rc);
}
}
/* note, the emulation thread may still be running the code between vblank_in

View File

@ -154,7 +154,7 @@ static int dc_load_bin(struct dreamcast *dc, const char *path) {
}
static int dc_load_disc(struct dreamcast *dc, const char *path) {
struct disc *disc = disc_create(path);
struct disc *disc = disc_create(path, 1);
if (!disc) {
return 0;

View File

@ -98,7 +98,7 @@ static void cdi_destroy(struct disc *disc) {
}
static int cdi_parse_track(struct disc *disc, uint32_t version,
int *track_offset, int *leadout_fad) {
int *track_offset, int *leadout_fad, int verbose) {
struct cdi *cdi = (struct cdi *)disc;
FILE *fp = cdi->fp;
@ -187,9 +187,11 @@ static int cdi_parse_track(struct disc *disc, uint32_t version,
track->ctrl = sector_mode == 0 ? 0 : 4;
track->file_offset = data_offset - track->fad * track->sector_size;
LOG_INFO("cdi_parse_track track=%d fad=%d off=%d mode=%s/%d", track->num,
track->fad, data_offset, cdi_sector_modes[sector_mode],
track->sector_size);
if (verbose) {
LOG_INFO("cdi_parse_track track=%d fad=%d off=%d mode=%s/%d", track->num,
track->fad, data_offset, cdi_sector_modes[sector_mode],
track->sector_size);
}
*track_offset += total_len * sector_size;
*leadout_fad = track->fad + track_len;
@ -198,7 +200,7 @@ static int cdi_parse_track(struct disc *disc, uint32_t version,
}
static int cdi_parse_session(struct disc *disc, uint32_t version,
int *track_offset) {
int *track_offset, int verbose) {
struct cdi *cdi = (struct cdi *)disc;
FILE *fp = cdi->fp;
@ -217,7 +219,7 @@ static int cdi_parse_session(struct disc *disc, uint32_t version,
int leadout_fad = 0;
while (num_tracks--) {
if (!cdi_parse_track(disc, version, track_offset, &leadout_fad)) {
if (!cdi_parse_track(disc, version, track_offset, &leadout_fad, verbose)) {
return 0;
}
@ -252,7 +254,7 @@ static int cdi_parse_session(struct disc *disc, uint32_t version,
return 1;
}
static int cdi_parse(struct disc *disc, const char *filename) {
static int cdi_parse(struct disc *disc, const char *filename, int verbose) {
struct cdi *cdi = (struct cdi *)disc;
FILE *fp = fopen(filename, "rb");
@ -281,7 +283,9 @@ static int cdi_parse(struct disc *disc, const char *filename) {
int found = 0;
for (int i = 0; i < ARRAY_SIZE(cdi_versions); i++) {
if (version == cdi_versions[i]) {
LOG_INFO("cdi_parse version %s detected", cdi_version_names[i]);
if (verbose) {
LOG_INFO("cdi_parse version %s detected", cdi_version_names[i]);
}
found = 1;
break;
}
@ -308,13 +312,15 @@ static int cdi_parse(struct disc *disc, const char *filename) {
return 0;
}
LOG_INFO("cdi_parse found %d sessions", num_sessions);
if (verbose) {
LOG_INFO("cdi_parse found %d sessions", num_sessions);
}
/* tracks the current track's data offset from the file start */
int track_offset = 0;
while (num_sessions--) {
if (!cdi_parse_session(disc, version, &track_offset)) {
if (!cdi_parse_session(disc, version, &track_offset, verbose)) {
return 0;
}
@ -329,7 +335,7 @@ static int cdi_parse(struct disc *disc, const char *filename) {
return 1;
}
struct disc *cdi_create(const char *filename) {
struct disc *cdi_create(const char *filename, int verbose) {
struct cdi *cdi = calloc(1, sizeof(struct cdi));
cdi->destroy = &cdi_destroy;
@ -343,7 +349,7 @@ struct disc *cdi_create(const char *filename) {
struct disc *disc = (struct disc *)cdi;
if (!cdi_parse(disc, filename)) {
if (!cdi_parse(disc, filename, verbose)) {
cdi_destroy(disc);
return NULL;
}

View File

@ -3,6 +3,6 @@
struct disc;
struct disc *cdi_create(const char *filename);
struct disc *cdi_create(const char *filename, int verbose);
#endif

View File

@ -84,7 +84,7 @@ static void chd_destroy(struct disc *disc) {
chd_close(chd->chd);
}
static int chd_parse(struct disc *disc, const char *filename) {
static int chd_parse(struct disc *disc, const char *filename, int verbose) {
struct chd *chd = (struct chd *)disc;
chd_error err = chd_open(filename, CHD_OPEN_READ, 0, &chd->chd);
@ -182,8 +182,10 @@ static int chd_parse(struct disc *disc, const char *filename) {
track->ctrl = strcmp(type, "AUDIO") == 0 ? 0 : 4;
track->file_offset = fad - cad;
LOG_INFO("chd_parse '%s' track=%d fad=%d secsz=%d", tmp, track->num,
track->fad, track->sector_size);
if (verbose) {
LOG_INFO("chd_parse '%s' track=%d fad=%d secsz=%d", tmp, track->num,
track->fad, track->sector_size);
}
/* chd block addresses are padded to a 4-frame boundary */
cad += ALIGN_UP(frames, 4);
@ -213,7 +215,7 @@ static int chd_parse(struct disc *disc, const char *filename) {
return 1;
}
struct disc *chd_create(const char *filename) {
struct disc *chd_create(const char *filename, int verbose) {
struct chd *chd = calloc(1, sizeof(struct chd));
chd->destroy = &chd_destroy;
@ -227,7 +229,7 @@ struct disc *chd_create(const char *filename) {
struct disc *disc = (struct disc *)chd;
if (!chd_parse(disc, filename)) {
if (!chd_parse(disc, filename, verbose)) {
chd_destroy(disc);
return NULL;
}

View File

@ -3,6 +3,6 @@
struct disc;
struct disc *chd_create(const char *filename);
struct disc *chd_create(const char *filename, int verbose);
#endif

View File

@ -280,15 +280,15 @@ void disc_destroy(struct disc *disc) {
disc->destroy(disc);
}
struct disc *disc_create(const char *filename) {
struct disc *disc_create(const char *filename, int verbose) {
struct disc *disc = NULL;
if (strstr(filename, ".cdi")) {
disc = cdi_create(filename);
disc = cdi_create(filename, verbose);
} else if (strstr(filename, ".chd")) {
disc = chd_create(filename);
disc = chd_create(filename, verbose);
} else if (strstr(filename, ".gdi")) {
disc = gdi_create(filename);
disc = gdi_create(filename, verbose);
}
if (!disc) {
@ -316,7 +316,9 @@ struct disc *disc_create(const char *filename) {
snprintf(disc->uid, sizeof(disc->uid), "%s %s %s %s", disc->prodnme,
disc->prodnum, disc->prodver, disc->discnum);
LOG_INFO("disc_create id=%s", disc->uid);
if (verbose) {
LOG_INFO("disc_create id=%s", disc->uid);
}
return disc;
}

View File

@ -85,7 +85,7 @@ struct disc {
void (*read_sector)(struct disc *, struct track *, int, void *);
};
struct disc *disc_create(const char *filename);
struct disc *disc_create(const char *filename, int verbose);
void disc_destroy(struct disc *disc);
int disc_get_format(struct disc *disc);

View File

@ -93,7 +93,7 @@ static void gdi_destroy(struct disc *disc) {
}
}
static int gdi_parse(struct disc *disc, const char *filename) {
static int gdi_parse(struct disc *disc, const char *filename, int verbose) {
struct gdi *gdi = (struct gdi *)disc;
FILE *fp = fopen(filename, "rb");
@ -162,8 +162,10 @@ static int gdi_parse(struct disc *disc, const char *filename) {
snprintf(track->filename, sizeof(track->filename), "%s" PATH_SEPARATOR "%s",
dirname, filename);
LOG_INFO("gdi_parse track=%d filename='%s' fad=%d secsz=%d", track->num,
track->filename, track->fad, track->sector_size);
if (verbose) {
LOG_INFO("gdi_parse track=%d filename='%s' fad=%d secsz=%d", track->num,
track->filename, track->fad, track->sector_size);
}
}
/* gdroms contains two sessions, one for the single density area (tracks 0-1)
@ -191,7 +193,7 @@ static int gdi_parse(struct disc *disc, const char *filename) {
return 1;
}
struct disc *gdi_create(const char *filename) {
struct disc *gdi_create(const char *filename, int verbose) {
struct gdi *gdi = calloc(1, sizeof(struct gdi));
gdi->destroy = &gdi_destroy;
@ -205,7 +207,7 @@ struct disc *gdi_create(const char *filename) {
struct disc *disc = (struct disc *)gdi;
if (!gdi_parse(disc, filename)) {
if (!gdi_parse(disc, filename, verbose)) {
gdi_destroy(disc);
return NULL;
}

View File

@ -3,6 +3,6 @@
struct disc;
struct disc *gdi_create(const char *filename);
struct disc *gdi_create(const char *filename, int verbose);
#endif

View File

@ -329,14 +329,17 @@ static void as_map(struct memory *mem, struct address_space *space,
#ifdef HAVE_FASTMEM
uint8_t *target = space->base + begin;
void *res = NULL;
if (offset >= 0) {
/* map physical memory into the address space */
map_shared_memory(mem->shmem, offset, target, size, ACC_READWRITE);
res = map_shared_memory(mem->shmem, offset, target, size, ACC_READWRITE);
} else {
/* disable access to mmio areas */
map_shared_memory(mem->shmem, 0x0, target, size, ACC_NONE);
res = map_shared_memory(mem->shmem, 0x0, target, size, ACC_NONE);
}
CHECK_NE(res, SHMEM_MAP_FAILED);
#else
(void)(offset);
#endif
@ -443,15 +446,23 @@ int sh4_init(struct memory *mem) {
return 0;
}
/* note, p0-p3 map to the entire external address space, while p4 only maps to
the external regions in between the gaps in its own internal regions. these
gaps map to areas 1-3 (0xe4000000-0xefffffff) and 6-7 (0xf8000000-
0xffffffff) */
/* area 0 */
sh4_map(mem, SH4_AREA0_BEGIN, SH4_AREA0_END, P0 | P1 | P2 | P3, MAP_MMIO,
(mmio_read_cb)&sh4_area0_read, (mmio_write_cb)&sh4_area0_write, NULL,
NULL);
sh4_map(mem, SH4_AREA0_BEGIN, SH4_AICA_MEM_BEGIN - 1, P0 | P1 | P2 | P3,
MAP_MMIO, (mmio_read_cb)&sh4_area0_read,
(mmio_write_cb)&sh4_area0_write, NULL, NULL);
sh4_map(mem, SH4_AICA_MEM_BEGIN, SH4_AICA_MEM_END, P0 | P1 | P2 | P3,
MAP_ARAM, NULL, NULL, NULL, NULL);
sh4_map(mem, SH4_AICA_MEM_END + 1, SH4_AREA0_END, P0 | P1 | P2 | P3, MAP_MMIO,
(mmio_read_cb)&sh4_area0_read, (mmio_write_cb)&sh4_area0_write, NULL,
NULL);
/* area 1 */
sh4_map(mem, SH4_AREA1_BEGIN, SH4_AREA1_END, P0 | P1 | P2 | P3, MAP_MMIO,
sh4_map(mem, SH4_AREA1_BEGIN, SH4_AREA1_END, P0 | P1 | P2 | P3 | P4, MAP_MMIO,
(mmio_read_cb)&sh4_area1_read, (mmio_write_cb)&sh4_area1_write, NULL,
NULL);
#if 0
@ -466,20 +477,19 @@ int sh4_init(struct memory *mem) {
/* area 2 */
/* area 3 */
sh4_map(mem, SH4_AREA3_RAM0_BEGIN, SH4_AREA3_RAM0_END, P0 | P1 | P2 | P3,
sh4_map(mem, SH4_AREA3_RAM0_BEGIN, SH4_AREA3_RAM0_END, P0 | P1 | P2 | P3 | P4,
MAP_RAM, NULL, NULL, NULL, NULL);
sh4_map(mem, SH4_AREA3_RAM1_BEGIN, SH4_AREA3_RAM1_END, P0 | P1 | P2 | P3,
sh4_map(mem, SH4_AREA3_RAM1_BEGIN, SH4_AREA3_RAM1_END, P0 | P1 | P2 | P3 | P4,
MAP_RAM, NULL, NULL, NULL, NULL);
sh4_map(mem, SH4_AREA3_RAM2_BEGIN, SH4_AREA3_RAM2_END, P0 | P1 | P2 | P3,
sh4_map(mem, SH4_AREA3_RAM2_BEGIN, SH4_AREA3_RAM2_END, P0 | P1 | P2 | P3 | P4,
MAP_RAM, NULL, NULL, NULL, NULL);
sh4_map(mem, SH4_AREA3_RAM3_BEGIN, SH4_AREA3_RAM3_END, P0 | P1 | P2 | P3,
sh4_map(mem, SH4_AREA3_RAM3_BEGIN, SH4_AREA3_RAM3_END, P0 | P1 | P2 | P3 | P4,
MAP_RAM, NULL, NULL, NULL, NULL);
/* area 4 */
/* note, this region is only accessed through sq / dma transfers, so only a
/* area 4. this region is only written through sq / dma transfers, so only a
write_string handler is added */
sh4_map(mem, SH4_AREA4_BEGIN, SH4_AREA4_END, P0 | P1 | P2 | P3, MAP_MMIO,
(mmio_read_cb)&mem_unhandled_read, NULL, NULL,
(mmio_read_cb)&sh4_area4_read, NULL, NULL,
(mmio_write_string_cb)&sh4_area4_write);
/* area 5 */
@ -487,12 +497,22 @@ int sh4_init(struct memory *mem) {
/* area 6 */
/* area 7 */
sh4_map(mem, SH4_AREA7_BEGIN, SH4_AREA7_END, P0 | P1 | P2 | P3, MAP_MMIO,
sh4_map(mem, SH4_AREA7_BEGIN, SH4_AREA7_END, P0 | P1 | P2 | P3 | P4, MAP_MMIO,
(mmio_read_cb)&sh4_area7_read, (mmio_write_cb)&sh4_area7_write, NULL,
NULL);
/* p4 */
sh4_map(mem, SH4_P4_BEGIN, SH4_P4_END, P4, MAP_MMIO,
/* p4. the unassigned regions have already been mapped to the external address
space. instead of mapping the entire p4 area, selectively map each internal
region to avoid overwriting the existing mappings */
sh4_map(mem, SH4_SQ_BEGIN, SH4_SQ_END, P4, MAP_MMIO,
(mmio_read_cb)&sh4_p4_read, (mmio_write_cb)&sh4_p4_write, NULL, NULL);
sh4_map(mem, SH4_ICACHE_BEGIN, SH4_ICACHE_END, P4, MAP_MMIO,
(mmio_read_cb)&sh4_p4_read, (mmio_write_cb)&sh4_p4_write, NULL, NULL);
sh4_map(mem, SH4_ITLB_BEGIN, SH4_ITLB_END, P4, MAP_MMIO,
(mmio_read_cb)&sh4_p4_read, (mmio_write_cb)&sh4_p4_write, NULL, NULL);
sh4_map(mem, SH4_OCACHE_BEGIN, SH4_OCACHE_END, P4, MAP_MMIO,
(mmio_read_cb)&sh4_p4_read, (mmio_write_cb)&sh4_p4_write, NULL, NULL);
sh4_map(mem, SH4_UTLB_BEGIN, SH4_UTLB_END, P4, MAP_MMIO,
(mmio_read_cb)&sh4_p4_read, (mmio_write_cb)&sh4_p4_write, NULL, NULL);
return 1;
@ -512,8 +532,11 @@ uint8_t *mem_ram(struct memory *mem, uint32_t offset) {
int mem_init(struct memory *mem) {
#ifdef HAVE_FASTMEM
/* create the shared memory object to back the physical memory */
mem->shmem = create_shared_memory("/redream", PHYSICAL_SIZE, ACC_READWRITE);
/* create the shared memory object to back the physical memory. note, because
mmio regions also map this shared memory object when disabling permissions,
the object has to at least be the size of an entire mmio region */
size_t shmem_size = MAX(PHYSICAL_SIZE, SH4_AREA_SIZE);
mem->shmem = create_shared_memory("/redream", shmem_size, ACC_READWRITE);
if (mem->shmem == SHMEM_INVALID) {
LOG_WARNING("mem_init failed to create shared memory object");

View File

@ -266,11 +266,11 @@ static void pvr_reconfigure_spg(struct pvr *pvr) {
pvr->line_clock *= 2;
}
const char *mode = "VGA";
const char *mode = "vga";
if (pvr->SPG_CONTROL->NTSC == 1) {
mode = "NTSC";
mode = "ntsc";
} else if (pvr->SPG_CONTROL->PAL == 1) {
mode = "PAL";
mode = "pal";
}
LOG_INFO(

View File

@ -365,33 +365,73 @@ static void tr_parse_bg(struct tr *tr, const struct ta_context *ctx,
/* translate the first 3 vertices */
struct ta_vertex *va = tr_reserve_vert(tr, rc);
struct ta_vertex *vb = tr_reserve_vert(tr, rc);
struct ta_vertex *vc = tr_reserve_vert(tr, rc);
struct ta_vertex *vd = tr_reserve_vert(tr, rc);
struct ta_vertex *vc = tr_reserve_vert(tr, rc);
int offset = 0;
offset = tr_parse_bg_vert(ctx, rc, offset, va);
offset = tr_parse_bg_vert(ctx, rc, offset, vb);
offset = tr_parse_bg_vert(ctx, rc, offset, vc);
/* not exactly sure how ISP_BACKGND_D is supposed to be honored. would be nice
to find a game that actually uses the texture parameter to see how the uv
coordinates look */
/*va->xyz[2] = ctx->bg_depth;
/* force z to background clip depth, not sure the purpose of the supplied z */
va->xyz[2] = ctx->bg_depth;
vb->xyz[2] = ctx->bg_depth;
vc->xyz[2] = ctx->bg_depth;*/
vc->xyz[2] = ctx->bg_depth;
/*
* these vertices don't seem to come in a particular order. i've seen:
* b---c a---b a---b a
* | / \ | | / |\
* | / and \ | and | / and | \
* |/ \| |/ | \
* a c c c---b
*
* in order to simplify calculating d, figure out the corner vertex based on
* the distance between its adjacent vertices, and rotate the vertices such
* that b is always the corner vertex. this feels pretty brute force, there
* must be a more elegant solution
*/
float d1[3], d2[3];
float scorea, scoreb, scorec;
vec3_sub(d1, vb->xyz, va->xyz);
vec3_sub(d2, vc->xyz, va->xyz);
scorea = vec3_dot(d1, d1) + vec3_dot(d2, d2);
vec3_sub(d1, va->xyz, vb->xyz);
vec3_sub(d2, vc->xyz, vb->xyz);
scoreb = vec3_dot(d1, d1) + vec3_dot(d2, d2);
vec3_sub(d1, va->xyz, vc->xyz);
vec3_sub(d2, vb->xyz, vc->xyz);
scorec = vec3_dot(d1, d1) + vec3_dot(d2, d2);
if (scorea < scoreb && scorea < scorec) {
/* rotate counterclockwise */
struct ta_vertex tmp = *va;
*va = *vc;
*vc = *vb;
*vb = tmp;
} else if (scorec < scorea && scorec < scoreb) {
/* rotate clockwise */
struct ta_vertex tmp = *vc;
*vc = *va;
*va = *vb;
*vb = tmp;
}
/* 4th vertex isn't supplied, fill it out automatically */
float xyz_ab[3], xyz_ac[3];
vec3_sub(xyz_ab, vb->xyz, va->xyz);
vec3_sub(xyz_ac, vc->xyz, va->xyz);
vec3_add(vd->xyz, vb->xyz, xyz_ab);
vec3_add(vd->xyz, vd->xyz, xyz_ac);
float xyz_ba[3], xyz_bc[3];
vec3_sub(xyz_ba, va->xyz, vb->xyz);
vec3_sub(xyz_bc, vc->xyz, vb->xyz);
vec3_add(vd->xyz, vb->xyz, xyz_ba);
vec3_add(vd->xyz, vd->xyz, xyz_bc);
float uv_ab[2], uv_ac[2];
vec2_sub(uv_ab, vb->uv, va->uv);
vec2_sub(uv_ac, vc->uv, va->uv);
vec2_add(vd->uv, vb->uv, uv_ab);
vec2_add(vd->uv, vd->uv, uv_ac);
float uv_ba[2], uv_bc[2];
vec2_sub(uv_ba, va->uv, vb->uv);
vec2_sub(uv_bc, vc->uv, vb->uv);
vec2_add(vd->uv, vb->uv, uv_ba);
vec2_add(vd->uv, vd->uv, uv_bc);
/* TODO interpolate this properly when a game is found to test with */
vd->color = va->color;

View File

@ -48,9 +48,11 @@ static int boot_validate(struct boot *boot) {
static int boot_load_rom(struct boot *boot) {
const char *filename = boot_bin_path();
LOG_INFO("boot_load_rom path=%s", filename);
FILE *fp = fopen(filename, "rb");
if (!fp) {
LOG_WARNING("failed to load '%s'", filename);
LOG_WARNING("boot_load_rom failed to open");
return 0;
}
@ -59,7 +61,7 @@ static int boot_load_rom(struct boot *boot) {
fseek(fp, 0, SEEK_SET);
if (size != (int)sizeof(boot->rom)) {
LOG_WARNING("boot rom size mismatch, is %d, expected %d", size,
LOG_WARNING("boot_load_rom size mismatch size=%d expected=%d", size,
sizeof(boot->rom));
fclose(fp);
return 0;
@ -70,12 +72,10 @@ static int boot_load_rom(struct boot *boot) {
fclose(fp);
if (!boot_validate(boot)) {
LOG_WARNING("failed to validate boot rom");
LOG_WARNING("boot_load_rom failed to validate");
return 0;
}
LOG_INFO("boot_load_rom loaded '%s'", filename);
return 1;
}

View File

@ -48,6 +48,9 @@ struct sh4 {
int tmu_stats;
struct list breakpoints;
/* ccn */
uint32_t sq[2][8];
/* intc */
enum sh4_interrupt sorted_interrupts[SH4_NUM_INTERRUPTS];
uint64_t sort_id[SH4_NUM_INTERRUPTS];

View File

@ -57,7 +57,7 @@ void sh4_ccn_pref(struct sh4 *sh4, uint32_t addr) {
dst |= addr & 0x3ffffe0;
}
sh4_memcpy_to_guest(mem, dst, sh4->ctx.sq[sqi], 32);
sh4_memcpy_to_guest(mem, dst, sh4->sq[sqi], 32);
}
uint32_t sh4_ccn_cache_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
@ -86,15 +86,17 @@ void sh4_ccn_cache_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t sh4_ccn_sq_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
uint32_t sqi = (addr & 0x20) >> 5;
unsigned idx = (addr & 0x1c) >> 2;
return sh4->ctx.sq[sqi][idx];
uint32_t idx = (addr & 0x1c) >> 2;
CHECK_EQ(mask, 0xffffffff);
return sh4->sq[sqi][idx];
}
void sh4_ccn_sq_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t mask) {
uint32_t sqi = (addr & 0x20) >> 5;
uint32_t idx = (addr & 0x1c) >> 2;
sh4->ctx.sq[sqi][idx] = data;
CHECK_EQ(mask, 0xffffffff);
sh4->sq[sqi][idx] = data;
}
uint32_t sh4_ccn_icache_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {

View File

@ -1,5 +1,6 @@
#include "guest/aica/aica.h"
#include "guest/holly/holly.h"
#include "guest/memory.h"
#include "guest/pvr/pvr.h"
#include "guest/pvr/ta.h"
#include "guest/rom/boot.h"
@ -53,12 +54,11 @@ void sh4_p4_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
sh4_ccn_ocache_write(sh4, addr - SH4_OCACHE_BEGIN, data, mask);
} else if (addr >= SH4_UTLB_BEGIN && addr <= SH4_UTLB_END) {
sh4_mmu_utlb_write(sh4, addr - SH4_UTLB_BEGIN, data, mask);
} else if (addr >= SH4_REG2_BEGIN && addr <= SH4_REG2_END) {
sh4_reg_write(sh4, addr - SH4_REG2_BEGIN, data, mask);
} else {
LOG_FATAL("sh4_p4_write unexpected addr 0x%08x", addr);
}
}
uint32_t sh4_p4_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
if (addr >= SH4_SQ_BEGIN && addr <= SH4_SQ_END) {
return sh4_ccn_sq_read(sh4, addr - SH4_SQ_BEGIN, mask);
@ -70,8 +70,6 @@ uint32_t sh4_p4_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
return sh4_ccn_ocache_read(sh4, addr - SH4_OCACHE_BEGIN, mask);
} else if (addr >= SH4_UTLB_BEGIN && addr <= SH4_UTLB_END) {
return sh4_mmu_utlb_read(sh4, addr - SH4_UTLB_BEGIN, mask);
} else if (addr >= SH4_REG2_BEGIN && addr <= SH4_REG2_END) {
return sh4_reg_read(sh4, addr - SH4_REG2_BEGIN, mask);
} else {
LOG_FATAL("sh4_p4_read unexpected addr 0x%08x", addr);
}
@ -117,7 +115,7 @@ void sh4_area4_write(struct sh4 *sh4, uint32_t addr, const uint8_t *ptr,
addr &= SH4_ADDR_MASK;
/* create the two area4 mirrors */
/* create the mirror */
addr &= SH4_AREA4_ADDR_MASK;
if (addr >= SH4_TA_POLY_BEGIN && addr <= SH4_TA_POLY_END) {
@ -127,17 +125,27 @@ void sh4_area4_write(struct sh4 *sh4, uint32_t addr, const uint8_t *ptr,
} else if (addr >= SH4_TA_TEXTURE_BEGIN && addr <= SH4_TA_TEXTURE_END) {
ta_texture_write(dc->ta, addr, ptr, size);
} else {
LOG_FATAL("sh4_area4_write unexpected addr 0x%08x", addr);
/* nop */
}
}
uint32_t sh4_area4_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
addr &= SH4_ADDR_MASK;
/* create the mirror */
addr &= SH4_AREA4_ADDR_MASK;
/* area 4 is read-only, but will return the physical address when accessed */
return addr;
}
void sh4_area1_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t mask) {
struct dreamcast *dc = sh4->dc;
addr &= SH4_ADDR_MASK;
/* create the two area1 mirrors */
/* create the mirror */
addr &= SH4_AREA1_ADDR_MASK;
if (addr >= SH4_PVR_VRAM64_BEGIN && addr <= SH4_PVR_VRAM64_END) {
@ -154,7 +162,7 @@ uint32_t sh4_area1_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
addr &= SH4_ADDR_MASK;
/* create the two area1 mirrors */
/* create the mirror */
addr &= SH4_AREA1_ADDR_MASK;
if (addr >= SH4_PVR_VRAM64_BEGIN && addr <= SH4_PVR_VRAM64_END) {
@ -173,28 +181,31 @@ void sh4_area0_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
/* mask off upper bits creating p0-p4 mirrors */
addr &= SH4_ADDR_MASK;
/* flash rom is not accessible in the area0 mirror */
/* flash rom is not accessible in the area 0 mirror */
if (addr >= SH4_FLASH_ROM_BEGIN && addr <= SH4_FLASH_ROM_END) {
flash_rom_write(dc->flash, addr - SH4_FLASH_ROM_BEGIN, data, mask);
} else {
/* create the two area0 mirrors */
addr &= SH4_AREA0_ADDR_MASK;
return;
}
if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) {
holly_reg_write(dc->holly, addr - SH4_HOLLY_REG_BEGIN, data, mask);
} else if (addr >= SH4_PVR_REG_BEGIN && addr <= SH4_PVR_REG_END) {
pvr_reg_write(dc->pvr, addr - SH4_PVR_REG_BEGIN, data, mask);
} else if (addr >= SH4_MODEM_BEGIN && addr <= SH4_MODEM_END) {
/* nop */
} else if (addr >= SH4_AICA_REG_BEGIN && addr <= SH4_AICA_REG_END) {
aica_reg_write(dc->aica, addr - SH4_AICA_REG_BEGIN, data, mask);
} else if (addr >= SH4_AICA_MEM_BEGIN && addr <= SH4_AICA_MEM_END) {
aica_mem_write(dc->aica, addr - SH4_AICA_MEM_BEGIN, data, mask);
} else if (addr >= SH4_HOLLY_EXT_BEGIN && addr <= SH4_HOLLY_EXT_END) {
/* nop */
} else {
LOG_FATAL("sh4_area0_write unexpected addr 0x%08x", addr);
}
/* create the mirror */
addr &= SH4_AREA0_ADDR_MASK;
if (/*addr >= SH4_BOOT_ROM_BEGIN*/ addr <= SH4_BOOT_ROM_END) {
/* read-only */
} else if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) {
holly_reg_write(dc->holly, addr - SH4_HOLLY_REG_BEGIN, data, mask);
} else if (addr >= SH4_PVR_REG_BEGIN && addr <= SH4_PVR_REG_END) {
pvr_reg_write(dc->pvr, addr - SH4_PVR_REG_BEGIN, data, mask);
} else if (addr >= SH4_MODEM_BEGIN && addr <= SH4_MODEM_END) {
/* nop */
} else if (addr >= SH4_AICA_REG_BEGIN && addr <= SH4_AICA_REG_END) {
aica_reg_write(dc->aica, addr - SH4_AICA_REG_BEGIN, data, mask);
} else if (addr >= SH4_AICA_MEM_BEGIN && addr <= SH4_AICA_MEM_END) {
aica_mem_write(dc->aica, addr - SH4_AICA_MEM_BEGIN, data, mask);
} else if (addr >= SH4_HOLLY_EXT_BEGIN && addr <= SH4_HOLLY_EXT_END) {
/* nop */
} else {
LOG_FATAL("sh4_area0_write unexpected addr 0x%08x", addr);
}
}
@ -204,17 +215,21 @@ uint32_t sh4_area0_read(struct sh4 *sh4, uint32_t addr, uint32_t mask) {
/* mask off upper bits creating p0-p4 mirrors */
addr &= SH4_ADDR_MASK;
/* boot / flash rom are not accessible in the area0 mirror */
/* boot / flash rom are not accessible in the area 0 mirror */
if (/*addr >= SH4_BOOT_ROM_BEGIN &&*/ addr <= SH4_BOOT_ROM_END) {
return boot_rom_read(dc->boot, addr - SH4_BOOT_ROM_BEGIN, mask);
} else if (addr >= SH4_FLASH_ROM_BEGIN && addr <= SH4_FLASH_ROM_END) {
return flash_rom_read(dc->flash, addr - SH4_FLASH_ROM_BEGIN, mask);
}
/* create the two area0 mirrors */
/* create the mirror */
addr &= SH4_AREA0_ADDR_MASK;
if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) {
if (/*addr >= SH4_BOOT_ROM_BEGIN*/ addr <= SH4_BOOT_ROM_END) {
return 0xffffffff;
} else if (addr >= SH4_FLASH_ROM_BEGIN && addr <= SH4_FLASH_ROM_END) {
return 0xffffffff;
} else if (addr >= SH4_HOLLY_REG_BEGIN && addr <= SH4_HOLLY_REG_END) {
return holly_reg_read(dc->holly, addr - SH4_HOLLY_REG_BEGIN, mask);
} else if (addr >= SH4_PVR_REG_BEGIN && addr <= SH4_PVR_REG_END) {
return pvr_reg_read(dc->pvr, addr - SH4_PVR_REG_BEGIN, mask);

View File

@ -2,7 +2,8 @@
#define SH4_MEM_H
/* clang-format off */
#define SH4_ADDR_MASK 0x1fffffff
#define SH4_AREA_SIZE 0x20000000
#define SH4_ADDR_MASK (SH4_AREA_SIZE-1)
/* area 0 */
#define SH4_AREA0_BEGIN 0x00000000
@ -116,21 +117,24 @@
#define SH4_OCACHE_END 0xf5ffffff
#define SH4_UTLB_BEGIN 0xf6000000
#define SH4_UTLB_END 0xf7ffffff
#define SH4_REG2_BEGIN 0xfc000000
#define SH4_REG2_END 0xffffffff
/* clang-format on */
uint32_t sh4_area0_read(struct sh4 *sh4, uint32_t addr, uint32_t mask);
void sh4_area0_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t mask);
uint32_t sh4_area1_read(struct sh4 *sh4, uint32_t addr, uint32_t mask);
void sh4_area1_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t mask);
uint32_t sh4_area4_read(struct sh4 *sh4, uint32_t addr, uint32_t mask);
void sh4_area4_write(struct sh4 *sh4, uint32_t addr, const uint8_t *ptr,
int size);
uint32_t sh4_area7_read(struct sh4 *sh4, uint32_t addr, uint32_t mask);
void sh4_area7_write(struct sh4 *sh4, uint32_t addr, uint32_t data,
uint32_t mask);
uint32_t sh4_p4_read(struct sh4 *sh4, uint32_t addr, uint32_t mask);
void sh4_p4_write(struct sh4 *sh4, uint32_t addr, uint32_t data, uint32_t mask);

View File

@ -6,6 +6,7 @@
#include "core/profiler.h"
#include "core/ringbuf.h"
#include "core/time.h"
#include "core/version.h"
#include "emulator.h"
#include "guest/aica/aica.h"
#include "host/host.h"
@ -287,9 +288,17 @@ static SDL_GLContext video_create_context(struct host *host) {
}
static void video_set_fullscreen(struct host *host, int fullscreen) {
uint32_t flags = fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
int res = SDL_SetWindowFullscreen(host->win, flags);
CHECK_EQ(res, 0);
if (fullscreen) {
int res = SDL_SetWindowFullscreen(host->win, SDL_WINDOW_FULLSCREEN_DESKTOP);
CHECK(res >= 0);
res = SDL_ShowCursor(SDL_DISABLE);
CHECK(res >= 0);
} else {
int res = SDL_SetWindowFullscreen(host->win, 0);
CHECK(res >= 0);
res = SDL_ShowCursor(SDL_ENABLE);
CHECK(res >= 0);
}
}
static void video_shutdown(struct host *host) {
@ -687,7 +696,7 @@ static void host_debug_menu(struct host *host) {
int enabled = options[i].enabled;
if (igMenuItem(desc, NULL, enabled, 1)) {
int len = strlen(OPTION_sync);
int len = (int)strlen(OPTION_sync);
if (enabled) {
for (int i = 0; i < len; i++) {
@ -967,16 +976,16 @@ static int host_init(struct host *host) {
CHECK_GE(res, 0, "host_create sdl initialization failed: %s", SDL_GetError());
uint32_t win_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
if (OPTION_fullscreen) {
win_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
}
host->win = SDL_CreateWindow("redream", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, VIDEO_DEFAULT_WIDTH,
VIDEO_DEFAULT_HEIGHT, win_flags);
CHECK_NOTNULL(host->win, "host_create window creation failed: %s",
SDL_GetError());
if (OPTION_fullscreen) {
video_set_fullscreen(host, 1);
}
if (!audio_init(host)) {
return 0;
}
@ -1008,6 +1017,8 @@ struct host *host_create() {
}
int main(int argc, char **argv) {
LOG_INFO("redream " GIT_VERSION);
#if PLATFORM_ANDROID
const char *appdir = SDL_AndroidGetExternalStoragePath();
fs_set_appdir(appdir);

View File

@ -247,8 +247,6 @@ static void imgui_update_font_tex(struct imgui *imgui) {
return;
}
LOG_INFO("imgui_update_font_tex w=%d h=%d", width, height);
font_tex = r_create_texture(imgui->r, PXL_RGBA, FILTER_BILINEAR, WRAP_REPEAT,
WRAP_REPEAT, 0, width, height, pixels);
io.Fonts->TexID = (void *)(intptr_t)font_tex;

View File

@ -15,34 +15,6 @@ extern "C" {
* x64 register layout
*/
/* %rax %eax %ax %al <-- both: temporary
%rcx %ecx %cx %cl <-- both: argument
%rdx %edx %dx %dl <-- both: argument
%rbx %ebx %bx %bl <-- both: available (callee saved)
%rsp %esp %sp %spl <-- both: reserved
%rbp %ebp %bp %bpl <-- both: available (callee saved)
%rsi %esi %si %sil <-- msvc: available (callee saved), amd64: argument
%rdi %edi %di %dil <-- msvc: available (callee saved), amd64: argument
%r8 %r8d %r8w %r8b <-- both: argument
%r9 %r9d %r9w %r9b <-- both: argument
%r10 %r10d %r10w %r10b <-- both: available (not callee saved)
%r11 %r11d %r11w %r11b <-- both: available (not callee saved)
%r12 %r12d %r12w %r12b <-- both: available (callee saved)
%r13 %r13d %r13w %r13b <-- both: available (callee saved)
%r14 %r14d %r14w %r14b <-- both: available (callee saved)
%r15 %r15d %r15w %r15b <-- both: available (callee saved)
msvc calling convention uses rcx, rdx, r8, r9 for arguments
amd64 calling convention uses rdi, rsi, rdx, rcx, r8, r9 for arguments
both use the same xmm registers for floating point arguments
our largest function call uses only 3 arguments
msvc is left with rax, rsi, rdi, r10 and r11
amd64 is left with rax, r8, r9, r10 and r11
rax is used as a scratch register
r10, r11, xmm1 are used for constant not eliminated by const propagation
r14, r15 are reserved for the context and memory pointers */
/* clang-format off */
#if PLATFORM_WINDOWS
const int x64_arg0_idx = Xbyak::Operand::RCX;
@ -64,29 +36,64 @@ const Xbyak::Reg64 guestctx(Xbyak::Operand::R14);
const Xbyak::Reg64 guestmem(Xbyak::Operand::R15);
const struct jit_register x64_registers[] = {
{"rbx", JIT_REG_I64 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::rbx},
{"rbp", JIT_REG_I64 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::rbp},
{"rax", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rax},
{"rcx", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rcx},
{"rdx", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rdx},
{"rbx", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rbx},
{"rsp", JIT_RESERVED | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rsp},
{"rbp", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rbp},
#if PLATFORM_WINDOWS
{"rsi", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::rsi},
{"rdi", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::rdi},
{"rsi", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rsi},
{"rdi", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rdi},
{"r8", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r8},
{"r9", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r9},
#else
{"r8", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::r8},
{"r9", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::r9},
{"rsi", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rsi},
{"rdi", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::rdi},
{"r8", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r8},
{"r9", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r9},
#endif
{"r10", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r10},
{"r11", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r11},
{"r12", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r12},
{"r13", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r13},
{"r14", JIT_RESERVED | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r14},
{"r15", JIT_RESERVED | JIT_CALLEE_SAVE | JIT_REG_I64, (const void *)&Xbyak::util::r15},
#if PLATFORM_WINDOWS
{"xmm0", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm0},
{"xmm1", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm1},
{"xmm2", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm2},
{"xmm3", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm3},
{"xmm4", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm4},
{"xmm5", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm5},
{"xmm6", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm6},
{"xmm7", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm7},
{"xmm8", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm8},
{"xmm9", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm9},
{"xmm10", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm10},
{"xmm11", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm11},
{"xmm12", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm12},
{"xmm13", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm13},
{"xmm14", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm14},
{"xmm15", JIT_ALLOCATE | JIT_CALLEE_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm15},
#else
{"xmm0", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm0},
{"xmm1", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm1},
{"xmm2", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm2},
{"xmm3", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm3},
{"xmm4", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm4},
{"xmm5", JIT_RESERVED | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm5},
{"xmm6", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm6},
{"xmm7", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm7},
{"xmm8", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm8},
{"xmm9", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm9},
{"xmm10", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm10},
{"xmm11", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm11},
{"xmm12", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm12},
{"xmm13", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm13},
{"xmm14", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm14},
{"xmm15", JIT_ALLOCATE | JIT_CALLER_SAVE | JIT_REG_F64 | JIT_REG_V128, (const void *)&Xbyak::util::xmm15},
#endif
{"r10", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::r10},
{"r11", JIT_REG_I64 | JIT_CALLER_SAVED, (const void *)&Xbyak::util::r11},
{"r12", JIT_REG_I64 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::r12},
{"r13", JIT_REG_I64 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::r13},
{"xmm6", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm6},
{"xmm7", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm7},
{"xmm8", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm8},
{"xmm9", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm9},
{"xmm10", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm10},
{"xmm11", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm11},
{"xmm12", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm12},
{"xmm13", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm13},
{"xmm14", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm14},
{"xmm15", JIT_REG_F64 | JIT_REG_V128 | JIT_CALLEE_SAVED, (const void *)&Xbyak::util::xmm15}
};
const int x64_num_registers = ARRAY_SIZE(x64_registers);
@ -127,6 +134,60 @@ Xbyak::Xmm x64_backend_xmm(struct x64_backend *backend,
return xmm;
}
int x64_backend_push_regs(struct x64_backend *backend, int mask) {
int size = 0;
auto &e = *backend->codegen;
for (int i = 0; i < x64_num_registers; i++) {
const struct jit_register *r = &x64_registers[i];
if ((r->flags & mask) != mask) {
continue;
}
if (r->flags & JIT_REG_I64) {
Xbyak::Reg reg = *(const Xbyak::Reg *)r->data;
CHECK(reg.isREG());
size += 8;
e.mov(e.qword[e.rsp - size], reg);
} else if (r->flags & (JIT_REG_F64 | JIT_REG_V128)) {
Xbyak::Xmm xmm = *(const Xbyak::Xmm *)r->data;
CHECK(xmm.isXMM());
size += 16;
e.movdqu(e.ptr[e.rsp - size], xmm);
}
}
return size;
}
void x64_backend_pop_regs(struct x64_backend *backend, int mask) {
int size = 0;
auto &e = *backend->codegen;
for (int i = 0; i < x64_num_registers; i++) {
const struct jit_register *r = &x64_registers[i];
if ((r->flags & mask) != mask) {
continue;
}
if ((r->flags & JIT_REG_I64)) {
Xbyak::Reg reg = *(const Xbyak::Reg *)r->data;
CHECK(reg.isREG());
size += 8;
e.mov(reg, e.qword[e.rsp - size]);
} else if (r->flags & (JIT_REG_F64 | JIT_REG_V128)) {
Xbyak::Xmm xmm = *(const Xbyak::Xmm *)r->data;
CHECK(xmm.isXMM());
size += 16;
e.movdqu(xmm, e.ptr[e.rsp - size]);
}
}
}
void x64_backend_load_mem(struct x64_backend *backend,
const struct ir_value *dst,
const Xbyak::RegExp &src_exp) {
@ -306,33 +367,19 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) {
backend->load_thunk[i] = e.getCurr<void (*)()>();
/* save caller-saved registers and offset the stack an extra 8 bytes to
align it */
#if PLATFORM_WINDOWS
e.push(e.rsi);
e.push(e.rdi);
#else
e.push(e.r8);
e.push(e.r9);
#endif
e.push(e.r10);
e.push(e.r11);
e.sub(e.rsp, X64_STACK_SHADOW_SPACE + 8);
/* save caller-saved registers that our code uses and ensure stack is
16-byte aligned */
int save_mask = JIT_ALLOCATE | JIT_CALLER_SAVE;
int offset = x64_backend_push_regs(backend, save_mask);
offset = ALIGN_UP(offset + X64_STACK_SHADOW_SPACE + 8, 16) - 8;
e.sub(e.rsp, offset);
/* call the mmio handler */
e.call(e.rax);
/* restore caller-saved registers */
e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8);
e.pop(e.r11);
e.pop(e.r10);
#if PLATFORM_WINDOWS
e.pop(e.rdi);
e.pop(e.rsi);
#else
e.pop(e.r9);
e.pop(e.r8);
#endif
e.add(e.rsp, offset);
x64_backend_pop_regs(backend, save_mask);
/* save mmio handler result */
e.mov(dst, e.rax);
@ -346,34 +393,19 @@ static void x64_backend_emit_thunks(struct x64_backend *backend) {
e.align(32);
backend->store_thunk = e.getCurr<void (*)()>();
/* save caller-saved registers and offset the stack an extra 8 bytes to
align it */
#if PLATFORM_WINDOWS
e.push(e.rsi);
e.push(e.rdi);
#else
e.push(e.r8);
e.push(e.r9);
#endif
e.push(e.r10);
e.push(e.r11);
e.sub(e.rsp, X64_STACK_SHADOW_SPACE + 8);
/* save caller-saved registers that our code uses and ensure stack is
16-byte aligned */
int save_mask = JIT_ALLOCATE | JIT_CALLER_SAVE;
int offset = x64_backend_push_regs(backend, save_mask);
offset = ALIGN_UP(offset + X64_STACK_SHADOW_SPACE + 8, 16) - 8;
e.sub(e.rsp, offset);
/* call the mmio handler */
e.call(e.rax);
/* restore caller-saved registers */
e.add(e.rsp, X64_STACK_SHADOW_SPACE + 8);
e.pop(e.r11);
e.pop(e.r10);
#if PLATFORM_WINDOWS
e.pop(e.rdi);
e.pop(e.rsi);
#else
e.pop(e.r9);
e.pop(e.r8);
#endif
e.add(e.rsp, offset);
x64_backend_pop_regs(backend, save_mask);
/* return to jit code */
e.ret();

View File

@ -75,6 +75,7 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) {
struct jit_guest *guest = backend->base.guest;
auto &e = *backend->codegen;
int stack_offset = 0;
/* emit dispatch thunks */
{
@ -152,18 +153,12 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) {
backend->dispatch_enter = e.getCurr<void (*)(int)>();
/* create stack frame */
e.push(e.rbx);
e.push(e.rbp);
#if PLATFORM_WINDOWS
e.push(e.rdi);
e.push(e.rsi);
#endif
e.push(e.r12);
e.push(e.r13);
e.push(e.r14);
e.push(e.r15);
e.sub(e.rsp, X64_STACK_SIZE + 8);
/* create stack frame and ensure stack is 16-byte aligned. note, the stack
is currently unaligned due to the 8-byte return address that was pushed
when this thunk was called */
stack_offset = x64_backend_push_regs(backend, JIT_CALLEE_SAVE);
stack_offset = ALIGN_UP(stack_offset + X64_STACK_SIZE + 8, 16) - 8;
e.sub(e.rsp, stack_offset);
/* assign fixed registers */
e.mov(guestctx, (uint64_t)guest->ctx);
@ -184,17 +179,9 @@ void x64_dispatch_emit_thunks(struct x64_backend *backend) {
backend->dispatch_exit = e.getCurr<void *>();
/* destroy stack frame */
e.add(e.rsp, X64_STACK_SIZE + 8);
e.pop(e.r15);
e.pop(e.r14);
e.pop(e.r13);
e.pop(e.r12);
#if PLATFORM_WINDOWS
e.pop(e.rsi);
e.pop(e.rdi);
#endif
e.pop(e.rbp);
e.pop(e.rbx);
e.add(e.rsp, stack_offset);
x64_backend_pop_regs(backend, JIT_CALLEE_SAVE);
e.ret();
}

View File

@ -51,7 +51,7 @@ struct x64_backend {
/*
* backend functionality used by emitters
*/
#define X64_THUNK_SIZE 1024
#define X64_THUNK_SIZE 8192
#define X64_STACK_SIZE 1024
#if PLATFORM_WINDOWS
@ -79,6 +79,8 @@ Xbyak::Reg x64_backend_reg(struct x64_backend *backend,
const struct ir_value *v);
Xbyak::Xmm x64_backend_xmm(struct x64_backend *backend,
const struct ir_value *v);
int x64_backend_push_regs(struct x64_backend *backend, int mask);
void x64_backend_pop_regs(struct x64_backend *backend, int mask);
void x64_backend_load_mem(struct x64_backend *backend,
const struct ir_value *dst,
const Xbyak::RegExp &src_exp);

View File

@ -114,7 +114,6 @@ struct sh4_context {
uint32_t fpul, mach, macl;
uint32_t sgr, spc, ssr;
uint64_t pending_interrupts;
uint32_t sq[2][8];
/* processor sleep state */
uint32_t sleep_mode;

View File

@ -27,33 +27,37 @@ struct jit_guest;
#endif
enum {
/* allocate to this register */
JIT_ALLOCATE = 0x1,
/* don't allocate to this register */
JIT_RESERVED = 0x2,
/* register is callee-saved */
JIT_CALLEE_SAVED = 0x1,
JIT_CALLEE_SAVE = 0x4,
/* register is caller-saved */
JIT_CALLER_SAVED = 0x2,
JIT_CALLER_SAVE = 0x8,
/* result must contain arg0. this signals the register allocator to insert a
copy from arg0 to result if it fails to reuse the same register for both.
this is required by several operations, namely binary arithmetic ops on
x64, which only take two operands */
JIT_REUSE_ARG0 = 0x4,
JIT_REUSE_ARG0 = 0x10,
/* argument is optional */
JIT_OPTIONAL = 0x8,
JIT_OPTIONAL = 0x20,
/* argument can be in a 64-bit or less int register */
JIT_REG_I64 = 0x10,
JIT_REG_I64 = 0x40,
/* argument can be in a 64-bit or less float register */
JIT_REG_F64 = 0x20,
JIT_REG_F64 = 0x80,
/* argument can be in a 128-bit or less vector register */
JIT_REG_V128 = 0x40,
JIT_REG_V128 = 0x100,
/* argument can be a 32-bit or less int immediate */
JIT_IMM_I32 = 0x80,
JIT_IMM_I32 = 0x200,
/* argument can be a 64-bit or less int immediate */
JIT_IMM_I64 = 0x100,
JIT_IMM_I64 = 0x400,
/* argument can be a 32-bit or less float immediate */
JIT_IMM_F32 = 0x200,
JIT_IMM_F32 = 0x800,
/* argument can be a 64-bit or less float immediate */
JIT_IMM_F64 = 0x400,
JIT_IMM_F64 = 0x1000,
/* argument can be a block reference */
JIT_IMM_BLK = 0x800,
JIT_IMM_BLK = 0x2000,
JIT_TYPE_MASK = JIT_REG_I64 | JIT_REG_F64 | JIT_REG_V128 | JIT_IMM_I32 |
JIT_IMM_I64 | JIT_IMM_F32 | JIT_IMM_F64 | JIT_IMM_BLK,
};

View File

@ -91,12 +91,14 @@ struct ra {
static int ra_reg_can_store(const struct jit_register *reg,
const struct ir_value *v) {
if (ir_is_int(v->type) && v->type <= VALUE_I64) {
return reg->flags & JIT_REG_I64;
} else if (ir_is_float(v->type) && v->type <= VALUE_F64) {
return reg->flags & JIT_REG_F64;
} else if (ir_is_vector(v->type) && v->type <= VALUE_V128) {
return reg->flags & JIT_REG_V128;
if (reg->flags & JIT_ALLOCATE) {
if (ir_is_int(v->type) && v->type <= VALUE_I64) {
return reg->flags & JIT_REG_I64;
} else if (ir_is_float(v->type) && v->type <= VALUE_F64) {
return reg->flags & JIT_REG_F64;
} else if (ir_is_vector(v->type) && v->type <= VALUE_V128) {
return reg->flags & JIT_REG_V128;
}
}
return 0;
}
@ -222,7 +224,7 @@ static void ra_validate(struct ra *ra, struct ir *ir, struct ir_block *block) {
for (int i = 0; i < ra->num_registers; i++) {
const struct jit_register *reg = &ra->registers[i];
if (reg->flags & JIT_CALLER_SAVED) {
if (reg->flags & JIT_CALLER_SAVE) {
active[i] = NULL;
}
}
@ -315,7 +317,7 @@ static void ra_spill_tmps(struct ra *ra, struct ir *ir,
/* only spill caller-saved regs */
struct ra_bin *bin = ra_get_bin(tmp->value->reg);
if (!(bin->reg->flags & JIT_CALLER_SAVED)) {
if (!(bin->reg->flags & JIT_CALLER_SAVE)) {
continue;
}

View File

@ -22,11 +22,12 @@ static const char *ta_vp =
" // if w is negative, this vertex will always fail the clip test which is\n"
" // defined as: -w <= z <= w\n"
" // however, since OpenGL tries to maintain connectivity when a polygon is\n"
" // clipped, a lot of junk vertices are generated in this case due to the z\n"
" // component not being valid for our vertices. the best workaround so far\n"
" // seems to be clamping w to always be positive, which doesn't explicitly\n"
" // clip this vertex, but avoids generating additional junk ones\n"
" w = max(w, 0.0);\n"
" // clipped, a lot of junk vertices are generated. the best workaround so\n"
" // far is to force xyz=0 to avoid generating visible junk vertices\n"
" if (w < 0.0) {\n"
" gl_Position = vec4(0.0, 0.0, 0.0, w);\n"
" return;\n"
" }\n"
" // scale x from [0,640] -> [-1,1] and y from [0,480] to [-1,1]\n"
" gl_Position.xy = attr_xyz.xy * u_video_scale.xz + u_video_scale.yw;\n"

View File

@ -518,7 +518,8 @@ static void ui_scan_games_f(struct ui *ui, const char *filename) {
snprintf(ui->scan_status, sizeof(ui->scan_status), "scanning %s", filename);
if (ui_has_game_ext(filename, game_exts, ARRAY_SIZE(game_exts))) {
struct disc *disc = disc_create(filename);
struct disc *disc = disc_create(filename, 0);
if (disc) {
struct game game = {0};
@ -1099,7 +1100,7 @@ enum {
};
static texture_handle_t ui_load_disc_texture(struct ui *ui, struct game *game) {
struct disc *disc = disc_create(game->filename);
struct disc *disc = disc_create(game->filename, 0);
if (!disc) {
return ui->disc_tex;
}
@ -1384,9 +1385,9 @@ void ui_set_page(struct ui *ui, int page_index) {
}
/* trigger global callbacks for when the ui is open / closed */
if (top_page == NULL && next_page != NULL) {
if (!top_page && next_page) {
ui_opened(ui->host);
} else if (next_page == NULL) {
} else if (!next_page) {
ui_closed(ui->host);
}
}
@ -1432,10 +1433,8 @@ int ui_keydown(struct ui *ui, int key, int16_t value) {
/* prioritize canceling any open dialog */
if (ui->dlg) {
ui_close_dlg(ui, UI_DLG_CANCEL);
}
/* else, pop the history stack */
else {
ui->history_pos = MAX(ui->history_pos - 1, 1);
} else if (ui->history_pos > 1) {
ui->history_pos = ui->history_pos - 1;
}
}