初探Nintendo DS程式開發與設計(一)

Nintendo Dual Screen是的,你沒有看錯,本篇文章的主題是「NDS 程式設計」

由任天堂公司所開發的 Nintendo Dual Screen 攜帶型掌上遊樂器,前幾年甫一上市就席捲了全世界的遊戲市場,而在 NDS 平台上的程式設計與開發,也已經是行之有年並且十分活躍的社群活動。一開始是由 GBA 平台,開啟了業餘愛好者在 Console 平台上自製程式的可能性,接著在效能強大的 NDS 掌上型遊樂器問世之後,很快地就有幾位能力高強的程式設計者,開發出能夠製作 NDS 程式的函式庫與工具

我自己原來就非常喜歡玩 NDS 上的各種遊戲,在機緣巧合之下,最近剛好接觸到 NDS 程式開發的相關知識,覺得實在是非常新奇有趣又好玩!所以往後在這個新增的「學習筆記」分類中,我將會分享自己在學習過程中所獲得的一些心得與經驗;包括從門外漢一步步踏入這個新領域的過程中,所需建立的概念以及所需閱讀的文章,並且由淺入深地詳細解釋每個必要步驟,希望能夠對於有興趣學習 NDS 程式設計的讀者有一點幫助。如果其中內容有所錯誤或疏漏之處,也請不吝指正。

在搜尋引擎中,鍵入 NDS 程式開發或 NDS 程式設計的相關字句,立即就能夠找到許多相關於 NDS 程式開發的網站教學,然而,對於一個完全沒有 Console 平台程式寫作經驗的人來說,應該要從哪裡入門比較合適呢?在本篇文章中,將使用 libnds 函式庫與 devkitPro 開發工具,加上 PAlib 的環境設定為輔,在 Windows 平台下,初探 NDS 程式設計領域中 Frame Buffer 的使用以及 Input System 的操作,並提供完整的程式碼範例下載。

由業餘程式設計者自己製作的 NDS 程式,常被稱為是 Homebrew(自家釀造)程式。而在 NDS 的 Homebrew 領域中,首先要認識的是 libndsdevkitProPAlib 這三項開發 NDS 程式的利器:

  • libnds:是由幾位熱愛 NDS 程式的開發者,經由反向工程所製作出來的一套非官方版本的函式庫。
  • devkitPro:開發各種 Console 平台程式的工具組,其中包含了開發 NDS 與 GBA 用的 devkitARM,開發 PSP 用的 devkitPSP,還有開發 Gamecube 用的 devkitPPC
  • PAlib:以 libnds 為基礎所建構起來的高階函式庫,能夠免除掉許多關於記憶體的操作與複雜的低階程序,相當便於 NDS 程式開發入門者使用。

在眾多素質參差不齊的網站資源與教學文章裡,想要選擇合適的對象做為踏入 NDS 程式設計領域的第一次親密接觸,我建議由「Introduction to Nintendo DS Programming」這篇文章開始認識並且學習 NDS 的各種基礎知識,依序閱讀下列的幾個小節:

  • 第一節:瞭解 NDS 程式設計的背景資訊以及至關緊要的合法性問題。
  • 第二節第三節:認識各種 Passthrough 裝置的緣由與沿革,瞭解如何在 NDS 遊樂器上利用這些裝置來執行自製程式。
  • 第四節:簡單介紹 libnds 與 devkitPro 兩者所扮演的角色與作用。
  • 第五節:以顯示背景圖片 (Background) 為目標,開始一步步建構起簡單的 NDS 程式。
  • 第八節:介紹 NDS 的輸入系統 (Input System) 行為與操作方法。

上述的教學文章裡還有許多其他的內容,不過我認為在一開始踏入不熟悉的領域時,能夠先搞懂這幾個部分的內容就已經很不容易了。特別是在第五節的內容中,開始進入程式設計的部分:那些 VRAM Bank 是怎麼回事?還有那些奇怪的操作行為是怎麼來的?為什麼在轉置矩陣的設定上要使用 Shift Operation?以上這些問題,可能已經讓某些讀者開始頭昏眼花了。這些部分都會在之後的文章裡一一解說,不過在本篇文章裡,會暫時先略過這些部分。

