2011年04月06日


広告


SNES9X最新版をPSPに移植してみる(7) gdbでソースコードデバッグ

そんな訳で、前回のメモリ不足エラーは、malloc()に失敗しまくっていた様であり、unix.cppに以下を追加することで回避できた。

PSP_HEAP_SIZE_KB(-1024);

コンパイルし直して、再度チャレンジ。

host0:/> ./snes9x15281.prx
Load/Start host0:/snes9x15281.prx UID: 0x04BA5F5D Name: "snes9x/1.52.81 for PSP"
host0:/> Sound buffer size: 12800 (3200 samples)
Port 1: Pad #1. Port 2: .
Error opening the ROM file.

host0:/>

あー、ROMファイルを用意していませんでした。hissoriiはシレンジャーなので風来のシレンのROMファイルを、ホストPCの開発ディレクトリ(EBOOT.PBPが生成されるディレクトリ)に、hoge.smcとして保存します。今のところROMファイル名はhoge.smc決め打ちです。
ちなみにhissoriiはROMの吸いだしにホンコンを使用しています。楽しいホンコン愉快なホンコンホンコンホンコーン。
今度は、ROMの読み込みはパスしましたが、exceptionが発生して止まりました。

host0:/> ./snes9x15281.prx
Load/Start host0:/snes9x15281.prx UID: 0x04BA5F79 Name: "snes9x/1.52.81 for PSP"
host0:/> Sound buffer size: 12800 (3200 samples)
Port 1: Pad #1. Port 2: .
Found ROM file header (and ignored it).
Map_HiROMMap
"FURAI NO SIREN" [checksum ok] HiROM, 32Mbits, ROM+RAM+BAT, NTSC, SRAM:256Kbits, ID:AAXJ, CRC32:AF5703EE
Exception - Address load/inst fetch
Thread ID - 0x04B9D305
Th Name - user_main
Module ID - 0x04BA5F79
Mod Name - "snes9x/1.52.81 for PSP"
EPC - 0x0884B658
Cause - 0x10000010
BadVAddr - 0x08D31296
Status - 0x20088613
zr:0x00000000 at:0x08CD0000 v0:0x08D31296 v1:0x00000010
a0:0x00000008 a1:0x00008006 a2:0x00000120 a3:0x00000000
t0:0x00000000 t1:0x00000120 t2:0x08AFB150 t3:0x08BC4B45
t4:0x0BABE9D0 t5:0x08BC4B2C t6:0x00010000 t7:0x01000000
s0:0x08B2F800 s1:0x08B0E21C s2:0x08B2F868 s3:0x08B2F868
s4:0x08B00000 s5:0x08B31408 s6:0x08B2F84C s7:0x08B2F87C
t8:0xDEADBEEF t9:0xDEADBEEF k0:0x0BABFF00 k1:0x00000000
gp:0x08B27230 sp:0x0BABE9B0 fp:0x08B30000 ra:0x08832598
0x0884B658: 0x8C450000 '..E.' - lw $a1, 0($v0)

host0:/>

lw $a1, 0($v0)というアセンブリ命令の箇所でexceptionが発生したことが分かります。命令の意味は、v0レジスタ、index 0に格納されたワード(4byte)データをa1レジスタにロードする、なのですが、MIPS CPUではワードデータの読み込みは最下位バイトが、0, 4, 8, 0xcの様に4の倍数である必要があります。上記を見るとv0レジスタの最下位バイトが6なので、4の倍数ではないため例外が発生しています。
では、ここからgdbを用いて、ソースのどの部分でエラーになっているのかを調査します。
gdbでソースコードデバッグをするためには、コンパイルオプションに-gをつけてコンパイルする必要があります。
Makefileに以下を追加し、gdbを使うときにはmake USE_GDB=1としてmakeするようにします。

ifdef USE_GDB
CCFLAGS += -g
endif


gdbが使えるようにmakeし直したら、早速gdbを使ってみます。
ホストPC側でusbhosths_pc、PSP側でpsplinkを起動してから、ホストPC側でpspshを起動し、pspshのプロンプトでdebug snes9x15281.prxを実行します。

host0:/> debug snes9x15281.prx
PSPLink USB GDBServer (c) 2k7 TyRaNiD
host0:/> Loaded host0:/snes9x15281.prx - UID 0x04B9B247, Entry 0x088040AC

さらにホストPCのシェル上で、psp-gdbを実行します。実行するディレクトリは開発ディレクトリ(EBOOT.PBPが生成されるディレクトリ)で、引数に実行ファイル(.elf)を指定します。

hissorii@MBA:~/src/snes9x-1.52.81-psp/psp$ psp-gdb snes9x15281.elf
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=psp".
(gdb)


さらにgdbのプロンプトで以下を実行します。

(gdb) target remote :10001
Remote debugging using :10001
[New Thread 0]
_start (args=0, argp=0x0) at crt0_prx.c:109
109 if (&sce_newlib_nocreate_thread_in_start != NULL) {
Current language: auto; currently c
(gdb)


ここで、cと入力し、処理を継続します。

(gdb) c
Continuing.
[New Thread 79255619]

Program received signal SIGHUP, Hangup.
[Switching to Thread 79255619]
0x0884b658 in Op5C () at ../cpuaddr.h:367
367 uint32 addr = READ_3WORD(CPU.PCBase + Registers.PCw);
Current language: auto; currently c++
(gdb)


上記から、cpuaddr.hの367行目、addr = READ_3WORD(CPU.PCBase + Registers.PCw);の実行で、エラーになったことが分かります。
gdbのコマンドp(実際には16進表示のp/x)を使って、変数を表示させてみます。

(gdb) p/x CPU.PCBase
$1 = 0x8d29290
(gdb) p/x Registers.PCw
There is no member named PCw.
(gdb) p/x Registers
$2 = {DB = 0x0, P = {B = {l = 0x34, h = 0x0}, W = 0x34}, A = {B = {l = 0x0,
h = 0x0}, W = 0x0}, D = {B = {l = 0x0, h = 0x0}, W = 0x0}, S = {B = {
l = 0xff, h = 0x1}, W = 0x1ff}, X = {B = {l = 0x0, h = 0x0}, W = 0x0},
Y = {B = {l = 0x0, h = 0x0}, W = 0x0}, PC = {B = {xPCl = 0x6, xPCh = 0x80,
xPB = 0x0, z = 0x0}, W = {xPC = 0x8006, d = 0x0}, xPBPC = 0x8006}}
(gdb)

Registers.PCwはRegisters.PC.W.xPCなので、CPU.PCBase + Registers.PCwは0x8d29290+0x8006=0x8d31296で先のv0レジスタの値と一致します。
確かにここでエラーになっていることが分かります。
READ_3WORD()のマクロを、ワードアクセスではなくバイト単位のアクセスになるようにソースを変更し、エラーを回避します。
修正後、再度コンパイルし直して実行し、画面がなんだが激しく点滅しますが、PSPのスクリーンに風来のシレンの画面が出る様になりました。まだパッドやボタンの実装をしていないので、見てるだけですが。

えみゅはにブログは写真や動画は使わないポリシーなので、画面写真はこの後ひっそりぃ.comの方に載せる予定です。
画面の点滅を解消し、パッドが使える程度まで実装したら、ソースと実行ファイルをWIPとして公開したいと思います。




タグ:SNES9X PSP
posted by ひっそりぃ at 2011/04/06 00:34 | Comment(0) | TrackBack(0) | SNES9X for PSP | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。