2000-01-04

いろんなこと

久々のHP更新になります。正月休みってことでまとめて書き殴ります。 まあいろんなところで書いたものの焼き直し、ていう感じですけど。
トップのページもすっかり古くなってどうしてやろうか、 と悩んだりしてますが多分しばらくこのままではないかと思います。
 メールくれた方、すいませんでした。 ほとんど返事書きませんでしたが他意はありません。 忙しかった、というか私生活を捨ててまで働いてる、 という姿勢が必要なぐらいヤバかったんですわ。

駐禁ネタ

最近の私は MOD 関係はちょっと静観 (というか例のヤツで日本の(表の)scene そのものが冷めちゃったので、 なんだか張り合いがない、て感じでやる気が薄れてきた感があります。 (一番の原因は私がハード方面に弱いということに尽きますが。) 幸い、DINO CRISIS からプロテクトが海外進出してくれましたので、 これからは英語圏のみなさまに期待したいですね。世界は広いっすよ。 頭メチャメチャいいんだけど使い道を間違ってるヒトはたくさんいますからね。

 一応 2000 年になりましたし、過去を振り返ってみようかと思います。 mod がらみは激動の1年(と1ヶ月ちょい)、 て感じですがこんな感じだったと思います。時系列のつもりですが多少違うかも。 えーと GIO さんの活躍について触れていませんが、これは私が知らないからです。 HEX も一般公開はなかった?んではないかと思います。 なにやら完璧な信号を発見したそうですが、真相は...知りません。

 駐禁の歴史を振りかえるつもりでしたが都合で前編のみになってしまいました。 何とぞご勘弁を。 えーと、現在主流の modchip、筋肉 mayumi 印のヤツをなんで紹介しないの? ってメールくれた方がいましたが、日本人に荒らされたら悪いかと思って リンクしてないんです。って日本語で書いても読めませんわね。

modchip に関しては多分私に出来ることはもうないんではないかと思います。 ていうか前から出来てないんですけど。 ロジアナ持ってないと手が出せない領域まで来ちゃいましたからね。 あ、modisasm ですがバグが1件出てます。ひそかに直しておきます。

XPS で触れた EDC/ECC 計算処理ですが、C を ASM に直したものをまた C に戻してみました。私はやっぱり理解できません(泣)。 誰かこれで良いツールを作ってくださいませ。 (x86 わかんないので辛かったです。)


#ifndef _CDROMXAmode1_EDC_ECC_H_
#define _CDROMXAmode1_EDC_ECC_H_
/*
 *	EDC/ECC calculator programmed by Hanimar.
 *	This is what XPS patcher does, and I converted it into C.
 *	Therefore, I don't really know what it does=(
 */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/*
 *	Calculates EDC.
 *	Usage:
 *	ISO-9660 Mode 1: CalcEDC(§or[0], 2064)
 *	CDROM-XA format 1: CalcEDC(§or[16], 2056)
 */
unsigned long CalcEDC(const unsigned char *from, int size);
/*
 *	Stores EDC into a sector image.
 *	This function copies edc to from in Little-Endian.
 *	Usage:
 *	ISO-9660 Mode 1: StoreEDC(§or[2064], edc)
 *	CDROM-XA format 1: StoreEDC(§or[2072], edc)
 */
void StoreEDC(unsigned char *from, unsigned long edc);

/*
 *	Calculates ECC (for CDROM XA form 1)
 */
void XaCalcECC(unsigned char *sector);

/* void ISO9660mode1CalcECC(const unsigned char *sector); */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif	/* _CDROMXAmode1_EDC_ECC_H_ */

#include "edcecc.h"

#define Multiply(a, b) do {			\
	int i, carry;				\
	b ^= a;					\
	for (i = 8 ; i > 0 ; i --) {		\
		carry = (b) & 1; b >>= 1;	\
		if (carry) b ^= 0xd8018001;	\
	}					\
} while (0)

/*
 *	EDC 計算
 */ 