閱讀連結文章中的幾個部分,是為了對 NDS 程式設計領域建立起基礎概念與印象。知道開發 NDS 程式大概是怎麼個回事之後,接下來就可以開始閱讀「NDS/Tutorials Day 3」這篇文章的內容,學習其中最簡單容易的 Frame Buffer 功能使用與 Input System 功能操作:

  • Frame Buffer:將 VRAM 視為最單純的 Frame Buffer 型態,進行螢幕畫面顯示上的操作使用。
  • Talking to the keypad:如何偵測使用者按下了哪個按鈕與按鈕的作用狀態,並且操作 NDS 的基本輸入系統,。
  • Touching things:介紹 NDS 上最特別的觸碰輸入系統。

具備了以上的知識以後,是不是已經覺得躍躍欲試了?不過在開始動手寫程式之前,需要先下載並且安裝幾項必備的軟體項目:

  • Visual C++ Express 2005(或 Professional 以上版本):Windows 平台上的程式開發必備 IDE,相信不用多做介紹。
  • devkitPro Windows Installer:這是安裝 devkitPro 工具組用的 Updater,確認要安裝的部分之後,它會直接連上網路下載所需的最新組件。請記得要把 devkitPro 安裝在沒有空格的目錄中,例如 C:\devkitPro 是合法的安裝路徑,但是如果將程式安裝在 C:\Program Files\devkitPro 中就會出現問題,進行安裝時需要多加注意。
  • PAlib 070717:開發 NDS 用的高階函式庫,本文中並不會直接使用 PAlib,而是為了以下的 AppWizard 而先安裝這個函式庫。
  • devkitARM release 20:由於目前的 PAlib 070717 僅對應至 devkitARM release 20 的版本,所以需要另外下載這個比較舊版的 devkitARM。安裝完 devkitPro 之後,先將原來目錄中的 devkitARM 重新命名為 devkitPro_21,然後再將這個 devkitARM release 20 的版本,安裝至 devkitPro 的目錄中。
  • PAlib AppWizard:這是 PAlib 專案的設定精靈,在依照安裝方式執行完畢後,就能夠很方便地在 Visual C++ 中創造出基本的 PAlib 專案,免除了 Make 檔相關的建置參數設定,可以幫助不熟悉 Unix/Linux 程式開發環境的程式設計者迅速上手。
  • Emulators:各種 PC 平台上模擬真實 NDS 執行環境的模擬器,能夠讓程式設計者很便利地檢視並測試程式的執行成果,這些模擬器包括有 No$GBADualisiDeaSDeSmuMe 等等,建議可以多下載幾個不同的模擬器交叉試用比較。

下載並安裝完以上的軟體之後,接著參照這篇文章的指示,在 Visual Studio 中一步步設定好建置程式的執行環境。首先將 devkitPro 與 PAlib 所需的環境變數設定完成,接著進行外部工具 (External Tools) 的設定程序;藉由外部執行檔與執行參數的設定,再加上快速鍵的按鍵組合設定,就能夠在 Visual Studio 中便利地執行模擬器,並且載入專案中的程式以迅速檢視執行成果。

具備了基礎概念與知識,並且將程式開發環境準備完畢後,終於可以真正開始在 Windows 上撰寫第一個 NDS 程式了!這裡的程式將以前述文章中的範例為基礎,使用 NDS 中最單純的 Frame Buffer 顯示模式,在上螢幕中以像素點的移動,模擬出星星流動的樣子,並且偵測 NDS 上所有按鈕與觸控螢幕的輸入,以 Console 顯示的方式將文字訊息輸出在下螢幕中。

程式的主流程非常單純而且簡單,只需要依順序進行以下幾項步驟:

  1. 初始化 IRQ 與 Console 設定
  2. 設定 Video Mode
  3. 映射 VRAM Bank
  4. 偵測 Input System
  5. 處理程式的 Update Procedure
  6. 將 RGB 值寫入 VRAM

主要進入點的程式碼如下所示:

int main(void) 
{
    // Initialize IRQ settings
    irqInit();
    irqEnable(IRQ_VBLANK);
    // Initialize console setting
    consoleDemoInit();

    // Setup video mode to frame buffer usage
    videoSetMode(MODE_FB0);
    // Mapping vram to frame buffer usage
    vramSetBankA(VRAM_A_LCD);

    // Initialize game logic
    srand(time(NULL));
    ClearScreen();
    InitStars();

    // Main loop
    while (true) {
        // Wait for V-Blank
        swiWaitForVBlank();
        // Clear console output
        consoleClear();

        // Game logic
        for (int i = 0; i < NUM_STARS; i++) {
            // Update stars
            if (g_bStarsMoving) {
                EraseStar(&g_tStars[i]);
                MoveStar(&g_tStars[i]);
            }
            // Write stars (RGB values) to VRAM
            DrawStar(&g_tStars[i]);
        }		
        // Input system handling
        ProcessInput();
    }
    return 0;
}

