diff --git a/PatternSelector/@code-data.txt b/PatternSelector/@code-data.txt
new file mode 100644
index 0000000..af61b72
--- /dev/null
+++ b/PatternSelector/@code-data.txt
@@ -0,0 +1,8 @@
+077F0441 00000035
+452020FF 213200FF
+621CFF1D 32005025
+25252630 01FF4520
+20213001 FFFF621C
+1D300151 0707FF08
+3102FF36 01FF0231
+021E6E20 FF000000
diff --git a/PatternSelector/@code.xml b/PatternSelector/@code.xml
new file mode 100644
index 0000000..25d0c0c
--- /dev/null
+++ b/PatternSelector/@code.xml
@@ -0,0 +1,280 @@
+
+ qol
+ PatternSelector
+ Pattern Selector
+ パターン選択
+ sup39(サポミク)
+ 0.4
+ Jan 31, 2023
+ drawText
+
+ Ⓑ is the cursor to select the pattern,
+ and the three digits are the numbers representing the pattern.
+ See below for more information.
+
+ | Combination | Result |
+ |---------------|-------------------------------------------------|
+ |L + D-Pad Left |Move cursor(Ⓑ) one digit to the left |
+ |L + D-Pad Right|Move cursor(Ⓑ) one digit to the right |
+ |L + D-Pad Up |Increase the number at the right of the cursor(Ⓑ)|
+ |L + D-Pad Down |Decrease the number at the right of the cursor(Ⓑ)|
+
+ When the cursor(Ⓑ) is not shown, you can press L+D-Pad Left/Right to make it appear.
+
+ You can change the position and color of the text [here](#PatternSelector-config).
+
+ ### Chain Chomp (PV4)
+
+ Use the [1st digit]{.emph} to select the pattern. The 2nd and 3rd are ignored.
+
+ |1st digit|Direction at the beginning|
+ |:-------:|:------------------------:|
+ | 1 | ← |
+ | 2 | ↑ |
+ | 3 | → |
+ | o.w. | Random |
+
+ ### Chain Chomplets (PV1)
+ Each digit represents the pattern of each Chain Chomplet.
+ Numbers not on the graph (e.g. 0) mean random.
+
+ #### 1st digit
+ %object[]{data="/img/PatternSelector/PV1-1.svg"}
+
+ #### 2nd digit
+ %object[]{data="/img/PatternSelector/PV1-2.svg"}
+
+ #### 3rd digit
+ %object[]{data="/img/PatternSelector/PV1-3.svg"}
+
+
+ Ⓑはパターンを選択するためのカーソルであり、三つの数字はパターンの番号を表します。
+ 各パターンの番号は下記を参照してください。
+
+ | ボタン | 動作 |
+ |--------------|------------------------------|
+ |L + 十字キー左|カーソル(Ⓑ)を左一桁に移動 |
+ |L + 十字キー右|カーソル(Ⓑ)を右一桁に移動 |
+ |L + 十字キー上|カーソル(Ⓑ)の右の数字を1増やす|
+ |L + 十字キー下|カーソル(Ⓑ)の右の数字を1減らす|
+
+ カーソル(Ⓑ)が表示されない時、L+十字キー左/右を押せば出てきます。
+
+ [ここ](#PatternSelector-config)で文字の位置や色を変えることができます。
+
+ ### ワンワン(PV4)
+
+ [1桁目]{.emph}でパターンを選択します。2桁目と3桁目は無視されます。
+
+ | 1桁目 | 最初の向き |
+ |:-------:|:----------:|
+ | 1 | ← |
+ | 2 | ↑ |
+ | 3 | → |
+ | その他 | ランダム |
+
+ ### キャンキャン(PV1)
+ 各桁は各キャンキャンのパターンを表します。図上にない数字(例えば0)はランダムを表します。
+
+ #### 1桁目
+ %object[]{data="/img/PatternSelector/PV1-1.svg"}
+
+ #### 2桁目
+ %object[]{data="/img/PatternSelector/PV1-2.svg"}
+
+ #### 3桁目
+ %object[]{data="/img/PatternSelector/PV1-3.svg"}
+
+
+
+
+
+
diff --git a/PatternSelector/info.xml b/PatternSelector/info.xml
new file mode 100644
index 0000000..49a5b4d
--- /dev/null
+++ b/PatternSelector/info.xml
@@ -0,0 +1,88 @@
+
+ qol
+ PatternSelector
+ Pattern Selector
+ パターン選択
+ sup39(サポミク)
+ 0.4
+ Jan 31, 2023
+ drawText
+
+ Ⓑ is the cursor to select the pattern,
+ and the three digits are the numbers representing the pattern.
+ See below for more information.
+
+ | Combination | Result |
+ |---------------|-------------------------------------------------|
+ |L + D-Pad Left |Move cursor(Ⓑ) one digit to the left |
+ |L + D-Pad Right|Move cursor(Ⓑ) one digit to the right |
+ |L + D-Pad Up |Increase the number at the right of the cursor(Ⓑ)|
+ |L + D-Pad Down |Decrease the number at the right of the cursor(Ⓑ)|
+
+ When the cursor(Ⓑ) is not shown, you can press L+D-Pad Left/Right to make it appear.
+
+ You can change the position and color of the text [here](#PatternSelector-config).
+
+ ### Chain Chomp (PV4)
+
+ Use the [1st digit]{.emph} to select the pattern. The 2nd and 3rd are ignored.
+
+ |1st digit|Direction at the beginning|
+ |:-------:|:------------------------:|
+ | 1 | ← |
+ | 2 | ↑ |
+ | 3 | → |
+ | o.w. | Random |
+
+ ### Chain Chomplets (PV1)
+ Each digit represents the pattern of each Chain Chomplet.
+ Numbers not on the graph (e.g. 0) mean random.
+
+ #### 1st digit
+ %object[]{data="/img/PatternSelector/PV1-1.svg"}
+
+ #### 2nd digit
+ %object[]{data="/img/PatternSelector/PV1-2.svg"}
+
+ #### 3rd digit
+ %object[]{data="/img/PatternSelector/PV1-3.svg"}
+
+
+ Ⓑはパターンを選択するためのカーソルであり、三つの数字はパターンの番号を表します。
+ 各パターンの番号は下記を参照してください。
+
+ | ボタン | 動作 |
+ |--------------|------------------------------|
+ |L + 十字キー左|カーソル(Ⓑ)を左一桁に移動 |
+ |L + 十字キー右|カーソル(Ⓑ)を右一桁に移動 |
+ |L + 十字キー上|カーソル(Ⓑ)の右の数字を1増やす|
+ |L + 十字キー下|カーソル(Ⓑ)の右の数字を1減らす|
+
+ カーソル(Ⓑ)が表示されない時、L+十字キー左/右を押せば出てきます。
+
+ [ここ](#PatternSelector-config)で文字の位置や色を変えることができます。
+
+ ### ワンワン(PV4)
+
+ [1桁目]{.emph}でパターンを選択します。2桁目と3桁目は無視されます。
+
+ | 1桁目 | 最初の向き |
+ |:-------:|:----------:|
+ | 1 | ← |
+ | 2 | ↑ |
+ | 3 | → |
+ | その他 | ランダム |
+
+ ### キャンキャン(PV1)
+ 各桁は各キャンキャンのパターンを表します。図上にない数字(例えば0)はランダムを表します。
+
+ #### 1桁目
+ %object[]{data="/img/PatternSelector/PV1-1.svg"}
+
+ #### 2桁目
+ %object[]{data="/img/PatternSelector/PV1-2.svg"}
+
+ #### 3桁目
+ %object[]{data="/img/PatternSelector/PV1-3.svg"}
+
+
diff --git a/PatternSelector/make.py b/PatternSelector/make.py
new file mode 100644
index 0000000..fc9460f
--- /dev/null
+++ b/PatternSelector/make.py
@@ -0,0 +1,34 @@
+from supSMSGecko import build, make_xml, symbols
+
+extra_ld_input = '''
+drawText = 0x817f0238;
+
+/** struct {u8 patterns[3], u8 cursor} */
+$patterns = 0x817f0024;
+
+/* size = 0x14 */
+$rectOpt = 0x817f0410;
+
+/* size = 0x10 */
+$textOpt = 0x817f0424;
+
+/* size = 13 "%c%X%c%X%c%X" */
+$fmt = 0x817f0434;
+
+/* size = 53 */
+$data = 0x817f0441;
+'''
+
+def main(g, ver):
+ S = symbols[ver]
+ g.C2(S['TSpineEnemy_goToRandomNextGraphNode'] + 0x50, 'src/selector.s', extra_ld_input=extra_ld_input)
+ g.C2(S['drawWater'] - 0x24, 'src/draw.s', extra_ld_input=extra_ld_input)
+
+def main_data(g, ver):
+ g.c_kit(0x817f0441, 'src/pattern-data.s', entries=[])
+
+# compile main code to @code.xml
+make_xml(main)
+# compile pattern-data.s to @code-data.txt
+with open('@code-data.txt', 'w') as fw:
+ print(build(main_data, 'GMSJ01').dump_txt(''), file=fw)
diff --git a/PatternSelector/src/draw.s b/PatternSelector/src/draw.s
new file mode 100644
index 0000000..b1b75ba
--- /dev/null
+++ b/PatternSelector/src/draw.s
@@ -0,0 +1,95 @@
+.set rPats, 3
+.set rPad, 4
+.set rCS, 11
+.set btnMask, 0x40 # L
+
+.draw2d:
+
+### check stage
+# lis r3, gpApplication+0xE@ha
+# lhz r3, gpApplication+0xE@l(r3)
+# cmplwi r3, 0x0800
+# cmplwi cr1, r3, 0x0803
+# cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
+# bne .draw2d.done
+
+.draw.background:
+ lis r3, 0x817F
+ ori r3, r3, $rectOpt@l
+ addi r4, r3, 0x10
+ lis r12, fill_rect@h
+ ori r12, r12, fill_rect@l
+ mtlr r12
+ blrl
+
+.update.state:
+ lis rPad, mPadButton+2@ha
+ lhzu r0, mPadButton+2@l(rPad)
+ lis rPats, $patterns@h
+ lwzu rCS, $patterns@l(rPats) # cs = [3]
+### L is pressed
+ andi. r0, r0, btnMask
+ beq+ .update.state.end
+## rPad = effective D-Pad
+ lbz rPad, -2+0x18+3(rPad)
+.update.cursor:
+ rlwinm r0, rPad, 0, 0x1 # DL
+ sub rCS, rCS, r0 # -1
+ rlwinm r0, rPad, 32-1, 0x1 # DR
+ add rCS, rCS, r0 # +1
+ rlwinm rCS, rCS, 0, 0x3 # %4
+.update.patterns:
+ rlwinm. r0, rPad, 32-2, 0x3 # DU,DD
+ beq+ .update.state.end
+## cursor = 0 if < 3
+ cmplwi rCS, 3
+ blt+ .update.cs3.end
+ li rCS, 0
+.update.cs3.end:
+## r0 = diff
+ rlwinm r0, rPad, 32-3, 0x1 # DU>>3 +1
+ rlwimi r0, rPad, 0, 0x4 # DD>>2<<2 +4
+## r12 = patterns[cs]
+ lbzx r12, rPats, rCS
+ add r12, r12, r0 # patterns[cs] += diff
+## pattern %= 5
+ cmplwi r12, 5
+ blt+ .update.pat5.end
+ addi r12, r12, -5
+.update.pat5.end:
+## store
+ stbx r12, rPats, rCS
+.update.state.end:
+ stb rCS, 3(rPats)
+
+.draw:
+## cursor
+ .set magic, 0x20202023
+ #.set magic, 0x4040409a ## star
+ #.set magic, 0x404040a8 ## right arrow
+ #.set magic, 0x2020207d ## right arrow (EU)
+ lis r0, magic@h
+ ori r0, r0, magic@l
+### 1st digit
+ rlwinm r12, rCS, 3, 0, 31 # r12 = rCS*8
+ rlwnm r0, r0, r12, 0, 31 # r0 = cursor value (24 bit)
+ rlwinm r5, r0, 0, 0xFF # 1st cursor
+### 2nd digit
+ rlwinm r7, r0, 32-8, 0xFF # 2nd cursor: rotate right 8
+### 3rd digit
+ rlwinm r9, r0, 32-16, 0xFF # 3rd cursor: rotate right 16
+## patterns
+ lbz r6, 0(rPats)
+ lbz r8, 1(rPats)
+ lbz r10, 2(rPats)
+## params
+ lis r12, 0x817F
+ ori r3, r12, $textOpt@l
+ ori r4, r12, $fmt@l
+ ori r12, r12, drawText@l
+ mtlr r12
+ blrl
+
+.draw2d.done:
+
+# vi:se ft=asm:
diff --git a/PatternSelector/src/pattern-data.s b/PatternSelector/src/pattern-data.s
new file mode 100644
index 0000000..323e9f4
--- /dev/null
+++ b/PatternSelector/src/pattern-data.s
@@ -0,0 +1,25 @@
+.set .sizeof.entry.PV1, 7
+.data.patterns.PV1:
+/** next[4], cur, name[19], pid */
+ /**** case '2' ****/
+ /* 33: up, right */
+ .byte 69, 32, 32, -1, 33, 0x32, 0
+ /* 29: up, right */
+ .byte -1, 98, 28, -1, 29, 0x32, 0
+ /**** case '0' ****/
+ /* 38: up, right */
+ .byte 80, 37, 37, 37, 38, 0x30, 1
+ /* 33: up, right */
+ .byte -1, 69, 32, 32, 33, 0x30, 1
+ /* 29: up, right */
+ .byte -1, -1, 98, 28, 29, 0x30, 1
+ /**** case '1' ****/
+ /* 8: down, left */
+ .byte 81, 7, 7, -1, 8, 0x31, 2
+ /* 2: down, left */
+ .byte -1, 54, 1, -1, 2, 0x31, 2
+.data.patterns.PV1.end:
+
+.data.patterns.PV4:
+ /* left, middle, right */
+ .byte 30, 110, 32, -1
diff --git a/PatternSelector/src/selector.s b/PatternSelector/src/selector.s
new file mode 100644
index 0000000..2010b29
--- /dev/null
+++ b/PatternSelector/src/selector.s
@@ -0,0 +1,77 @@
+.set .data.PV1.entrySize, 7
+.set .data.PV1.entryCount, 7
+.set .data.PV1.size, .data.PV1.entrySize * .data.PV1.entryCount
+.set .data.PV4.offset, .data.PV1.size
+
+## Do not change r3~r6 for fallback function call
+.set rCur, 4
+.set rPrev, 5
+.set rPid, 7
+.set rEntry, 8 # offset of pattern entry
+.set rEntryEnd, 9
+.set rPats, 10
+
+.getRandomNextIndex:
+## r0 = vt
+ lwz r0, 0(r31)
+ lis r12, 0x817F
+ ori rEntry, r12, $data-1@l
+ ori rPats, r12, $patterns@l
+### PV4
+ xoris r12, r0, TBossWanwan___vt@h
+ cmplwi r12, TBossWanwan___vt@l
+ beq .getRandomNextIndex.PV4
+### PV1
+ xoris r12, r0, TFireWanwan___vt@h
+ cmplwi r12, TFireWanwan___vt@l
+ bne .fallback
+.getRandomNextIndex.PV1:
+## r12 = (curIdx, name[19])
+ lwz r12, 4(r31) # name
+ lbz r12, 19(r12) # name[19]
+ rlwimi r12, rCur, 8, 0x10, 0x17
+## foreach entry
+ addi rEntryEnd, rEntry, .data.PV1.size
+.getRandomNextIndex.PV1.loop:
+### pid
+ lbz r0, 1+6(rEntry)
+ lbzx rPid, rPats, r0
+### check id
+ lhz r0, 1+4(rEntry)
+ cmplw r0, r12
+ beq- .getRandomNextIndex.result
+ addi rEntry, rEntry, .data.PV1.entrySize
+ cmplw rEntry, rEntryEnd
+ blt+ .getRandomNextIndex.PV1.loop
+
+.fallback:
+ lis r12, getRandomNextIndex@h
+ ori r12, r12, getRandomNextIndex@l
+ mtlr r12
+ blrl
+ b .getRandomNextIndex.done
+
+.getRandomNextIndex.PV4:
+## handle initial node only
+ cmpwi rPrev, -1
+ bne+ .fallback
+## use patterns[0]
+ lbz rPid, 0(rPats)
+ addi rEntry, rEntry, .data.PV4.offset
+## DONE
+ #b .getRandomNextIndex.result
+
+.getRandomNextIndex.result:
+## if pid == 0, goto fallback
+ mr. rPid, rPid # TODO pid>4
+ beq .fallback
+## ans = patterns[idx][pid-1] = entry[pid]
+ lbzx r0, rEntry, rPid
+ cmplwi r0, 255 # invalid
+ beq .fallback
+## valid result (r0) as return value (r3)
+ mr r3, r0
+
+.getRandomNextIndex.done:
+
+# vi:se ft=asm: