Internals - changed memory start addres to avoid overlaps

Graphics - added options for 480p Nintendo Revolution SDK bug fix patch
           (Thanks leseratte)
Graphics - added options for deflickering settings (Thanks blackb0x)
Graphics - added options for disabling dithering (Thanks blackb0x)
Graphics - added options for framebuffer width patch (Thanks blackb0x)
Languages - Updated ZH_CN.lang (Thanks kavid)
Documentation - Updated README.md with the new configuration options
This commit is contained in:
unknown 2024-09-15 10:38:50 +02:00
parent c5477d4dae
commit 93014def68
17 changed files with 645 additions and 75 deletions

View File

@ -1,3 +1,18 @@
15-09-2024 cfg 70r78.13 (release)
- Internals - changed memory start addres to avoid overlaps
- Graphics - added options for 480p Nintendo Revolution SDK bug fix patch (Thanks leseratte)
- Graphics - added options for deflickering settings (Thanks blackb0x)
- Graphics - added options for disabling dithering (Thanks blackb0x)
- Graphics - added options for framebuffer width patch (Thanks blackb0x)
- Languages - Updated KO.lang (Thanks DDinghoya)
- Languages - Updated ZH_CN.lang (Thanks kavid)
- Documentation - Moved README-CFG.txt to README.md and converted to markdown format
03-09-2024 cfg 70r78.12 (release)
- Internals - changed online update URL paths
- GC - updated nintendont config support to version 0x0000000A
- Usability - Wiimmfi WFC patching fixed (Thanks leseratte)
15-01-2017 cfg 70r78.11 (release)
- GC - updated nintendont config support to version 0x00000006
- GC - if nintendont_config_mode=arg is set nintendont configuration is passed via command line argument

View File

