国产成人欧美一区二区三区vr_久久国产精品人人爽人人爽_国产精品永久免费播放_肉欲啪啪a∨无码精品一区二区_国产超短裙jk丝袜在线_亚洲AV片高清资源在线观看_国模无码一区二区三区久久_国产成年人未进视频_中文字幕无码精品夜_一区二区三区在线视频免费看_亚洲成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)唷0裡ngine層抽象出補(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
返回資訊列表
黑人猛交| 91欧美偷拍| 亚洲欧美综合网| 色鬼在线综合| 色老汉玖玖爱| 亚洲免费成人精品电影| 欧美色性情| 美女黄码视频午夜| 天天干天天日天天射黄色| 国产欧美岛国精品一区| 日韩精品-原创伙伴| 天美传媒Av在线| 国产成人网址| 99色综合| www.婷婷| 人人看人人摸人人色| 日本东京热久久久电影| 亚洲色图A| 久9久精品视频| 久久鲁夜| 97精品视频免费| 婷婷精品视频| 狠狠色婷婷| 婷婷五月天激情网| 亚洲av强奸乱伦| 亚洲成人免费中文字幕| 日韩乱伦视频| 国产真实野战在线视频| 亚洲另类电影| 97操操| 国产成人欧美一区二区三区的国产| 偷拍综合网| 欧美性爱第1 页| 九九九九九精品视频| 久久人妻无码毛片A片麻豆| 午夜福利久久久噜久噜久久综合 | 日本3级一区二区免费| 在线中文字幕| 强奸乱伦大香蕉网| 国产自偷自拍一区| 长长久久免费视频| 97一区二区蜜臀| 丁香五月天婷婷姐| 天天天做天天天爱天天天爽| 青久久| 亚洲综合色在线| 亚洲综合 欧美| 超碰精品人妻狠狠干| 97视频在线视频| 东北女人操比视频| 999熟女精品| 久热99999| 麻豆av一区二区| 96久久久久久久| 国产97在线 | 亚洲| 天天影视色香欲综合网小说| 另类TS人妖一区二区三区| 免费日韩黄片| 色男人色天堂东京热| 精品一区二区三区四区外站| 婷婷午夜清品久久久久久久性色视频观| 国产区在线| 麻豆亚洲AV成人无码久久精品| 91久久婷婷| 日韩欧美亚洲自拍偷拍| 很很热性爱视频| 五月婷婷综合在线| 亚洲综人| 啪啪视频免费在线观看| 97精品熟女少妇一区| 久操精品网| 九九在线视频| 亚洲综合九| 久久亚州大香蕉| 夜夜躁狠狠躁日日躁av| 最新日日夜夜天天干干| 亚洲日韩精品在线播放| 国产精品经典一卡久久久| www.91欧美| 欧美日韩人妻精品系列一区二区三区| 人人妻人射| 两性综合网| 动漫片子网站3黄| 情色五月天就去干| a片自拍直播视频| 国产尹人在线视频免费| 欧美91在线+|+欧美| 综合熟妇一区二区三区| 一区二区免费电影久久| 26uuu国产| 天天舔天天日天天射| 午夜啊啊| 操逼网免费无码视频| 欧美第38页| 欧美一级二级三级| 99色综合| 久久久性爱| 最近2019中文字幕国语免费版| 韩国轻伦国内自拍一区| 天天日天天干少妇日| 久久国产性爱| 色呦呦、国产精品| 青青在线视频日韩欧美| 久久xx| 欧美78| 久久超碰国产一区二区三区| 五月丁香六月婷| 久热大香蕉网站| 日韩欧美大片免费高清啪啪| 久久久爆乳翘臀一线天伦理视频| 亚洲情色 自拍| 萌白酱自拍视频| 黄总AV色图| 曰韩中文人妻视频| 国产91美女高潮| 天天热精品| 日韩乱伦影音先锋| 男人把坤坤插入女人的下体 | 欧美图片偷拍| 亚洲?V高清一区二区三区尤物| 思思在线免费视频| 国产丸一视频| 日本天天吊| 日本色日夜干| 久久久久久大| 精品人妻视频入口| 9999亚洲精品| 久99久视频| 91高清欧美| 九月丁香婷婷| 日韩一级二级三级免费看完整版| 天天综合,91综合永久| 人人操,人人液| 欧美亚洲美少妇一区二区| 国产高清无码一区三区二区| 日韩三级av片| 久久久久中出| av一区二区三区四区| 欧美性爱一区| 久久久久久国产精品免费网站| 色眯眯av| 欧美99热| 伦激情人妻另类人妻| 亚洲限制级| 精品成人亚洲午夜电影| 青青草久久在线| 国产精品自拍欧美在线| 亚洲图片另类| 四虎AV影视国产精品亚洲精品| 69综合网| 巨爆乳肉感一区二区三区竹菊影视| 夜夜国自区| 久久人妻办公室视频| 午夜福利国产欧美日韩夜夜| 久久色AV线| 五月天婷婷色| 成人性爱视频在线看| 91精品操美女| 97久久免费| 一级免费啪啪片| 欧洲性爱无码区| 91影视亚洲| 狠狠操夜夜操蜜桃视频三区| 超碰成人国产| 香蕉国产精品麻豆亚洲欧美日韩| 97久久超碰日韩精品| 97超碰天天| 99热这里只有精品地址| 97在线观看播放视频| 亚洲无码一区成人免费午夜| 啊灬快c我灬啊灬用力灬啊灬-国产精品性做久久久久久-成人AV | 手机在线视频国内精品| 男人的天堂va在线| 国产又长又大又粗的视频| 91色碰| 欧美日韩免费性爱| 欧洲黄色网| 亚洲精品97p| 国产性感骚丝袜在线| 视频黄色国产一级| 亚洲码在线中文在线观看| 91 国产丝袜在线播放-百度| 亚洲无码成人精品| 97在线观| 五月天AV资源| 97av,com| 夜夜骑操视频| 亚洲男人的天堂在线看| 国产嫩草精品A88AV在线| 亚洲精品美女久久久久久久久| 日本黄大片在线观看视频| 限制级中的三级片中的黑粗大屌屌日人妻熟女| 无码视频一区二区| 二对二中文字幕。| 97精品久久久久久久| 久久久久13| 国产亚洲综合欧美一区| 国产三级日产三级韩国三级| 中文字幕亚洲永久精品| 久久久久久久国产a∨| 欧美天天干| 欧美一级黄色免费专区| 九九九精品| juliaann欧美丝袜办公室| 亚洲中文字幕一区| 91bbbbbb| 免费a v| 久热这里只有精品9| 好吊爽好吊爽在线视频,中文字幕精品一区二区日本,国产良妇出轨视频在线观看, | 激情五月天中文字幕色| 国产精品天堂| 欧美色青| 亚洲一区二区在线观看91| 欧美伊人电影| 日韩色| 亚洲不雅视频1区二区| 欧美日韩久久精品爱爱| 色97干| 国产精品剧情| 少妇一区二区三区精选| 偷拍自拍在线视频观看| 婷婷五月天补不补| 五月天综合网| 亚洲se电影| 青草伊人网| 天天躁日日躁狠狠狠躁| 亚洲图片激情小说| 久久五月天婷婷丁香中文字幕| 91av一区二区在线观看| 日韩婷婷| 97视频在线免费看| 久久久久久裸体| 91无码人妻精品一区二区三区蜜桃| 久久久久人| 0755午夜福利视频| 国产精品久久久久久亚洲色欲| 91视频精品| 乳欲人妻办公室奶水| 肉嘟嘟www视频在线观看高清| 操逼视频免费日韩无码| 精品妇女一区二区三区| 亚洲色综网| 亚洲天堂男人天堂网| 国产一级舔足在线观看| 色色色欧美| 凹凸视频特色日本特黄| 99啪| 中文子幕一二三| 丰满人妻-区二区三区免费看| 校园春色亚洲| 欧美视频边做饭边橾| 无码视频黄色网战| 国产97色在线| 欧美在线|亚洲| 免费视频观看60秒| 精品人妻1237| 欧美黑人91| 97视频在线免费观看| 亚洲成人性爱网站在线播放| 五月天开心网| 91熟女.com| 少妇久久| 亚洲夜夜欢无码一区二区 | 久久、1234| 91熟女视频网| 亚洲午夜福利在线影院| 99亚洲人人| 91性网| 加勒比在线观看一区二区| 亚洲免费看片| 五十路三区在线| 近亲乱伦一区二区| 天天插夜夜爽| 亚洲av综合伊人久久| 性爱精品一区| 狠狠操狠狠燥| 白天啪啪晚上啪啪视频| 欧美 亚洲 大香| 快灬快灬 一下爽蜜桃在线观看| A级毛片在线看免费| 懂色综合久久久| 99夜夜操| 午夜精品久久久久久久男人的天堂| 后入式在线免费观看60秒| 色婷婷国产精品一区在线观看| 久久久久国产精品片区无码直播| 欧美亚洲宗合色性图| 国产在线播放成人免费| 中亚av| JuliaAnnXXX888| 爽 好舒服 无码刺激久久| 97在线观看免费视频l| 国产福利一区二| 亚洲熟妇自偷自拍另欧美| 免费视频观看60秒| a在线观看| 夜夜操夜夜高潮夜夜爽国产精品区| 成人免费性爱视视| 操我啊啊啊啊啊| 久久久com| 中文乱码字幕观看| 99999精品视频| 国产9区| 亚洲色人妻综合| 九九亚洲| 国产精品高潮久久AV| 岛国在线国产| 欧色性第一页| 影音先锋国产精品| 91人人| 九九九久千久久激情蜜桃在线看| 老子午夜伦不卡影院| 97综合国产精品高潮久久| 欧美日韩午夜精品一区二区三区| 国产又大又粗又色生活片亚洲国产精品成人久久久综合免费 | 国产人人干| 一起草精品人妻| 亚洲中文字幕久久无码精品| 精品妇女一区二区三区| {男男暴菊gay无套网站| 中文字幕78| 韩国一级做A片免费的| 欧美三四五区| 欧美中文字幕男人天堂久久精品| 亚洲欧美在线观看2021| 亚洲午夜精品久久久中文影院| 亚洲国产欧美日韩人妻日中文| 亚洲超碰97| 97视频620| 亚洲国产一区二区三区四区国产| 夫妻天天操岛国视频| 久久只有精品一区二区三区| 懂色AV蜜臀无码精品APP| 亚洲色电影在线| 九九热超碰97亚洲最新香蕉| 亚洲超碰在线| av在线观看不卡网站| 国产精品久久久鸭无码的功能| 后入式999| 啪啪91| 极品尤物女神在线观看| 综合网 欧美| 久久久不卡区一区二区三区久久久| 亚欧国产无码精品在线| 在线毛片片免费观看| 羞答答AV中文字| 蜜臀久久99精品久久久久免费观| 人妻熟女av国产网站| 免费岛国一级片| 9久9久| 色狠狠综合噜一二三区| 久久XX| 飘花国产午夜精品不卡| 久久久久久久91| 欧洲精品网| 青青草视频爽一爽| 激情婷婷| 亚洲无码色| 欧美一区二区三区蜜桃| 91精品久久久| 高清国产精品无码| 国产精品久久久吖| 国产白丝精品在线观看| 搡老女人老91二区| 91综合天天| 中文在线视频| 丝袜视频网国产90| 欧美线天码中字| 久久久久ab| 超碰97资源中文字幕| 天天做天天爱| 亚洲有码 视频一区| JIZZJIZZ国产精品喷水| 精品久久久久av影院| 黄视频免费| 一区二区三区美女超清| 新亚洲无码| 中文字幕欧美丝袜07资源| 精品二区久久| 亚洲精品 超碰| 六月激情婷婷| 五月天婷婷色色| 国产免费永久精品无码| 亚洲欧美中文日韩视频中国语| www.av在线视频| 日本成人A片免费看| 自拍偷拍第26| 婷婷丁香九月| www黄片免费看com| 亚洲精品久久久久久久蜜桃臀| 日本操嫩b网| av午夜影院在线播放| 干干干天天| 免费精品中文字幕| 亚洲综合一区二区| 狠狠干狠狠干| 国产精品亚洲四五区在线观看| 国产久久一区二区三区野外在线| 97久久免费| 欧美乱妇狂野欧美在线视频| 丁香7月婷婷| 9.1小视频| 夜夜黄| 久操电影网| 91老司机在线| 无码高清操逼网址| 国产精品久久久久久久毛片1| 成人性爱美曰韩| 婷婷久月| 亚洲色图 欧美热图 清纯唯美 另类自拍 | 男人的天堂日韩| 中文字幕精品三级久久久| 九九综合久久| 夜夜嗨一区二区| 亚洲AV资源| 夜夜 中文视频rt| 爱丝福利| jazzjazz国产精品麻豆| 婷婷丁香五月天综合东京热| 色色99| 日韩99神马视频片| 97这里有精品| 久久精品午夜国产亚洲AV无码 | 国产精品久久久九九九| 超碰色图| 国产一区二区a毛片| 五月婷婷激情网| 精品射1999| 亚州九九九精品视频| 97超碰超| 久久精品店| 欧美性猛交美女自慰91| 九久久精品| 青娱乐淫乱1314| 一区二区三区四区免费视频| 欧洲Au麻豆| 国产精品白丝AV| 91被操| 久热无码| 人妻 欧美亚洲| 日本人妻最新在线中| 国产综合网站在线播放 | 九九热国产| 嗯啊抽插大香蕉网页| 婷婷香蕉欧美在线一区二区三区| 97超碰这里只有精品| 色综合av综合久久| 亚洲色婷婷| 久久人妻无码毛片A片麻豆| 2020久久免费视频| 97 亚洲 日韩 欧美 在线| 亚洲欧美激情小说| 大香蕉免费乱伦视频| 91国产大片| 亚洲91在线| 97色婷| 婷婷探花久久精品一区| 人妻人人做人人澡人人爽欧美一区| 五月天春色激情网| 少妇精品久久| 日本久久久久久久久| 一区二区视频在看| 啊灬啊灬啊灬好深灬快高潮了动漫-国产字幕国产在线观看-B049AV | 欧美一二在线| 亚洲无码超碰免费| 精品一区96| 亚洲天堂久久久久久粉红视频| 亚洲色欲天天人妻无码系列专区| 是还免费视频1727我| 激情五月综合开心五月| 欧美se亚洲| 大象AV在线| 天美av在线观看| 久久春色| 丰满少妇一区二区三区四区观看 | 天天干天天日天天射黄色| 男人综合网| 另类小说五月天| 亚洲天堂另类| 91爱综合| 一区二区三区高清天码| 一区二区三区成人| 白嫩国模丰满一二三区| 国产精品伦理| 亚洲,欧美,春色,另类| 国产极品馒头逼| 男人的天堂2018东京热啪啪啪| 91欧美综合| 青青草视频爽一爽| 午夜亚洲国产理论秋霞| 9 1果冻精品视频| 91麻豆天美国产欧美| 久久亚洲中文字幕视频| 国产久久一区二区| 九九黄色网| 秋霞怕怕片| 久操九九九九九九九九九九九九九九九九九九九九九九九九九九九九 | 日影院久久婷婷夜夜网| 欧美亚洲中文字幕| 97色碰| 久久大线蕉一区| 久久夜黄色无码A级大片| 91亚洲狠狠色| 欧美三级免费伊人| 男人的天堂一区三区| 丝袜AV一区二区三区| 国产男女无套97| 91精品无码人妻系列| 熟妇一区二区| 91色色综合| 成人情色一区二区| 99国产精品视频尤物| 午夜啊啊| 试看60秒| 日韩美脚一区二区网站| 60秒免费小视频| 久久99精品视频| 日本在线观看网址| 亚洲中文字幕av| A啊啊在线观看| 精品国产精品一区二区| 欧美性生活免费网| 国产精品扒开腿做爽爽爽视频| 熟妇精品juliaannAV| 国产激情视频在线观看| 天天操夜夜嗨| 在线播放成人高清免费视频| 综合熟妇一区二区三区| 久久精品夜色国产亚洲AV| 色久综合| 国产AV超爽| 中文字幕,人妻,日韩| 人妻丝袜二区| 香蕉国产97| 欧美亚洲AN| 97久精品| 九月丁香| 国产精品老师| 久久精品店| 无码国产Av| 亚洲欧美国产中文视频| 国产精品9999| 男人的天堂Va| 午夜噜噜噜| 五月天人妻综合| 激情视频一二三| 久久超碰大香蕉| 岛国小电影| 亚码激情| 青青草原综合久久大伊人精品| 爽爽淫人网| 五月丁香啪啪网| 国产无码一二三区| www.色操逼| 国产三级中文有码在线视频| 国产精品999zyz| 性色生活片久久毛片婬片免费放女人一级毛片| 搡老熟女免费视频| 波多野42部激情无码喷潮| 国产极品馒头逼| 中文字幕三四区| 夜夜精品视频| 1769成人国产精品视频| 亚洲九九九| 992视频一区| 免费操逼视频下载| 国产男女无套视频免费观看| 在线观看黄色电话| 中文激情网| 吻戏激情性巴克| 欧美专区第一页| 老女人日韩美91| oumeisetupian| 久久綜合很很很| 久久久久久9999| 久久久成人精品| 中文字幕无码不卡啪啪| 欧美日韩制服| 国产1024在线播放| 天堂а√在线最新版在线 | 欧美操逼一二三区| 日韩伦理视频| 亚洲欧美在线综合| 欧美姓爱综合网| 超碰78| 久久性爱精品一区| 牛黄色久午久| 熟妇人妻一区二区 | 日本操嫩b网| 夜夜草网站| 国产怡红院| 国产一区二区三区久久精品太古里| 亚洲91综合| 资源新线在线天堂| 91香蕉视频在线观看免费| 欧美日韩国产色图在线| 久久久9视频| 超碰97在线中文| 亚洲精品91| 国产一级特黄大片处女| 国产这里只有精品| 久久綜合很很很| 国产精品白丝www| 免费观看性欧美一级| 亚洲第一成人影院色播| 一区中文字幕二区日韩| 国产白丝网站| 午夜一区二区三区国产| 亚洲AV无码天美传媒一区| 天操老女人| 97国产超碰| 亚洲成?V人片在线观看福利| 男人天堂站| 色狠狠一区二区三区香蕉| 99亚洲国产精品色一区二区三区| 日本 欧美 国产一区| 啊啊啊在线观看免费视频| 九九九九九九综合| blacked精品一区国产| 久久综合乱子伦国产免费| 天天干人妻视频| 午夜福利无毒不卡| 久久精品视-一级做a爰片性色毛片16美国-中国女与老外在线精品 | 91麻豆天美国产欧美高潮| 国产v片在线免费观看| 九九综合久久| 国产精品久久久午夜夜伦鲁鲁| 久久无码一区二区二三区性色| 亚洲 日本 一 二 三| 久久久久久裸体| 中日亚韩免费视频| 台湾肥佬网一区二区三区| 青青草久草| 五月丁香综合激情| 亚洲第一视频 欧美风情 日韩| 操逼逼中文字幕| 日本精品免费一区二区三区四区| 一区二区乱码福利| 人妻天堂综合网| 好涩综合| 久久综合九九| 天天操天天干美女网址导航| 性爱乱伦一区| 人人九九精| 操逼不卡中文字幕| 色香欲天天天天综合色| 日本性爱网址| 区自美91| 激情看片网站| 美女黄页网站| 亚洲一区二区三区久久 亚洲一区二区| 九九九九热只有精品| 成年女人18级毛片毛片免费观看| 日本道日本道中文字幕日本道最新日本道在线观看 | 日本日皮视频逼| 欧洲自拍第一页| 一级性爱aaaa| 日韩91网站| 中文字幕一区 二区三四五 区日 日骚| 色亚洲欧美| 开心五月天激情网| 国产精品人妻免费精品| 蜜臀精品1区2区| 日本高清视频xxxx| 国产久久久久影院老熟女| 特级丰满少妇一级AAAA爱毛片| 91少妇通奸网站| 亚洲国产欧美中文永久| 91天天综合日韩欧美| 香蕉一区二区三区在线视频| 澳门黄片一香蕉视频| 91国产美女丝袜足交精品视频| 美女午夜福利免费视频| 欧美BT 亚洲色图| 男人的天堂2018东京热啪啪啪| 国产一区二区成人av在线播放| 久久久久久久久久久999| 欧洲成人性爱视频| 中国91AV| 啊操爽品善一区二区三区| 亚洲乱码国产乱码精网站| 青青草原香蕉日本Ap| 日韩AV电影网站| 飘花国产午夜精品不卡| 亚洲双插| 日韩少妇丰满亚洲| 自拍偷拍2025在线观看| 亚洲高清视频在线免费观看| 欧洲精品人妻| 久久一二三四五六七八九区区区| 欧美日韩电影成人在线| 老司机香蕉| 在线视频一区二区传媒| 91一起操| 综合av社区| 97色欧洲| 老鸭窝黄色视频网站| 日韩精品99999| 一级性爱啪啪视频| 国产精品久久久久久久久久久久久久吹| 亚洲人在线| 91丨九色丨43老版熟女| 亚洲精品国产日韩无码AV永久免| 又黄又硬又粗又长国产视频| 1204金沙人妻懂旧版免费| 激情小说五月天| 干日本人少妇午夜寂寞影院| A级片一区| 一本大道青青| 欧美黑人极品高潮喷吹熟女黑人性暴力日韩在线欧美极品一区二区老师 | 综合第一页| 91撸色网 玖玖网 欧美| 日韩欧美天堂| 亚洲综合影视| 欧美后进式| 熟女六十路| 国产大陆天天艹| 草草电影院| 97久久超碰日韩精品| 东北操逼| 超碰地址97| 欧美黄色图片| 青青操青娱乐| 六月婷婷色综合| 最新日韩黄片| 黄色小视频日本txt| 国产亚洲精品A在线观看下载| 亚洲资源站| 麻豆天天躁天天揉揉AV| 97精品97久久| 亚洲AV不卡在线观看尤物| www老逼91| 蜜桃色色网站视频三区| 99熟女| 欧美精品自慰系列寂寞少妇 | 亚洲色色色| 中文字幕性感少妇av| 最新中文字幕精品在线| 国产精品麻豆视频网站| 国产女同视频在线播放| 亚洲性爱成人| 在线有码中文字幕| 国产乱色国产精品免费视| 26uuu久久| 亚洲精品一二牛牛| 亚洲一卡二卡在线免费| 国产精品人妻一区二区| 精品无码一区二区三区| 日本韩国国产精品一区| 一区二区免费电影久久| 日本高清免费一本视频在线观看| 免费精品国偷自产在线在线| 免费观看成人www精品视频| 国产强奸乱伦欧美| 久久精品福利影院| 国产欧美精选激情视频| 国产人妖视频一区在线观看| 亚洲 日韩 丝袜 熟女 变态| 免费A V在线播放| 五月丁香社区婷婷日韩欧美精品影院 | 亚洲影院无码在线| www.亚洲成人一区| 天天色,天天干,天天干| 8050午夜少妇无码| 天天射,天天操,天天爽-国内精品一区二区三区-成人AV | 嗯啊抽插大香蕉网页| 亚洲成人美女无吗| 婷婷伊人网| 欧美色图天堂在线| 色欲人妻一区二区在线| 日韩人妻精品| 精品1区2区3区| 91社区伊人| 亚洲精品一二区| 中文字幕jul-617人妻熟女| 韩国一区二区精品亚洲| 青青操在线亚洲视频观看欧美在线 | 校园春色AV天堂| 中文操逼字幕| 亚洲色图殴美色图激情乱伦| 夜夜操2028| 久操大香蕉超碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰碰 | 日韩无码a片| 亚洲天堂 视频你懂的| 人人妻人人操人人乐| 亚洲91网站| 中国91AV| 欧美黄色片在线播放| 免费视频a级毛片免费视频| 日韩影片中文字幕一区二区三区| 任你干在线视频| 精品九九九九九| 欧美不卡二区| 青青欧美在线| 亚洲AV色图一区| 无码137片内射在线影院| 国产福利第一视频| 国内操逼视频二区| 神马麻豆福利院| 欧美人妻久久精品二区三区| 色香阁在线| 天天综合网合集91| 天天躁日日躁AAAAXXXX国产| 91狠狠综合久久久| 日本久久999| 日本羞羞的视频在线播放| 中文字幕一区二区三区视频播放| 在线97在线| 欧美色宗合| 国产粉嫩出水在线播放| 久久国99999| 东京热一区二区中文字幕| 囯产乱伦一区二区三女| 国产亚洲精品美女| 超清福利精品视频在线| 亚洲精品久| 亚洲一区二区av| 曰韩av中文字幕专区| 今日头条成人一区二区三区四虎精品| 丰满人妻一区二区三区蜜桃视频| 亚洲成人久久美女| 青青操视频在线| 日本免费中文字幕在线| 中文字幕人妻色偷偷久久皮 | 午夜精品视频777| 欧美91色| 成人免费福利在线观看| 日韩精品9999| 中文字幕,人妻,日韩| 国产精品视频电影| 日本影视久久免费| 不卡超碰护士AV在线免费播放| 精品人妻丰满熟妇一区二区三| 日本精品高清一二区一本到| 天天插天天操天天摸天天射天天看| 美日韩男女操屄视频| 久久久久无码| 精品无码秘 人妻一区二区| 麻豆 欧美 日韩| 久久久久久久97| 久操视频免费在线观看| 东京热天堂网| 色狠狠综合噜一二三区| 一区AV| 免费久久9999| 搡老女人老妇女AAA一VU麻豆| 天天天天天天天天综合| 国产亚洲美日韩Aⅴ中文字幕无码成人| 9久久美女首页| 免费亚洲黄色视频在线观看| 一区二区三区色综合| 欧美日韩性爱操大逼| 日本熟妇自慰性高潮一区二区三区| 精品一啪| 97chaopengongkai| 麻豆60秒| 性色av大全| 十八禁一区二区无码观看| 老司机射| 九热久| 玖玖爱综合| 为用户提供免费看黄网址在线观看| 狠狠2050在线观看| 色爱综合网| 超碰95| 色婷婷久久综合超碰| 日本色色色色色视频| 欧美少妇高潮| 情色av电影| 3P乱轮视频| 91欧美网| 熟妇艹鸡八| 911粉嫩人妻| 99热| AV色五月天| 超碰79人人乐| 911av网站免费观看| 撸无码不卡免费视频| 厕所偷拍在线| 333kkkk·亚洲com久久| 亚洲97综| 国产精品动态一区二区三区四四| 色婷婷电影网| 福利操逼| www.男人的天堂| 亚洲97p| 九九九九九九九精品视频| 国产操逼网站亚洲一级黄色| 人人操人人射人人干| 天天射影院| 久久精品中文字幕观看| 中文区中文字幕免费看| 人妻爽爽啪视频| 五月天成人综合| 福利社区午夜一区二区| 欧美色图20p| 无码人妻丰满熟妇区毛片| 亚洲情色五月天| 深田咏美亚洲精品福利社| 亚洲电影中字一区二区| 精品日韩产品在线,日韩在线不卡视频,欧美日韩免费专区/久, | www久久国产精品| 久久久久久人| 亚洲欲| 日本青青草在线| 综合色久| 在线观看国产黄色| 欧美一级黄片视频在线| 人妻三级在线中文字幕| 美女t无毒不卡不卡| 97干综合网| 精品小视频在线| 欧美熟爽综合| 99热免费| 九色婷婷| 色小视频蜜乳| 国产人妖视频一区在线观看| 国产午夜福利电影免费在线观看| 91高潮| 天天操妹子| 一二区在线观看视频| 色亚州人久干视频在线观看免费版| 欧美 综合| 日本一区二区三区欧美日韩中文字幕| 五月丁香成人网| 日韩精品一区的| 户外裸露刺激视频第一区| 强奸乱伦大香蕉| 九X超碰| 亚洲激情 欧美色图| 精品网站9999| 亚洲免费精品一区| 国产怡红院| 精品无码一区二区| 无码欧美有限公司| 日本亚洲vr欧美不卡高清专区| 亚洲欧美精品91| 激情五月天网| 人妻啊啊人妻啊啊| 啪啪91| 欧美性,亚州色| 欧美日本久久精品一区 | 色香综合天天影视综合 | 日韩欧美麻豆大片| 啊啊啊com| 亚洲第一页欧美| 先锋音影AV| 色婷婷一区二区三区久久午夜| 丝袜天堂网| 97在线/亚洲| 五月情色天| 思思久热在线精品66| 欧美gv在线观看| 强奸国产在线| 91干熟女| 亚洲色婷婷| 狠狠躁AV| 搞中出视频在线观看| 久久久精品一区二区| 欧美综合自拍亚洲综合图| 91国产丝袜白虎| 神马久久午夜| 伊人专区一区二区三区| 天天综合网日韩7799| 1769精品一区二区三区| 伊人久久88国产女| 91精品人妻一区二区-全集完整版免费正片国语-B02AV | 色综合中文字幕不卡| A啊啊在线观看| 亚洲怡春院| 亚洲资源站| 国产精品一区二区亚洲人成毛片 | 舔人妻中文免费视频| 国产精品夜夜| 亚洲另类欧美精品| 8050午夜少妇无码| 久久精品欧美一区蜜桃| 91国产美女丝袜足交精品视频| 大香蕉日韩欧美| 试看60秒 爽| 久久一区二区高清免费| 99视频内射三四| 884t在线| 97K超碰在线| 狠狠操官网| 色人久久| 91五月天| 好吊色综合| 国产亚洲美日韩Aⅴ中文字幕无码成人| www.激情| 欧美91网站| 美女久久久久久久久久久| 日韩精品碰碰| 97国产色综合| 夜夜做夜夜爽精品视频| 无码人妻一区二区三区色欲aⅴ | 在线视频一区二区传媒| 91痴汉| 亚洲精品性爱片| 在线观看一卡二卡| 欧美国产操逼| 强奸乱伦AV一天堂网| 色五月综合网| 久久精品视| 国产综合色精品在线观看| 第一高清av中文字幕| 欲射影视| 秋霞一集毛片观看| 欧美有码激情视频一区二区三区| 日韩精品国模| AV在线性爱| 999久久久九| juliaann欧美丝袜办公室| 亚洲乱码国产乱码精网站| 好看的91视频| 偷拍精品一区二区三区| 五月花婷婷| 久久99干一本高清| 国产操偷| 色天堂综合| 内射夫妻三片| 91美腿丝袜在线观看| 91第一页| 成人丁香五月| 亚洲日韩黑丝| 久久久免费懂色| 成人一二| 人妻一区二区三区| 国产精品96久久久久久| 久久久久国产无av| 91男人综合| 国产强奸超碰AV| 亚洲色图综合网| 久久美女国产| 99re这里| 欧美大香蕉同搞| 熟女高潮合集-永久久久-成人AV| 日韩免费高清大片在线| 欧美超碰96| 人妻献身系列第54部| 91久久18禁| 日韩乱伦AⅤ| 亚av顶级裸体一区二区三区四区五区 | 久久久久白虎| 五月婷婷六月天| 大香蕉狠狠爱| www.狠狠干.coom| 国产捆绑一区| 天美一二三在线观看Av| 国产无马在线| 60秒免费小视频| 美国aaaaa一级黄片| 色一区二区三区综合| 日本在线不卡一二区| 九九九精品美女| 天天肏美女| 嫩草美女久久| 亚洲青青草| www.久久久久| 色99999| 亚州 综合 色图| AV无码久久久精品| 大香蕉人妻久久| 九九久久久久久爱| 在线观看免费视频国产| 91在线一起| 亚洲AV小说| 午夜无遮挡男女啪啪视频| 成人一级二级| a久久| 91看黄片| 国产精品3| 亚洲性综合9| 日韩中文字幕精品一区在线| 哑洲在线| 亚洲熟妇乱女区二区三区| 尤物黄色在线观看网站| 精品免费成人久久| 淫色网综合| 国产浮力影院第1页| 女人综合网| 综合视频91| 精品丰满人妻一区二区三区免费观| 岛国黄片网站| 久久久性少妇| 久久人人爽爽爽人久久久| 天堂中文资源在线bt| 欧美第二页| 劲爆欧美人妖三区91| 五月丁香六月| 在线播放一级无码视频| 国产sv美女内射| 性爱AV天堂| 麻豆人妻精品一区二区| 免费一级黄色录像影片| 美女诱惑久久| 丝袜色综合| 99爱久久视频频| 久久久久国产无av| 岛国片在线播放| 777超碰| 欧美第一页| 97内射偷拍| 五月丁香综合激情| 日韩丰满熟妇| 一级性爱视频免费观看| 羞答答AV中文字| 超碰1024久久| 欧美极品女人的天堂| 亚洲乱码国产乱码精网站| 极品销魂美女一区二区 | 五月天成人综合| 一本一道波多野毛片中文在线| 亚洲学生妹高清av| 欧洲人妻视频| 91人妻久久久久久久久久久久久| 99999精品视频| 性吧在线视频| 精品一区二区成人动漫| 99热久| 国产一区二区在线播放| 亚洲熟妇白浆无码AV| 天堂麻豆天美| 色一射色一射| 防屏蔽在线视频| 999岛国大片| 国产1769在线| 中国zzijzzijzzwww精品| 一级性爱视频免费在线| 天久久久噜噜噜久久国产精品爽爽| 欧美综合色综合| 2017天天透天天通天天擦| 欧美精品偷拍| 97视频在线| 久久超碰com| 亚洲人妻色图| 偷拍导航视频网站| 国产久9| 久久国产精品视频| 天天热精品| 欧亚日韩综合精品国产| 91美女看B| 东北女人操比视频| 日韩欧美偷拍美女视频| 台湾大香蕉99热| 亚州色图狠狠干| 国产精品欧美激在线| 中文字幕版| 日日夜夜青青草母狗| 97国产天堂岛| 91色色综合| 亚州色图片在线色| 大香蕉综合在线| 亚洲爱爱视频一区二区| 精品国产久久乱码| 热久久无毒不卡| 超碰色大香蕉| …亚洲黄色厕厕女女在线播…| 91色香| 一级做a爰片性色毛片久久|