色五月色开心色婷婷色丁香,五月婷婷丁香花综合网,婷婷丁香五月激情综合在线,五月婷婷六月丁香动漫,婷婷丁香五月激情综合在线,丁香花中文字幕在线观看,播五月色五月开心五月网,开心激情综合网,狠狠色丁香婷婷综合最新地址,丁香视频在线观看,狠狠做六月爱婷婷综合av,久久激情五月丁香伊人

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營(yíng)的一線實(shí)戰(zhàn)洞察。

基于C++與GTK3的IPS補(bǔ)丁工具實(shí)現(xiàn):解析、應(yīng)用與避坑指南

基于C++與GTK3的IPS補(bǔ)丁工具實(shí)現(xiàn):解析、應(yīng)用與避坑指南 簡(jiǎn)介基于 GTK3 的 ips-patcher 是一款用 C 寫(xiě)成的 IPS 補(bǔ)丁程序包含命令行模式與圖形界面模式面向需要給 ROM 或二進(jìn)制數(shù)據(jù)打 IPS 補(bǔ)丁的玩家、開(kāi)發(fā)者以及想學(xué)習(xí) GTK 編程的初學(xué)者。包內(nèi)共 15 個(gè)文件其中 6 個(gè) cpp 源文件與 4 個(gè) h 頭文件構(gòu)成核心代碼另有構(gòu)建腳本負(fù)責(zé)編譯、界面描述文件定義 UI 布局、內(nèi)聯(lián)實(shí)現(xiàn)文件補(bǔ)充邏輯以及許可證和說(shuō)明文檔壓縮包整體大小僅 21KB代碼量精簡(jiǎn)。該工具支持 Release 與 Debug 兩種編譯模式命令行版按“源文件 補(bǔ)丁 目標(biāo)文件”的參數(shù)順序工作圖形版則完整演示了 GTK3 控件在文件選擇與進(jìn)度展示上的用法。目前已有 255 人學(xué)習(xí)。通過(guò)研讀源碼可以同時(shí)掌握 IPS 文件格式解析、二進(jìn)制補(bǔ)丁算法、命令行參數(shù)處理以及如何組織一個(gè)帶界面的小型 C 項(xiàng)目對(duì)理解文件修補(bǔ)工具的內(nèi)部機(jī)制頗有幫助。1. 從一次補(bǔ)丁序列錯(cuò)亂說(shuō)起為什么需要一個(gè)看得見(jiàn)過(guò)程的IPS工具如果你玩過(guò)模擬器游戲大概率碰過(guò)這一幕下好了ROM又找到幾個(gè)號(hào)稱能修復(fù)bug、替換漢化文本的IPS補(bǔ)丁然后打開(kāi)命令行工具手敲參數(shù)一個(gè)文件一個(gè)文件地往下推。某個(gè)黃昏我連打了三個(gè)補(bǔ)丁進(jìn)游戲發(fā)現(xiàn)角色臺(tái)詞全變成了亂碼開(kāi)頭動(dòng)畫(huà)卡死。逐條排查才發(fā)現(xiàn)我在順序上混用了一次反向補(bǔ)丁把已經(jīng)寫(xiě)進(jìn)ROM的字節(jié)又原樣覆蓋了一遍。問(wèn)題不在ROM也不在命令本身而在于過(guò)程完全是個(gè)黑匣子我不知道追加上去的補(bǔ)丁到底改了哪些偏移量也不知道哪一個(gè)文件才是罪魁禍?zhǔn)?。后?lái)?yè)Q了本項(xiàng)目的主角ips-patcher——一個(gè)基于GTK的圖形化IPS補(bǔ)丁程序所有補(bǔ)丁記錄、偏移、變更前后差異都在界面上直接攤開(kāi)這才把調(diào)試成本降了下來(lái)。它適合三類人經(jīng)常用IPS補(bǔ)丁折騰ROM的玩家想把補(bǔ)丁過(guò)程寫(xiě)進(jìn)工具鏈的模擬器開(kāi)發(fā)者以及想拿一個(gè)完整GTK桌面應(yīng)用當(dāng)范例的C初學(xué)者。這篇文章會(huì)把技術(shù)棧、目錄結(jié)構(gòu)、核心補(bǔ)丁鏈路和改造方法一次講完。2. 項(xiàng)目骨架與技術(shù)選型C與GTK3的模塊邊界2.1 技術(shù)棧選型C標(biāo)準(zhǔn)庫(kù)打底GTK3做交互外殼項(xiàng)目用C17標(biāo)準(zhǔn)庫(kù)處理字節(jié)流和文件IO界面層直接對(duì)接GTK3的C API而不是引入gtkmm這一層C包裝。這個(gè)取舍一開(kāi)始看著像偷懶實(shí)際上是有意的GTK的C API穩(wěn)定且文檔量大而補(bǔ)丁引擎本身只需要vector、ifstream、string這三個(gè)標(biāo)準(zhǔn)庫(kù)組件完全沒(méi)必要為了一個(gè)按鈕事件把整個(gè)gtkmm的對(duì)象模型拉進(jìn)來(lái)。代碼里唯一用到的第三方構(gòu)建依賴是GTK3的開(kāi)發(fā)包在Debian系系統(tǒng)上對(duì)應(yīng)libgtk-3-dev在Fedora系上對(duì)應(yīng)gtk3-devel其余全部由編譯器和標(biāo)準(zhǔn)庫(kù)提供。選擇GTK3而不是GTK4或Qt原因也很實(shí)際。GTK3在桌面Linux發(fā)行版中還處于主流生命周期的尾部大多數(shù)仍在維護(hù)的模擬器工具和ROM管理軟件還在用它參考資料多、踩坑答案全。GTK4的構(gòu)造器機(jī)制和CSS節(jié)點(diǎn)模型變化較大對(duì)這個(gè)體量的項(xiàng)目收益不明顯??缙脚_(tái)方面GTK3在Windows上通過(guò)MSYS2可以流暢運(yùn)行在macOS上配合homebrew也能跑恰好覆蓋了ROM玩家最常見(jiàn)的三類操作系統(tǒng)。整個(gè)工程的模塊邊界只有兩條補(bǔ)丁引擎不依賴任何GTK頭文件界面層不直接讀寫(xiě)補(bǔ)丁數(shù)據(jù)。前者保證了引擎可以用純命令行測(cè)試程序單獨(dú)驗(yàn)證后者讓界面回調(diào)里不需要關(guān)心IPS格式的字節(jié)細(xì)節(jié)。這兩條邊界在代碼審查時(shí)是重點(diǎn)檢查對(duì)象一旦出現(xiàn)界面層include引擎頭文件以外的GUI類型就說(shuō)明邊界破了。2.2 目錄結(jié)構(gòu)引擎、界面與資源文件的職責(zé)劃分典型的工程布局如下每個(gè)文件只干一件事ips-patcher/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp # GTK入口初始化、加載Glade文件、啟動(dòng)主循環(huán) │ ├── patch_engine.hpp # PatchEngine類聲明純邏輯不碰GUI │ ├── patch_engine.cpp # IPS解析、應(yīng)用、生成的核心實(shí)現(xiàn) │ ├── main_window.cpp # 窗口構(gòu)造、按鈕布局、各控件引用綁定 │ ├── callback_helpers.cpp # 將GTK事件轉(zhuǎn)換為類方法調(diào)用的適配層 │ └── resource.h # Glade資源ID常量防止字符串魔法值散落 ├── ui/ │ └── main_window.glade # XML界面布局按鈕、文件選擇器、日志視圖 ├── tests/ │ ├── test_patch_engine.cpp # 引擎級(jí)單元測(cè)試不啟動(dòng)GUI │ └── fixtures/ # 預(yù)生成的測(cè)試用IPS補(bǔ)丁和ROM └── README.mdengine和window分離后最明顯的收益是測(cè)試不需要顯示設(shè)備。CI環(huán)境里跑單元測(cè)試只需要構(gòu)建patch_engine.cpp和test_patch_engine.cpp兩個(gè)文件不需要X server不需要Wayland連GTK庫(kù)都可以不鏈接。下面這段CMake配置充分體現(xiàn)了這一點(diǎn)引擎目標(biāo)與GUI目標(biāo)分開(kāi)構(gòu)建測(cè)試目標(biāo)只依賴引擎目標(biāo)。cmake_minimum_required(VERSION 3.16) project(ips-patcher CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 REQUIRED gtk-3.0) # 引擎只依賴標(biāo)準(zhǔn)庫(kù) add_library(patch_engine STATIC src/patch_engine.cpp ) target_include_directories(patch_engine PUBLIC src) # GUI目標(biāo)依賴引擎和GTK add_executable(ips-patcher src/main.cpp src/main_window.cpp src/callback_helpers.cpp ) target_link_libraries(ips-patcher PRIVATE patch_engine ${GTK3_LIBRARIES}) target_include_directories(ips-patcher PRIVATE ${GTK3_INCLUDE_DIRS}) target_compile_options(ips-patcher PRIVATE ${GTK3_CFLAGS_OTHER}) # 測(cè)試目標(biāo)不鏈GTK純命令行運(yùn)行 enable_testing() add_executable(test_engine tests/test_patch_engine.cpp) target_link_libraries(test_engine PRIVATE patch_engine) add_test(NAME test_engine COMMAND test_engine)2.3 參數(shù)解析和輸入校驗(yàn)的約定程序啟動(dòng)后收到的第一個(gè)參數(shù)是待修補(bǔ)的ROM路徑第二個(gè)參數(shù)是可選參數(shù)——補(bǔ)丁文件路徑。兩者都允許通過(guò)GTK的文件選擇對(duì)話框二次指定但如果命令行參數(shù)已經(jīng)帶上窗口打開(kāi)時(shí)就直接預(yù)填并自動(dòng)執(zhí)行一次打補(bǔ)丁。這是為了讓腳本調(diào)用和交互使用走同一套入口邏輯。讀取文件時(shí)統(tǒng)一以二進(jìn)制模式打開(kāi)避免Windows平臺(tái)下文本模式下?lián)Q行符被改寫(xiě)導(dǎo)致補(bǔ)丁錯(cuò)位。引用參數(shù)的含義逐個(gè)說(shuō)清gtk_init負(fù)責(zé)初始化GTK運(yùn)行環(huán)境在沒(méi)有顯示設(shè)備的情況下它會(huì)輸出告警并返回程序隨后走一個(gè)無(wú)界面的“靜默模式”gtk_builder_add_from_file把glade文件解析成控件樹(shù)GtkFileFilter用于限制文件選擇器默認(rèn)顯示.ips和.rom后綴的文件。所有控件ID集中在resource.h里定義成常量例如ID_BTN_APPLY_PATCH、ID_BTN_REVERSE_PATCH、ID_TXT_LOGS。這樣做的好處是拼寫(xiě)錯(cuò)誤在編譯期就能被發(fā)現(xiàn)而不是運(yùn)行時(shí)拿到一個(gè)NULL指針后才崩潰。2.4 程序運(yùn)行的交互路徑界面按功能分成三個(gè)區(qū)域上半部是ROM文件和補(bǔ)丁文件的選擇區(qū)各帶一個(gè)“瀏覽”按鈕中部是動(dòng)作按鈕區(qū)包含“應(yīng)用補(bǔ)丁”“生成補(bǔ)丁”“反向補(bǔ)丁”三個(gè)主操作下半部是一個(gè)多行文本框充當(dāng)補(bǔ)丁過(guò)程的審計(jì)日志。點(diǎn)擊“應(yīng)用補(bǔ)丁”后程序先把原ROM做一個(gè)備份備份文件名默認(rèn)追加.bak然后讀入補(bǔ)丁文件逐條記錄應(yīng)用日志區(qū)同步輸出每一條記錄的偏移量、字節(jié)長(zhǎng)度和修改方式。如果中途出錯(cuò)日志區(qū)會(huì)給出錯(cuò)誤上下文并提示用戶備份文件已經(jīng)保留。這一章到目前還沒(méi)有涉及一行補(bǔ)丁邏輯是因?yàn)槲覉?jiān)持先讓讀者理解這個(gè)工程是“兩層架構(gòu)”把引擎和界面釘死。有了這個(gè)前提第3章把引擎拆開(kāi)時(shí)才能聚焦字節(jié)操作本身。3. 核心模塊拆解補(bǔ)丁引擎的解析、應(yīng)用與生成鏈路3.1 IPS格式的數(shù)據(jù)結(jié)構(gòu)偏移表與RLE記錄IPS格式的補(bǔ)丁文件由三部分組成若干條補(bǔ)丁記錄、一條EOF標(biāo)記、可選的文件截?cái)喽巍F胀ㄓ涗浀慕Y(jié)構(gòu)是3字節(jié)偏移地址 2字節(jié)數(shù)據(jù)長(zhǎng)度 N字節(jié)數(shù)據(jù)全部小端序。RLE記錄是特殊形式當(dāng)數(shù)據(jù)長(zhǎng)度字段為0時(shí)后面跟著2字節(jié)的重復(fù)長(zhǎng)度和1字節(jié)的重復(fù)數(shù)據(jù)表示“從偏移地址開(kāi)始把同一個(gè)字節(jié)重復(fù)寫(xiě)M次”。EOF標(biāo)記就是三個(gè)ASCII字符EOF讀到它意味著補(bǔ)丁結(jié)束。文件的偏移一律相對(duì)于ROM文件頭從0開(kāi)始計(jì)算。引擎內(nèi)部用下面這個(gè)結(jié)構(gòu)體表示一條解析后的記錄struct PatchRecord { uint32_t offset; // 記錄起始偏移 uint32_t length; // 數(shù)據(jù)長(zhǎng)度RLE時(shí)表示重復(fù)后的總長(zhǎng)度 std::vectoruint8_t data; // 普通記錄原始字節(jié) uint8_t rle_value; // RLE記錄被重復(fù)的字節(jié)值 bool is_rle; // 是否為RLE編碼 };這個(gè)結(jié)構(gòu)體的設(shè)計(jì)要點(diǎn)是把文件和邏輯解耦。length字段保存的是邏輯長(zhǎng)度——無(wú)論這條記錄在文件里占用的是普通數(shù)據(jù)還是壓縮后的RLE頭部引擎在應(yīng)用階段統(tǒng)一按length字節(jié)處理。因此解析函數(shù)只需要判斷is_rle就可以確定后續(xù)字節(jié)流如何解讀。3.2 解析補(bǔ)丁文件用流式讀取規(guī)避內(nèi)存翻倍解析函數(shù)的核心思路是“讀頭、讀長(zhǎng)度、分派”。最容易被忽視的細(xì)節(jié)是文件末尾可能沒(méi)有EOF標(biāo)記所以解析循環(huán)必須以文件流是否耗盡為終止條件而不能只依賴EOF字符串。下面這段代碼展示了完整流程std::vectorPatchRecord PatchEngine::parse(const std::string patchPath) { std::ifstream file(patchPath, std::ios::binary); if (!file) { throw std::runtime_error(無(wú)法打開(kāi)補(bǔ)丁文件: patchPath); } std::vectorPatchRecord records; uint8_t header[5]; while (file.read(reinterpret_castchar*(header), 5)) { // 判斷三個(gè)字節(jié)是否是 EOF 標(biāo)記 if (header[0] E header[1] O header[2] F) { break; } PatchRecord rec; rec.offset (header[0] 16) | (header[1] 8) | header[2]; rec.length (header[3] 8) | header[4]; if (rec.length 0) { // RLE記錄讀取2字節(jié)重復(fù)長(zhǎng)度 1字節(jié)重復(fù)數(shù)據(jù) uint8_t rleLen[2], rleVal; file.read(reinterpret_castchar*(rleLen), 2); file.read(reinterpret_castchar*(rleVal), 1); rec.is_rle true; rec.length (rleLen[0] 8) | rleLen[1]; rec.rle_value rleVal; } else { // 普通記錄按長(zhǎng)度讀取數(shù)據(jù) rec.is_rle false; rec.data.resize(rec.length); file.read(reinterpret_castchar*(rec.data.data()), rec.length); } records.push_back(std::move(rec)); } return records; }邏輯說(shuō)明讀取循環(huán)每次先取5字節(jié)頭部檢查前三個(gè)字節(jié)是否等于EOF再拆解偏移量和高低位長(zhǎng)度。rec.offset的實(shí)際取值范圍是0到0xFFFFFF因?yàn)镮PS格式偏移是24位定長(zhǎng)超過(guò)16MB的ROM需要對(duì)每條記錄手動(dòng)加上基址偏移初始基址通過(guò)補(bǔ)丁頭部約定。這屬于IPS格式的已知邊界不在這里展開(kāi)。rec.length取到0時(shí)按照IPS規(guī)范它不表示“空記錄”而是RLE的哨兵值此時(shí)后續(xù)字節(jié)按重復(fù)長(zhǎng)度和重復(fù)值解讀。參數(shù)說(shuō)明RLE重復(fù)長(zhǎng)度的單位是字節(jié)最大0xFFFF。引擎最終落盤(pán)時(shí)會(huì)檢查重復(fù)長(zhǎng)度是否為0。如果解析出長(zhǎng)度為0的RLE記錄說(shuō)明補(bǔ)丁文件可能在傳輸過(guò)程中被截?cái)喑绦驎?huì)拒絕后續(xù)操作防止無(wú)限循環(huán)寫(xiě)空數(shù)據(jù)。3.3 應(yīng)用補(bǔ)丁改寫(xiě)文件、備份與回滾策略把解析后的記錄寫(xiě)入ROM是第二個(gè)關(guān)鍵步驟。第一步永遠(yuǎn)是生成備份文件——備份在原文件同目錄下追加.bak后綴。這一步在半途崩潰時(shí)扮演后悔藥的角色。隨后按記錄順序逐條打開(kāi)ROM文件流用seekp跳到偏移位置寫(xiě)入數(shù)據(jù)。任何一條寫(xiě)入失敗都會(huì)觸發(fā)回滾從備份文件恢復(fù)原ROM。bool PatchEngine::apply(const std::string romPath, const std::vectorPatchRecord records, std::string log) { std::string backupPath romPath .bak; // 生成備份 std::ifstream src(romPath, std::ios::binary); std::ofstream bak(backupPath, std::ios::binary | std::ios::trunc); bak src.rdbuf(); src.close(); bak.close(); // 打開(kāi)ROM準(zhǔn)備改寫(xiě) std::fstream rom(romPath, std::ios::binary | std::ios::in | std::ios::out); if (!rom) { log 無(wú)法打開(kāi)ROM文件\n; return false; } // 先檢查所有偏移是否越界避免寫(xiě)一半才發(fā)現(xiàn)后面的記錄越界 rom.seekg(0, std::ios::end); const auto fileSize rom.tellg(); for (const auto rec : records) { if (static_castuint64_t(rec.offset) rec.length fileSize) { log 記錄越界應(yīng)用中止\n; std::filesystem::rename(backupPath, romPath); return false; } } for (const auto rec : records) { rom.seekp(rec.offset); if (rec.is_rle) { for (uint32_t i 0; i rec.length; i) { rom.put(static_castchar(rec.rle_value)); } } else { rom.write(reinterpret_castconst char*(rec.data.data()), rec.length); } // 每條記錄完成后立即flush順帶定位失敗點(diǎn) rom.flush(); } rom.close(); log 補(bǔ)丁應(yīng)用成功共寫(xiě)入 std::to_string(records.size()) 條記錄\n; return true; }邏輯說(shuō)明備份不是可選項(xiàng)而是默認(rèn)行為。用std::ofstream的rdbuf()整體拷貝是拿到備份最簡(jiǎn)潔的寫(xiě)法不依賴額外庫(kù)。前置越界檢查需要在寫(xiě)入前完成因?yàn)檫@能確?!耙匆粭l都不寫(xiě)要么全寫(xiě)”避免寫(xiě)入一半后失敗導(dǎo)致ROM處于半補(bǔ)丁的尷尬狀態(tài)。flush()每次調(diào)用會(huì)強(qiáng)制把緩沖區(qū)同步到磁盤(pán)雖然犧牲了一點(diǎn)性能但對(duì)于少量補(bǔ)丁記錄完全可接受而且錯(cuò)誤定位更精確。records.size()的值可以被當(dāng)成審計(jì)日志的一部分輸出幫助使用者確認(rèn)應(yīng)用了多少條補(bǔ)丁。實(shí)際操作中補(bǔ)丁引擎對(duì)“重復(fù)打同一個(gè)補(bǔ)丁”的情況做了一種防御應(yīng)用前計(jì)算ROM文件哈希并緩存二次應(yīng)用同一補(bǔ)丁時(shí)發(fā)現(xiàn)目標(biāo)偏移的字節(jié)和補(bǔ)丁數(shù)據(jù)完全一致就在日志中輸出警告“發(fā)現(xiàn)與補(bǔ)丁一致的字節(jié)已跳過(guò)”防止用戶手滑重復(fù)應(yīng)用。3.4 生成補(bǔ)丁雙ROM二進(jìn)制比對(duì)生成IPS生成補(bǔ)丁是反向操作用戶提供一個(gè)未修補(bǔ)的原始ROM和一個(gè)已修補(bǔ)的目標(biāo)ROM程序逐字節(jié)比較兩個(gè)文件把差異整理成補(bǔ)丁記錄。算法本身不復(fù)雜但需要對(duì)連續(xù)差異區(qū)域進(jìn)行分段合并避免把每個(gè)變化字節(jié)生成一條記錄。std::vectorPatchRecord PatchEngine::diff(const std::string origPath, const std::string modPath) { std::ifstream orig(origPath, std::ios::binary); std::ifstream mod(modPath, std::ios::binary); auto origData readAll(orig); auto modData readAll(mod); std::vectorPatchRecord records; uint32_t i 0; while (i origData.size() i modData.size()) { uint32_t start i; while (i origData.size() i modData.size() origData[i] ! modData[i]) { i; } if (i start) { PatchRecord rec; rec.offset start; rec.length i - start; rec.is_rle false; rec.data.assign(modData.begin() start, modData.begin() i); records.push_back(std::move(rec)); } i; } return records; }這個(gè)實(shí)現(xiàn)使用了“連續(xù)差異塊合并”策略每次遇到第一個(gè)不同字節(jié)就從這里連續(xù)掃描直到字節(jié)重新相同中間的區(qū)域整體打包成一條記錄。由于IPS對(duì)單條記錄長(zhǎng)度限制在0xFFFF字節(jié)內(nèi)超過(guò)這一上限的差異段會(huì)被拆分。拆分規(guī)則定在while循環(huán)內(nèi)部另有一個(gè)MAX_RECORD_LENGTH常量控制向量長(zhǎng)度上限實(shí)際應(yīng)用里我會(huì)按0xFFFF設(shè)定。4. GTK界面與事件回調(diào)用戶點(diǎn)擊到落盤(pán)的完整鏈路4.1 Glade界面布局與控件ID綁定ui/main_window.glade文件用GTK Builder的XML語(yǔ)法描述布局其中復(fù)選框、按鈕、路徑輸入框全部帶有穩(wěn)定的id屬性。程序啟動(dòng)后通過(guò)gtk_builder_new_from_file()加載該XML然后按id獲取控件實(shí)例。使用Glade文件而不是C代碼手寫(xiě)布局的好處是界面調(diào)整不用重新編譯改一行XML就可以重新預(yù)覽。布局上日志顯示區(qū)用的是GtkTextView它比GtkLabel更適合展示多行且可能滾動(dòng)的文本內(nèi)容。按鈕組的“應(yīng)用補(bǔ)丁”和“反向補(bǔ)丁”共用同一個(gè)GtkNotebook的頁(yè)面以標(biāo)簽頁(yè)切換操作模式而不是堆疊所有按鈕。日志視圖的文本緩沖在每次補(bǔ)丁操作結(jié)束后通過(guò)gtk_text_buffer_set_text()整體覆蓋保留最近一次操作的完整輸出不保留歷史流水避免界面被日志刷成信息海洋。4.2 回調(diào)適配從C函數(shù)指針到C方法調(diào)用GTK3的按鈕信號(hào)clicked需要注冊(cè)一個(gè)普通的C函數(shù)指針而我們的業(yè)務(wù)邏輯在C的PatchEngine類成員里。這里需要一層適配器把所有回調(diào)統(tǒng)一轉(zhuǎn)發(fā)到同一個(gè)入口再用一個(gè)上下文結(jié)構(gòu)體區(qū)分是哪個(gè)按鈕觸發(fā)。常見(jiàn)做法是使用g_object_set_data把this指針掛到控件上回調(diào)里通過(guò)g_object_get_data取回并轉(zhuǎn)換。struct CallbackContext { MainWindow* window; int actionId; // 0應(yīng)用補(bǔ)丁1生成補(bǔ)丁2反向補(bǔ)丁 }; void on_action_clicked(GtkWidget* widget, gpointer user_data) { auto* ctx static_castCallbackContext*(user_data); if (!ctx || !ctx-window) return; MainWindow* win ctx-window; std::string romPath win-getSelectedRomPath(); std::string patchPath win-getSelectedPatchPath(); try { if (ctx-actionId 0) { win-applyPatch(romPath, patchPath); } else if (ctx-actionId 1) { win-generatePatch(romPath, patchPath); } else if (ctx-actionId 2) { win-reversePatch(romPath, patchPath); } } catch (const std::exception ex) { win-appendLog(std::string(操作失敗: ) ex.what()); } }邏輯說(shuō)明CallbackContext充當(dāng)了GTK事件與C對(duì)象之間的橋梁而不是直接在回調(diào)里寫(xiě)業(yè)務(wù)邏輯。getSelectedRomPath是MainWindow的成員函數(shù)負(fù)責(zé)從界面的GtkFileChooserButton或輸入框中提取路徑。異常捕獲放在回調(diào)最外層這樣任何引擎內(nèi)拋出的異常都能被捕獲并以文本形式展示在日志區(qū)而不是作為未處理異常導(dǎo)致程序退出。這段適配模式的取舍在于函數(shù)指針是GTK C API定的規(guī)矩但我們把它的實(shí)現(xiàn)做得很薄只做路由不做邏輯。如果你需要新增一個(gè)“校驗(yàn)補(bǔ)丁合法性”的按鈕查看現(xiàn)有回調(diào)并復(fù)制一條路由分支即可不必修改引擎相關(guān)代碼。4.3 日志刷新技術(shù)與異步處理補(bǔ)丁大文件時(shí)全部寫(xiě)入可能耗時(shí)數(shù)十秒界面如果同步等待會(huì)讓窗口卡成未響應(yīng)。目前的實(shí)現(xiàn)通過(guò)g_idle_add注冊(cè)一個(gè)空閑回調(diào)把補(bǔ)丁任務(wù)拆成兩段第一段在用戶點(diǎn)擊后立即同步做備份和解析第二段在GTK主循環(huán)空閑時(shí)逐條寫(xiě)入記錄。寫(xiě)入十條更新一次日志并在日志末尾追加當(dāng)前進(jìn)度百分比。這樣界面在長(zhǎng)時(shí)間寫(xiě)入期間也能保持響應(yīng)用戶能看到進(jìn)度在動(dòng)而不是死等。5. 避坑指南IPS打補(bǔ)丁時(shí)翻車的幾個(gè)典型場(chǎng)景5.1 補(bǔ)丁應(yīng)用后ROM體積翻倍現(xiàn)象應(yīng)用補(bǔ)丁后ROM文件從8MB變成16MB打開(kāi)游戲直接白屏。原因在使用std::fstream::seekp定位偏移時(shí)如果偏移量設(shè)置超過(guò)了文件當(dāng)前末尾fstream并不會(huì)報(bào)錯(cuò)而是會(huì)自動(dòng)用零字節(jié)填充中間區(qū)域。IPS記錄里的字節(jié)偏移如果被錯(cuò)誤解析成ROM地址以外的數(shù)值例如把滾動(dòng)校驗(yàn)數(shù)據(jù)也當(dāng)成了記錄起點(diǎn)就會(huì)導(dǎo)致每次寫(xiě)入都產(chǎn)生大量空洞。解決應(yīng)用補(bǔ)丁前必須做雙重校驗(yàn)——先檢查文件長(zhǎng)度再檢查記錄中最大偏移是否超過(guò)ROM末尾。引擎里的越界檢查代碼會(huì)在寫(xiě)入前把所有記錄的offset length與文件大小比較一旦越界馬上中止并恢復(fù)備份。5.2 GTK回調(diào)內(nèi)拿到的控件指針是NULL現(xiàn)象點(diǎn)擊按鈕時(shí)程序直接段錯(cuò)誤退出gdb回溯發(fā)現(xiàn)是某個(gè)控件上調(diào)用了gtk_widget_get_*。原因Glade文件里的控件ID拼寫(xiě)錯(cuò)誤gtk_builder_get_object返回了NULL但.glade文件中同一ID在后續(xù)又被定義了一次Builder沒(méi)有報(bào)錯(cuò)而是靜默返回最后一次實(shí)例。這類錯(cuò)誤常見(jiàn)的玄學(xué)之處在于日志區(qū)按鈕正常而文件選擇按鈕直接崩潰因?yàn)閮蓚€(gè)控件ID的起名風(fēng)格太接近。解決所有控件ID統(tǒng)一在resource.h中定義編譯期常量不再在C代碼里寫(xiě)字符串字面量。同時(shí)增加一個(gè)開(kāi)發(fā)模式加載Glade文件后遍歷檢查每個(gè)常量的get_object返回值是否為NULL發(fā)現(xiàn)NULL立即在日志區(qū)輸出紅色錯(cuò)誤提示。從那以后我每次新增控件都把id常量放到位強(qiáng)制編譯期檢查。5.3 EOF標(biāo)記誤觸發(fā)導(dǎo)致補(bǔ)丁提前結(jié)束現(xiàn)象補(bǔ)丁文件明明包含后續(xù)記錄但程序只應(yīng)用了一部分剩余記錄被靜默忽略。原因有個(gè)別補(bǔ)丁生成工具把三條連續(xù)字節(jié)E O F作為普通數(shù)據(jù)寫(xiě)進(jìn)了某個(gè)記錄的同一位次而我的解析循環(huán)判斷EOF的時(shí)機(jī)過(guò)早——它在讀取記錄頭部三字節(jié)后直接比對(duì)沒(méi)有先判斷當(dāng)前處于“數(shù)據(jù)區(qū)”還是“頭部區(qū)”。數(shù)據(jù)區(qū)內(nèi)部可能天然出現(xiàn)這三個(gè)ASCII字符。解決解析循環(huán)把“識(shí)別文件流當(dāng)前位置”和“讀取頭部”拆成兩步只有在每次讀取頭部之前才進(jìn)行EOF判斷。修正后的循環(huán)把read邏輯與EOF判定放在同一個(gè)循環(huán)體頂部避免數(shù)據(jù)區(qū)內(nèi)的EOF字節(jié)干擾。5.4 Windows下原文件無(wú)法重命名現(xiàn)象在Windows上點(diǎn)擊“恢復(fù)備份”時(shí)操作系統(tǒng)提示文件正在被另一個(gè)進(jìn)程使用無(wú)法覆蓋原文件。原因補(bǔ)丁應(yīng)用完成后fstream雖然調(diào)用了close()但在異常路徑上忘記關(guān)閉文件流。例如在應(yīng)用過(guò)程中有一條記錄發(fā)生越界檢查異常函數(shù)直接返回false而沒(méi)有走到rom.close()那一行。Windows對(duì)打開(kāi)的文件句柄有強(qiáng)制寫(xiě)保護(hù)導(dǎo)致后續(xù)備份恢復(fù)失敗。解決所有文件流都使用RAII確保離開(kāi)作用域即關(guān)閉不再依賴手動(dòng)close()。std::fstream的析構(gòu)函數(shù)會(huì)自動(dòng)釋放句柄所以把代碼改成不顯式調(diào)用close()依賴局部變量生命周期管理。這條血淚經(jīng)驗(yàn)后來(lái)我用在項(xiàng)目所有文件操作上沒(méi)再出過(guò)同類問(wèn)題。5.5 補(bǔ)丁應(yīng)用一半突然斷電導(dǎo)致文件損壞現(xiàn)象進(jìn)程被強(qiáng)制結(jié)束后ROM文件長(zhǎng)度停留在某個(gè)中間值后續(xù)字節(jié)全部丟失。原因?qū)懭雴螚l記錄后雖然調(diào)用了flush()但操作系統(tǒng)層面的頁(yè)面緩存還沒(méi)來(lái)得及落盤(pán)斷電就帶來(lái)文件截?cái)?。這與其說(shuō)是代碼bug不如說(shuō)是強(qiáng)殺路徑預(yù)留不足。解決在“應(yīng)用補(bǔ)丁”和“生成補(bǔ)丁”前把備份文件寫(xiě)入同一個(gè)磁盤(pán)分區(qū)但不在同目錄防止目錄項(xiàng)損壞時(shí)備份一起消失。寫(xiě)入完所有記錄后再調(diào)一次fsync級(jí)別的落盤(pán)接口GTK跨平臺(tái)下直接調(diào)用fflush并重新打開(kāi)文件確認(rèn)長(zhǎng)度一致不一致則在日志區(qū)報(bào)錯(cuò)并引導(dǎo)用戶手動(dòng)恢復(fù)備份。6. 二次開(kāi)發(fā)把補(bǔ)丁引擎改造成支持多格式的通用工具最后一章落在“怎么改”。當(dāng)前引擎只處理IPS格式但現(xiàn)代ROM社區(qū)常用的BPS格式在一些場(chǎng)景下壓縮率更高、支持文件截?cái)?。把engine層抽象出補(bǔ)丁格式接口是相對(duì)價(jià)值高的一個(gè)改造方向。改造點(diǎn)主要是給PatchEngine增加格式虛函數(shù)接口。IPS與BPS的差異在于BPS是變長(zhǎng)整數(shù)編碼加校驗(yàn)和但兩者都有“解析記錄”“應(yīng)用記錄”“生成記錄”三個(gè)生命周期。我把現(xiàn)有代碼的重構(gòu)思路寫(xiě)出來(lái)class IFormatHandler { public: virtual ~IFormatHandler() default; virtual bool parse(const std::string patchPath, std::vectorPatchRecord out) 0; virtual bool apply(const std::string romPath, const std::vectorPatchRecord records, std::string log) 0; virtual bool generate(const std::string origPath, const std::string modPath, const std::string outPatchPath) 0; }; class IpsHandler : public IFormatHandler { // 現(xiàn)有實(shí)現(xiàn)原樣遷入 }; class BpsHandler : public IFormatHandler { // BPS解析與生成邏輯 };然后MainWindow根據(jù)補(bǔ)丁文件后綴選擇handler.ips走IpsHandler.bps走BpsHandler。新增格式時(shí)只需要添加新的子類實(shí)現(xiàn)不需要?jiǎng)哟翱诖a。驗(yàn)證方式給tests/fixtures目錄新增一個(gè)BPS樣例文件測(cè)試用例寫(xiě)兩輪——第一輪用IpsHandler做了一遍第二輪用BpsHandler跑一遍然后斷言兩次應(yīng)用結(jié)果的文件哈希完全一致。這樣保證“應(yīng)用-驗(yàn)證”閉環(huán)在不同格式下輸出一致。實(shí)際改這段代碼時(shí)我最深的體會(huì)是當(dāng)初把引擎與GUI分成兩個(gè)目標(biāo)編譯是值得的。測(cè)試BPS格式時(shí)完全沒(méi)碰GTK相關(guān)庫(kù)在命令行下直接跑測(cè)試程序幾十毫秒就得到結(jié)果。反觀早期版本把引擎函數(shù)全部塞在main_window.cpp里要驗(yàn)證格式改動(dòng)就得開(kāi)著窗口點(diǎn)半天按鈕效率完全不在一個(gè)量級(jí)。從那以后我再設(shè)計(jì)這類工具時(shí)都先強(qiáng)制定好純邏輯層與界面層的邊界再動(dòng)手寫(xiě)第一行代碼。希望這篇拆解能幫你在自己的項(xiàng)目里少走一段彎路。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
一个色导综合| 日韩午夜啪啪视频| 手机在线A片| 久久人人爽人人爽人人片Ⅴ| www.久久| 超碰人人乐97| 伊人久久大香线蕉亚洲五月天,青草青草欧美日本一区二区,欧美日产欧美日产国产 | 91精品人| 无码操逼视频一下| 精品少妇一区二区三区在线视频 | 大香蕉人妻| 四虎AV在线观看| 一区二区三区国产精产| 亚洲偷91色| 精品999一区二区| 黄色大片视频在线免费看| av在线一区二区三区| 91成人久久| Julia在线播放亚洲久久| 国产精品午夜成人福利| 日韩9999| 亚洲风情在线观看| 色操逼网| 狠狠中文字幕| 国产视频大全| 94色色电影网| 国产高清精品一区二区三区毛片| www网站黄| 婷婷成人久久久精品| 日本女厕偷拍| 中文字幕一二三av| 久久久少妇| 午夜寂寞欧美| 精品人妻夜夜草| 免费看污网址| 精品国产乱码久久久A| 九九九免费视频| 亚洲天堂中文字| 亚洲城人男人的天堂| 国产中午字一暮区| 亚洲成人无码影院| 国产精品制服丝袜中文字幕日韩一区二区三区 | 国产JDAV无码视频在线观看| 久久久 国产精品| 玖玖97综合| 9久久美女首页| 婷婷九月丁香| 亚洲阿v天堂无码z2018| 激情五月综合| 91女优在线观看| 偷偷人人精品女女久久| 精品亚洲黄色片 国产精品导航一区二区| 极品白嫩美女白浆成人福利在线看| 97视频观看| 极品人妻少妇综合| 国产成人精品日本视频| 欧美后入视频| 精品久久久av无码免费| 91色综| 天天天操天天天爱| 国产网红精品| 中 文字幕一区二区三四 五 区日 日 骚 | 一中国女人毛片水真多| 亚洲AV成人无码一区二区三区在线观看 | 人人干人人操人人..com| 久久25| 97在线免费视频观看| av天堂手机版追回 | 婷婷色中文字幕| 精品视频久久区| 国内偷自视频区视频综合| 99久久这里只有精品| 亚洲欧美洲综合| 日韩精品在线观看网站| 国模久久在线| 亚洲一欧洲中文字幕在线 | 久操97| av天堂5| 青青草久草AV| 2021久久国产综合精品青草| 欧美国产有色电影| 草莓精品视频在线免费观看| 亚州人妻| 国产强奸超碰AV| 久久动漫精品视频这里只有精品| 中国一区二区亚洲人妻| 超碰久草| 丝袜美腿制服人妻二区中文字幕 | 日本孕妇孕交| 亚洲色图亚洲无码强奸乱伦| 东北老熟女| 91足交| 99日免费视频中文字幕| 精品亚洲黄色片 国产精品导航一区二区| 国产农村妇女精品1区二区| 肉动漫无遮挡h在线观看| 免费黄色片子| 国产精品自拍视频| 欧美大香蕉在线观看| 91欧美在线| 欧美操逼一二三区| 免费福利视频中文字幕| 精品乱码久久久久| 丁香五月综合| 亚洲欧美清纯| 青青青操| 久久亚州精品成人Av无| 91 丝袜在线观看| 九色视频91| 欧美小说区视频区| 六六久久日韩不卡| 日韩免费av片高清无码| 中文一区二区婷婷视频| 99re国产精品视频| 国产超碰97| 99热精品在线在线| 国产在线综合网| 少妇人妻精品| 欧美三级中文字幕hd| 综合熟妇一区二区三区| 成人精品电影| 在线a v| 夜夜嗨老熟女AV一区二区三区| www.99在线| 久久久久久久91| 黄页18禁| 午夜寂寞欧美| 亚欧成人一级片在线播放| 人妻出轨一区二区三区| 国产精品久久伊人| 精品人妻一区二区免费看| 亚洲aV性爱| 老熟女网站| 午夜精品久久久久久久99热影院| 一区二区三区激情在线观看| 亚洲牲交| 欧美高潮| 色综合中文字幕不卡| 91精品网站| 97超碰亚洲| 日韩免费性爱视频在线观看| 亚洲自拍偷拍视频在线| 好看的久久不射无码影视影院| 操逼操网| 日本孕妇一区二区视频操逼免费看| 日本九九久久99| www.91色综合| 国产亲戚伦亲在线| 麻豆国产97在线| 国产精品一区二区密臀| 91精品久久久久五月天精品| 999国产精品999久久久久久| 小草三级久久观看| 中国国产精品一区视频| 男人的天堂va| 一区二区不卡| 天天天天操| 中文操逼字幕| 熟女熟妇一区二区三四区| www.狠狠干.coom| 亚洲强奸乱伦影视网| 色区97| 校园春色综合香蕉| 九一屌逼| 色播五月婷婷| 亚洲国产一区二区三区四区国产| 久久午夜色播影院免费高清| 亚洲人精品午夜不卡| 成人影 天天操 亚洲| 亚洲无线码一区国产欧美国| 99亚洲精品| 成人怡红院| 免费99精品国产自在在线| 天天操天天射青青草| 免费一级视频特黄色大片| 天天干人人干天天日97| 中文字幕五月婷婷免费| 一个国产在线综合网站| 精品一区二区三区麻豆| 好属操| 欧美自拍网| 精品二区三四区五电影 | 在线视频资源| 久久久天美| 欧美啪啪天堂| 精品人妻一区二区免费看| 国产精品久久久久久久久久二区三区| 日韩亚洲97| 人妻 欧美 中文| 日韩丝袜高跟制服在线观看| 久久久国产护士丝袜美腿一| 99福利社| 国产精品69久久久久久久| 婷婷久草| 久久久久女教师免费一区| 久久九九久精品国产尤物|国产精品爽黄69天堂A片潘金莲,国产亚洲精品第一综合 | 久久伊人青青草| 97午夜剧场日韩| 黄页18禁| 久久天天躁日日躁狠狠躁| 91中文精品日韩欧美在线| 91欧美丨精品丨入口| 91超碰碰在线| 欲综合网| 狠狠婷婷亚洲中文综合久久| 成 人片 黄色大片| WWW黄片COM| 97av在线视频| 中美日韩毛片| 久久精品国产99久久,亚洲日韩久久日本一区一区三区 | 日韩欧美午夜一区二区| 国产成人精品日本亚洲语言| 91人妻人人妻| 91草草草| 91丝袜美女视频| 亚洲欧美一区二区网址| 国产极品美女高潮无套在线观看| 多乙久久久久久| 五月婷婷六月色| 91麻豆天美传媒HD| 熟妇女伦乱视频视频| 91丨国产丨白浆秘 洗澡动漫| 亚洲欧美精品国产一区二区| 欧美在线观看综合国产| 亚洲区限制级| 麻豆天美AV传媒第一页| 国产精品久久久久久久无码AV| 久久无码成人| 啊啊啊啊嗯嗯嗯用力好爽| 热久久精品| 久操| 亚洲A色| 91人妻尻屄视频| 三级日韩一区二区三区| 男人的天堂VA| 操逼啊啊啊91| 最新AVzaixian| 一区二区无码视频| 国产精品亚洲天堂网址| 东京热激情视频一二三区| WWW.加勒比人妻一区不卡.com| 秋霞Av理论一级在线| 亚洲欧美日韩精品久| 日韩不卡一二三四| 亚洲AV成人无码久久精品播放| 亚洲欧美综合网站| 国产 三级自拍| 极品美女嘿咻| 蜜色网色哟哟| 无套内射人妻在线播放| 99热这里只有精品1| 五月丁香六月激情| 成年人黄色视频免费| 美女AV一区二区| 国产欧美岛国精品一区| 欧美碰碰综合色| 九色 人妻 大香蕉| 日韩卡一卡二卡三在线| 精品无码少妇| 久久久不卡区一区二区三区久久久| 激情抓乳插进去啪啪啪日韩 | 大屁股国产在线视频| 久久久18| 日本免费一级AAA大片器 | 欧美性天天| 久久日本熟女精品一区| www.夜夜操| 白丝被操91| 超碰97.com| 中文字幕日韩精品一区二区三区| 日韩不卡毛片Av免费高清| 99久在线精品99re8蜜桃| 91美女在线精品视频| 成·人免费午夜在线观看| 校园春色中文字幕AV| 日韩国语字幕| 久久AV无码网址| 三男一女不戴套的A片| 夜夜高潮夜夜爽国产伦精品| 久久97资源 网| 99热网站| 国语对白在线播放视频| 日韩黄色片子| 亚洲欧洲激情卡通另类文学四射小说网站| 97视频www| 91偷拍欧美亚洲| 思思99热| 99热成人| 国产热RE99久久6国产精品首 | 男人a天堂手机在线版| 国产高清自拍| 91国模| 国产人人干| 欧洲精品人妻| 99蜜桃臀久久久欧美精品网站| 伊人成人中文字幕久久网| 强歼乱伦资源网| 懂色av色欲av蜜臀av| 三男一女不戴套的A片| 我想要 啊 啊 啊| 人妻丝袜一区二区三区在线| 久久久久久免费电影| 搞中出久久| 欧美亚洲情色| 人人搞人人插人人操| 96麻豆精品一区二区三区| 久草老司机| 欧美爱国产综合、| 自拍啪啪视频| 久久系列| 青娱乐二区免费| 毛片久久| 国产成人精品无码久久| 91c色| 天天天天天天天天天天干美女| 国产精品嫩草久久久久| 艹精品| 永久免费发布性爱网| 操逼操网| 9久热| 国产v片在线免费观看| 日本美女性生活久久久久久久| 97香焦色区| 亚洲小说视频| 亚洲国产日韩欧美熟妇在线| 啊啊啊久久久视频| 国产一区在线观看无码AV | 亚洲 另类 丝袜 自拍 动漫| 激情五月天中文字幕色| 色噜噜狠狠色综无码久久合欧美| 欧美综合色图网| 人人插人人摸人人| 五月天欧美色图| 久久AV无码网址| 亚洲女人毛茸茸91| 黄aaaaaaaaaaaaaaaaaa色网站| 亚洲男人综合网| 免费簧片在线观看| 职场同事知名国产国产精品久久欧美日韩| 91av一区二区在线观看| 国产av白丝| a亚洲欧美色欲| 思思热在线视频免费| 在线观看一卡二卡| 欧美一区二区三区日韩| 在线综合 亚洲 欧美中文字幕| 手机在线播放国产福利| 久久精品区| 欧美一区二区三区互相| 啪啪91| 在线观看不卡一区二区三区| 91人妻Pr| 大香蕉一线视频| 国产精品久久伊人| 51一区二区三区| 人妻久热在线| 999久久芭蕾| 性爱视频啪啪啪啪| 香蕉一区二区三区在线视频| 亚春色色| 蜜臀操逼黄色视频操的好爽| 中文97国产| 香蕉视频欧美一卡二卡| 丁香六月婷| 淫穴高潮色图| 亚洲精品中文字幕一区在线视频| 日日黄色三级网站| 強姦亂倫a| 91久热这里只有精品| 人人操人人摸超碰| 日本女人操逼| 久操免费电影| 丁香婷婷大香蕉| 一本色道久久综合狠狠操| 日韩精品中文字幕一| 好屌色综合| 日韩综合无码色欲vv| 少妇天堂网络| 人妻一二三区| 久久精品人妻一区二区| 26uuu性物| 亚洲黄色网址| 精品偷拍13p欧美dodk视频| 日韩精品大香蕉伊人在线| 免费啪啪av| 91影视亚洲| 免费中文在线| 97亚洲精品超碰| 花野真衣| 色翁荡息又大又硬又粗又爽| 色九九九综合| 青青草天天亲夜夜操网| 欧美综合综合| 男人的天堂激情| 日韩欧美午夜一区二区| 91N综合网在线| 亚卅熟女乱色| 亚州综合色| av情色影音| 老熟女乱子伦中文字幕一区二区| 4虎在线视频| 看一级黄色视频| 综合网天天| 五十路二区在线| 欧美视频一区二区在线| 狠狠爱夜夜| 久久综合日韩亚洲欧美| 日本Xx性爱| 91亚洲综合在线| 美国久久一二三四| 91狼人| 蜜臀一区二区三区在线| 好爽要喷了| 1024亚洲中文字幕久在线看片你懂的 | 爱啪精品一区| 综合熟女| 亚洲精品国产熟女久久久久久| 亚洲精品蜜桃久久久| 色婷婷综合久久久久中文一区二区| 免费亚洲黄色视频在线观看| 国产400孕妇孕交群| 欧美久久人妻少妇一区二区| 亚洲精品一区中文字幕乱码| 国产中文大片资源中文字幕| 亚洲图片欧美| 久久有码视频| 久久人人爽av亚洲精品天堂桃色| 神马视频久久久久久| 在线啊v一区| 777琪琪午夜免费A片| 热99re69精品8在线播放| 亚洲日产专区婷婷| 五月天综合网| 中文字幕艹艹| 蜜桃久久综合视频| 激情综合网五月婷婷| 天天色天天干天天射| 97天天日| 中日韓欧美高清| 欧美色图小说综合| 国产精品在线一区二区| 操b网站亚洲无码| 国产亚洲在线观看| 国产亚洲国产超碰| 1769精品一区二区三区| 伊人网综合在线视频| 欧美午夜视频免费观看| 天天躁日日躁成人字幕aⅴ| 日韩精品一二三四| 日韩成人精品视频自拍| 一起草欧美| 日本爽爽爽爽爽爽免费视频| 国产品精品自在在线午夜免费| 欧美性色欧美| 麻豆91熟妇人妻中文字幕茄子| 无码九九| 深夜激情| 0755午夜福利视频| 国产精品第一页国产大屁股视频免费区| 日夜尻逼网| 91美女视频直播| 女人香蕉久久毛毛片精品| 9美女超碰在线免费观看| 夜夜高潮夜夜爽国产伦精品| 校园春色AV天堂| 啊啊啊网站| 看免费一级在线播放毛片| 一中国女人毛片水真多| 午夜超爽| 中文字幕成人理论在线| 丁香五月成人| 中文有码第五页| 91N综合网| av在线观看不卡网站| 一区=区三区视频| 欧美激情性爱视频网站| 成人性爱美曰韩| 中文字幕jul-617人妻熟女| 97自拍视频在线| 野狼激情网| 亚洲免费97免费| 欧美玖玖爱免费玖玖| 欧美色亚洲色| 国产色图乱伦| 岛国大片在线观看网站入口| 久久五月综合| 亚洲男人天堂2012| 九99久久| 日本一级真人黄色性爱视频| 精品午夜福利国产一区二区在线观看 | 中文字幕精品探花视频| 无码天天操| 五月丁香婷婷综合网| 夫妻四区五区六区| 日产成人久久| 亚洲精品久久久久毛片A片拉屎 | 超碰爽人妻熟女Av| 婷婷九月国产| 在线观看中文字幕| 18禁的网站在线| 亚州少妇| 国产热av| 欧州一区二区三区四区| 久久久精品无码亚免费| 亚洲美女精品| 日韩欧美~中文字| 蜜臀无码视频在线观看| 日本五十路熟女一区二区| 开心激情站| 欧天美中出| 啊啊啊啊好多水| 亚洲小电影免费涩涩成人在线高清| 97婷婷色| 国产成人天堂| 在线免费观看高清无码视频| 亚洲AV永久无码一区仙野| 江都AV在线| 蜜桃传媒视频第一区入口在线看| 黄色操人| 久久超碰久| 91欧美综合在线| 欧美性性性| 91久久久老司机| 色原狠狠天天天| 亚洲黄片免费在线播放| 欧美男人一区| 久久成人东京热人妻| 八戒午夜福利理论片| 色五月婷婷五月天| 男女香蕉一区二区| 天天操夜夜操狠很操| 蜜臀久久99精品久久久老,,| 后入式福利| 国产黄色影片在线观看| 青娱乐av在线| 蜜臀一区二区三区亚洲最新章节在线观看 - 高清蜜臀一区二区三区亚洲全集播放 | 亚洲精品久久久久毛片A片拉屎 | 99热自拍| 亚洲少妇色| 国产精品 久久久精品一牛| 日韩AV噜噜噜一区二区三区四区| 天天舔九色婷婷| 久9热| 日本无码1| 草草电影院| 我要色综合网站| 美女久久久久久久| 亚洲天堂在线怕怕视频| 欧美超碰96| 欧美日韩理论一区| 91久久久久久| 日本大片日本一区二区免费高清 | 日本 欧美 国产一区| 好看的久久不射无码影视影院| 精品99999| 夜夜爽33333| 99热婷婷一区二区三| 最近2019中文字幕国语免费版| 久久 亚洲 日韩 人妻| 亚洲中文字幕熟女| 欧美亚洲综合色| 好吊色青靑草| 久久香蕉国产传媒一区剧情天美| 久久精品超碰| 婷婷色色五月天| 变态综合色| 丁香五月激情综合| 久久久久久久唑| 色色国产| 日韩少妇无码| 五月黑AⅤ| 国产福利合集| 亚洲欧美天堂在线| 亚洲日韩精品久久久久一区壹牛| 97超碰无码网| 一级岛国大片| 中文字幕、久久精品国产2020、久久综合久久自在自线精品自、亚洲 | 日本高清电影欧美色图| 国产剧情在线| 熟妇女人妻呻吟久久AV| 午夜福利1区2区3区| 啊啊好多水| 国产最新小视频在线播放下载| 婷婷另类小说| 亚洲黄色网址视频| 日本2020一区二区| 蜜桃久久综合视频| 亚洲欧美日韩免费观看| 青青草色情网站视频| 成人一级性爱| 久久久91福利姬| 在线播放成人网站| 国产99热| 日少妇亚洲版| 韩国成人精品久久久免费看| 欧美综合狠| 26uuu国产| 大JI巴好深好爽又大又粗视频| 一道本东京热加勒比一区二区三区 | 欧美色欧美| 久久九七| 欧美日韩中文亚洲v在线综合| 台湾佬大香蕉| 欲色影视综合吧| 操老熟女AV| 亚洲日本韩国在线| 少妇综合| 男人网站婷婷| 久久99视频| 秋霞Av理论一级在线| 亚洲综合99999| 中文自拍欧美影视| 欧美色偷偷| 欧美亚洲美少妇一区二区| 亚洲欧美在线观看2021 | 中日亚韩免费视频| 国产自偷自拍一区| 日本A级视频| 亚洲 欧美 第一页| 看大黄色大片原件| 69AV女优男人的天堂| 欧美在线亚洲| 熟女精品va中文字幕| 高凊专区人人操| 女人久久久| 91人妻中文| 亚洲天堂男人的天堂| 欧美日韩在线小说 | 四虎精品永久在线观看| 亚洲导航深夜福利| 久久尹人大香焦视| 久久久久密臀一区二区| 婷婷五月色| 天天日天天搞天天干| 欧美92| 久热久操| 六月婷激情福利天堂69| 亚洲乱码国产乱码精网站| 99热在线播放| 在线五区| 天天弄欧美| 日本一级一级一级一级| 97在线观看播放视频| 亚洲久9| 物业黑人 AV一区| AV天堂电影网| 久久精彩视频| 乱伦av.com| 色欲久久久久综合网| 精品免费囯产一区二区三区 | 精品97久久| 成人一区二区三区四区| 日韩人妻操B| 精品超碰国产| 岛国网址国产 | 欧美色图99| 色超碰综合| 少妇毛片久久| 一级黄色影片| 日日碰狠狠添天天爽超| 国产欧美精选激情视频| 国产精品人妻无码久久久互動交流| 国产少妇内射| 97碰碰日本乱偷人妻中文的| 国产九九久久久精品| 天天色播| 免费看欧美美女黄色大片 | 性爱动态120秒| 亚洲精品久久久久久久蜜桃臀| 国产精品视频麻豆入口| 欧美性爱第一页久久| 美女诱惑久久| 久久香蕉国产线看观看亚洲女人 | 中文字幕一区二区三区蜜桃视频| 久久99999| 色婷婷蜜臀av| 欧美中文字幕男人天堂久久精品| 久久久久成人蜜桃精品| 五月丁香影视| 色色综合网站| 国产伦精品一区二区三区在线观 | 免费网站观看www在线观| 九九热免费国产视频婷婷伊人| 99热啪啪| 国产99热| 五月婷婷大香蕉| 99热最新网址| 久久久久久欧美精品se一二三四| 久久精品国产72国产精品福利 | 乱抡国产91| 国产一区二区三区视频在线看| 插B在线观看| 亚洲城人男人的天堂| 中文一区在线视频| 欧美日韩黄色片一区二区三区四区人与兽做爱| 亚洲一卡二卡在线免费| 蜜汁欧美| 九九九精品色乱九九九| 国产伦精品免编号公布| 免费又黄又裸乳的视频| 欧美性爱第1 页| 绑缚麻绳人妻寝取完整版| 久久久久久亚洲中文| 97超碰人操| 色噜噜人妻丝袜AV资源| 亚洲一二三精品久久网| 黄色高清无码无码破解免费暗网| 啪啪资源网| h无码动漫在线观看| 少妇高潮对白在线观看| 国产激情av女片自拍| 麻豆啪啪啪视频| 91丨九色丨大屁股| 超91综合网| 蜜桃传媒一区二区亚洲| 久草资源在线视频官方总站日韩丝袜美腿 | 国产嫩草精品A88AV在线| 一级黄碟在线观看| 欧美色图人妻| 中文字幕欧洲有码| 亚洲人妻久久| 大二网站亚洲| 超碰成人公开| 日韩午夜啪啪视频| 又大又白奶子| 亚洲第一页欧美| 久操大香蕉超碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰 | 超碰97.com| 91人妻人人澡人人爽人人精品| 亚洲色天| 久久av一级av少妇av高潮| 唐山老熟妇露脸啪啪叫| 99色综合| 日本一二三高清| 久污| 啊啊啊免费| 100啪啪视频大全| 日本午夜操逼| 屌逼麻豆| 精品一久久久| 99在线精品观看视频中文| 久久久96| 3d成人精品一区二区| 久久xxxx| 老熟女区| 抽插一区二区视频| 日韩性爱啪啪视频| 永久免费发布性爱网| 婷婷色色五月天| 99xav| 99日视频在线免费| 日本操逼视频免费| 久久久久成人亚洲国产| 蜜臀久久一区二区| 亚洲男人的天堂网| 一起草视频在线| 色色色色日本| 国产原创自拍| 欧洲精品久久| 91n美女视频| 夜夜免费视频| 日韩成人高清一区二区| 久草免费在线一区二区| 强奸少妇AV导航网| av日韩中文字幕| 亚洲成人精品在线一区| 91精品国产麻豆国产自产在| 99热在线不卡| 亚洲黄色电影| 久久国产免费激情视频| 国产女人高潮视频| 综合一区二区影视| 日韩欧美亚洲自拍偷拍| 亚洲精品国产精品乱码不99| 国产乱弄免费在线视频。 | 920日本午夜免费| 亚洲精品 欧美精品| 3PAV乱伦视频| 啊视频在线| 美女毛片999| 偷拍亚洲| 91精品丝袜在线观看| 欧美伦乱爱| 亚洲国产精品无码AV久久| 欧美刺激色黄片免费看| 欧美亚洲日韩16色| 日韩在线国产字幕| 综合色色网| 91久久久亚洲| 综合婷婷| 亚洲熟女乱色一区二区三区久久久| 午夜爽爽爽| 熟女字幕| 成人欧美日超碰| 国内精品a| 日本一区二区三区欧美日韩中文字幕| 91色射| 日韩乱中文| 操人妻逼91| 欧美影院一区二区三区| 中文字幕老熟妇黄色视频| 日本三级黄页| 日韩精品第3页| a片自拍直播视频| 成人久久无码www| 蜜臀av网址| 蜜桃AV天堂| av午夜影院在线播放| 欧美A√综合网| 免费视频一二三区| 超碰人人干| 超碰97在线色男人??| 91丨九色丨国产丨人妻在线| 看看小穴| 欧亚日韩一区在线| 一区二区激情国产熟女| 97人人夜| 亚洲欧美中文日韩视频中国语| 黄色片G G G| 91香蕉视频在线观看免费| 日本少妇va7777| 天天色图| 久久久亚洲精品电影免费看| 一区二区三区不卡视频| 欧美综合第一| 欧美97在线观看| 老熟女乱伦片| 亚洲中文字幕有码视频一区二区三区| 国产一区在线看| 一区二区激情国产熟女| 欧美97色| 国产91美女高潮| 精品人妻一区二区三区四区不卡在| 99色在线视频| 国内一级精品| 久久99热这里只频精品6学生| 嗯嗯不要 视频| 在线另类| 天天色欧美| 十八禁网站在线| 亚洲欧美另类激情小说| 97蜜桃综合| 久热精品在线国产| 亚洲激情色片 | 日韩熟女精品无码专区一区二区| 亚洲无992tv| 麻豆久久久久久久久丝袜| 日本高清免费一本视频在线观看| 久久超碰97中文字幕| 人人摸.人人色| 成人熟女区| 婷婷五月天激情网| 亚洲人妻色图| 校园春色综合| 免费观看网黄| 麻豆传媒一区二区在线观看| 人人爱人人操人人性| 97色欧洲| 天天综合网一91网| 国产无码久久高清| 丝袜翘臀后入欧美校园亚洲自拍另类小说一区中文字幕少妇诱惑 | 黑丝少妇在线观看| 翔田千里AV无码秘 三区| 在线视频一区二区传媒| 夜夜天天噜狠狠爱2021| 激情文学小说一区二区| 九九伊人网| 亚洲日韩人妻中文字幕一区| 东京热av男人的天堂| 老司机射| 女人综合网| 美骚妇av高清在线| 在线强奷到舒服的无码视频 | 999 久久久| 91free福利| 大香蕉综合网| 啊啊啊不要好爽日韩无码一区| 秋霞免费AV| 高清无码人妻久久久一区二区三区aⅴ| 97在线国产精品| 性久久| 中文字幕免费在线观看| 91爱综合| 久久直播国产| 超碰美国| 97在线观看免费视频l| 高清无码国产亚洲| 欧美巨大性舒爽顶到了| 欧美国产操逼| 91亚洲黑人| 97精品熟女少妇一区| 亚洲人妻爽爽爽| 色五月69夫妻| 日韩精品一区二区三区色欲| 久久精品国产欧美日韩亚洲欧美日韩中文久久国产一区 | 精品亚洲国产成人av网站| 91女日逼| 国产又大又粗又长视频在线| 手机看av网站在线看| 91美女视频| 欧美日韩亚洲国产中文永久天天看| 亚洲色图激情小说| 黄色AAAAAAAAAAA大片| 草草草视频| 国产情色在线| 97AV爱| 破苞ⅩXXX性无码动漫无码| 黄片视频观看| 精品少妇一区二区| 国产二区三区粉嫩在线| 九九九九久久久| 操逼1区| 九九综合九九综合| 208天天久久九九九| 超碰性爱97| 大香蕉啪啪啪| 国产乱伦亚洲| 青青久久艹| 吊色| 亚洲欧美色综合| 啪啪啪综合网| 久久毛卡| а√天堂资源官网在线资源| 婷婷激情丁香| 91少妇通奸网站| 超硑97精品| 97色色视频| 国产女人操逼视频| 美女操逼A A| 青青草福利视频| 加勒比久久av| 欧美性爱一级操| 国产第12页| 国产农村妇女精品| ...日韩成人一区二区三区字幕| 久久久久亚洲Av无码专区老牛影视| 99re热有精品视频国产| 久久精彩免费视频| 蜜屁Av| 亚洲se91| 天天躁日日躁AAA片李宗瑞| 91精品国产综合久久久蜜臀| 天天天操天天天爱| 国产强奸乱伦欧美| 120分钟婬片免费看| 亚洲青色欧美| 国产精品直播在线观看直播| 亚洲天堂人妻一区二区| 综合色久欲| 免费簧片在线观看| 天天操狠狠日夜夜干超碰撸com视频在线观看 | 岛国免费视频在线| 亚洲综合码| 日韩人妻精品久久久久| a级理论午夜日本| 亚洲AV无线| 日韩av不卡在线看| 日产欧美电影一区二区三区| 国产传媒日韩| 久久久久久久免费A片国产成a人亚洲精∨品无码 | A一区片| 日韩精品-原创伙伴| 我爱操| 无码人妻丰满熟妇区毛片| 亚洲色悠悠久久88| 欧美性爱一区二区三区四区| 午夜天堂精品久久| 久久国产视频专区一二三| 丰满欧美少妇| 欧美日韩高潮喷水91| 99这里只有精品| 五月婷婷六月丁香| 婷婷五月综合在线| 久久久激情| 亚洲操操操| 五月天激情小说网| 发朗少妇买婬全视频中文| 丁香五月天堂网| 欧洲色色| 人人天天欧洲| 国产欧美精品日韩区二区麻豆天美| 99在线免费观看| 看日韩美女二区三区免费操逼视频| 天天爽天天干| 久久久久久久一级黄色打同平台| 久久精品一区二区三区不卡| 97干日韩| 白丝AV网站| 综合天天网| 北野未奈加勒比av| 白嫩白嫩的午夜九久久久久久久久久久久成人剧场 | 自拍欧美| 69久久久久久久久久久久久| 超碰97在线中文| 97少妇人妻中文字幕久久 | 国产av激情无码久久天堂| 人人做天天爱| 视频国产精品未满十八禁止在线观看| 操逼操网| 亚洲黄色影视| 欧美亚性天堂| 国产久久视频| 人妻丰满熟妇一区二区三| 亚洲av综合色区无码一| 欧美成人一区二区三区在线播放| 十八禁啪啦拍视频无遮挡| 日韩三级视频一区二区三区| 大鸡吧尹人在线| 久久鲁夜| 亚洲涩图欧美| 久久在肏| 国产久久免费精品视频| 黄色网址在线免费观看| 五月婷婷激情综合| 6080yy午夜理论三级一区二区三区无码| 四虎影视在线| 在线观看午夜婷婷久久久久清性观看| 精品国产乱码久久久久久日本公司| 亚州欧美在线| 亚洲影院成人| 乱伦1色页| 色情五月婷婷| 91色噜噜狠狠| 9997se| 亚洲久9| 青草草免费网站av| 国产高清无码一区二区三区四区皇冠| 亚洲天堂男人在线| 日日夜夜青青草母狗| 高清孕妇孕交 交孕妇| 97亚洲欧美| 黄色在线网站| 99热66| 久日91在线| 97在线视频免费看| 国产成人拍国产亚洲精品| 狠狠色噜噜狠狠狠狠狠色综合久久| 九九AV| 欧美夜色| 亚洲高清91| 性爱乱伦视频免费| 爱射综合| 天天看高清麻豆| 天天干18禁| 福利操逼| 超91综合网| 偷拍五区| 中国一级αV| 国产呦精品一区二区三区下载| 97视频在线观看播放与子乱对白在线……| 熟女网站最新| 熟女人妻一区二区三区免费看| 成全在线观看免费观看| 五月天综合在线| 91超碰碰在线| 国产精品操| 日本在线播放不卡一区| 毛片17S| 人妻夜爽夜夜爽| 国产女人和拘做爰视频 | 免费精品国偷自产在线在线| 超碰人人超在线观看| 抽查国产福利主播| 四虎av在线| 欧美天天干| 国产视频三区四区| 欧美第五页| 亚洲欧美自拍偷拍| 粉嫩国产精品久久粉嫩| 亚洲欧美91√| 亚洲一区日韩精品| 99热精品在线观看| 黑人粗大V S日韩女优视频| 国产午夜福利专区综合| 色色无码| 天天操狠狠日夜夜干超大胆开放com大香蕉视频在线观看 | 91暧暧| 综合天天网| 狠狠超| 凹凸视频特色日本特黄| 91天天c| 免费A片三p视频| 东京热毛片调教| 国产二区三区免费视频| 国产精品极品美女视频| 99自拍视频在线| 日本九九久久99播| 欧美高潮| 放黄片放3级黄片没穿衣服| 中文字幕日韩精品久久| 久草免费在线一区二区| 97久久精品亚洲| 欧美日韩人妻婷婷一区| 天美传媒婬乱在| 99精品视频在线观看免费| 大香蕉综合| 成人天天看站长推荐| 亚洲区小说| 天天爽夜夜爽夜夜爽精| 夜夜操2028| 精品视频久久区| 操逼www.| 久久久九97| 超碰97护士| 韩国成人精品久久久免费看| 亚洲欧美国产日本一区二区三区| 玖玖综合.com| 啊啊啊啊啊舒服| 盗摄女人妻在线| 亚洲色阁| 亚洲网污污污污| 色嗨嗨在线| 夜夜嗷嗷一区二区| 日本精品一级二级三级| 玖色AV| 丰满人妻一区二区三区免费| 伊人久久婷婷| 亚州欧美在线| 五月激情啪啪| 少妇淫妇久久久久久久| 婷婷色在线| 欲香欲色综合天天伊人| 九九性视频| 日本熟妇人妻一区二区三区| 亚洲成人免费电影| 欧中美三级一区二区三区| 久久久18| 欧美偷拍| 亚洲欲色9532548967一区| 久久久久久9| 人妻精品综合中文字幕在线 | 国产高清MV操逼视频| 色悠久久久av| 国产精品成人蜜臀AV在线| 91精品婷婷国产综合久久| 国产精品亚洲美女久久久久| 少妇高潮一区二区三区在线| 99色热| 亚洲情色欧美| 在线人妻熟女一区二区三区四区五区| 日韩无码人妻| 久久超碰97中文字幕| 国产传媒操逼视频| 久湿久久 | 猛交交| 沈阳熟女高潮对白视频| 干b在线性社区| 一类无码操逼视频| 亚州欧美综合| 九九色综合| 青娱乐休闲视频在线观看| 中文有码第五页| 国产欧美日韩一区二区三区| 国产后入清纯| 久操热| 精品国产Av无码久久久伦古装| 国产婷婷一区| AA特级绝黄| 日韩久射综合| 久久久久久亚洲精品中文字幕人妻|