@ -1,7 +1,7 @@
# Configurable USB Loader ZH-CN By 91wii.com
# Copyright (C) 2010 91wii.Com THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Kavid <kavid@sina.com>, 2010.
# CFG USB Loader language file template.
# Put the translated string in msgstr ""
# Fill in the Last-Translator and Language-Team fields.
# Please use utf-8 charset when editing.
#
#, fuzzy
msgid ""
@ -15,7 +15,18 @@ msgstr ""
"MIME-Version: 2.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: Simplified Chinese\n"
msgid " 59 blocks"
msgstr "59格"
msgid " 123 blocks"
msgstr "123格"
msgid " 251 blocks"
msgstr "251格"
msgid " 507 blocks"
msgstr "507格"
#, c-format
msgid "%.1fGB free of %.1fGB"
@ -74,6 +85,9 @@ msgstr ".dol文件太小"
msgid "1.2+"
msgstr "1.2以上版本"
msgid "1019 blocks"
msgstr "1019格"
msgid "1st-Person Shooter"
msgstr "第一人称射击"
@ -86,6 +100,9 @@ msgstr "2.1以上版本"
msgid "2.2+"
msgstr "2.2以上版本"
msgid "2043 blocks"
msgstr "2043格"
msgid "3D cover"
msgstr "3D封面"
@ -216,9 +233,15 @@ msgstr "平衡板游戏"
msgid "Boot Disc"
msgstr "启动光盘"
msgid "Boot Method:"
msgstr "引导方式:"
msgid "Boot disc"
msgstr "运行光盘"
msgid "Boot method:"
msgstr "引导方式:"
msgid "Booting game, please wait..."
msgstr "正在启动游戏,请稍等..."
@ -367,6 +390,9 @@ msgstr "板球"
msgid "Current Version: %s"
msgstr "当前版本:%s"
msgid "Custom"
msgstr "自定义"
#, c-format
msgid ""
"Custom IOS %d could not be found!\n"
@ -390,6 +416,9 @@ msgstr "cIOS %s加载成功"
msgid "DEVO"
msgstr "DEVO"
msgid "DIOS MIOS"
msgstr "DIOS MIOS"
msgid "DISC cover"
msgstr "光盘封面"
@ -411,6 +440,12 @@ msgstr "数据库更新成功。"
msgid "Debug"
msgstr "调试"
msgid "Default"
msgstr "缺省"
msgid "Default Gamecube Loader:"
msgstr "缺省GameCube启动器"
msgid "Delete Game"
msgstr "删除游戏"
@ -475,6 +510,10 @@ msgstr "下载游戏信息"
msgid "Downloadable Content"
msgstr "支持下载增值内容DLC"
#, c-format
msgid "Downloading %s plugin."
msgstr "正在下载 %s 插件。"
msgid "Downloading ALL MISSING covers"
msgstr "正在下载所有缺失的封面"
@ -501,12 +540,6 @@ msgstr "正在下载数据库"
msgid "Downloading devolution."
msgstr "正在下载devolution。"
msgid "Downloading mighty plugin."
msgstr "正在下载mighty插件。"
msgid "Downloading neek2o plugin."
msgstr "正在下载neek2o 插件。"
msgid "Downloading titles.txt ..."
msgstr "正在下载titles.txt文件..."
@ -836,6 +869,9 @@ msgstr "平面封面"
msgid "FULL cover"
msgstr "完整封面"
msgid "FWD Emulators"
msgstr "FWD模拟器"
msgid "Fav"
msgstr "收藏"
@ -900,9 +936,6 @@ msgstr "飞行模拟"
msgid "Football"
msgstr "足球"
msgid "Force Devolution:"
msgstr "强制Devolution:"
msgid "Force NTSC"
msgstr "强制NTSC"
@ -1142,6 +1175,12 @@ msgstr "读取中..."
msgid "Loading..%s\n"
msgstr "正在读取..%s\n"
msgid "MC size:"
msgstr "MC大小"
msgid "MC size::"
msgstr "MC大小"
msgid "Main"
msgstr "主菜单"
@ -1323,9 +1362,19 @@ msgstr "对应Nintendo DS"
msgid "Nintendo DS Connectivity"
msgstr "支持与Nintendo DS联动"
msgid "Nintendont"
msgstr "Nintendont"
#, c-format
msgid "Nintendont Ver. %d.%d\n"
msgstr "Nintendont 版本. %d.%d\n"
msgid "No"
msgstr "否"
msgid "No Speed Limit:"
msgstr "无速度限制:"
#, c-format
msgid "No domain part in URL '%s'"
msgstr "URL'%s'中没有域名部分"
@ -1345,6 +1394,9 @@ msgstr "未找到更新"
msgid "NoDisc:"
msgstr "免光盘:"
msgid "NoSSL only"
msgstr "仅用NoSSL"
msgid "None found on disc"
msgstr "光盘上未找到内容"
@ -1676,6 +1728,9 @@ msgstr "按%s键弹出DVD光盘"
msgid "Priiloader"
msgstr "Priiloader"
msgid "Private server:"
msgstr "私服:"
msgid "Profile:"
msgstr "配置:"
@ -1735,6 +1790,9 @@ msgstr "发售日期"
msgid "Release Notes: (short)"
msgstr "发布说明:(简介)"
msgid "Remove Speed Limit:"
msgstr "删除速度限制:"
msgid "Removing game, please wait..."
msgstr "正在删除游戏,请稍候..."
@ -1842,6 +1900,9 @@ msgstr "已选游戏"
msgid "Settings"
msgstr "设置"
msgid "Shared"
msgstr "已分享"
msgid "Shooter"
msgstr "射击游戏"
@ -2317,47 +2378,5 @@ msgstr "无法打开Wii光盘"
msgid "used: %p - %p"
msgstr "已使用: %p - %p"
#~ msgid " Copying files from USB to SD card...(%c)"
#~ msgstr "正在把文件从USB设备中复制到SD卡中...(%c)"
#~ msgid "Booting Wii game, please wait..."
#~ msgstr "正在启动Wii游戏请稍候......"
#~ msgid "Console Def."
#~ msgstr "主机定义。"
#~ msgid "DISK1:%s[%s]\n"
#~ msgstr "磁盘1%s[%s]\n"
#~ msgid "DISK2:%s[%s]2\n"
#~ msgstr "磁盘2%s[%s]2\n"
#~ msgid "Download titles.txt"
#~ msgstr "下载Titltes.txt文件"
#~ msgid "Front"
#~ msgstr "前"
#~ msgid "Loading previous game list..."
#~ msgstr "正在读取上次游戏列表..."
#~ msgid "Not Found boot.dol!!"
#~ msgstr "未找到Boot.dol"
#~ msgid "Remove Game"
#~ msgstr "删除游戏"
#~ msgid "Synopsis Len"
#~ msgstr "摘要长度"
#~ msgid "Update WiiTDB Game Database"
#~ msgstr "更新WiiTDB游戏数据库"
#~ msgid "Update titles.txt"
#~ msgstr "更新titles.txt"
#~ msgid "WiiTDB Game Database"
#~ msgstr "WiiTDB游戏数据库"
#~ msgid "Wiird"
#~ msgstr "Wii金手指"
msgid "wiimmfi.de"
msgstr "wiimmfi.de"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-15 00:36+0100\n"
"POT-Creation-Date: 2024-09-14 22:07+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -442,6 +442,12 @@ msgstr ""
msgid "Default Gamecube Loader:"
msgstr ""
msgid "Defaults"
msgstr ""
msgid "Deflicker Filter:"
msgstr ""
msgid "Delete Game"
msgstr ""
@ -466,6 +472,9 @@ msgstr ""
msgid "Devolution only accepts clean dumps!\n"
msgstr ""
msgid "Disable Dithering:"
msgstr ""
msgid "Disc"
msgstr ""
@ -917,6 +926,9 @@ msgstr ""
msgid "Fitness"
msgstr ""
msgid "Fix 480p:"
msgstr ""
msgid "Fixing EXTEND partition..."
msgstr ""
@ -951,6 +963,9 @@ msgstr ""
msgid "Found %s"
msgstr ""
msgid "Framebuffer width:"
msgstr ""
msgid "French"
msgstr ""
@ -1382,12 +1397,27 @@ msgstr ""
msgid "Nunchuk"
msgstr ""
msgid "OFF (Extended)"
msgstr ""
msgid "OFF (Safe)"
msgstr ""
msgid "OK"
msgstr ""
msgid "OK!"
msgstr ""
msgid "ON (High)"
msgstr ""
msgid "ON (Low)"
msgstr ""
msgid "ON (Medium)"
msgstr ""
msgid "Ocarina (cheats):"
msgstr ""

