KITAQ SERIES • 參考版
驗證紀錄
已確認的執行畫面
原始碼快照:2026 年 9 月 14 日 · 繁體中文版:2026 年 9 月 14 日
原生編譯器驗證
Windows、Linux、macOS ARM 和 macOS Intel 的原生建置及執行驗證均成功。KITAQGB 在每個環境通過 48 項測試與 395 項輔助工具檢查;KITAQFC 通過 55 項測試與 401 項檢查,也驗證了 Rust 1.85。PUBLIC_DISTRIBUTION.json 記錄已配置程式的雜湊與驗證來源。公開 GitHub Actions 會獨立建置及驗證這些原始碼。
保存的參考輸出用於檢查 ROM 位元組、診斷與輔助工具格式。先前的 C# 模擬器驗證保留為對應原始碼指紋的歷史紀錄,並不自動證明所有 Rust API、實體硬體或完整的 FDS BIOS 遊戲啟動。原始 PNG 轉換腳本無法取得,因此依規格重新實作,不能宣稱與原腳本位元組一致。
2026-10-03 本機程式庫差異與驗證
已將 C:/kitaqgb_project/lib 的原始碼與公開版 2de7f4b 比較。僅憑時間戳記無法確定哪個版本較新。本機版有新增功能,公開版也有其他新增功能與修正。以下說明針對保存的本機原始碼,與原有公開 API 的驗證紀錄分開。
physics2d.c 保留接觸 API,並透過 KQ2D_CACHE_SURFACE 提供快取接觸與速度限制實作。啟用時須預留 ROM bank 13。定義 KQ2D_EXTERNAL_SCALE_Q8、KQ2D_EXTERNAL_REST_COMPONENT 或 KQ2D_EXTERNAL_SURFACE 時,呼叫端須提供對應實作。下列 8,872 項測試使用未定義這些選項的預設路徑。
KQ3D_BODY_SPHERE=0x04 選擇球與盒的接觸處理。球半徑為 half_x。kq3d_overlap_sphere_aabb(sphere, box) 包含相切邊界;指標為 NULL 或半徑不大於 0 時回傳 0。沒有專用的球與球求解器。座標差、乘積與平方和須保持在各自的 16 位元範圍內。
帶有 KQ3D_BODY_KINEMATIC=0x02 的活動 body,即使逆質量為 0,也會在 kq3d_step 中更新 X/Y 速度和位置。Z 位置和速度不變。逆質量為 0 的 body 不會被接觸推移。kq3d_integrate_body 仍跳過靜態 body。break_speed 和 KQ3D_BODY_BROKEN 不會自動觸發破壞。
本機 bank_switch 寫入 kq_bank_current 與位址 0x2000。它與公開版的 __bankswitch 路徑不同,不更新編譯器的 bank 追蹤狀態。應從固定 bank 切換;需要維護編譯器還原狀態時使用 __bankswitch。
本機 cgb_bg_color/cgb_obj_color 及單色 RGB 包裝函式未啟用調色盤索引自動遞增。CGB 執行確認 0x1234 的低位元組被 0x12 覆寫。請使用公開版修正或 colors 陣列 API。DMG 不執行寫入。
本機 metasprite_draw 僅在全部完成時將使用數增加到 first_id+count。到達 40 個上限而提前回傳時不會更新。first_id=39、count=2 時回傳 1,槽位 39 啟用,使用數為 0。公開版在處理每個槽位時更新使用數。
本機版提供 vram_get_queue_used 和 vram_get_queue_free,但沒有公開版的 vram_get_queue_capacity。容量可使用 VRAM_QUEUE_MAX,預設 32。登記一個命令後,已用 1,空餘 31。
wire3d_dmg.h 僅在 96 行設定宣告 DrawRect2D。DrawBoxEdges2D 在兩種設定均有宣告,DrawIndexedEdges 僅在 120 行設定宣告。請選擇一個與設定對應的原始檔。本次未重新驗證這些函式的繪製結果。 保存的 lib 原始碼中未找到 DrawRect2D 或 DrawBoxEdges2D 的實作。這些僅為宣告,呼叫需要另外提供實作。
本機 audio_vblank 不含公開版的 AudioVBlank_QueueReset/QueueRefill/QueuePlay 和 audio_vblank_queue.inc。ZX0 也僅存在於公開版。這些屬於公開版新增功能,不計入已驗證的本機功能。
kq3d_overlap_sphere_aabb
u8 kq3d_overlap_sphere_aabb(const KQBody3D* sphere, const KQBody3D* box);KQ3D_BODY_SPHERE=0x04 選擇球與盒的接觸處理。球半徑為 half_x。kq3d_overlap_sphere_aabb(sphere, box) 包含相切邊界;指標為 NULL 或半徑不大於 0 時回傳 0。沒有專用的球與球求解器。座標差、乘積與平方和須保持在各自的 16 位元範圍內。
本次執行的驗證
2D 預設路徑:透過 KOKURA C API 自動選擇硬體,8,872 項全部通過。檢查了速度限制、接觸、有號 Q8 乘法與接觸時刻。這不是分別指定 DMG/CGB 的測試。
19 項物理邊界測試在 DMG 與 CGB 各執行一次,共 38 次全部通過。獨立的 3D 擴充與精靈/VRAM/調色盤重現測試也在兩種模式符合預期。調色盤和精靈結果是成功重現缺陷,不是確認正確運作。
這些結果是 C# 編譯器產生 ROM 的模擬器驗證,不證明 Rust 等價性、實機、音訊、繪製或所有 API 的正確性。原有圖片與測試仍是綁定到各紀錄原始碼指紋的歷史結果。
原始碼指紋、輸入、預期值、實測值與重現步驟 · evidence.tar.gz · verify_rom_cases.py · verify_surface.py
擷取畫面
模擬器擷取畫面會顯示在範例說明旁。請將輸出與列出的預期結果比較;僅憑畫面無法驗證聲音、控制器輸入、周邊設備或實體硬體的行為。
顯示提供的字元集 gb_font
目的: 了解提供的原創字型包含哪些字母、數字與標點符號,以及如何繪製。
運作方式: m_init 準備顯示與字型。m_text 繪製各列,m_put 則以字元碼 34 繪製雙引號。
操作方式與預期結果: 請確認有 26 個大寫字母、26 個小寫字母、10 個數字及 30 個標點符號,並檢查每個字形是否清晰可辨。無須輸入操作。

