2017-07-21 25 views
1

我想先說我的問題,首先說我是一個非常有經驗的程序員,尤其是Java已經使用了8年。Z80 DAA實現和Blargg的測試ROM問題

爲了提高我對硬件操作和操作系統主題的理解,我決定編寫一個簡單的Gameboy模擬器。在短短几天內對核心功能進行了編程後,我只對模擬器進行了測試,發現屏幕上沒有畫出任何東西。在我的模擬器中逐個遍歷數百個操作碼並將其與BGB模擬器中的值進行比較後,我意識到正在討論的磁貼和精靈正被加載到內存中,而未被繪製。由此我發現問題必須出現在我的一個或多個操作碼實現中,這會導致程序在某個時刻顯示出錯誤的行爲。因此,我決定使用Blargg的cpu測試ROM(http://gbdev.gg8.se/files/roms/blargg-gb-tests/)來幫助我確定問題。但是,在運行第一個測試ROM,提供了以下錯誤信息:

01-special 

36E1FE30 
DAA 

Failed #6 

我已經檢查了DAA操作幾次,它似乎得到正確執行我。給出的錯誤代碼(「36E1FE30」)完全沒有幫助,因爲我似乎無法找到這意味着什麼。對我而言,這意味着要麼DAA被錯誤地實現,我只是看不到我的錯誤,或者用於驗證DAA正確性的操作之一是不正確的。如果我運行任何其他測試他們似乎無限循環

03-op sp,hl 

03-op sp,hl 

03-op sp,hl 

03-op sp,hl 

僅供參考我的DAA實現是在github(https://github.com/qkmaxware/GBemu/blob/master/src/gameboy/cpu/Opcodes.java),或者可以如下如下圖所示:

Op DAA = new Op(0x27, "DAA", map,() -> { 
    int a = reg.a(); 

    if(!reg.subtract()){ 
     if(reg.halfcarry() || (a & 0xF) > 9) 
      a += 0x06; 

     if(reg.carry() || a > 0x9F) 
      a += 0x60; 
    }else{ 
     if(reg.halfcarry()) 
      a = (a - 0x6) & 0xFF; 

     if(reg.carry()) 
      a = (a - 0x60) & 0xFF; 
    } 

    reg.a(a); 

    reg.zero(isZero(a)); 
    reg.carry((a & 0x100) == 0x100); 
    reg.halfcarry(false); 

    clock.m(1); 
    clock.t(4); 
}); 

當如調用reg.a()表示從寄存器a讀取,reg.a(value)表示寫入寄存器a(掩碼爲8或16位,取決於寄存器)。類似地,標誌Z,N,H,C可以用'reg'對象的進位函數零,減半運算來獲得或設置/重置。

所以我的問題有三個方面,我是否錯誤地執行了DAA操作,以至於它無法通過Blargg的測試,是否有人知道我有錯誤代碼的含義,或者沒有人有任何想法,我可以如何將搜索的焦點操作。

回答

3

看起來Blargg的測試從舊Z-80試驗程序調用zexlax這需要處理指令測試作爲簡單的數據比較的實用方法借用。對於​​,它運行所有可能的輸入組合,並根據預期的答案進行有效檢查。但是保持所有答案會使測試代碼不切實際地大。而是比較數據的CRC。正如你所經歷的,這在驗證仿真器的正確操作方面非常有效,但在指出如何修復它時卻毫無用處。

雖然這會是理想的,如果有人保存了正確的輸出,所以你可以檢查一下對你實現你仍然可以通過運行在一個已知的良好模擬器測試這樣做。或者只是將你的實現與一個熟知的模擬器進行比較。

這裏的MAME是怎麼做的:

case 0x27: /*  DAA */ 
    { 
     int tmp = m_A; 

     if (! (m_F & FLAG_N)) { 
      if ((m_F & FLAG_H) || (tmp & 0x0F) > 9) 
       tmp += 6; 
      if ((m_F & FLAG_C) || tmp > 0x9F) 
       tmp += 0x60; 
     } else { 
      if (m_F & FLAG_H) { 
       tmp -= 6; 
       if (! (m_F & FLAG_C)) 
        tmp &= 0xFF; 
      } 
      if (m_F & FLAG_C) 
        tmp -= 0x60; 
     } 
     m_F &= ~ (FLAG_H | FLAG_Z); 
     if (tmp & 0x100) 
      m_F |= FLAG_C; 
     m_A = tmp & 0xFF; 
     if (! m_A) 
      m_F |= FLAG_Z; 
    } 
    break; 

更多情況下,這裏的整個源鏈接:

https://github.com/mamedev/mame/blob/master/src/devices/cpu/lr35902/opc_main.hxx#L354

看起來有可能是您的代碼,但我有些差異沒有看得很仔細。

我注意到Blargg的測試包括未記錄的標誌位3和5.如果這是一個Z-80處理器,它會使仿真器失敗,而不會將這些位設置爲Z-80,記錄爲你可以依賴的任何東西。我不知道夏普LR35902是否有類似的問題,但如果是這樣的話,MAME完全有可能沒有實現。這些位對於「真實」的程序永遠不會有所作爲。

+1

哇,謝謝你提供關於測試ROM和MAME操作碼實現的所有信息。操作碼的實現比其他一些開源項目更適合閱讀。 – Hals

+0

@Hals:你有沒有發現問題出在你自己的代碼中,或者你是否拋棄它並使用MAME? – usr2564301

+0

@ usr256430:1我最終使用了GAMEHub上其他模擬器的MAME版本和其他版本的組合,而不是我自己的版本。 – Hals