View File

@ -15,7 +15,7 @@ include $(DEVKITPPC)/wii_rules
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
VERSION := 70r78.12
VERSION := 70r78.13
RELEASE := release
# to override RELEASE use: make announce RELEASE=beta
ifeq ($(findstring compat,$(VERSION)),compat)
@ -63,8 +63,16 @@ BUILD_DEBUG := 0
ifeq ($(BUILD_DEBUG),1)
BUILD := build_dbg
TARGET := $(BINBASE)-dbg
BUILD_DBG_FLAG := -DBUILD_DBG=3
BUILD_DBG_FLAG := -DBUILD_DBG=3 -DDEBUG_PATCH=1
endif
BUILD_DEBUG_PATCH := 0
ifeq ($(BUILD_DEBUG_PATCH),1)
BUILD := build_dbg_patch
TARGET := $(BINBASE)-dbg-patch
BUILD_DBG_FLAG := -DDEBUG_PATCH=1
endif
#"-g" tells the compiler to include support for the debugger
#"-Wall" tells it to warn us about all suspicious-looking code
DEBUG_OPT = -Os
@ -79,7 +87,8 @@ CXXFLAGS = $(CFLAGS)
# cfg 33-36: 0x80c00000
# cfg 37-49: 0x80b00000
# cfg 50-..: 0x80a80000
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80a80000
# cfg 70r78.13-..: 0x80a50000
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80a50000
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
@ -168,6 +177,9 @@ $(BUILD):
debug:
@$(MAKE) --no-print-directory BUILD_DEBUG=1
debug_patch:
@$(MAKE) --no-print-directory BUILD_DEBUG_PATCH=1
#---------------------------------------------------------------------------------
lang:
@[ -d Languages ] || mkdir -p Languages
@ -188,6 +200,7 @@ clean:
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol
@rm -fr $(BUILD)_222 $(OUTPUT)-222.elf $(OUTPUT)-222.dol
@rm -fr $(BUILD)_dbg $(OUTPUT)-dbg.elf $(OUTPUT)-dbg.dol
@rm -fr $(BUILD)_dbg_patch $(OUTPUT)-dbg-patch.elf $(OUTPUT)-dbg-patch.dol
cleanall: clean
@rm -fr *.dol *.elf

View File

@ -1100,6 +1100,24 @@ Example:
# 2 = wiimmfi.de
# 3 = Custom string from "custom_private_server"
#
# fix_480p = [0], 1
# enable/disable 480p Nintendo Revolution SDK bug fix patch
#
# deflicker = [0], 1, 2, 3, 4, 5
# override deflicker filter settings:
# 0 = Defaults as hardcoded in the game
# 1 = Turns off deflickering setting the vfilter to Off
# 2 = Turns off deflickering setting the vfilter and patchig GXSetCopyFilter function
# 3 = Turns on deflickering setting vfilter to Low
# 4 = Turns on deflickering setting vfilter to Medium
# 5 = Turns on deflickering setting vfilter to High
#
# dithering = [0], 1
# enable/disable dithering removal patch
#
# fix_fb = [0], 1
# enable/disable framebuffer width patch
#
# Profile Options:
# ================
#

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