第一次顯示文字 gb_hello
目的: 學習啟動 ROM 並在背景繪製文字與數字的基本步驟。
運作方式: m_init 後,m_text 繪製問候文字,m_number 格式化 42。最後的迴圈等待影格並保持畫面顯示。
操作方式與預期結果: 畫面顯示 HELLO WORLD 與 042。前面的零來自三位數十進位格式。

使用較寬型別的中間值運算 gb_arithmetic
目的: 學習如何保留超出八位元範圍的中間結果。
運作方式: (u16)200 + 100 的結果為 300。程式先除以 10,再轉為 u8 顯示。請注意,擴大型別的轉型發生在加法之前。
操作方式與預期結果: 030 表示計算結果 30。

分支與迴圈 gb_control
目的: 在簡單計算中試用 for、continue、while、do/while 與 switch。
運作方式: 將 0 到 7 相加但略過 3,得到 25。while 迴圈推進至 30,do/while 推進至 32,switch 再選擇 case 32 並指定 42。
操作方式與預期結果: 042 是這些迴圈與分支的最終結果。

函式、陣列、結構與指標 gb_aggregate
目的: 學習如何將值分組,並透過函式與指標存取。
運作方式: 程式複製包含 (10,20) 的 Point,再透過指標將 1 至 4 寫入陣列。它將函式結果 30 加上陣列值 1、2、4 與常數 5。
操作方式與預期結果: 總和顯示為 042。請追蹤結構複製、ptr[i] 寫入與函式傳回值。
![函式、陣列、結構與指標:總和顯示為 042。請追蹤結構複製、ptr[i] 寫入與函式傳回值。](../verification/gb_aggregate.png)
位元旗標與緩衝區複製 gb_bits_memory
目的: 將旗標打包成一個位元組,並將緩衝區複製至另一個儲存區。
運作方式: __memset 清除四個位元組。程式設定位元 3、切換位元 1,再以 __memcpy 複製全部四個位元組。
操作方式與預期結果: 目的緩衝區的第一個位元組顯示為 010,其中位元 3 貢獻 8,位元 1 貢獻 2。

