diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 0000000..c18dd8d
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1 @@
+__pycache__/
diff --git a/src/InStageAttemptCounter.ld b/src/InStageAttemptCounter.ld
new file mode 100644
index 0000000..7a09dad
--- /dev/null
+++ b/src/InStageAttemptCounter.ld
@@ -0,0 +1,2 @@
+$$ = 0;
+$C2$.direct = 0xA0 + TMarDirector.direct;
diff --git a/src/InStageAttemptCounter.s b/src/InStageAttemptCounter.s
new file mode 100644
index 0000000..fe7b096
--- /dev/null
+++ b/src/InStageAttemptCounter.s
@@ -0,0 +1,42 @@
+.set r817F, 10
+.set rPad, 11
+.set crSave, 7
+.set addrTimer, 0x817F0478
+.set addrDuration, 0x817F0479
+.set addrAttemptCount, 0x817F04A6
+
+.direct:
+.checkController:
+ lis rPad, mPadButton+2@ha
+ lhzu r0, mPadButton+2@l(rPad)
+ cmplwi crSave, r0, 0x1
+ beq- crSave, .checkController.done
+ cmplwi r0, 0x2
+ bne+ .done
+.checkController.done:
+
+.prepare:
+ lis r817F, 0x817F
+## set display timer
+ lbz r0, addrDuration@l(r817F)
+ stb r0, addrTimer@l(r817F)
+## done for Save
+ beq crSave, .done
+
+.checkPress:
+## prev = cur XOR pressed XOR released
+### Case 1: newly pressed == DR
+### Case 2: something released
+## prev != 0x2 => pressed XOR released != 0
+ lhz r0, 4(rPad)
+ lhz r12, 8(rPad)
+ xor. r0, r0, r12
+ beq .done
+.updateAttemptCount:
+ lhz r12, addrAttemptCount@l(r817F)
+ addi r12, r12, 1
+ sth r12, addrAttemptCount@l(r817F)
+
+.done:
+## orig
+ li r7, 0
diff --git a/src/ManualAttemptCounter.ld b/src/ManualAttemptCounter.ld
new file mode 100644
index 0000000..1883a90
--- /dev/null
+++ b/src/ManualAttemptCounter.ld
@@ -0,0 +1,2 @@
+$$ = 0;
+$C2$.direct = 0x9C + TMarDirector.direct;
diff --git a/src/ManualAttemptCounter.s b/src/ManualAttemptCounter.s
new file mode 100644
index 0000000..ccad85e
--- /dev/null
+++ b/src/ManualAttemptCounter.s
@@ -0,0 +1,50 @@
+.set rPad, 9
+.set r817F, 10
+.set addrTimer, 0x817F0478
+.set addrDuration, 0x817F0479
+.set addrCount, 0x817F04A4
+
+.direct:
+.checkController:
+## R+X
+ lis rPad, mPadButton+2@ha
+ lhzu r0, mPadButton+2@l(rPad)
+ andi. r0, r0, 0xFFF0
+ cmplwi r0, 0x420
+ bne+ .done
+## effective D-Pad
+ lbz rPad, -2+0x18+3(rPad)
+### skip if no D-Pad pressed
+ rlwinm. r0, rPad, 0, 0xF
+ beq .done
+.prepare:
+ lis r817F, 0x817F
+## set display timer
+ lbz r0, addrDuration@l(r817F)
+ stb r0, addrTimer@l(r817F)
+
+.update.success:
+ lhz r12, addrCount@l(r817F)
+### DD(0x4)
+ rlwinm r0, rPad, 32-2, 0x1
+ sub r12, r12, r0
+### DU(0x8)
+ rlwinm r0, rPad, 32-3, 0x1
+ add r12, r12, r0
+## write back
+ sth r12, addrCount@l(r817F)
+
+.update.attempt:
+ lhz r12, addrCount+2@l(r817F)
+### DL(0x1)
+ rlwinm r0, rPad, 0, 0x1
+ sub r12, r12, r0
+### DR(0x2)
+ rlwinm r0, rPad, 32-1, 0x1
+ add r12, r12, r0
+## write back
+ sth r12, addrCount+2@l(r817F)
+
+.done:
+## orig
+ li r6, 0
diff --git a/src/NoShineGet-base.ld b/src/NoShineGet-base.ld
new file mode 100644
index 0000000..de42343
--- /dev/null
+++ b/src/NoShineGet-base.ld
@@ -0,0 +1,8 @@
+$$ = 0;
+
+$C2$.onWinDemo.fireGetStar = 0x88 + TMario.winDemo;
+$C2$.onWinDemo.sendMessageToShine = 0xA4 + TMario.winDemo;
+$C2$.onWinDemo.changeSubstate = 0xAC + TMario.winDemo;
+$C2$.onShineTouchPlayer = TShine.touchPlayer;
+$C2$.reset = 0x28 + TMarDirector.setupObjects;
+/* $C2$.onSetShineGetStatus = 0x801629f4; */
diff --git a/src/NoShineGet-base.s b/src/NoShineGet-base.s
new file mode 100644
index 0000000..70691b2
--- /dev/null
+++ b/src/NoShineGet-base.s
@@ -0,0 +1,73 @@
+.set slot, 0x817F003C
+.set addrTimer, 0x817F0478
+.set addrDuration, 0x817F0479
+.set addrSuccessCount, 0x817F04A4
+
+.onWinDemo.fireGetStar:
+ lis r12, 0x817F
+## update grab game QF
+ lwz r11, 0x58(r3)
+ stw r11, slot@l(r12)
+## QFT freeze
+### set freezeTime = +4 rounded globalQF
+ lwz r11, 0x5C(r3)
+ addi r11, r11, 4
+ rlwinm r11, r11, 0, 0, 29
+ stw r11, 0xB8(r12)
+### freeze duration = inf
+ li r0, -1
+ stw r0, 0xBC(r12)
+## Attempt Counter
+### display timer
+ lbz r0, addrDuration@l(r12)
+ stb r0, addrTimer@l(r12)
+### success count
+ lhz r11, addrSuccessCount@l(r12)
+ addi r11, r11, 1
+ sth r11, addrSuccessCount@l(r12)
+
+.onWinDemo.sendMessageToShine:
+## make shine collision active again
+### clear 0x1 bit
+ lwz r0, 0x64(r3)
+ rlwinm r0, r0, 0, 0, 30
+ stw r0, 0x64(r3)
+
+.onWinDemo.changeSubstate:
+## this->prevState = this->curState
+ #lwz r0, 0x7C(r31)
+ #stw r0, 0x80(r31)
+## this->curState = idle
+ lis r0, 0x0C40
+ ori r0, r0, 0x0201
+ stw r0, 0x7C(r31)
+ li r0, 0
+## 0x88
+ #stw r0, 0x88(r31)
+## substate (0x84), substate timer (0x86)
+ stw r0, 0x84(r31)
+
+.onShineTouchPlayer:
+ lis r12, 0x817F
+### r0 = last grab game QF
+### r11 = current grab game QF
+ lwz r0, slot@l(r12)
+ lwz r11, gpMarDirector$r13(r13)
+ lwz r11, 0x58(r11)
+### r0 = elapsed time since last grab
+ sub r0, r11, r0
+ cmplwi r0, 4
+### update last grab game QF
+ stw r11, slot@l(r12)
+### return if contiguous grab
+ blelr
+## orig
+ mflr r0
+
+.reset:
+## update last grab game QF to 0
+ lis r12, 0x817F
+ li r11, 0
+ stw r11, slot@l(r12)
+## orig
+ mr r3, r0
diff --git a/src/NoShineGet-base.xml b/src/NoShineGet-base.xml
new file mode 100644
index 0000000..54e04a5
--- /dev/null
+++ b/src/NoShineGet-base.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
diff --git a/src/NoShineGet.py b/src/NoShineGet.py
new file mode 100644
index 0000000..19e4e54
--- /dev/null
+++ b/src/NoShineGet.py
@@ -0,0 +1,21 @@
+import xml.etree.ElementTree as ET
+from __gecko__ import *
+
+tree = ET.parse('NoShineGet-base.xml')
+root = tree.getroot()
+for src in root:
+ version = src.attrib['version']
+ winDemo = symbols['winDemo'][version]
+ touchShine = symbols['TShine.touchPlayer'][version]
+ fireGetStar = symbols['TMarDirector.fireGetStar'][version]
+ mPadStatus = symbols['mPadStatus'][version]
+ print(f'''''')
diff --git a/src/__gecko__.py b/src/__gecko__.py
new file mode 100644
index 0000000..303fad9
--- /dev/null
+++ b/src/__gecko__.py
@@ -0,0 +1,43 @@
+GECKO = lambda ct, addr, payload: '%08X %08X'%(ct<<24 | addr&0x1ff_ffff, payload)
+BL = lambda dis: 0x4800_0001 | dis&0x3ff_ffff
+
+VERSIONS = ['GMSJ01', 'GMSJ0A', 'GMSP01', 'GMSE01']
+
+symbols = {
+ 'mPadStatus': {
+ 'GMSJ01': 0x80400d50,
+ 'GMSJ0A': 0x803f5428,
+ 'GMSP01': 0x803fbbf4,
+ 'GMSE01': 0x80404454,
+ },
+ 'winDemo': {
+ 'GMSJ01': 0x801204b8,
+ 'GMSJ0A': 0x802210c0,
+ 'GMSP01': 0x80239104,
+ 'GMSE01': 0x80241378,
+ },
+ 'TShine.touchPlayer': {
+ 'GMSJ01': 0x80195304,
+ 'GMSJ0A': 0x8019d0bc,
+ 'GMSP01': 0x801b51ec,
+ 'GMSE01': 0x801bd334,
+ },
+ 'TMarDirector.fireGetStar': {
+ 'GMSJ01': 0x800edae8,
+ 'GMSJ0A': 0x8027a214,
+ 'GMSP01': 0x802923fc,
+ 'GMSE01': 0x8029a564,
+ },
+ 'gpMarioOriginal': {
+ 'GMSJ01': 0x8040a378,
+ 'GMSJ0A': 0x803fef88,
+ 'GMSP01': 0x804057b0,
+ 'GMSE01': 0x8040e0e8,
+ },
+ 'TMarDirector.__dtor': {
+ 'GMSJ01': 0x800efa34,
+ 'GMSJ0A': 0x8027c218,
+ 'GMSP01': 0x80294400,
+ 'GMSE01': 0x8029c524,
+ },
+}
diff --git a/src/savestate/MarioState.py b/src/savestate/MarioState.py
new file mode 100644
index 0000000..6e479cd
--- /dev/null
+++ b/src/savestate/MarioState.py
@@ -0,0 +1,45 @@
+from __gecko__ import *
+
+# 0: curState+prevState+substate+88 [7C, 8C)
+# 1: flag [118, 120)
+# 2: HSpd {B0}
+# 3: VSpd {A8}
+# 4: grab target {384}
+# 5: FLUDD {3E4}
+# 6: water {r5->1C80}
+
+for version in VERSIONS:
+ mario = symbols['gpMarioOriginal'][version]
+ mPadStatus = symbols['mPadStatus'][version]
+ onDestroy = symbols['TMarDirector.__dtor'][version]
+ print(f'''''')
diff --git a/src/savestate/__gecko__.py b/src/savestate/__gecko__.py
new file mode 120000
index 0000000..d2004c0
--- /dev/null
+++ b/src/savestate/__gecko__.py
@@ -0,0 +1 @@
+../__gecko__.py
\ No newline at end of file
diff --git a/src/savestate/reset.ld b/src/savestate/reset.ld
new file mode 100644
index 0000000..6def60e
--- /dev/null
+++ b/src/savestate/reset.ld
@@ -0,0 +1,3 @@
+$$ = 0;
+
+$C2$.reset = 0x4 + TMarDirector._dtor_TMarDirector$0;
diff --git a/src/savestate/reset.s b/src/savestate/reset.s
new file mode 100644
index 0000000..f9a53a0
--- /dev/null
+++ b/src/savestate/reset.s
@@ -0,0 +1,10 @@
+.set slot, 0x817F0040
+
+.reset:
+## orig
+ stw r0, 4(r1)
+## main
+ lis r12, 0x817F
+ li r0, 0
+ stw r0, slot@l(r12)
+ #stw r0, slot+4@l(r12)