unsigned long CalcEDC(const unsigned char *from, int size)
{
	int i;
	unsigned long a, b = 0;

	for (i = 0 ; i < size ; i ++) {
		a = (unsigned long)from[i];
		Multiply(a, b);
	}
	return b;
}

void StoreEDC(unsigned char *from, unsigned long edc)
{
	from[0] = (unsigned char)(edc >> 0) & 0xff;
	from[1] = (unsigned char)(edc >> 8) & 0xff;
	from[2] = (unsigned char)(edc >> 16) & 0xff;
	from[3] = (unsigned char)(edc >> 24) & 0xff;

	return;
}

static void mkTable4ECC(unsigned char *table);
static void calcPParity(const unsigned char *from, unsigned char *dest,
	const unsigned char *table);
static void calcQParity(const unsigned char *from, unsigned char *dest,
	const unsigned char *table);
/*
 *	ECC 計算 (XA form 1 専用)
 *
 *	Pパリティ
 *	ヘッダ4バイト、サブヘッダ8バイト、データ、EDCを含む2064バイトに
 *	対して計算します。ただし、ヘッダ(セクタ、モードを示す4バイト)はゼロと
 *	して計算します。
 *	0x81c から 0x8c7 までの172バイトを算出します。
 *
 *	Qパリティ
 *	ヘッダ4バイト、サブヘッダ8バイト、データ、EDC、Pパリティの
 *	2236バイトに対して計算します。ただし、ヘッダ
 *	(セクタ番号を示す4バイト)はゼロとして計算します。
 *	0x8c8 から最後(0x92f)までの104バイトを算出します。
 *
 *	引数:
 *	sector:
 *		セクタの先頭位置。同期信号部の先頭
 *		要するに 00 FF FF FF FF FF FF FF FF FF FF 00 となっているところ。
 *
 */
void XaCalcECC(unsigned char *sector)
{
	unsigned char table[256];
	unsigned char tmp[4];
	int i;

	mkTable4ECC(table);

	for (i = 0 ; i < 4 ; i ++) {	// ヘッダ部を一端クリア
		tmp[i] = sector[12 + i]; sector[12 + i] = 0;
	}

	calcPParity(§or[0x0c], §or[0x81c], table);
	calcQParity(§or[0x0c], §or[0x8c8], table);

	for (i = 0 ; i < 4 ; i ++) {	// ヘッダ部を戻す
		sector[12 + i] = tmp[i];
	}
	return;
}

/*
 *	だたの memmove() です。
 */
#if 0
void StoreECC(unsigned char *sector, unsigned char *ecc)
{
	unsigned char *src = §or[0x81c];
	int i;
	
	for (i = 0x114; i > 0 ; i --) *ecc ++ = *src ++;
	return;
}
#endif

static void mkTable4ECC(unsigned char *table)
{
	int i, c;

	for (i = 0 ; i < 256 ; i ++) {
		c = i << 1;
		if (c >> 8) c ^= 0x11d;	// if (carry) dl ^= 01dh
		table[i ^ c] = i;
	}
	return;
}

static void calcPParity(const unsigned char *from, unsigned char *dest,
	const unsigned char *table)
{
	int i, j;
	int a, b;
	int index;
	int c;

	for (i = 0 ; i < 86 ; i ++) {
		a = b = 0;
		for (j = 0 ; j < 24 ; j ++) {
			index = ((j * 43 + (i >> 1)) << 1) + (i & 1);
			c = from[index];
			a ^= c; b ^= c;

			if ((a <<= 1) >> 8) a ^= 0x11d;
		}
		if ((a <<= 1) >> 8) a ^= 0x11d;
		a ^= b;
		*dest = table[a];
		dest[86] = table[a] ^ b;
		dest ++;
	}

	return;
}

