Doc.7 GBAの仕様について(BIOS)

BIOS

GBAのSystem ROM(BIOS)には、あらかじめ用意されているいくつかの機能があります。
具体的には次のようなものです。

  • Arithmetic Functions
  • Rotation/Scaling Functions
  • Decompression Functions
  • Memory Copy
  • Halt Functions
  • Reset Functions
  • Multi Boot (Single Game Pak)
  • Sound Functions
BIOS Function Summary

 SWI    Hex     Function
 0      00h     SoftReset
 1      01h     RegisterRamReset
 2      02h     Halt
 3      03h     Stop
 4      04h     IntrWait
 5      05h     VBlankIntrWait
 6      06h     Div
 7      07h     DivArm
 8      08h     Sqrt
 9      09h     ArcTan
 10     0Ah     ArcTan2
 11     0Bh     CpuSet
 12     0Ch     CpuFastSet
 13     0Dh     -Undoc- ("GetBiosChecksum")
 14     0Eh     BgAffineSet
 15     0Fh     ObjAffineSet
 16     10h     BitUnPack
 17     11h     LZ77UnCompWram
 18     12h     LZ77UnCompVram
 19     13h     HuffUnComp
 20     14h     RLUnCompWram
 21     15h     RLUnCompVram
 22     16h     Diff8bitUnFilterWram
 23     17h     Diff8bitUnFilterVram
 24     18h     Diff16bitUnFilter
 25     19h     SoundBias
 26     1Ah     SoundDriverInit
 27     1Bh     SoundDriverMode
 28     1Ch     SoundDriverMain
 29     1Dh     SoundDriverVSync
 30     1Eh     SoundChannelClear
 31     1Fh     MidiKey2Freq
 32-36  20h-24h -Undoc- (Sound Related ???)
 37     25h     MultiBoot
 38     26h     -Undoc- ("HardReset")
 39     27h     -Undoc- ("CustomHalt")
 40     28h     SoundDriverVSyncOff
 41     29h     SoundDriverVSyncOn
 42     2Ah     -Undoc- ("GetJumpList" for Sound ???)
 43-255 2Bh-FFh -Not used-

The BIOS SWI handler does not perform any range checks,
so calling SWI 43-255 will blindly lock up the GBA.

SWI:18(12h) LZ77UnCompVramの使用例

BIOSとはなんぞやって思っている方は、C言語でいうところの関数の集まりと思ってください。
ただし普通の関数とは呼び出し方法が違っていてCPUのSWI命令と機能番号を使って呼び出します。

ここでは機能番号18(12h)のLZ77UnCompVramを使います。
この機能はLZ77圧縮された画像ファイルを解凍しつつ、VRAM領域に展開する機能です。
LZ77のアルゴリズムについてはgoogle先生に聞いてみてください。

作業の順番としては

  • 1.LZ77圧縮された画像ファイルを作成して
  • 2.BIOSを呼び出すコードを用意し
  • 3.BIOSを呼び出す関数(main)を作ります

LZ77圧縮された画像ファイルを用意する

ここではdevkitProに標準で用意されているgritを使用します。
コマンドのオプションに-gzlを付け加えることでLZ77圧縮の指定になります。

  • モード3 240x160サイズの画像の場合
    無圧縮76800バイト
    LZ7716968バイト

BIOSを呼び出すコードを用意する

仕様についてはGBATEKより抜粋してきたものを以下に表します。

SWI 17 (11h) - LZ77UnCompWram
SWI 18 (12h) - LZ77UnCompVram
Expands LZ77-compressed data. The Wram function is faster, and writes in units of 8bits.
For the Vram function the destination must be halfword aligned, data is written in units of 16bits.
If the size of the compressed data is not a multiple of 4,
please adjust it as much as possible by padding with 0.
Align the source address to a 4-Byte boundary.

 r0   Source address, pointing to data as such:
       Data header (32bit)
         Bit 0-3   Reserved
         Bit 4-7   Compressed type (must be 1 for LZ77)
         Bit 8-31  Size of decompressed data
       Repeat below. Each Flag Byte followed by eight Blocks.
       Flag data (8bit)
         Bit 0-7   Type Flags for next 8 Blocks, MSB first
       Block Type 0 - Uncompressed - Copy 1 Byte from Source to Dest
         Bit 0-7   One data byte to be copied to dest
       Block Type 1 - Compressed - Copy N+3 Bytes from Dest-Disp-1 to Dest
         Bit 0-3   Disp MSBs
         Bit 4-7   Number of bytes to copy (minus 3)
         Bit 8-15  Disp LSBs
 r1   Destination address

Return: No return value.

引数には転送元のアドレス(r0)と転送先のアドレス(r1)の値が必要なのがわかりました。
早速、コードを書いてみます。libgbaと同じものを使用しました。

  • gba.h(65行目)
    #if	defined	( __thumb__ )
    #define	SystemCall(Number)	 __asm ("SWI	  "#Number"\n" :::  "r0", "r1", "r2", "r3")
    #else
    #define	SystemCall(Number)	 __asm ("SWI	  "#Number"	<< 16\n" :::"r0", "r1", "r2", "r3")
    #endif
  • sys_arm.c(47行目)
    IWRAM_CODE void LZ77UnCompVram(void *source, void *dest)
    {
    	SystemCall(18);
    }

呼び出し側の関数を用意する

#include "lib/gba.h"
#include "res.h"

//---------------------------------------------------------------------------
void WaitForVsync(void)
{
	while (*(volatile u16*)0x4000006 >= 160) {};
	while (*(volatile u16*)0x4000006 <  160) {};
}
//---------------------------------------------------------------------------
int main(void)
{
	SetMode(MODE_3 | BG2_ENABLE);

	LZ77UnCompVram(&imageBitmap, (void*)VRAM);

	for(;;)
	{
		WaitForVsync();
	}
}

動作画面

clip_1.png

履歴

  • 2014/11/09
  • 2007/09/19

添付ファイル: fileclip_1.png 254件 [詳細]

Last-modified: 2014-11-18 (火) 18:29:47 (2825d)