2009-11-13 20 views
3

我需要儘可能高效地在較舊的基於CD的遊戲控制檯上加載大型模型和其他結構化二進制數據。什麼是最好的方式來做到這一點?數據將從Python應用程序中導出。這是一個相當複雜的愛好項目。在遊戲控制檯上加載最佳數據文件格式

Requierements:

  • 上完全符合標準STL不依賴 - 我可能會使用雖然uSTL。
  • 儘可能少的開銷。力求解決方案如此之好。它可以用在原始的Playstation上,而且儘可能現代和優雅。
  • 不需要向後/向前兼容性。
  • 不需要複製大塊數據塊 - 最好在後臺將文件加載到內存中,並在後面直接從那裏訪問所有大塊數據。
  • 不應該依賴具有相同字節順序和對齊的目標,即Python中將C結構轉儲到光盤上的C插件不是一個好主意。
  • 應該允許移動加載的數據,如單個文件的1/3大小,碎片可能是一個問題。沒有MMU濫用。
  • 魯棒性是一個很大的好處,因爲我的注意力非常短,即我會改變保存部分代碼並忘記加載代碼,反之亦然,所以至少默默保護會很好。
  • 加載的數據和運行時生成的數據之間的可交換性沒有運行時間開銷並且沒有嚴重的內存管理問題將是一個不錯的獎勵。

我種具有其中將使用結構與偏移,而不是指針的Python微不足道的,有限的語法C頭解析的半計劃和方便包裝結構在主應用程序/類的getter這將轉化偏移到正確類型的指針/引用,但我想聽聽你的建議。

說明:請求主要是關於數據加載框架和內存管理問題。

回答

3

這是一個常見的遊戲開發模式。

通常的做法是在離線預處理步驟中烹飪數據。所產生的blob可以以最小的開銷進行流式傳輸。 Blob是平臺相關的,應該包含目標平臺的正確對齊。

在運行時,您可以簡單地將指針投射到內存中的Blob文件。你也可以處理嵌套結構。如果你保留了一個含有偏移到blob內所有指針值的目錄,你可以修改指針指向正確的地址。這與dll加載的工作方式類似。

我一直在研究一個紅寶石庫,bbq,我用它來爲我的iphone遊戲做數據。

這裏的內存佈局我使用的BLOB標題:

// Memory layout 
// 
// p begining of file in memory. 
// p + 0 : num_pointers 
// p + 4 : offset 0 
// p + 8 : offset 1 
// ... 
// p + ((num_pointers - 1) * 4) : offset n-1 
// p + (num_pointers * 4) : num_pointers // again so we can figure out 
//           what memory to free. 
// p + ((num_pointers + 1) * 4) : start of cooked data 
// 

下面是如何加載二進制的blob文件,並修復了指針:

void* bbq_load(const char* filename) 
{ 
    unsigned char* p; 
    int size = LoadFileToMemory(filename, &p); 
    if(size <= 0) 
     return 0; 

    // get the start of the pointer table 
    unsigned int* ptr_table = (unsigned int*)p; 
    unsigned int num_ptrs = *ptr_table; 
    ptr_table++; 

    // get the start of the actual data 
    // the 2 is to skip past both num_pointer values 
    unsigned char* base = p + ((num_ptrs + 2) * sizeof(unsigned int)); 

    // fix up the pointers 
    while ((ptr_table + 1) < (unsigned int*)base) 
    { 
     unsigned int* ptr = (unsigned int*)(base + *ptr_table); 
     *ptr = (unsigned int)((unsigned char*)ptr + *ptr); 
     ptr_table++; 
    } 

    return base; 
} 

bbq庫是沒有完全準備好黃金時間,但它可以給你一些關於如何在python中編寫自己的想法。

祝你好運!

0

考慮將數據存儲爲SQLite數據庫中的BLOB。 SQLite非常便於攜帶,而且ANSI C具有C++和Python接口。這將處理大文件,無碎片,快速訪問的可變長度記錄等等。剩下的就是這些BLOB的結構序列化。

+0

謝謝,但請考慮一下如果您嘗試使用存儲在CD上的數據庫處理4x慢速驅動器中的數據(僅使用千字節緩衝區)會發生什麼情況。沒有MMU,沒有MMAP,沒有RAM空餘,也沒有真正的操作系統。實際上我的特定平臺上有16MB內存,但是我想用它來裝滿。 ;) 另外我想幾乎完全避免反序列化開銷。 我對設備的細節含糊不清,因爲我實際上想從90年代中期開始到現在的手持設備上使用多種不同遊戲機的部分技術。 請不要冒犯,我很喜歡SQLite,但它會是自殺。 – 3yE 2009-11-13 08:31:49

4

像任天堂GameCube,DS平臺,3D模型通常存儲在一個非常簡單的自定義格式:

  • 一個簡短的頭,包含幻數標識文件,頂點,法線數量,以及可選的頭部後面的數據(Adler-32,CRC-16等)的校驗和。
  • 每個向量和法向的32位浮點3元組的可能壓縮列表。
  • 可能壓縮的邊或面的列表。
  • 所有的數據都是目標平臺的本地端格式。壓縮格式通常是微不足道的(哈夫曼),簡單的(算術)或標準的(gzip)。所有這些都需要很少的內存或計算能力。

你可以把這樣的格式作爲提示:它是一個相當緊湊的表示。

我的建議是使用與您的內存數據結構最相似的格式,以最大限度地減少後處理和複製。如果這意味着你自己創建了這個格式,那就這樣吧。你有極端的需求,所以需要採取極端的措施。

3

我注意到你的描述中沒有任何地方要求「易於編程」。 :-)

因此,這裏就是想到爲我創造這個的一種方式:

  • 的數據應該在同一磁盤上的格式,它會在目標的內存,這樣它可以簡單地將磁盤從磁盤拖入內存,而不需要重新格式化。根據你想要把東西放入內存的多少自由度,「blob」可能是整個文件,或者可能是其中的較小位;我不太瞭解你的數據,不足以建議如何細分它,但大概你可以。因爲我們不能依賴主機上的相同排序和對齊方式,所以在主機端編寫文件時,您需要有點聰明地翻譯內容,但至少這樣,您只需要在一邊進行巧妙處理而不是兩者。

  • 爲了提供目標端和主機端代碼相匹配的一點保證,您應該以提供單個數據描述並具有一些代碼的形式編寫該代碼,以生成目標端C代碼和來自它的主機端Python代碼。您甚至可以讓您的生成器在過程中生成一個小的隨機「版本」編號,並讓主機端代碼將其寫入文件頭並由目標端進行檢查,如果它們不匹配會給出錯誤。 (使用隨機值的一點是,你所關心的唯一信息位是否匹配,你不希望有人工加一。)

+0

非常感謝,這是朝着正確的方向發展。 :) 而且作爲簡單說明,使用比「易於編程」更容易,更靈活和更可靠,而且性能方式高於此。 這將是一個巨大的長期項目,我不想在某個時候遇到malloc慘敗,細分不會是一個完美的保證,所以想法是有一個單獨的大型的,通常加載的對象堆,我可以緊湊,甚至可以縮小,如果正常堆滿了。然後我想細分的需要消失了。 如果您有任何其他建議,他們將非常歡迎。 – 3yE 2009-11-13 10:59:50