static void calcQParity(const unsigned char *from, unsigned char *dest,
	const unsigned char *table)
{
	int i, j;
	int a, b;
	int index;
	int c;

	for (i = 0 ; i < 52 ; i ++) {	
		a = b = 0;
		for (j = 0 ; j < 43 ; j ++) {
			index = ((((j * 44) + (i >> 1) * 43) % 1118) << 1) + (i & 1);
			c = from[index];
			a ^= c; b ^= c;

			if ((a <<= 1) >> 8) a ^= 0x11d;
		}
		if ((a <<= 1) >> 8) a ^= 0x11d;
		a ^= b;
		*dest = table[a];
		dest[52] = table[a] ^ b;
		dest ++;
	}

	return;
}


ありゃー、#if 0 とかそのまんまですね。まあいいや。 だいぶ前に作ったのでどうやって使うか忘れました。質問してこないでね。

次、PS2 のこと

えーと PS2 をいぢる、というのは今から楽しみですが、 不正競争なんとか法をかわしながら遊ばないといけないのがツラいところです。 で、どこから崩していくかが問題です。 さしあたり自作プログラムを動かせるところまでいけば、 おのずと?道が開けるってもんですが、PAR の穴はふさがれてしまう(と思う)し、 modchip は(多分)無理だろうし。さてどうしましょう。どっかに穴はないんでしょうかね。ま、とりあえず PS2 出たら、メディアが読める DVD を買おう。 やっぱり全部で10万ぐらいは出て行くわけやね。そんだけ。

以下、アクションリプレイ系

PAR 3 のこと

えーと、買って間もないんですが、わかったことを書きます。

メモリ配置

1f000000-1f01ffff	ROM。バンク切り替えで変わる。
1f020000-1f03ffff	ROM。バンク切り替えで変わる。
1f040000-1f05ffff	なんと RAM。使えるかも。
1f060000-1f06003f	I/O。以後 1f07ffff までひたすらミラー。
なかの ROM は SST 28SF040 ていう、4Mのタイプでした。 ちなみに PAR/XT なんかの ROM サイズの見分け方は、型番の最後の 040 っていうところの数字でわかるみたいです。 010 なら1Mっていうことです。
 ついでなんでうちの各種 PAR を開けた結果を載せときます。

PAR2 を開けたら SST 29EE020 というのが入っていた。(Silicon Storage Technology) この 020 というのが2Mという意味らしい。 あとは DATEL ASIC1 A8B1944A 9832 というでっかい 44pin のが入っていた。 次にパチモン。 SST 29EE010 てのが1Mの。 AMD AM29F010 も互換品(どっちが?) ATMEL AT29C010 も1M。 29F010 と基盤に書いてるのでこれでもOK。 ATMEL のはでっかい 32pin だ。ご丁寧にソケット付きなのでいいこと出来るかも。 ゼロプレでものっけておくかな。 で、PAR じゃないけど 190 円で売ってた裏ワザデータ郎。 H9730 AJ NM27C010V 120 と書いてる。うーむ。1Mらしいけど... EPROM だそうです。UV Erasable か。でも窓がないよ??? あと PIC 16C55。プロテクト掛かってるのかな?ROM吸い出せるかも。 PAR3。 SST 28SF040 4Mですね。回路も格段にややこしくなっている。 MODでおなじみの 12C508 もはいってるぞ。外せば modchip として使えます、 とかだったら面白いんだけどなあ。 XT2: SST 29EE020。ATMEL のと同じでっかい 32pin。DIP っていうの? 蓋を開けたときにバネとネジが飛んでいった。部屋汚くてどこいったかわからん。 PSとのコネクタ部の左上に付いてたものみたいだけど、まあいいや。 なんでこんなネジがあるのか理解不能。 あきばんぐで売ってた「あくしょそ」。1f040000 からROMがあるようなこと をいうのだけど、実際は 1f000000 のミラーだったりする。 AM29F010。 あきばおーで売ってた EMS GOLD FINGER。(HAPPY PLAY) ATMEL AT29BV020。 256byte 書きが必要です。おや、基盤にはやっぱり 29F010 と書いている。 Game Booster (パチモン) ATMEL AT29C010A,同 AT29C020 の切り替え式。