這個程式中最重要的部分,在於以 videoSetMode(MODE_FB0) 指定 NDS 繪圖引擎使用 Frame Buffer 的繪圖模式,然後再使用 vramSetBankA(VRAM_A_LCD),將 Bank A 的繪圖記憶體 (VRAM) 指定給螢幕顯示 (LCD) 使用。所謂的 Frame Buffer 模式,可以視為是直接由記憶體數值映射至螢幕顯示顏色的一種方式,所以只要將 RGB 值寫入對應的記憶體位址中,就能夠在螢幕上直接看到顏色值的顯示結果。

因此,在繪製星星的時候,就能夠將 VRAM_A 的內容,直接以一維陣列的方式存取並填入適當的 RGB 值:

void DrawStar(Star* ptStar)
{
    VRAM_A[ ptStar->x + ptStar->y * SCREEN_WIDTH ] = RGB15( g_sStarColorR, g_sStarColorG, g_sStarColorB );
}

void EraseStar(Star* ptStar)
{
    VRAM_A[ ptStar->x + ptStar->y * SCREEN_WIDTH ] = BACKGROUND_COLOR;
}

這裡所使用的是 NDS 架構中的 15 Bits Color 模式,R、G、B 三原色分別各佔 5 Bits 的大小,然後透過 RGB15 這個 Preprocessor Macro 的使用,就能夠很方便的指定螢幕像素點的顏色值。

NDSDev_FrameBuffer Screenshot

在使用 PAlib AppWizard 創建 NDS 程式專案的情形下,按下「編譯」或「建置」都會使專案直接連結至 devkitPro 的相關工具以進行建置程序。在程式建置完畢之後,會產生出 *.nds*.ds.gba 格式的 NDS 專用檔案,並不是一般 Windows 平台中常見的 *.exe 可執行檔。所以在此不能夠按下 F5 快速鍵來直接執行程式,而是必須使用之前設置好的外部工具,如 No$GBA 之類的模擬器,以執行建置完成的程式。左邊的圖,就是以模擬器執行這個簡單範例程式的畫面。

按照以上學習、安裝、撰寫的三拍子節奏行進,就能夠優雅而輕鬆地進入 NDS 的程式設計領域,親手寫出人生中的第一個 NDS 程式!接下來的文章裡,將會陸續介紹 NDS 的硬體架構與繪圖模式,並且開始學習如何載入與繪製背景圖片等等非常有趣的部分。

完整程式碼下載:NDSDev_FrameBuffer.zip (下載次數: 1670 )

