2000-01-04
駐禁の歴史を振りかえるつもりでしたが都合で前編のみになってしまいました。
何とぞご勘弁を。
えーと、現在主流の 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; }
1f000000-1f01ffff ROM。バンク切り替えで変わる。 1f020000-1f03ffff ROM。バンク切り替えで変わる。 1f040000-1f05ffff なんと RAM。使えるかも。 1f060000-1f06003f I/O。以後 1f07ffff までひたすらミラー。なかの ROM は SST 28SF040 ていう、4Mのタイプでした。 ちなみに PAR/XT なんかの ROM サイズの見分け方は、型番の最後の 040 っていうところの数字でわかるみたいです。 010 なら1Mっていうことです。
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 でした。バンクがらみだと思います。 |
【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
#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
800c0044-0041 800c0046-2403でみれます。 強制的にみれるようにするわけではありませんので、 駐禁に引っかかれる恵まれた環境にないとみれません。