メモを張りつけただけなんで意味不明だったらごめんなさい。

しかしこの容量でメモカ8枚分と言い切るのはどうかと思います。 どんなメモカのデータを想定した数値なんでしょう。 それとも実はもっと EEPROM 積んでるんでしょうか... 1080 ブロックとうたってるカートリッジはどんだけ ROM がのってるのか気になってきました。買おうかな、使わないけど。

I/O

8バイト境界で8種類?あるみたいな感じです。
1f060000 受信用。(1f060000 だけ使用。)全バイト同じ扱いみたい。なにも繋がない状態では 01h です。
1f060008 送信用。(1f060008 だけ使用。)なにも繋がない状態では ffh です。
1f060010 データ受信中は最下位ビットが立ちます。普段は fe です。
1f060018 プッシュボタンの状態。押してないと fefefefefefefefe で、おすと ffffffffffffffff になります。
1f060020 未使用と思う。ffffffffffffffff です。
1f060028 未使用と思う。ffffffffffffffff です。
1f060030 バンク切り替え。1 を入れると実行時のROM、3だと起動時のROMに変わります。
1f060038 なんだろう? lbu してる。ビット0と1に意味があるみたい。fcfcfcfcfcfcfcfc でした。バンクがらみだと思います。

ROM の吸い出し方

えーと 1f000000 から 1f03ffff というか 1f07ffff までをメインメモリに転送するプログラムを書いてCDに焼きます。 ついでに 80000000 から 10000 もコピっておくと勉強になるかもしれません。 あと modchip か青ステが必要です。

以上は説明しません。出来ないひとは吸い出しても意味ないでしょう、たぶん。 なあに、勉強すれば出来るもんです。私は突然できるようになりました。 えーとまず BERO さんの NOT YAROZE でお勉強です。 私が見たときはサンプルソースとか結構リンクが切れてましたが今はどうなんでしょう。で、次に K-Comm. さんとこで猛勉強。多分これが王道です。 とか自慢げに説教してますが私もまだあんまりわかってません。 割り込みまわりとかさっぱりです。

本題。バンク切り替えがある、と言ったとおり、 ゲーム起動前と起動後ではすっかりROMが変わってしまいます。

PAR起動前のROMを吸い出す

これを行った結果なにが破損しようと私は責任を持ちません。
  1. 拡張端子になにも刺さずに起動する。
  2. 起動処理中(白とか黒の画面時でよい。)にPAR3を差す。
  3. 該当メモリをメインメモリに転送するCDを起動。
  4. リセットボタンを押しながら
  5. caetla に差し替える。
  6. psxread で吸い上げ。
もうちょっとがんばってメインメモリを圧縮しつつメモリーカードに吸い上げる、 なんていうプログラムを書けばちっとは安全なんですけど、 UNISYS のバカって感じで圧縮方法で困ってます。 (個人で使うぶんにはいいんでしょうけど。)

PAR起動中のメモリを吸い出す

私が確認したぶんでは 1f000230 から 1f000 バイト(1f01f230 まで)を 80040000 にコピー。(1f01f000 からの改造コードの一部を転送してるのはただの間違い?) そこから 80090000 に圧縮データを展開してます。
  1. PAR を起動。メインメニュー表示
  2. リセットを押しながら caetla に交換
  3. 吸出し。
おんなじですね。

ゲーム起動中のROMを吸い出す

もう書かなくてもわかりますよね。

えーと通信方法については THUMP! さんとことか K-Comm. さんとこで触れてたように思いますので興味ある方は探してみてください。
通信してるプログラムは2個所(もっとあるかも?)にあって、80044c0c からと 800ac9e4 からにそれぞれコマンドに対する関数アドレスの配列が置かれています。 受信した番号 - 100 してから配列参照です。 で、プログラムを実行できるコマンドがあるか、っていうのが一番の興味なんですが、 よくわかりませんでした(泣)。あってもよさそうなんですけど。