計算按鈕新按下的次數 gb_input
目的: 區分按鈕剛按下與持續按住的狀態。
運作方式: 每個影格都會呼叫 input_update。只有 input_pressed(BTN_A) 為真時,計數器才會增加。
操作方式與預期結果: 初始值為 000。按 A 後變成 001,持續按住不會累加。放開後再按一次便變成 002。此位元組計數器會從 255 回繞至 000。

Q8.8 定點數相乘 gb_fixed
目的: 學習將整數轉為 Q8.8、相乘,再轉回整數。
運作方式: fix_from_int 將 3、4 轉成 Q8.8,fix_mul 將兩者相乘,fix_to_int 再將乘積轉回整數。
操作方式與預期結果: 012 表示 3 × 4 = 12,是轉換後的整數,不是內部放大 256 倍的值。

從固定物件池配置 gb_entity
目的: 從固定的一組槽位建立物件,無須動態配置記憶體。
運作方式: entity_init 重設物件池。entity_create 在 (20,30) 建立型別 1;程式先檢查失敗 ID 0xFF,再將 vx 設為 2。
操作方式與預期結果: 001 是啟用中的物件數,不是 ID 或座標。此範例不更新或繪製物件,因此不會出現移動角色。

將診斷值記錄至 RAM gb_debug
目的: 將具名遊戲值保存在診斷緩衝區,與畫面顯示分開處理。
運作方式: 程式初始化除錯功能,將影格標記設為 1,並以 HP 為名稱記錄值 42。
操作方式與預期結果: 001 是追蹤項目數。HP=42 存於診斷緩衝區,僅靠畫面無法顯示或驗證該內容。

儲存位置歷程 gb_chain
目的: 學習如何將位置軌跡儲存在環形緩衝區中。
運作方式: chain_init 掛接可容納四個點的陣列,接著 chain_push_head 記錄 (20,30)。
操作方式與預期結果: 042 是固定完成標記,不是座標或數量。請檢查 trail 與 points 以確認儲存的歷史。此程式不繪製跟隨的身體。

讀取函式庫影格計數器 gb_system
目的: 觀察以影格計數的等待如何影響函式庫影格計數器。
運作方式: system_init 後,程式呼叫兩次 system_wait_vblank,再顯示 system_get_frame8。
操作方式與預期結果: 結果為 002。閒置迴圈使用手冊輔助函式 m_wait,因此顯示值不會持續增加。

選取目前場景 ID gb_scene
目的: 學習如何選取 ID,以區分標題畫面、遊戲進行等場景。
運作方式: 程式登錄兩個以零初始化的 SceneDef 項目,再以 scene_change 選取 ID 1。
操作方式與預期結果: 001 是 scene_get_current 傳回的目前 ID。此範例未註冊場景回呼或轉場繪製。

顯示提供的字元集 fc_font
目的: 了解提供的原創字型包含哪些字母、數字與標點符號,以及如何繪製。
運作方式: m_init 準備顯示與字型。m_text 繪製各列,m_put 則以字元碼 34 繪製雙引號。
操作方式與預期結果: 請確認有 26 個大寫字母、26 個小寫字母、10 個數字及 30 個標點符號,並檢查每個字形是否清晰可辨。無須輸入操作。

第一次顯示文字 fc_hello
目的: 學習啟動 ROM 並在背景繪製文字與數字的基本步驟。
運作方式: m_init 後,m_text 繪製問候文字,m_number 格式化 42。最後的迴圈等待影格並保持畫面顯示。
操作方式與預期結果: 畫面顯示 HELLO WORLD 與 042。前面的零來自三位數十進位格式。

使用較寬型別的中間值運算 fc_arithmetic
目的: 學習如何保留超出八位元範圍的中間結果。
運作方式: (u16)200 + 100 的結果為 300。程式先除以 10,再轉為 u8 顯示。請注意,擴大型別的轉型發生在加法之前。
操作方式與預期結果: 030 表示計算結果 30。

分支與迴圈 fc_control
目的: 在簡單計算中試用 for、continue、while 與 if/else。
運作方式: for 迴圈累加 0 至 7,但跳過 3,得到 25。while 迴圈將值增加至 32;接著的 if 在值相符時指定為 42。
操作方式與預期結果: 042 是最終結果。此程式使用 if/else 分支。