@ -17,6 +17,7 @@
#include "gettext.h"
#include "menu.h"
#include "dolmenu.h"
#include "deflicker.h"
/* Apploader function pointers */
typedef int (*app_main)(void **dst, int *size, int *offset);
@ -291,8 +292,7 @@ s32 Apploader_Run(entry_point *entry)
TIME.size += appldr_len;
// used mem range by the loader
//void *mem_start = (void*)0x80b00000; // as set in Makefile
void *mem_start = (void*)0x80a80000; // as set in Makefile
void *mem_start = (void*)0x80a50000; // as set in Makefile
void *mem_end = memalign(32,32);
//printf("malloc = %p sta = %p\n", mem, &ret);
@ -753,6 +753,54 @@ void maindolpatches(void *dst, int len)
if (!CFG.disable_pop_patch) {
PrinceOfPersiaPatch();
}
// Deflicker filter patch
if (CFG.game.deflicker == DEFLICKER_ON_LOW)
{
patch_vfilters(dst, len, vfilter_low);
patch_vfilters_rogue(dst, len, vfilter_low);
}
else if (CFG.game.deflicker == DEFLICKER_ON_MEDIUM)
{
patch_vfilters(dst, len, vfilter_medium);
patch_vfilters_rogue(dst, len, vfilter_medium);
}
else if (CFG.game.deflicker == DEFLICKER_ON_HIGH)
{
patch_vfilters(dst, len, vfilter_high);
patch_vfilters_rogue(dst, len, vfilter_high);
}
else if (CFG.game.deflicker != DEFLICKER_DEFAULT)
{
patch_vfilters(dst, len, vfilter_off);
patch_vfilters_rogue(dst, len, vfilter_off);
// This might break fade and brightness effects
if (CFG.game.deflicker == DEFLICKER_OFF_EXTENDED)
deflicker_patch(dst, len);
}
// 480p Pixel Fix
if (CFG.game.fix_480p) {
PatchFix480p();
}
// Dithering patch
if (CFG.game.dithering) {
dithering_patch(dst, len);
}
// Framebuffer width patch
if (CFG.game.fix_fb) {
framebuffer_patch(dst, len);
}
#ifdef DEBUG_PATCH
// wait to read debug output
printf_(gt("Press any button..."));
printf("\n");
Wpad_WaitButtons();
#endif
// Nintendo Wi-Fi Connection (WFC) patch
if (CFG.game.private_server) {
NoSSLPatch(dst, len);

View File

@ -484,6 +484,17 @@ struct TextMap map_private_server[] =
{ NULL, -1 }
};
struct TextMap map_deflicker[] =
{
{ "Defaults", 0 },
{ "OFF (Safe)", 1 },
{ "OFF (Extended)", 2 },
{ "ON (Low)", 3 },
{ "ON (Medium)", 4 },
{ "ON (High)", 5 },
{ NULL, -1 }
};
struct playStat {
char id[7];
s32 playCount;
@ -1423,6 +1434,10 @@ void CFG_Default()
CFG.game.alt_controller_cfg = 0;
CFG.game.rem_speed_limit = 0;
CFG.game.private_server = 0; //off
CFG.game.deflicker = 0; //default game settings
CFG.game.fix_480p = 0; //off
CFG.game.dithering = 0; //default game settings
CFG.game.fix_fb = 0; //default game settings
cfg_ios_set_idx(DEFAULT_IOS_IDX);
// all other game settings are 0 (memset(0) above)
STRCOPY(CFG.sort_ignore, "A,An,The");
@ -2508,6 +2523,10 @@ void cfg_set_game(char *name, char *val, struct Game_CFG *game_cfg)
cfg_map_auto("hooktype", map_hook, &game_cfg->hooktype);
cfg_int_max("write_playlog", &game_cfg->write_playlog, 3);
cfg_int_max("private_server", &game_cfg->private_server, 3);
cfg_int_max("deflicker", &game_cfg->deflicker, 5);
cfg_bool("fix_480p", &game_cfg->fix_480p);
cfg_bool("dithering", &game_cfg->dithering);
cfg_bool("fix_fb", &game_cfg->fix_fb);
}
@ -3286,6 +3305,10 @@ bool CFG_Save_Settings(int verbose)
SAVE_BOOL(alt_controller_cfg);
SAVE_BOOL(rem_speed_limit);
SAVE_NUM(private_server);
SAVE_NUM(deflicker);
SAVE_BOOL(fix_480p);
SAVE_BOOL(dithering);
SAVE_BOOL(fix_fb);
if (game_cfg->clean == CFG_CLEAN_OFF) {
SAVE_STR("clear_patches", "0");
} else if (game_cfg->clean == CFG_CLEAN_ON) {

View File

@ -269,6 +269,10 @@ struct Game_CFG
int alt_controller_cfg;
int rem_speed_limit;
int private_server;
int deflicker;
int fix_480p;
int dithering;
int fix_fb;
};
struct Game_CFG_2
@ -750,6 +754,7 @@ extern struct TextMap map_channel_boot[];
extern struct TextMap map_gc_boot[];
extern struct TextMap map_mem_card_size[];
extern struct TextMap map_private_server[];
extern struct TextMap map_deflicker[];
extern char *names_vpatch[CFG_VIDEO_PATCH_NUM];
extern u8 cIOS_base[];

184
source/deflicker.c Normal file
View File