て感じです。あんまり役にたたないですけど、これくらいまでは解析できるようになったんだよ、だれか誉めてよーって感じで書いてみました。 PS2 に向けて勉強を続けたいと思います。
私が吸ったのはこんだけですが、まだ展開されてないコードはきっとあります。見つけたら教えて欲しいです。

(2000-01-09 追記) こっちのページに ROM の書き込みかたとかを書きました。 よかったらどうぞ。

あと忘れてたけどなんで PrintInstalledDevices() をフックしてんの? メモカセーブしてから吸い上げるってのもやらなきゃな。

各種 PAR の NTSC 化

よその BBS に投稿したんですけど、そのうち流れてしまうだろうから貼り付けておきます。stealth の NTSC 化はやめときます。解析時には PALPAR のお世話になりました。 あと CPU のキャッシュとかぜんぜん無視してますんで、 怪しいなあと思ったかたは是非良いもんを送り出してやってください。


【PSX Action Replay Version 2.6 (par26frn) NTSC patch】


1f0041ec: 10 fc 24 ac	sw a0,$8005fc10
--------> 10 fc 20 ac	sw zero,$8005fc10
タイトルは NTSC になった。

800a5c9c: a0 96 24 ac
--------> a0 96 20 ac
でもこれは圧縮されてるところ。

てことは
	lui v0, $800a
	li  v1, $20ac
	jr  ra
	sh  v1, $5c9e(v0)

の 16byte をどっかに潜らせる。
68b0 のintr.c の RCS ID の場所を使おう。ってこれ
SCE のライブラリ使ってるやんか。卑怯だなあ。

0a80023c ac200324 0800e003 9e5c43a4

	jal $800468b0 -> 2c1a010c


80040134 にこれをうめる。
10*4bytes うしろにずらして、うめる

というわけで、
00001134: 10 -> 2c
00001135: 00 -> 1a
00001136: a4 -> 01
00001137: 27 -> 0c
00001138: 18 -> 10
00001139: 80 -> 00
0000113a: 05 -> a4
0000113b: 3c -> 27
0000113c: ca -> 18
0000113d: 0e -> 80
0000113e: 01 -> 05
0000113f: 0c -> 3c
00001140: 00 -> ca
00001141: 20 -> 0e
00001142: a5 -> 01
00001143: 34 -> 0c
00001144: 40 -> 00
00001145: 0e -> 20
00001146: 01 -> a5
00001147: 0c -> 34
00001148: 21 -> 40
00001149: 20 -> 0e
0000114a: 00 -> 01
0000114b: 00 -> 0c
0000114c: 34 -> 21
0000114d: 00 -> 20
0000114e: bf -> 00
0000114f: 8f -> 00
00001150: 38 -> 34
00001152: bd -> bf
00001153: 23 -> 8f
00001154: 09 -> 38
00001155: 80 -> 00
00001156: 08 -> bd
00001157: 3c -> 23
00001158: 08 -> 09
00001159: 00 -> 80
0000115a: 00 -> 08
0000115b: 01 -> 3c
0000115c: 00 -> 08
0000115f: 00 -> 01
000041ee: 24 -> 20
000078b0: 24 -> 0a
000078b1: 49 -> 80
000078b2: 64 -> 02
000078b3: 3a -> 3c
000078b4: 20 -> ac
000078b5: 69 -> 20
000078b6: 6e -> 03
000078b7: 74 -> 24
000078b8: 72 -> 08
000078b9: 2e -> 00
000078ba: 63 -> e0
000078bb: 2c -> 03
000078bc: 76 -> 9e
000078bd: 20 -> 5c
000078be: 31 -> 43
000078bf: 2e -> a4

成功、うひゅ。

hanimar