函式、陣列、結構與指標 fc_aggregate
目的: 學習如何將值分組,並透過函式與指標存取。
運作方式: 程式複製包含 (10,20) 的 Point,再透過指標將 1 至 4 寫入陣列。它將函式結果 30 加上陣列值 1、2、4 與常數 5。
操作方式與預期結果: 總和顯示為 042。請追蹤結構複製、ptr[i] 寫入與函式傳回值。
![函式、陣列、結構與指標:總和顯示為 042。請追蹤結構複製、ptr[i] 寫入與函式傳回值。](../verification/fc_aggregate.png)
位元旗標與緩衝區複製 fc_bits_memory
目的: 將旗標打包成一個位元組,並將緩衝區複製至另一個儲存區。
運作方式: __memset 清除四個位元組。程式設定位元 3、切換位元 1,再以 __memcpy 複製全部四個位元組。
操作方式與預期結果: 目的緩衝區的第一個位元組顯示為 010,其中位元 3 貢獻 8,位元 1 貢獻 2。

計算按鈕新按下的次數 fc_input
目的: 區分按鈕剛按下與持續按住的狀態。
運作方式: 每個影格都會呼叫 input_update。只有 input_pressed(BTN_A) 為真時,計數器才會增加。
操作方式與預期結果: 初始值為 000。按 A 後變成 001,持續按住不會累加。放開後再按一次便變成 002。此位元組計數器會從 255 回繞至 000。

Q8.8 定點數相乘 fc_fixed
目的: 學習將整數轉為 Q8.8、相乘,再轉回整數。
運作方式: fix_from_int 將 3、4 轉成 Q8.8,fix_mul 將兩者相乘,fix_to_int 再將乘積轉回整數。
操作方式與預期結果: 012 表示 3 × 4 = 12,是轉換後的整數,不是內部放大 256 倍的值。

從固定物件池配置 fc_entity
目的: 從固定的一組槽位建立物件,無須動態配置記憶體。
運作方式: entity_init 重設物件池。entity_create 在 (20,30) 建立型別 1;程式先檢查失敗 ID 0xFF,再將 vx 設為 2。
操作方式與預期結果: 001 是啟用中的物件數,不是 ID 或座標。此範例不更新或繪製物件,因此不會出現移動角色。

將診斷值記錄至 RAM fc_debug
目的: 將具名遊戲值保存在診斷緩衝區,與畫面顯示分開處理。
運作方式: 程式初始化除錯功能,將影格標記設為 1,並以 HP 為名稱記錄值 42。
操作方式與預期結果: 001 是追蹤項目數。HP=42 存於診斷緩衝區,僅靠畫面無法顯示或驗證該內容。

儲存位置歷程 fc_chain
目的: 學習如何將位置軌跡儲存在環形緩衝區中。
運作方式: chain_init 掛接可容納四個點的陣列,接著 chain_push_head 記錄 (20,30)。
操作方式與預期結果: 042 是固定完成標記,不是座標或數量。請檢查 trail 與 points 以確認儲存的歷史。此程式不繪製跟隨的身體。

讀取函式庫影格計數器 fc_system
目的: 觀察以影格計數的等待如何影響函式庫影格計數器。
運作方式: system_init 後,程式呼叫兩次 system_wait_vblank,再顯示 system_get_frame8。
操作方式與預期結果: 結果為 002。閒置迴圈使用手冊輔助函式 m_wait,因此顯示值不會持續增加。

選取目前場景 ID fc_scene
目的: 學習如何選取 ID,以區分標題畫面、遊戲進行等場景。
運作方式: 程式登錄兩個以零初始化的 SceneDef 項目,再以 scene_change 選取 ID 1。
操作方式與預期結果: 001 是 scene_get_current 傳回的目前 ID。此範例未註冊場景回呼或轉場繪製。

將世界座標轉換為畫面座標 gb_camera
目的: 從世界位置減去攝影機位置,求得畫面位置。
運作方式: Camera_Set 接收 Q8.8 值 2560,也就是 X=10 像素。接著 Camera_WorldToScreenX 轉換世界座標 X=52。
操作方式與預期結果: 052 減去 010 得到畫面上的 042。這是座標計算,不會捲動背景。