@ -0,0 +1,184 @@
/*
* Deflicker filter patching by wiidev (blackb0x @ GBAtemp)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gccore.h>
#include <sys/unistd.h>
#ifdef DEBUG_PATCH
#define debug_printf(fmt, args...) \
printf(fmt, ##args)
#else
#define debug_printf(fmt, args...)
#endif
static u8 PATTERN[12][2] = {
{6, 6}, {6, 6}, {6, 6},
{6, 6}, {6, 6}, {6, 6},
{6, 6}, {6, 6}, {6, 6},
{6, 6}, {6, 6}, {6, 6}
};
static u8 PATTERN_AA[12][2] = {
{3, 2}, {9, 6}, {3, 10},
{3, 2}, {9, 6}, {3, 10},
{9, 2}, {3, 6}, {9, 10},
{9, 2}, {3, 6}, {9, 10}
};
// Patch known and unknown vfilters within GXRModeObj structures
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter)
{
u8 *addr_start = addr;
while (len >= sizeof(GXRModeObj))
{
GXRModeObj *vidmode = (GXRModeObj *)addr_start;
if ((memcmp(vidmode->sample_pattern, PATTERN, 24) == 0 || memcmp(vidmode->sample_pattern, PATTERN_AA, 24) == 0) &&
(vidmode->fbWidth == 640 || vidmode->fbWidth == 608 || vidmode->fbWidth == 512) &&
(vidmode->field_rendering == 0 || vidmode->field_rendering == 1) &&
(vidmode->aa == 0 || vidmode->aa == 1))
{
debug_printf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p (GXRModeObj)\n",
vidmode->vfilter[0], vidmode->vfilter[1], vidmode->vfilter[2], vidmode->vfilter[3],
vidmode->vfilter[4], vidmode->vfilter[5], vidmode->vfilter[6], addr_start);
memcpy(vidmode->vfilter, vfilter, 7);
addr_start += (sizeof(GXRModeObj) - 4);
len -= (sizeof(GXRModeObj) - 4);
}
addr_start += 4;
len -= 4;
}
}
// Patch rogue vfilters found in some games
void patch_vfilters_rogue(u8 *addr, u32 len, u8 *vfilter)
{
u8 known_vfilters[7][7] = {
{8, 8, 10, 12, 10, 8, 8}, // Ntsc480ProgSoft
{4, 8, 12, 16, 12, 8, 4}, // Ntsc480ProgAa
{7, 7, 12, 12, 12, 7, 7}, // Mario Kart Wii
{5, 5, 15, 14, 15, 5, 5}, // Mario Kart Wii
{4, 4, 15, 18, 15, 4, 4}, // Sonic Colors
{4, 4, 16, 16, 16, 4, 4}, // DKC Returns
{2, 2, 17, 22, 17, 2, 2}
};
u8 *addr_start = addr;
u8 *addr_end = addr + len - 8;
while (addr_start <= addr_end)
{
u8 known_vfilter[7];
int i;
for (i = 0; i < 7; i++)
{
int x;
for (x = 0; x < 7; x++)
known_vfilter[x] = known_vfilters[i][x];
if (!addr_start[7] && memcmp(addr_start, known_vfilter, 7) == 0)
{
debug_printf("Replaced vfilter %02x%02x%02x%02x%02x%02x%02x @ %p\n", addr_start[0], addr_start[1],
addr_start[2], addr_start[3], addr_start[4], addr_start[5], addr_start[6], addr_start);
memcpy(addr_start, vfilter, 7);
addr_start += 7;
break;
}
}
addr_start += 1;
}
}
// Patch GXSetCopyFilter to disable the deflicker filter
void deflicker_patch(u8 *addr, u32 len)
{
u32 SearchPattern[18] = {
0x3D20CC01, 0x39400061, 0x99498000,
0x2C050000, 0x38800053, 0x39600000,
0x90098000, 0x38000054, 0x39800000,
0x508BC00E, 0x99498000, 0x500CC00E,
0x90698000, 0x99498000, 0x90E98000,
0x99498000, 0x91098000, 0x41820040};
u8 *addr_start = addr;
u8 *addr_end = addr + len - sizeof(SearchPattern);
while (addr_start <= addr_end)
{
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
{
*((u32 *)addr_start + 17) = 0x48000040; // Change beq to b
debug_printf("Patched GXSetCopyFilter @ %p\n", addr_start);
return;
}
addr_start += 4;
}
}
// Patch Dithering
void dithering_patch(u8 *addr, u32 len)
{
u32 SearchPattern[10] = {
0x3C80CC01, 0x38A00061, 0x38000000,
0x80C70220, 0x5066177A, 0x98A48000,
0x90C48000, 0x90C70220, 0xB0070002,
0x4E800020};
u8 *addr_start = addr;
u8 *addr_end = addr + len - sizeof(SearchPattern);
while (addr_start <= addr_end)
{
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
{
*((u32 *)addr_start - 1) = 0x48000028;
debug_printf("Patched Dithering @ %p\n", addr_start - 1);
return;
}
addr_start += 4;
}
}
// Patch Framebuffer Width
void framebuffer_patch(void *addr, u32 len)
{
u8 SearchPattern[32] = {
0x40, 0x82, 0x00, 0x08, 0x48, 0x00, 0x00, 0x1C,
0x28, 0x09, 0x00, 0x03, 0x40, 0x82, 0x00, 0x08,
0x48, 0x00, 0x00, 0x10, 0x2C, 0x03, 0x00, 0x00,
0x40, 0x82, 0x00, 0x08, 0x54, 0xA5, 0x0C, 0x3C};
u8 *addr_start = (u8 *)addr;
u8 *addr_end = addr_start + len - sizeof(SearchPattern);
while (addr_start <= addr_end)
{
if (memcmp(addr_start, SearchPattern, sizeof(SearchPattern)) == 0)
{
if (addr_start[-0x70] == 0xA0 && addr_start[-0x6E] == 0x00 && addr_start[-0x6D] == 0x0A)
{
if (addr_start[-0x44] == 0xA0 && addr_start[-0x42] == 0x00 && addr_start[-0x41] == 0x0E)
{
u8 reg_a = (addr_start[-0x6F] >> 5);
u8 reg_b = (addr_start[-0x43] >> 5);
// Patch to the framebuffer resolution
addr_start[-0x41] = 0x04;
// Center the image
void *offset = addr_start - 0x70;
u32 old_heap_ptr = *(u32 *)0x80003110;
*(u32 *)0x80003110 = old_heap_ptr - 0x40;
u32 heap_space = old_heap_ptr - 0x40;
u32 org_address = (addr_start[-0x70] << 24) | (addr_start[-0x6F] << 16);
*(u32 *)(heap_space + 0x00) = org_address | 4;
*(u32 *)(heap_space + 0x04) = 0x200002D0 | (reg_b << 21) | (reg_a << 16);
*(u32 *)(heap_space + 0x08) = 0x38000002 | (reg_a << 21);
*(u32 *)(heap_space + 0x0C) = 0x7C000396 | (reg_a << 21) | (reg_b << 16) | (reg_a << 11);
*(u32 *)offset = 0x48000000 + ((heap_space - (u32)offset) & 0x3ffffff);
*(u32 *)(heap_space + 0x10) = 0x48000000 + ((((u32)offset + 0x04) - (heap_space + 0x10)) & 0x3ffffff);
debug_printf("Patched resolution. Branched from 0x%x to 0x%x\n", (u32) offset, (u32) heap_space);
return;
}
}
}
addr_start += 4;
}
}

24
source/deflicker.h Normal file
View File

@ -0,0 +1,24 @@
/*
* Deflicker filter patching by wiidev (blackb0x @ GBAtemp)
*/
enum
{
DEFLICKER_DEFAULT,
DEFLICKER_OFF,
DEFLICKER_OFF_EXTENDED,
DEFLICKER_ON_LOW,
DEFLICKER_ON_MEDIUM,
DEFLICKER_ON_HIGH
};
u8 vfilter_off[7] = {0, 0, 21, 22, 21, 0, 0};
u8 vfilter_low[7] = {4, 4, 16, 16, 16, 4, 4};
u8 vfilter_medium[7] = {4, 8, 12, 16, 12, 8, 4};
u8 vfilter_high[7] = {8, 8, 10, 12, 10, 8, 8};
void patch_vfilters(u8 *addr, u32 len, u8 *vfilter);
void patch_vfilters_rogue(u8 *addr, u32 len, u8 *vfilter);
void deflicker_patch(u8 *addr, u32 len);
void dithering_patch(u8 *addr, u32 len);
void framebuffer_patch(void *addr, u32 len);