【Action Replay Version 2.81 (ar281) NTSC patch】 1f001800 から 1f01ffff までは 80010000 に転送される。 まず 80010f80 c406043c 80010f84 40028434 li a0, $06c40240 (水平) 80010f88 0407073c 80010f8c 3080e734 li a3, $07048030 (垂直) を li a3, $07040010 にします。 80010f8c: 1000e734 です。 80011000 09008434 ori a0,a0, $0009 は $0001 に変更。 #2800 09->01 あと 80010000 からのコードでは呼ばれてないようだけど、 800109b0 21308000 mov a2,a0 を mov a2,zero に変更。 #21b0 21308000->25300000 同じコードが 800938c4 にあって、 800938c4 21308000 mov a2,a0。 あと 80093ea0 に 80093ea0: 3080e734 or a3, a3, $8030 (li a3,$07048030) 上記は使われてないかもしれない。 さらに 80093f14 に 80093f14: 09008434 ori a0,a0, $0009 それから View Video Image で表示が PAL になるので、 80094d50 21408000 mov t0,a0 を or t0, zero,zero (25400000) にかえる。 これは展開後にパッチをあてます。 80010230 で 80090000 に飛ぶので、この前。 8001022c の lui t0,$8009 と次の jalr t0 を4バイトずらして 8001022c にパッチをあてます。 jal どっか lui t0, $8009 jalr t0 になります。 t0 は 80090000 の状態で飛ぶので利用します。 飛び先は li v0, $0010 sh v0, $3ea0(t0) nop li v0, $0001 sh v0, $3f14(t0) nop li v0, $3025 sw v0,$38c4(t0) nop li v0, $4025 jr ra sw v0, $4d50(t0) だけなんだけど、使いそうにない syscall のところを使わせて貰おう。 a0_90 にします。 8001412c。 てことで jal $8001412c -> 4b50000c 8001022c: 0980083c 09f80001 00000000 ------->: 4b50000c 0980083c 09f80001 8001412c: a0000a24 08004001 90000924 a0000a24 08004001 91000924 a0000a24 08004001 ------->: 10000224 a03e02a5 00000000 01000224 143f02a5 00000000 25300224 c43802ad : 92000924 a0000a24 08004001 93000924 ------->: 00000000 25400224 0800e003 504d02ad という訳で、 00001a2c: 09 -> 4b 00001a2d: 80 -> 50 00001a2e: 08 -> 00 00001a2f: 3c -> 0c 00001a31: f8 -> 80 00001a32: 00 -> 08 00001a33: 01 -> 3c 00001a34: 00 -> 09 00001a35: 00 -> f8 00001a37: 00 -> 01 000021b0: 21 -> 25 000021b2: 80 -> 00 0000278c: 30 -> 10 0000278d: 80 -> 00 00002800: 09 -> 01 0000592c: a0 -> 10 0000592e: 0a -> 02 00005930: 08 -> a0 00005931: 00 -> 3e 00005932: 40 -> 02 00005933: 01 -> a5 00005934: 90 -> 00 00005936: 09 -> 00 00005937: 24 -> 00 00005938: a0 -> 01 0000593a: 0a -> 02 0000593c: 08 -> 14 0000593d: 00 -> 3f 0000593e: 40 -> 02 0000593f: 01 -> a5 00005940: 91 -> 00 00005942: 09 -> 00 00005943: 24 -> 00 00005944: a0 -> 25 00005945: 00 -> 30 00005946: 0a -> 02 00005948: 08 -> c4 00005949: 00 -> 38 0000594a: 40 -> 02 0000594b: 01 -> ad 0000594c: 92 -> 00 0000594e: 09 -> 00 0000594f: 24 -> 00 00005950: a0 -> 25 00005951: 00 -> 40 00005952: 0a -> 02 00005956: 40 -> e0 00005957: 01 -> 03 00005958: 93 -> 50 00005959: 00 -> 4d 0000595a: 09 -> 02 0000595b: 24 -> ad できた、うひゅ。 hanimar
【PSX Game Buster Version 2.3 (gbust23) NTSC patch】 なんだか PAR26 「ふらんす」と同じ様相。 1f0041ec: 10 fc 24 ac sw a0,$8005fc10 --------> 10 fc 20 ac sw zero,$8005fc10 800a5afc e09524ac -> e09520ac この辺の変更は kaja さんの PALPAR で探せます。 SCE のライブラリを使ったプログラムだと探せるようです。 圧縮された部分のコードを動的に変更。 lui v0, $800a li v1, $20ac jr ra sh v1, $5afe(v0) なんで 0a80023c ac200324 0800e003 fe5a43a4 フランス版と少しだけアドレスが違う。 ...というわけで、今回は説明つき。 ROM のアドレス: 元 -> 変更後、です。 00001146: 01 -> a5 00001147: 0c -> 34 00001148: 21 -> 40 00001149: 20 -> 0e a534400eを挿入した。あとはずらしてるだけ。 0000114a: 00 -> 01 0000114b: 00 -> 0c 0000114c: 34 -> 21 0000114d: 00 -> 20 0000114e: bf -> 00 0000114f: 8f -> 00 00001150: 38 -> 34 1151 は変更なし。気を付けて。 00001152: bd -> bf 00001153: 23 -> 8f 00001154: 09 -> 38 00001155: 80 -> 00 00001156: 08 -> bd 00001157: 3c -> 23 00001158: 08 -> 09 00001159: 00 -> 80 0000115a: 00 -> 08 0000115b: 01 -> 3c 0000115c: 00 -> 08 0000115f: 00 -> 01 ここまで「ずらし」。 000041ee: 24 -> 20 タイトルを NTSC にする。 000078b0: 24 -> 0a 上記のアセンブラ部分。 000078b1: 49 -> 80 000078b2: 64 -> 02 000078b3: 3a -> 3c 000078b4: 20 -> ac 000078b5: 69 -> 20 000078b6: 6e -> 03 000078b7: 74 -> 24 000078b8: 72 -> 08 000078b9: 2e -> 00 000078ba: 63 -> e0 000078bb: 2c -> 03 000078bc: 76 -> fe 000078bd: 20 -> 5a 000078be: 31 -> 43 000078bf: 2e -> a4 おしまい。 hanimar