19 Replies to “初探Nintendo DS程式開發與設計(一)”

  1. 呵 蠻久前有用這個寫過小遊戲。
    還蠻屌的,可以在捷運上玩自己寫的遊戲,

    之前也是有用這個把妹過,就是寫一些小程式
    放到nds裡面,送給美眉,如果預算夠的可以試試,
    效果還不錯。

    那篇教學網頁其實是有中文版,英文連結頁面也可以找到,
    http://www.palib.info/wiki/doku.php?id=day1tw
    英文不好的朋友可以看中文,
    我也差不多忘光了。

    半路:
    果然是高手啊!
    原來可以用這招把妹!(筆記)
    這樣各位讀者有沒有更大的動力學習 NDS 程式設計了? XDDDD

    之前你是用 PAlib 寫的嗎?
    PAlib Wiki 是有幾篇翻譯成中文版的教學文章,但是進度落後英文版的很多呀。
    不過在安裝和入門的部分,還是可以先參考看看囉~

  2. 超感謝的

    半路:
    (._.?)
    請問是感謝什麼?

    (謎之音:據說續集已經拖稿很久了喔~XD)

  3. 超感謝的 只是完全看不懂@@
    原本想自己做做東西來玩…
    不過太難了啦

    你的”(謎之音:據說續集已經拖稿很久了喔~XD)”
    是指啥???
    “http://www.palib.info/wiki/doku.php?id=day1tw”
    是指這個的第幾課嗎? 中文只到第三課= =
    其他語言的很像都畢業了說….

    對了這個blog好難找@@

    半路:
    你好,

    那個謎之音是在說我自己啦,因為第二篇文章拖稿太久了。 XD

    PAlib 的中文教學,因為沒有善心人士幫忙翻譯,所以一直停在第三課很久囉。如果你覺得這篇文章的內容太難,我想你可以從 PAlib 的中文教學看起,然後再想辦法啃一下後續的英文版教學文章,應該可以比較容易學會喔。

    你是說這裡很難找嗎?如果覺得部落格的網址太難記的話,在 Google 打上猴子靈藥就一定找得到連結,也不會迷路囉~ :D

  4. 如果不知道.在找NDS相關資料時
    不會想到猴子靈藥這是我的意思

    對了..這樣子NDS敎學
    NINTENDO不會叫叫叫嗎?
    (合法性)

  5. 有辦法把商業遊戲的NDS檔變回人看的懂得模式(很像叫做原始碼?)嗎
    …..阿…
    這樣說很像對遊戲開發者不太尊重..(很像不只不尊重@@)

    但不參考”佳作”很難寫出好”文章”

  6. @HHH:
    首先,必須要聲明的是,自製 NDS 遊戲是合法的,模擬器也是合法的,這一點已經在「Is Homebrew Legal?」裡解釋的非常地清楚明瞭。只要沒有商業行為就都是合法的囉。

    其實國外有很多自製的 NDS 遊戲都有釋出原始碼,只要能夠看得懂英文和 C 語言,就不是什麼太困難的問題。但如果是商業化的遊戲,就沒機會也不可能釋出原始碼。

    NDS 程式開發與設計,只是其中一罐靈藥而已,這裡還有賣很多不同療癒效果的靈藥,歡迎多多參考比較~ = =+

  7. @spot:
    你好,

    我沒有接觸過 GBA 平台的遊戲程式開發哩。不過就我所知,GBA 與 NDS 平台的程式設計概念非常相近,網路上也有很多教學文章和工具資源可用。

  8. 幾年前因為興趣而研究過GBA的程式設計,因為本身是在嵌入式系統上寫程式,所以看GBA相關資料時還滿習慣的,其實以GBA開發環境來說,有高階也有低階,高階的環境就會提供不錯的程式庫讓開發者使用,當然低階的環境就得直接跟繪圖硬體打交道囉!! 自己寫繪圖的API,說穿了也不難,也就是將資料填入繪圖晶片的各種暫存器中. 這邊推薦一本GBA程式設計的書應該是Free的,內容相當簡單易懂,可以當成先期參考書. 連結在這:http://www.jharbour.com/?page_id=89

  9. @Retvalue:
    你好,

    GBA 的東西,我之前在玩 NDS 的時候有稍微看過一點,就我印象所及,的確多數的程式碼,都和操作繪圖硬體以及如何把資料填入暫存器相關。不過我現在已經很久沒碰 GBA/NDS 程式設計囉~ XD

    感謝你提供的免費開發學習資源!

  10. 請問這個程式能不能把PC的遊戲移植成NDS的遊戲,之前看到有人把PC遊戲FATE/STAY NIGHT
    移植成NDS的遊戲,所以也想要來試試看,但不知道該用哪個程式才能移植。

  11. @寬腹螳螂:
    你好,

    把 PC 遊戲移植成 NDS 遊戲,理論上可行,但是 NDS 的程式設計,可以說是非常地艱深困難。如果你對於程式設計與 NDS 的硬體繪圖層沒有深入的研究與涉獵的話,我想成功將遊戲移植過去的機會並不高。

  12. 我不认为PCgame能有移植到NDS平台上。PC有专门的图形处理芯片,而NDS用一款ARM7作为图形处理,性能不是一个量级。

  13. @Lu Fangjie:
    以 NDS 來說,確實不適合直接將 PC 平台的遊戲原封不動地移植上去。還是一句老話,遊戲得根據硬體平台量身訂製,才能達到最好的效果哪。

  14. 你好~請問如果自己寫了一個NDS遊戲,在模擬器可以跑

    但是沒辦法在NDS上跑大概是甚麼問題呢?

    不好意思找不大到網路資源所以很不好意思的發問OTZ

  15. @simba:
    我之前是用最老的 NDS 機型,搭配 R4 謎卡,寫出來的程式可以在實機上玩沒問題。

    建議你先寫個最基礎的程式,例如只有一張圖片或幾個文字,先確定看看能不能在 NDS 上執行吧。

  16. 這~猴子大大,我不得不佩服你,雖然我只有13歲,但你至少能弄出 主要進入點的程式碼 ,幫忙鋪陳,還有截圖,光這2點,我就太佩服 猴子大師了,請接受 小第一拜~

  17. @dgjg0622:
    你好,我是半路,不是猴子大大。 XD

    只要你從現在開始學習程式設計,以後也可以做NDS遊戲或App遊戲開發喔~

Leave a Reply