將 RLE 資料解壓縮至 RAM gb_rle
目的: 嘗試以次數與數值,精簡表示重複的位元組。
運作方式: 壓縮位元組 {3,42,0} 代表重複三次 42,再以零次數結束標記收尾。rle_decode 寫入三位元組目的緩衝區。
操作方式與預期結果: 最後一個位元組 out[2] 顯示為 042。解壓縮後的三個位元組應全部為 42。
![將 RLE 資料解壓縮至 RAM:最後一個位元組 out[2] 顯示為 042。解壓縮後的三個位元組應全部為 42。](../verification/gb_rle.png)
讀寫棋盤格子 gb_board
目的: 了解棋盤遊戲的格子座標如何對應到儲存位置。
運作方式: 以 16 位元組陣列儲存 4×4 棋盤。程式清空棋盤、在格子 (2,1) 寫入 42,再讀回同一格。
操作方式與預期結果: 042 是讀回的值。程式不繪製 4×4 棋盤本身。

將方盒推進一個物理步驟 gb_physics
目的: 初始化世界與方盒剛體,再根據速度更新位置。
運作方式: 剛體從位置 (40,40)、速度 (2,0)、零重力開始。程式呼叫 kq2d_step 一次。
操作方式與預期結果: 042 是算出的 X 座標,此範例以整數像素為單位。不繪製方盒或連續動畫。

處理序列傳輸完成與逾時 gb_link
目的: 區分已完成的傳輸與未在等待上限內完成的傳輸。
運作方式: 主端送出 42 並以 Link_WaitByte 等待。完成時顯示收到的位元組;逾時則取消傳輸並顯示零。
操作方式與預期結果: 未連線時若傳輸完成,可能傳回 255。逾時顯示 000;連接對端時顯示收到的位元組。結果不一定是 042。

指定記憶體庫引數讀取 ROM 資料 gb_bank
目的: 學習將 ROM 資料複製到 RAM 所需的引數。
運作方式: far_data_read 使用記憶體庫引數 0 與長度 2,將位元組 7、42 複製到 copied。
操作方式與預期結果: 目的緩衝區的第二個位元組顯示為 042。此範例讀取固定 ROM,不示範不同可切換記憶體庫之間的傳輸。

依素材 ID 載入資料 gb_asset
目的: 登錄素材的位置與長度,再依 ID 取得位元組資料。
運作方式: 素材 0 的型別為 RAW、記憶體庫為 0,包含指向 {7,42} 的指標及長度 2。asset_load_raw 將其複製到兩位元組 RAM 緩衝區。
操作方式與預期結果: 第二個位元組顯示為 042。這示範素材查找與複製,不是影像繪製。

配置一顆子彈 gb_danmaku
目的: 初始化子彈池,並在生成子彈後檢查使用狀況。
運作方式: danmaku_reset 後,程式呼叫 danmaku_spawn(40,40,16,0) 並顯示 dm_count。
操作方式與預期結果: 001 是已配置的子彈數。此處沒有子彈更新迴圈或背景合成器,因此不繪製移動子彈。

累積 Q5.3 小數位移 fc_subpixel
目的: 將次像素移動量保留為餘數,並把整數像素部分累加至位置。
運作方式: 從 X=40 開始,迴圈將 2/8 像素累加八次。右移運算取出整數像素,遮罩則保留餘數。
操作方式與預期結果: 總位移為兩像素,因此畫面將 X=42 顯示為 042。此手動積分範例處理正向移動;負向移動須搭配借位處理。

設定 CGB 背景調色盤 gb_cgb_palette
目的: 使用 Game Boy Color 的 RGB 分量選擇背景與文字顏色。
運作方式: 程式在 VBlank 期間關閉 LCD,將調色盤 0 的顏色 0 設為白色 (31,31,31)、顏色 3 設為紫色 (12,0,22),再啟用顯示。
操作方式與預期結果: 以 CGB 模式執行,可看到白底上的紫色文字與 042。DMG 單色輸出無法呈現這些顏色。

水平捲動背景 gb_scroll
目的: 移動觀景位置,無須重新繪製背景內容。
運作方式: 每個影格都會遞增 phase,並將其傳給 Scroll_SetBg。八位元位置值超過 255 後會回繞至 0。
操作方式與預期結果: SCROLL 字樣會向左移動。請觀察它隨時間改變的位置;單張螢幕擷取畫面無法呈現動作。