View File

@ -478,6 +478,10 @@ struct W_GameCfg
Widget *alt_controller_cfg;
Widget *rem_speed_limit;
Widget *private_server;
Widget *deflicker;
Widget *fix_480p;
Widget *dithering;
Widget *fix_fb;
} wgame;
@ -1160,6 +1164,10 @@ void InitGameOptionsPage(Widget *pp, int bh)
char *names_private_server[num_private_server];
num_private_server = map_to_list(map_private_server, num_private_server, names_private_server);
int num_deflicker = map_get_num(map_deflicker);
char *names_deflicker[num_deflicker];
num_deflicker = map_to_list(map_deflicker, num_deflicker, names_deflicker);
ww = wgui_add_game_opt(op, gt("Language:"), CFG_LANG_NUM, languages);
BIND_OPT(language);
@ -1219,6 +1227,18 @@ void InitGameOptionsPage(Widget *pp, int bh)
ww = wgui_add_game_opt(op, gt("Private server:"), num_private_server, names_private_server);
BIND_OPT(private_server);
ww = wgui_add_game_opt(op, gt("Fix 480p:"), 2, NULL);
BIND_OPT(fix_480p);
ww = wgui_add_game_opt(op, gt("Deflicker Filter:"), num_deflicker, names_deflicker);
BIND_OPT(deflicker);
ww = wgui_add_game_opt(op, gt("Disable Dithering:"), 2, NULL);
BIND_OPT(dithering);
ww = wgui_add_game_opt(op, gt("Framebuffer width:"), 2, NULL);
BIND_OPT(fix_fb);
pos_move_to(pp, PAD0, -bh);
pos_pad(pp, PAD0);
pos_columns(pp, 4, SIZE_FULL);

View File