caetla の CDROM メニューのこと

えーと、元はと言えば tayan さんの CDAR なんですが、 CDのディレクトリツリーを読むっていうお話。

なんでも BIOS 内蔵の firstfile() とかは1セクタの収まるデータ量のディレクトリ情報しか取り出せないらしいです。 ためしにやってみたら確かに取れないです。CDAR8 では特定の? ディレクトリの下のファイルが見えないとか確認できました。 プレステってかなり見切り発車で出してしまったようですね、CDまわりが最悪です。
で、これはファイルマネージャ系のプログラムを書くとなったときに、 キツい制限事項となってしまいます。じゃあ、出来ないのかと言えば、 caetla でやってるんですよね。やっぱりすげーなあ、と感心してしまいました。 で、どうやってんのかな?って覗いてみたんですが、 割り込みまわりがよく分からない私ではさっぱり理解できませんでした。 一応 CDMANAGER 部分をとりだすプログラムをのっけときます。 だれか噛み砕いて教えてください。 おいらもCDを有効利用できるプログラム作りたい...
#include "syscall.h"

int doit(char *romAddr, long *dest);

int main(int argc, char **argv)
{
	unsigned long sz;
	char *p = (char *)0x80100000;
	int fd;
	char fname[128];

	if (argc == 1) strcpy(fname, "pcdrv:a.out");
	else {
		strcpy(fname, "pcdrv:");
		strcat(fname, argv[1]);
	}

/*	sz = doit((char *)0x1f01736c, (long *)0x80100000);  FLASHER */
/*	sz = doit((char *)0x1f001c20, (long *)0x80100000);  EXECUTE */
/*	sz = doit((char *)0x1f00a5a4, (long *)0x80100000);  CHEAT CODE */
/*	sz = doit((char *)0x1f00cb9c, (long *)0x80100000);  MEMORY CARD */
/*	sz = doit((char *)0x1f00ee70, (long *)0x80100000);  FRAME BUFFER */
	sz = doit((char *)0x1f0109a0, (long *)0x80100000);	/* CDROM */
/*	sz = doit((char *)0x1f016668, (long *)0x80100000);  CONFIG */


	printf("decoded from $80100000 to 0x%08x (%d bytes).\n",
		(unsigned long)0x80100000 + sz - 1, sz);

	printf("writing to %s\n", fname);
	fd = open(fname, O_CREAT);
	if (fd < 0) {
		printf("Cannot open file %s\n", fname);
	} else {
		close(fd);
		fd = open(fname, O_WRONLY);

		write(fd, p, sz);
		close(fd);
	}
	return 0;
}