將圖塊更新加入佇列 gb_vram_queue
目的: 將繪圖請求與套用該請求的 VRAM 傳輸分開。
運作方式: vram_queue_bg_tile 將圖塊 52 排入圖塊座標 (3,8),vram_flush 再執行傳輸。提供的字型中,圖塊 52 是數字 4。
操作方式與預期結果: 請確認背景圖塊座標 (3,8) 出現一個 4。這是圖塊更新,不是數字計數器。

透過 OAM DMA 顯示精靈 gb_sprite
目的: 獨立於背景配置並顯示精靈。
運作方式: 新初始化的池提供槽位 0。程式選取圖塊 65、設定位置 (70,80)、啟用 OBJ 顯示,並在每個影格傳輸影子 OAM。
操作方式與預期結果: 指定的精靈位置出現靜止字母 A。遊戲中須先檢查配置是否失敗,再使用傳回的 ID。

產生可重現的亂數 gb_rng
目的: 使用種子重現偽亂數序列。
運作方式: rng_seed(1234) 初始化產生器後,呼叫 rng_range(10) 一次。上限 10 不包含在結果中。
操作方式與預期結果: 畫面顯示 000 至 009 之間的一個值。以相同種子重新啟動同一程式,會重現相同結果;此值不會每個影格改變。

儲存遊戲狀態旗標 gb_flags
目的: 使用旗標編號表示布林狀態,例如事件是否完成。
運作方式: 程式先清除旗標 12、再設定它,最後以 flag_get 讀回。
操作方式與預期結果: 001 表示旗標 12 為真。此範例操作 RAM 旗標,關機再開機後不會保留。

將圓形推進一個物理步驟 gb_circle
目的: 設定圓形剛體,並根據速度更新位置。
運作方式: 啟用中的圓形半徑為 4、位置為 (40,40)、速度為 (2,0)。重力為零,linear_damping_q8 為 255;kq2dc_step 執行一次。
操作方式與預期結果: 042 是算出的整數 X 座標。此範例不繪製圓形外框或碰撞動畫。

捲動 NES 背景 fc_scroll
目的: 更新 PPU 捲動位置以移動背景。
運作方式: 從 __scroll_set(0,0) 開始,程式每個影格將 phase 遞增一次,並用作水平位置。
操作方式與預期結果: SCROLL 字樣的水平位置會改變。phase 從 255 回繞至 0。這不是跨越多個名稱表的寬幅地圖範例。

透過 NMI 套用圖塊更新 fc_vram_queue
目的: 由主程式提交 PPU 更新,再由 NMI 處理流程套用。
運作方式: __vramq_put 將圖塊 52 排入名稱表位址 0x2103,__vramq_commit 再提交。該位址對應圖塊座標 (3,8)。
操作方式與預期結果: 背景座標 (3,8) 出現一個 4。提供的字型中,圖塊 52 就是數字 4。

顯示 NES OAM 精靈 fc_sprite
目的: 準備精靈顏色與 OAM 資料,以繪製獨立於背景的圖像。
運作方式: 程式載入精靈調色盤,將槽位 0 設為位置 (70,80)、圖塊 65、屬性 0,啟用繪製後重複執行 OAM DMA。
操作方式與預期結果: 靜止的字母 A 以精靈顯示。此範例示範 OAM 設定與傳輸,不是動畫。

播放 APU 脈衝音 fc_sound
目的: 設定 NES 內建脈衝聲道的控制、計時器與長度值。
運作方式: nes_apu_init 後,程式呼叫 nes_sfx_square1(0xBF,400,20)。控制值 0xBF 選擇固定音量並停止長度計數器,因此聲音持續。20 是長度表索引,不是 20 影格。
操作方式與預期結果: 顯示 042 時持續播放脈波音。呼叫 nes_apu_silence_all 可停止。僅靠畫面標記無法驗證聲音輸出。

每個影格處理音效 gb_sound
目的: 啟動音效串流,並透過規律的影格更新推進播放。
運作方式: Audio_Init 後,Audio_PlaySFX 在通道 ID 1 啟動 tone。主迴圈每影格呼叫一次 Audio_Update。
操作方式與預期結果: 顯示 042 的同時播放短促脈波音效。數字是固定標記,不是音量或播放位置。請透過音訊輸出或錄音判斷聲音。
