* Doc.7 GBAの仕様について(BIOS) [#s1b23f96]


** BIOS [#gdd37a95]
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の使用例 [#o082559f]
BIOSとはなんぞやって思っている方は、C言語でいうところの関数の集まりと思ってください。~
ただし普通の関数を呼び出し方法が違っていて''CPUのSWI命令と機能番号''を使って呼び出します。~
ただし普通の関数とは呼び出し方法が違っていて''CPUのSWI命令と機能番号''を使って呼び出します。~

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

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

*** LZ77圧縮された画像ファイルを用意する [#ce7bdf93]
ここではdevkitProに標準で用意されているgritを使用します。~
コマンドのオプションに''-gzl''を付け加えることでLZ77圧縮の指定になります。~

- モード3 240x160サイズの画像の場合
| 無圧縮 | 76800バイト |
| LZ77   | 16968バイト |


*** BIOSを呼び出すコードを用意する [#d8b1a14d]
仕様については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);
 }


*** 呼び出し側の関数を用意する [#p1f877f7]
 #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();
 	}
 }

*** 動作画面 [#n1a6659a]
#ref(clip_1.png,nolink)


** 履歴 [#s309c1fc]
- 2014/11/09
- 2007/09/19