#	int doit(char *romAddr, long *dest);
#
#	romAddr: 暗号化?されたイメージへのポインタ
#	dest:	展開先アドレス
#
#	戻り値:展開したサイズ
#
.set reorder
.globl	doit
.ent	doit
doit:
	addiu	sp, sp, -36
	sw	s0, $0010(sp)
	sw	s1, $0014(sp)
	sw	ra, $0018(sp)
	sw	a0, $001c(sp)
	sw	a1, $0020(sp)

	li	s0, $1f006a20	# API 0B だけど直接呼んでしまった。0.34 専用
	jalr	s0		# call API 0B
	li	t2, $00a0
	li	t1, $0044	# FlushCache() 動かさないからいらないんだけど。
	jalr	t2

	or	v0, zero, a1
	lw	v1, $0020(sp)
	subu	v0, v0, v1

	lw	ra, $0018(sp)
	lw	s1, $0014(sp)
	lw	s0, $0010(sp)
	addiu	sp, sp, 36
	jr	ra
.end	doit


えーと実際には 80010000 に展開されます。caetla 0.34 専用です。 あと適当なんで出力ファイルは消してから実行してください。実は caetla API の $0B を呼んでるだけです。 EXE は 80100000 にかぶらないように作らないとダメです。 char *p とか、中途半端な使い方ではずかしいっす。最近 noreorder の人になったのでソースが気持ち悪いです。一回限り、と思って書いたソースなんでこのように醜いもんなわけです。勘弁してください。おしまい。

caetla のパチモン

最近日本では見かけなくなったCDが止まるパチモンですが、 あれは体によろしくないです。 CDメニューから復帰したときに倍速状態から一気に止まるので、 反動でCDが逆回転してます。 巷ではCDのコマンド叩いたら次のコマンドまで VSync 3回分待たないとダメだそうで、じゃあ待たしてみようかと思ったんですが、 割り込みとかカウンタとかわからんので(くどいか)PAD 待ちの周辺をあたってみました。が、 ウェイトを入れたい部分っていうのはちょうどプログラムの切れ目で、 PAD動いてないみたいでした、多分。しかたないのでループで適当に wait を入れたら健康的に止まるようになりました。 どっちにしてもこの機能は一生使わないと思います。

そうそう、PAR の EEPROM って書き換えは 100000 回ぐらいで寿命らしいですから無駄な書き換え、 しょーもないコード入力は控えましょう。 1日1回書き換えるとたった 274 年で使えなくなってしまいます。 1日3回だと 100 年持ちません。

英語の駐禁

頼まれてコナミの実況Jリーグ99を調べたところ、 海外のPSで動かしたら英語で駐禁が出るようになっていました。
800c0044-0041
800c0046-2403
でみれます。 強制的にみれるようにするわけではありませんので、 駐禁に引っかかれる恵まれた環境にないとみれません。
 電話するとどうなるんでしょうね。どこに繋がるんでしょう。 イタ電攻撃で番号なくなってたりして。
で、XPS 作ってくれって言われたんですが、出来ません。 ていうか作って焼いてみたら動かなかったんで戦意喪失。 まだまだ修行が足りないです。

(追記:なんだ、圧縮してたんじゃないのか。てか、素直に汎用2...)

[email protected]