@ -212,6 +212,16 @@ char *str_private_server[4] =
gts("Custom")
};
char *str_deflicker[6] =
{
gts("Defaults"),
gts("OFF (Safe)"),
gts("OFF (Extended)"),
gts("ON (Low)"),
gts("ON (Medium)"),
gts("ON (High)")
};
int Menu_Global_Options();
int Menu_Game_Options();
void Switch_Favorites(bool enable);
@ -1836,7 +1846,7 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
int opt_saved;
//int opt_ios_reload;
int opt_language, opt_video, opt_video_patch, opt_vidtv, opt_padhook, opt_nand_emu;
int opt_mem_card_emu, opt_mem_card_size, opt_country_patch, opt_anti_002, opt_ocarina, opt_wide_screen, opt_nodisc, opt_ntsc_j_patch, opt_screenshot, opt_private_server;
int opt_mem_card_emu, opt_mem_card_size, opt_country_patch, opt_anti_002, opt_ocarina, opt_wide_screen, opt_nodisc, opt_ntsc_j_patch, opt_screenshot, opt_private_server, opt_deflicker, opt_fix_480p, opt_dithering, opt_fix_fb;
f32 size = 0.0;
int redraw_cover = 0;
int i;
@ -1882,7 +1892,7 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
game_cfg = &game_cfg2->curr;
struct Menu menu;
int NUM_OPT = 20;
int NUM_OPT = 24;
if (header->magic == GC_GAME_ON_DRIVE) NUM_OPT = 18;
if (header->magic == CHANNEL_MAGIC) NUM_OPT = 19;
char active[NUM_OPT];
@ -1927,6 +1937,10 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
opt_ntsc_j_patch = game_cfg->ntsc_j_patch;
opt_nand_emu = game_cfg->nand_emu;
opt_private_server = game_cfg->private_server;
opt_deflicker = game_cfg->deflicker;
opt_fix_480p = game_cfg->fix_480p;
opt_dithering = game_cfg->dithering;
opt_fix_fb = game_cfg->fix_fb;
if (game_cfg->clean == CFG_CLEAN_ALL) {
opt_language = CFG_LANG_CONSOLE;
@ -1943,6 +1957,10 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
opt_nodisc = 0;
opt_screenshot = 0;
opt_private_server = 0;
opt_deflicker = 0;
opt_fix_480p = 0;
opt_dithering = 0;
opt_fix_fb = 0;
active[1] = 0; // language
active[2] = 0; // video
active[3] = 0; // video_patch
@ -2174,6 +2192,14 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
PRINT_OPT_A(gt("Savegame:"), gt("Dump savegame"));
if (menu_window_mark(&menu))
PRINT_OPT_A(gt("Private server:"), gt(str_private_server[opt_private_server]));
if (menu_window_mark(&menu))
PRINT_OPT_B(gt("Fix 480p:"), opt_fix_480p);
if (menu_window_mark(&menu))
PRINT_OPT_A(gt("Deflicker Filter:"), gt(str_deflicker[opt_deflicker]));
if (menu_window_mark(&menu))
PRINT_OPT_B(gt("Disable Dithering:"), opt_dithering);
if (menu_window_mark(&menu))
PRINT_OPT_B(gt("Framebuffer width:"), opt_fix_fb);
}
DefaultColor();
@ -2445,6 +2471,18 @@ int Menu_Boot_Options(struct discHdr *header, bool disc) {
case 19:
CHANGE(game_cfg->private_server, 3);
break;
case 20:
CHANGE(game_cfg->fix_480p, 1);
break;
case 21:
CHANGE(game_cfg->deflicker, 5);
break;
case 22:
CHANGE(game_cfg->dithering, 1);
break;
case 23:
CHANGE(game_cfg->fix_fb, 1);
break;
}
}
if (buttons & CFG.button_confirm.mask) {

View File

@ -12,7 +12,12 @@
//#include "fwrite_patch.h"
//#include "fwrite_patch_slota.h"
//#include "main.h"
#ifdef DEBUG_PATCH
#define debug_printf(fmt, args...) \
printf(fmt, ##args)
#else
#define debug_printf(fmt, args...)
#endif
bool hookpatched = false;
@ -1077,3 +1082,102 @@ u32 do_new_wiimmfi() {
// returns 0 when all patching is done and game is ready to be booted.
return 0;
}
/*
* 480p Pixel Fix Patch by leseratte
*
* fix for a Nintendo Revolution SDK bug found by Extrems affecting early Wii console when using 480p video mode.
* https://shmups.system11.org/viewtopic.php?p=1361158#p1361158
* https://github.com/ExtremsCorner/libogc-rice/commit/941d687e271fada68c359bbed98bed1fbb454448
*
*/
void PatchFix480p()
{
u8 prefix[2] = { 0x4b, 0xff };
/// Patch offset: ----------VVVVVVVV
u32 Pattern_MKW[8] = { 0x38000065, 0x9b810019, 0x38810018, 0x386000e0, 0x98010018, 0x38a00002};
u32 patches_MKW[2] = { 0x38600003, 0x98610019 };
/// Used by: MKWii, Wii Play, Need for Speed Nitro, Wii Sports, ...
/// Patch offset: ----------------------------------------------VVVVVVVV
u32 Pattern_NSMB[8] = { 0x38000065, 0x9801001c, 0x3881001c, 0x386000e0, 0x9b81001d, 0x38a00002};
u32 patches_NSMB[2] = { 0x38a00003, 0x98a1001d };
/// Used by: New Super Mario Bros, ...
/*
* Code block that is being patched (in MKW):
*
* 4bffe30d: bl WaitMicroTime
* 38000065: li r0, 0x65
* 9b810019: stb r28, 25(r1) // store the wrong value (1)
* 38810018: addi r4, r1, 0x18
* 386000e0: li r3, 0xe0
* 98010018: stb r0, 24(r1)
* 38a00002: li r5, 2
* 4bffe73d: bl __VISendI2CData
*
* r28 is a register that is set to 1 at the beginning of the function.
* However, its contents are used elsewhere as well, so we can't just modify this one function.
*
* The following code first searches for one of the patterns above, then replaces the
* "stb r28, 25(r1)" instruction that stores the wrong value on the stack with a branch instead
* That branch branches to the injected custom code ("li r3, 3; stb r3, 25(r1)") that stores the
* correct value (3) instead. At the end of the injected code will be another branch that branches
* back to the instruction after the one that has been replaced (so, to "addi r4, r1, 0x18").
* r3 can safely be used as a temporary register because its contents will be replaced immediately
* afterwards anyways.
*
*/
void * offset = NULL;
void * addr = (void*)0x80000000;
u32 len = 0x900000;
void * patch_ptr = 0 ;
void * a = addr;
while ((char*)a < ((char*)addr + len)) {
if (memcmp(a, &Pattern_MKW, 6 * 4) == 0) {
// Found pattern?
if (memcmp(a - 4, &prefix, 2) == 0) {
if (memcmp(a + 8*4, &prefix, 2) == 0) {
offset = a + 4;
patch_ptr = &patches_MKW;
break;
}
}
}
else if (memcmp(a, &Pattern_NSMB, 6 * 4) == 0) {
// Found pattern?
if (memcmp(a - 4, &prefix, 2) == 0) {
if (memcmp(a + 8*4, &prefix, 2) == 0) {
offset = a + 16;
patch_ptr = &patches_NSMB;
break;
}
}
}
a+= 4;
}
if (offset == 0) {
// offset is still 0, we didn't find the pattern, return
debug_printf("Didn't find offset for 480p patch!\n");
return;
}
// If we are here, we found the offset. Lets grab some space
// from the heap for our patch
u32 old_heap_ptr = *(u32*)0x80003110;
*((u32*)0x80003110) = (old_heap_ptr - 0x20);
u32 heap_space = old_heap_ptr-0x20;
debug_printf("Found offset for 480p patch - create branch from 0x%x to heap (0x%x)\n", (u32) offset, (u32) heap_space);
memcpy((void*)heap_space, patch_ptr, 8);
*((u32*)offset) = 0x48000000 + (((u32)(heap_space) - ((u32)(offset))) & 0x3ffffff);
*((u32*)((u32)heap_space + 8)) = 0x48000000 + (((u32)((u32)offset + 4) - ((u32)(heap_space + 8))) & 0x3ffffff);
return;
}

View File

@ -22,6 +22,9 @@
#ifndef __PATCHCODE_H__
#define __PATCHCODE_H__
#define STR(X) #X
#define QUOTE(X) STR(X)
// Globals
extern u32 hooktype;
extern int patched;
@ -30,7 +33,7 @@ extern u32 regionfree;
extern bool hookpatched;
#define APP_NAME "Cfg USB Loader MOD patched"
#define APP_VERSION "70r78.12"
#define APP_VERSION QUOTE(VERSION)
#define PRIVSERV_WIIMMFI "wiimmfi.de"
// Function prototypes
@ -42,6 +45,6 @@ bool PatchReturnTo(void *Address, int Size, u32 id);
void WFCPatch(void *addr, u32 len, const char* domain);
u32 do_new_wiimmfi();
u32 do_new_wiimmfi_nonMKWii();
void PatchFix480p();
#endif // __PATCHCODE_H__

View File

@ -14,6 +14,19 @@ metaxml=</long_description>
metaxml=<ahb_access/>
metaxml=</app>
release = 70r78.13
size = 2018688
date = 2024-09-15
url = http://cfgusbloader.ntd.homelinux.org/binaries/dol/r12/cfg70r78.13-222.dol
-Internals - changed memory start addres to avoid overlaps
-Graphics - added options for 480p Nintendo Revolution SDK bug fix patch
-Graphics - added options for deflickering settings
-Graphics - added options for disabling dithering
-Graphics - added options for framebuffer width patch
-Languages - Updated KO.lang
-Languages - Updated ZH_CN.lang
-Documentation - Moved to README.md
release = 70r78.12
size = 1908544
date = 2024-09-03

View File

@ -14,6 +14,19 @@ metaxml=</long_description>
metaxml=<ahb_access/>
metaxml=</app>
release = 70r78.13
size = 2018688
date = 2024-09-15
url = http://cfgusbloader.ntd.homelinux.org/binaries/dol/r13/cfg70r78.13.dol
-Internals - changed memory start addres to avoid overlaps
-Graphics - added options for 480p Nintendo Revolution SDK bug fix patch
-Graphics - added options for deflickering settings
-Graphics - added options for disabling dithering
-Graphics - added options for framebuffer width patch
-Languages - Updated KO.lang
-Languages - Updated ZH_CN.lang
-Documentation - Moved to README.md
release = 70r78.12
size = 1908512
date = 2024-09-03