diff --git a/UndertaleModTool/MainWindow.xaml.cs b/UndertaleModTool/MainWindow.xaml.cs
index 68189f287..e90d211bf 100644
--- a/UndertaleModTool/MainWindow.xaml.cs
+++ b/UndertaleModTool/MainWindow.xaml.cs
@@ -166,7 +166,7 @@ private async Task SaveFile(string filename)
if (IsGMS2 == Visibility.Visible)
{
- MessageBox.Show("This is not yet tested and may break. You have been warned.", "GMS2 game", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+ MessageBox.Show("This is not yet tested and may break. You have been warned.", "GMS2 game", MessageBoxButton.OK, MessageBoxImage.Warning);
}
LoaderDialog dialog = new LoaderDialog("Saving", "Saving, please wait...");
@@ -503,6 +503,8 @@ private void MenuItem_RunBuiltinScript_SubmenuOpened(object sender, RoutedEventA
foreach(var path in Directory.EnumerateFiles("SampleScripts"))
{
var filename = System.IO.Path.GetFileName(path);
+ if (!filename.EndsWith(".csx"))
+ continue;
MenuItem subitem = new MenuItem() { Header = filename.Replace("_", "__") };
subitem.Click += MenuItem_RunBuiltinScript_Item_Click;
subitem.CommandParameter = path;
diff --git a/UndertaleModTool/SampleScripts/MixMod.csx b/UndertaleModTool/SampleScripts/MixMod.csx
new file mode 100644
index 000000000..a3b99fc92
--- /dev/null
+++ b/UndertaleModTool/SampleScripts/MixMod.csx
@@ -0,0 +1,1650 @@
+EnsureDataLoaded();
+
+/* TODO: Respect loop/no loop setting properly */
+
+var browserext = new UndertaleExtension() {
+ Name = Data.Strings.MakeString("GMWebBrowser"),
+ ClassName = Data.Strings.MakeString(""),
+ EmptyString = Data.Strings.MakeString("")
+};
+browserext.Files.Add(new UndertaleExtension.ExtensionFile() {
+ Filename = Data.Strings.MakeString("GMWebExtension.dll"),
+ Kind = UndertaleExtension.ExtensionKind.DLL,
+ InitScript = Data.Strings.MakeString("__webextension_native_init"),
+ CleanupScript = Data.Strings.MakeString("__webextension_native_exit"),
+});
+// 0xc = cdecl?
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 1, 0xc, "RegisterCallbacks", UndertaleExtension.ExtensionVarType.Double, "RegisterCallbacks", UndertaleExtension.ExtensionVarType.String, UndertaleExtension.ExtensionVarType.String, UndertaleExtension.ExtensionVarType.String, UndertaleExtension.ExtensionVarType.String);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 2, 0xc, "__webextension_native_init", UndertaleExtension.ExtensionVarType.Double, "__webextension_native_init");
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 3, 0xc, "__webextension_native_exit", UndertaleExtension.ExtensionVarType.Double, "__webextension_native_exit");
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 4, 0xc, "__webextension_set_device", UndertaleExtension.ExtensionVarType.Double, "__webextension_set_device", UndertaleExtension.ExtensionVarType.String);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 5, 0xc, "browser_create", UndertaleExtension.ExtensionVarType.Double, "browser_create", UndertaleExtension.ExtensionVarType.String);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 6, 0xc, "browser_destroy", UndertaleExtension.ExtensionVarType.Double, "browser_destroy", UndertaleExtension.ExtensionVarType.Double);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 7, 0xc, "browser_load", UndertaleExtension.ExtensionVarType.Double, "browser_load", UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.String);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 8, 0xc, "browser_load_html", UndertaleExtension.ExtensionVarType.Double, "browser_load_html", UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.String);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 9, 0xc, "browser_resize", UndertaleExtension.ExtensionVarType.Double, "browser_resize", UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.Double);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 10, 0xc, "browser_draw", UndertaleExtension.ExtensionVarType.Double, "browser_draw", UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.Double);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 11, 0xc, "browser_is_initialized", UndertaleExtension.ExtensionVarType.Double, "browser_is_initialized", UndertaleExtension.ExtensionVarType.Double);
+browserext.Files[0].Functions.DefineExtensionFunction(Data.Functions, Data.Strings, 12, 0xc, "browser_js", UndertaleExtension.ExtensionVarType.Double, "browser_js", UndertaleExtension.ExtensionVarType.Double, UndertaleExtension.ExtensionVarType.String);
+Data.Extensions.Add(browserext);
+
+Data.Functions.EnsureDefined("window_device", Data.Strings);
+Data.Functions.EnsureDefined("http_get", Data.Strings);
+Data.Functions.EnsureDefined("ds_list_size", Data.Strings);
+Data.Functions.EnsureDefined("ds_list_find_value", Data.Strings);
+Data.Functions.EnsureDefined("show_message", Data.Strings);
+Data.Functions.EnsureDefined("show_debug_message", Data.Strings);
+Data.Variables.EnsureDefined("my_browser", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+Data.Variables.EnsureDefined("youtube_current_song", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+Data.Variables.EnsureDefined("youtube_request", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+Data.Variables.EnsureDefined("youtube_song_title", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+Data.Variables.EnsureDefined("youtube_last_song", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+Data.Variables.EnsureDefined("youtube_cache", UndertaleInstruction.InstanceType.Self, false, Data.Strings, Data);
+var var_song = Data.Variables.IndexOf(Data.Variables.DefineLocal(1, "song", Data.Strings, Data));
+var var_w = Data.Variables.IndexOf(Data.Variables.DefineLocal(1, "w", Data.Strings, Data));
+var var_h = Data.Variables.IndexOf(Data.Variables.DefineLocal(2, "h", Data.Strings, Data));
+var var_data = Data.Variables.IndexOf(Data.Variables.DefineLocal(1, "data", Data.Strings, Data));
+var var_items = Data.Variables.IndexOf(Data.Variables.DefineLocal(1, "items", Data.Strings, Data));
+var var_item = Data.Variables.IndexOf(Data.Variables.DefineLocal(2, "item", Data.Strings, Data));
+var var_type = Data.Variables.IndexOf(Data.Variables.DefineLocal(1, "type", Data.Strings, Data));
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.Create, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+call.i window_device(argc=0)
+call.i __webextension_set_device(argc=1)
+popz.v
+
+push.s """"
+conv.s.v
+call.i browser_create(argc=1)
+pop.v.v self.my_browser
+
+push.s """"
+pop.v.s self.youtube_current_song
+
+pushi.e -4
+pop.v.i self.youtube_request
+
+push.s """"
+pop.v.s self.youtube_song_title
+
+push.s """"
+pop.v.s self.youtube_last_song
+
+call.i ds_map_create(argc=0)
+pop.v.v self.youtube_cache
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.Draw, EventSubtypeDraw.PostDraw, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+.localvar 1 w " + var_w + @"
+.localvar 2 h " + var_h + @"
+call.i window_get_width(argc=0)
+push.d 6.5
+div.d.v
+pop.v.v local.w
+pushloc.v local.w
+pushi.e 16
+conv.i.d
+div.d.v
+pushi.e 9
+mul.i.v
+pop.v.v local.h
+pushloc.v local.h
+pushloc.v local.w
+push.v self.my_browser
+call.i browser_resize(argc=3)
+popz.v
+
+pushi.e 5
+conv.i.v
+pushi.e 5
+conv.i.v
+push.v self.my_browser
+call.i browser_draw(argc=3)
+popz.v
+
+push.v self.youtube_current_song
+call.i window_set_caption(argc=1)
+popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.Draw, EventSubtypeDraw.DrawGUI, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+pushi.e 2
+conv.i.v
+call.i draw_set_font(argc=1)
+popz.v
+
+push.i " + 0x00FFFF.ToString() + @"
+conv.i.v
+call.i draw_set_color(argc=1)
+popz.v
+
+; why is it so hard to get something centered horizontally
+; it's almost like trying to do vertical centering in CSS
+; no, actually CSS is worse
+; I hope nobody tries to play Undertale in portrait orientation or this is going to break :P
+push.v self.youtube_song_title
+pushi.e 0
+conv.i.v
+pushvar.v self.application_surface
+call.i surface_get_width(argc=1)
+pushglb.v global.window_scale
+mul.v.v
+push.v self.youtube_song_title
+call.i string_width(argc=1)
+sub.v.v
+pushi.e 2
+div.i.v
+pushglb.v global.window_yofs
+add.v.v
+call.i draw_text(argc=3)
+popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+var MOD_get_mus_query = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_MOD_get_mus_query") };
+MOD_get_mus_query.Append(Assembler.Assemble(@"
+; yeah, I compiled that in GameMaker: Studio :P
+00000: pushvar.v self.argument0
+00002: pushi.e 213
+00003: cmp.i.v EQ
+00004: bf 00009
+00005: push.s ""Ghost+Fight""
+00007: conv.s.v
+00008: ret.v
+
+00009: pushvar.v self.argument0
+00011: pushi.e 214
+00012: cmp.i.v EQ
+00013: bf 00018
+00014: push.s ""Once+Upon+a+Time""
+00016: conv.s.v
+00017: ret.v
+
+00018: pushvar.v self.argument0
+00020: pushi.e 216
+00021: cmp.i.v EQ
+00022: bf 00027
+00023: push.s ""Fallen+Down""
+00025: conv.s.v
+00026: ret.v
+
+00027: pushvar.v self.argument0
+00029: pushi.e 217
+00030: cmp.i.v EQ
+00031: bf 00036
+00032: push.s ""Your+Best+Friend""
+00034: conv.s.v
+00035: ret.v
+
+00036: pushvar.v self.argument0
+00038: pushi.e 218
+00039: cmp.i.v EQ
+00040: bf 00045
+00041: push.s ""Anticipation""
+00043: conv.s.v
+00044: ret.v
+
+00045: pushvar.v self.argument0
+00047: pushi.e 219
+00048: cmp.i.v EQ
+00049: bf 00054
+00050: push.s ""Unnecessary+Tension""
+00052: conv.s.v
+00053: ret.v
+
+00054: pushvar.v self.argument0
+00056: pushi.e 220
+00057: cmp.i.v EQ
+00058: bf 00063
+00059: push.s ""Start+Menu""
+00061: conv.s.v
+00062: ret.v
+
+00063: pushvar.v self.argument0
+00065: pushi.e 221
+00066: cmp.i.v EQ
+00067: bf 00072
+00068: push.s ""Start+Menu""
+00070: conv.s.v
+00071: ret.v
+
+00072: pushvar.v self.argument0
+00074: pushi.e 222
+00075: cmp.i.v EQ
+00076: bf 00081
+00077: push.s ""Start+Menu""
+00079: conv.s.v
+00080: ret.v
+
+00081: pushvar.v self.argument0
+00083: pushi.e 223
+00084: cmp.i.v EQ
+00085: bf 00090
+00086: push.s ""Start+Menu""
+00088: conv.s.v
+00089: ret.v
+
+00090: pushvar.v self.argument0
+00092: pushi.e 224
+00093: cmp.i.v EQ
+00094: bf 00099
+00095: push.s ""Start+Menu""
+00097: conv.s.v
+00098: ret.v
+
+00099: pushvar.v self.argument0
+00101: pushi.e 225
+00102: cmp.i.v EQ
+00103: bf 00108
+00104: push.s ""Start+Menu""
+00106: conv.s.v
+00107: ret.v
+
+00108: pushvar.v self.argument0
+00110: pushi.e 226
+00111: cmp.i.v EQ
+00112: bf 00117
+00113: push.s ""Menu+%28Full%29""
+00115: conv.s.v
+00116: ret.v
+
+00117: pushvar.v self.argument0
+00119: pushi.e 227
+00120: cmp.i.v EQ
+00121: bf 00126
+00122: push.s ""Home""
+00124: conv.s.v
+00125: ret.v
+
+00126: pushvar.v self.argument0
+00128: pushi.e 232
+00129: cmp.i.v EQ
+00130: bf 00135
+00131: push.s ""Heartache""
+00133: conv.s.v
+00134: ret.v
+
+00135: pushvar.v self.argument0
+00137: pushi.e 233
+00138: cmp.i.v EQ
+00139: bf 00144
+00140: push.s ""Home+%28Music+Box%29""
+00142: conv.s.v
+00143: ret.v
+
+00144: pushvar.v self.argument0
+00146: pushi.e 234
+00147: cmp.i.v EQ
+00148: bf 00153
+00149: push.s ""Ruins""
+00151: conv.s.v
+00152: ret.v
+
+00153: pushvar.v self.argument0
+00155: pushi.e 235
+00156: cmp.i.v EQ
+00157: bf 00162
+00158: push.s ""Enemy+Approaching""
+00160: conv.s.v
+00161: ret.v
+
+00162: pushvar.v self.argument0
+00164: pushi.e 236
+00165: cmp.i.v EQ
+00166: bf 00171
+;00167: push.s ""Determination""
+00167: push.s ""game+over+theme""
+00169: conv.s.v
+00170: ret.v
+
+00171: pushvar.v self.argument0
+00173: pushi.e 241
+00174: cmp.i.v EQ
+00175: bf 00180
+00176: push.s ""Dogsong""
+00178: conv.s.v
+00179: ret.v
+
+00180: pushvar.v self.argument0
+00182: pushi.e 242
+00183: cmp.i.v EQ
+00184: bf 00189
+00185: push.s ""Bonetrousle""
+00187: conv.s.v
+00188: ret.v
+
+00189: pushvar.v self.argument0
+00191: pushi.e 243
+00192: cmp.i.v EQ
+00193: bf 00198
+00194: push.s ""Shop""
+00196: conv.s.v
+00197: ret.v
+
+00198: pushvar.v self.argument0
+00200: pushi.e 244
+00201: cmp.i.v EQ
+00202: bf 00216
+00203: push.s ""Snowdin+Town""
+00205: conv.s.v
+00206: ret.v
+
+;00207: pushvar.v self.argument0
+;00209: pushi.e 246
+;00210: cmp.i.v EQ
+;00211: bf 00216
+;00212: push.s ""Mysterious+Place""
+;00214: conv.s.v
+;00215: ret.v
+
+00216: pushvar.v self.argument0
+00218: pushi.e 251
+00219: cmp.i.v EQ
+00220: bf 00225
+00221: push.s ""%22Dating+Start%21%22""
+00223: conv.s.v
+00224: ret.v
+
+00225: pushvar.v self.argument0
+00227: pushi.e 252
+00228: cmp.i.v EQ
+00229: bf 00234
+00230: push.s ""%22Dating+Tense%21%22""
+00232: conv.s.v
+00233: ret.v
+
+00234: pushvar.v self.argument0
+00236: pushi.e 253
+00237: cmp.i.v EQ
+00238: bf 00243
+00239: push.s ""%22Dating+Fight%21%22""
+00241: conv.s.v
+00242: ret.v
+
+00243: pushvar.v self.argument0
+00245: pushi.e 254
+00246: cmp.i.v EQ
+00247: bf 00252
+00248: push.s ""Premonition""
+00250: conv.s.v
+00251: ret.v
+
+00252: pushvar.v self.argument0
+00254: pushi.e 255
+00255: cmp.i.v EQ
+00256: bf 00270
+00257: push.s ""Snowy""
+00259: conv.s.v
+00260: ret.v
+
+;00261: pushvar.v self.argument0
+;00263: pushi.e 256
+;00264: cmp.i.v EQ
+;00265: bf 00270
+;00266: push.s ""sans.""
+; OH PLEASE MEGALOVANIA STOP IT
+; (-megalovania just totally breaks the results for some reason)
+;00266: push.s ""sans+theme""
+;00268: conv.s.v
+;00269: ret.v
+
+00270: pushvar.v self.argument0
+00272: pushi.e 257
+00273: cmp.i.v EQ
+00274: bf 00297
+00275: push.s ""Nyeh+Heh+Heh%21""
+00277: conv.s.v
+00278: ret.v
+
+;00279: pushvar.v self.argument0
+;00281: pushi.e 260
+;00282: cmp.i.v EQ
+;00283: bf 00288
+;00284: push.s ""Dogbass""
+;00286: conv.s.v
+;00287: ret.v
+
+;00288: pushvar.v self.argument0
+;00290: pushi.e 261
+;00291: cmp.i.v EQ
+;00292: bf 00297
+;00293: push.s ""Danger+Mystery""
+;00295: conv.s.v
+;00296: ret.v
+
+00297: pushvar.v self.argument0
+00299: pushi.e 262
+00300: cmp.i.v EQ
+00301: bf 00315
+00302: push.s ""Bird+That+Carries+You+Over+A+Disproportionately+Small+Gap""
+00304: conv.s.v
+00305: ret.v
+
+;00306: pushvar.v self.argument0
+;00308: pushi.e 263
+;00309: cmp.i.v EQ
+;00310: bf 00315
+;00311: push.s ""The+Choice""
+;00313: conv.s.v
+;00314: ret.v
+
+00315: pushvar.v self.argument0
+00317: pushi.e 264
+00318: cmp.i.v EQ
+00319: bf 00324
+00320: push.s ""Dummy%21""
+00322: conv.s.v
+00323: ret.v
+
+00324: pushvar.v self.argument0
+00326: pushi.e 267
+00327: cmp.i.v EQ
+00328: bf 00333
+00329: push.s ""Thundersnail""
+00331: conv.s.v
+00332: ret.v
+
+00333: pushvar.v self.argument0
+00335: pushi.e 268
+00336: cmp.i.v EQ
+00337: bf 00342
+00338: push.s ""NGAHHH%21%21""
+00340: conv.s.v
+00341: ret.v
+
+00342: pushvar.v self.argument0
+00344: pushi.e 269
+00345: cmp.i.v EQ
+00346: bf 00351
+00347: push.s ""She%27s+Playing+Piano""
+00349: conv.s.v
+00350: ret.v
+
+00351: pushvar.v self.argument0
+00353: pushi.e 270
+00354: cmp.i.v EQ
+00355: bf 00360
+00356: push.s ""Waterfall""
+00358: conv.s.v
+00359: ret.v
+
+00360: pushvar.v self.argument0
+00362: pushi.e 271
+00363: cmp.i.v EQ
+00364: bf 00369
+00365: push.s ""Quiet+Water""
+00367: conv.s.v
+00368: ret.v
+
+00369: pushvar.v self.argument0
+00371: pushi.e 273
+00372: cmp.i.v EQ
+00373: bf 00387
+00374: push.s ""Run%21""
+00376: conv.s.v
+00377: ret.v
+
+;00378: pushvar.v self.argument0
+;00380: pushi.e 274
+;00381: cmp.i.v EQ
+;00382: bf 00387
+;00383: push.s ""Undyne""
+;00385: conv.s.v
+;00386: ret.v
+
+00387: pushvar.v self.argument0
+00389: pushi.e 276
+00390: cmp.i.v EQ
+00391: bf 00396
+00392: push.s ""Memory""
+00394: conv.s.v
+00395: ret.v
+
+00396: pushvar.v self.argument0
+00398: pushi.e 279
+00399: cmp.i.v EQ
+00400: bf 00405
+00401: push.s ""Pathetic+House""
+00403: conv.s.v
+00404: ret.v
+
+00405: pushvar.v self.argument0
+00407: pushi.e 282
+00408: cmp.i.v EQ
+00409: bf 00414
+00410: push.s ""Chill""
+00412: conv.s.v
+00413: ret.v
+
+00414: pushvar.v self.argument0
+00416: pushi.e 283
+00417: cmp.i.v EQ
+00418: bf 00423
+00419: push.s ""Spooktune""
+00421: conv.s.v
+00422: ret.v
+
+00423: pushvar.v self.argument0
+00425: pushi.e 284
+00426: cmp.i.v EQ
+00427: bf 00432
+00428: push.s ""Spookwave""
+00430: conv.s.v
+00431: ret.v
+
+00432: pushvar.v self.argument0
+00434: pushi.e 285
+00435: cmp.i.v EQ
+00436: bf 00441
+00437: push.s ""Ghouliday""
+00439: conv.s.v
+00440: ret.v
+
+00441: pushvar.v self.argument0
+00443: pushi.e 286
+00444: cmp.i.v EQ
+;00445: bf 00450
+00445: bf 00468
+00446: push.s ""Spear+of+Justice""
+00448: conv.s.v
+00449: ret.v
+
+; this one just like never works
+; people remix it please
+;00450: pushvar.v self.argument0
+;00452: pushi.e 289
+;00453: cmp.i.v EQ
+;00454: bf 00459
+;00455: push.s ""Alphys""
+;00457: conv.s.v
+;00458: ret.v
+
+00459: pushvar.v self.argument0
+00461: pushi.e 290
+00462: cmp.i.v EQ
+00463: bf 00468
+00464: push.s ""It%27s+Showtime%21""
+00466: conv.s.v
+00467: ret.v
+
+00468: pushvar.v self.argument0
+00470: pushi.e 291
+00471: cmp.i.v EQ
+00472: bf 00477
+00473: push.s ""Metal+Crusher""
+00475: conv.s.v
+00476: ret.v
+
+00477: pushvar.v self.argument0
+00479: pushi.e 292
+00480: cmp.i.v EQ
+00481: bf 00495
+00482: push.s ""Hotel""
+00484: conv.s.v
+00485: ret.v
+
+;00486: pushvar.v self.argument0
+;00488: pushi.e 293
+;00489: cmp.i.v EQ
+;00490: bf 00495
+;00491: push.s ""For+The+Fans""
+;00493: conv.s.v
+;00494: ret.v
+
+00495: pushvar.v self.argument0
+00497: pushi.e 294
+00498: cmp.i.v EQ
+00499: bf 00504
+00500: push.s ""Spider+Dance""
+00502: conv.s.v
+00503: ret.v
+
+00504: pushvar.v self.argument0
+00506: pushi.e 295
+00507: cmp.i.v EQ
+00508: bf 00513
+00509: push.s ""It%27s+Raining+Somewhere+Else""
+00511: conv.s.v
+00512: ret.v
+
+00513: pushvar.v self.argument0
+00515: pushi.e 297
+00516: cmp.i.v EQ
+00517: bf 00522
+00518: push.s ""Live+Report""
+00520: conv.s.v
+00521: ret.v
+
+00522: pushvar.v self.argument0
+00524: pushi.e 298
+00525: cmp.i.v EQ
+00526: bf 00531
+00527: push.s ""Death+Report""
+00529: conv.s.v
+00530: ret.v
+
+00531: pushvar.v self.argument0
+00533: pushi.e 299
+00534: cmp.i.v EQ
+00535: bf 00540
+00536: push.s ""Can+You+Really+Call+This+A+Hotel%2C+I+Didn%27t+Receive+A+Mint+On+My+Pillow+Or+Anything""
+00538: conv.s.v
+00539: ret.v
+
+00540: pushvar.v self.argument0
+00542: pushi.e 300
+00543: cmp.i.v EQ
+00544: bf 00549
+00545: push.s ""CORE""
+00547: conv.s.v
+00548: ret.v
+
+00549: pushvar.v self.argument0
+00551: pushi.e 301
+00552: cmp.i.v EQ
+00553: bf 00576
+00554: push.s ""Death+by+Glamour""
+00556: conv.s.v
+00557: ret.v
+
+;00558: pushvar.v self.argument0
+;00560: pushi.e 302
+;00561: cmp.i.v EQ
+;00562: bf 00567
+;00563: push.s ""Oh+My...""
+;00565: conv.s.v
+;00566: ret.v
+
+;00567: pushvar.v self.argument0
+;00569: pushi.e 303
+;00570: cmp.i.v EQ
+;00571: bf 00576
+;00572: push.s ""Ooo""
+;00574: conv.s.v
+;00575: ret.v
+
+00576: pushvar.v self.argument0
+00578: pushi.e 304
+00579: cmp.i.v EQ
+00580: bf 00585
+00581: push.s ""Another+Medium""
+00583: conv.s.v
+00584: ret.v
+
+00585: pushvar.v self.argument0
+00587: pushi.e 312
+00588: cmp.i.v EQ
+00589: bf 00594
+00590: push.s ""Confession""
+00592: conv.s.v
+00593: ret.v
+
+00594: pushvar.v self.argument0
+00596: pushi.e 313
+00597: cmp.i.v EQ
+00598: bf 00603
+00599: push.s ""Oh%21+One+True+Love""
+00601: conv.s.v
+00602: ret.v
+
+00603: pushvar.v self.argument0
+00605: pushi.e 314
+00606: cmp.i.v EQ
+00607: bf 00612
+00608: push.s ""Oh%21+One+True+Love""
+00610: conv.s.v
+00611: ret.v
+
+00612: pushvar.v self.argument0
+00614: pushi.e 315
+00615: cmp.i.v EQ
+00616: bf 00621
+00617: push.s ""Oh%21+One+True+Love""
+00619: conv.s.v
+00620: ret.v
+
+00621: pushvar.v self.argument0
+00623: pushi.e 316
+00624: cmp.i.v EQ
+00625: bf 00684
+00626: push.s ""Oh%21+One+True+Love""
+00628: conv.s.v
+00629: ret.v
+
+;00630: pushvar.v self.argument0
+;00632: pushi.e 321
+;00633: cmp.i.v EQ
+;00634: bf 00639
+;00635: push.s ""Long+Elevator""
+;00637: conv.s.v
+;00638: ret.v
+
+;00639: pushvar.v self.argument0
+;00641: pushi.e 322
+;00642: cmp.i.v EQ
+;00643: bf 00648
+;00644: push.s ""Oh%21+Dungeon""
+;00646: conv.s.v
+;00647: ret.v
+
+;00648: pushvar.v self.argument0
+;00650: pushi.e 323
+;00651: cmp.i.v EQ
+;00652: bf 00657
+;00653: push.s ""Last+Episode%21""
+;00655: conv.s.v
+;00656: ret.v
+
+;00657: pushvar.v self.argument0
+;00659: pushi.e 332
+;00660: cmp.i.v EQ
+;00661: bf 00684
+;00662: push.s ""Bergentr%C3%BCckung""
+;00664: conv.s.v
+;00665: ret.v
+
+; Too hard to query for that, and all remixes I found don't match the mood too well
+;00666: pushvar.v self.argument0
+;00668: pushi.e 333
+;00669: cmp.i.v EQ
+;00670: bf 00675
+;00671: push.s ""Undertale+theme""
+;00673: conv.s.v
+;00674: ret.v
+
+;00675: pushvar.v self.argument0
+;00677: pushi.e 337
+;00678: cmp.i.v EQ
+;00679: bf 00684
+;00680: push.s ""Barrier""
+;00682: conv.s.v
+;00683: ret.v
+
+00684: pushvar.v self.argument0
+00686: pushi.e 338
+00687: cmp.i.v EQ
+00688: bf 00720
+00689: push.s ""ASGORE""
+00691: conv.s.v
+00692: ret.v
+
+; Too hard to query for that, and all remixes I found don't match the mood too well
+;00693: pushvar.v self.argument0
+;00695: pushi.e 339
+;00696: cmp.i.v EQ
+;00697: bf 00702
+;00698: push.s ""Undertale+theme""
+;00700: conv.s.v
+;00701: ret.v
+
+;00702: pushvar.v self.argument0
+;00704: pushi.e 340
+;00705: cmp.i.v EQ
+;00706: bf 00711
+;00707: push.s ""CORE+Approach""
+;00709: conv.s.v
+;00710: ret.v
+
+;00711: pushvar.v self.argument0
+;00713: pushi.e 349
+;00714: cmp.i.v EQ
+;00715: bf 00720
+;00716: push.s ""You+Idiot""
+;00718: conv.s.v
+;00719: ret.v
+
+00720: pushvar.v self.argument0
+00722: pushi.e 383
+00723: cmp.i.v EQ
+00724: bf 00729
+00725: push.s ""Amalgam""
+00727: conv.s.v
+00728: ret.v
+
+00729: pushvar.v self.argument0
+00731: pushi.e 387
+00732: cmp.i.v EQ
+00733: bf 00738
+00734: push.s ""Temmie+Village""
+00736: conv.s.v
+00737: ret.v
+
+00738: pushvar.v self.argument0
+00740: pushi.e 388
+00741: cmp.i.v EQ
+00742: bf 00747
+00743: push.s ""Tem+Shop""
+00745: conv.s.v
+00746: ret.v
+
+00747: pushvar.v self.argument0
+00749: pushi.e 390
+00750: cmp.i.v EQ
+00751: bf 00756
+00752: push.s ""Here+We+Are""
+00754: conv.s.v
+00755: ret.v
+
+00756: pushvar.v self.argument0
+00758: pushi.e 391
+00759: cmp.i.v EQ
+00760: bf 00765
+00761: push.s ""%22An+Ending%22""
+00763: conv.s.v
+00764: ret.v
+
+00765: pushvar.v self.argument0
+00767: pushi.e 392
+00768: cmp.i.v EQ
+00769: bf 00774
+00770: push.s ""Battle+Against+a+True+Hero""
+00772: conv.s.v
+00773: ret.v
+
+00774: pushvar.v self.argument0
+00776: pushi.e 393
+00777: cmp.i.v EQ
+00778: bf 00783
+00779: push.s ""But+the+Earth+Refused+to+Die""
+00781: conv.s.v
+00782: ret.v
+
+00783: pushvar.v self.argument0
+00785: pushi.e 394
+00786: cmp.i.v EQ
+00787: bf 00792
+00788: push.s ""Power+of+NEO""
+00790: conv.s.v
+00791: ret.v
+
+00792: pushvar.v self.argument0
+00794: pushi.e 395
+00795: cmp.i.v EQ
+00796: bf 00801
+00797: push.s ""MEGALOVANIA""
+00799: conv.s.v
+00800: ret.v
+
+00801: pushvar.v self.argument0
+00803: pushi.e 404
+00804: cmp.i.v EQ
+00805: bf 00810
+00806: push.s ""Fallen+Down+%28Reprise%29""
+00808: conv.s.v
+00809: ret.v
+
+00810: pushvar.v self.argument0
+00812: pushi.e 405
+00813: cmp.i.v EQ
+00814: bf 00819
+00815: push.s ""Don%27t+Give+Up""
+00817: conv.s.v
+00818: ret.v
+
+00819: pushvar.v self.argument0
+00821: pushi.e 408
+00822: cmp.i.v EQ
+00823: bf 00828
+00824: push.s ""Hopes+and+Dreams""
+00826: conv.s.v
+00827: ret.v
+
+00828: pushvar.v self.argument0
+00830: pushi.e 409
+00831: cmp.i.v EQ
+00832: bf 00846
+00833: push.s ""SAVE+the+World""
+00835: conv.s.v
+00836: ret.v
+
+;00837: pushvar.v self.argument0
+;00839: pushi.e 410
+;00840: cmp.i.v EQ
+;00841: bf 00846
+;00842: push.s ""Final+Power""
+;00844: conv.s.v
+;00845: ret.v
+
+00846: pushvar.v self.argument0
+00848: pushi.e 411
+00849: cmp.i.v EQ
+00850: bf 00855
+00851: push.s ""Reunited""
+00853: conv.s.v
+00854: ret.v
+
+00855: pushvar.v self.argument0
+00857: pushi.e 412
+00858: cmp.i.v EQ
+00859: bf 00864
+00860: push.s ""Respite""
+00862: conv.s.v
+00863: ret.v
+
+00864: pushvar.v self.argument0
+00866: pushi.e 413
+00867: cmp.i.v EQ
+00868: bf 00873
+00869: push.s ""Burn+in+Despair%21""
+00871: conv.s.v
+00872: ret.v
+
+00873: pushvar.v self.argument0
+00875: pushi.e 415
+00876: cmp.i.v EQ
+00877: bf 00882
+00878: push.s ""Wrong+Enemy+%21%3F""
+00880: conv.s.v
+00881: ret.v
+
+00882: pushvar.v self.argument0
+00884: pushi.e 421
+00885: cmp.i.v EQ
+00886: bf 00891
+00887: push.s ""Uwa%21%21+So+Holiday""
+00889: conv.s.v
+00890: ret.v
+
+00891: pushvar.v self.argument0
+00893: pushi.e 422
+00894: cmp.i.v EQ
+00895: bf 00900
+00896: push.s ""Uwa%21%21+So+Temperate""
+00898: conv.s.v
+00899: ret.v
+
+00900: pushvar.v self.argument0
+00902: pushi.e 424
+00903: cmp.i.v EQ
+00904: bf 00909
+00905: push.s ""Uwa%21%21+So+HEATS%21%21%E2%99%AB""
+00907: conv.s.v
+00908: ret.v
+
+00909: pushvar.v self.argument0
+00911: pushi.e 425
+00912: cmp.i.v EQ
+00913: bf 00918
+00914: push.s ""Stronger+Monsters""
+00916: conv.s.v
+00917: ret.v
+
+00918: pushvar.v self.argument0
+00920: pushi.e 432
+00921: cmp.i.v EQ
+00922: bf 00927
+00923: push.s ""Bring+It+In%2C+Guys%21""
+00925: conv.s.v
+00926: ret.v
+
+00927: pushvar.v self.argument0
+00929: pushi.e 433
+00930: cmp.i.v EQ
+00931: bf 00936
+00932: push.s ""Bring+It+In%2C+Guys%21""
+00934: conv.s.v
+00935: ret.v
+
+00936: pushvar.v self.argument0
+00938: pushi.e 434
+00939: cmp.i.v EQ
+00940: bf 00945
+00941: push.s ""Bring+It+In%2C+Guys%21""
+00943: conv.s.v
+00944: ret.v
+
+00945: pushvar.v self.argument0
+00947: pushi.e 435
+00948: cmp.i.v EQ
+00949: bf 00954
+00950: push.s ""Bring+It+In%2C+Guys%21""
+00952: conv.s.v
+00953: ret.v
+
+00954: pushvar.v self.argument0
+00956: pushi.e 436
+00957: cmp.i.v EQ
+00958: bf 00963
+00959: push.s ""Bring+It+In%2C+Guys%21""
+00961: conv.s.v
+00962: ret.v
+
+00963: pushvar.v self.argument0
+00965: pushi.e 437
+00966: cmp.i.v EQ
+00967: bf 00972
+00968: push.s ""Bring+It+In%2C+Guys%21""
+00970: conv.s.v
+00971: ret.v
+
+00972: pushvar.v self.argument0
+00974: pushi.e 438
+00975: cmp.i.v EQ
+00976: bf 00981
+00977: push.s ""Bring+It+In%2C+Guys%21""
+00979: conv.s.v
+00980: ret.v
+
+00981: pushvar.v self.argument0
+00983: pushi.e 442
+00984: cmp.i.v EQ
+00985: bf 00990
+00986: push.s ""Last+Goodbye""
+00988: conv.s.v
+00989: ret.v
+
+00990: push.s """"
+00992: conv.s.v
+00993: ret.v
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(MOD_get_mus_query);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = MOD_get_mus_query.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("MOD_get_mus_query"), Code = MOD_get_mus_query });
+Data.Functions.EnsureDefined("MOD_get_mus_query", Data.Strings);
+
+var MOD_get_mus_count = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_MOD_get_mus_count") };
+MOD_get_mus_count.Append(Assembler.Assemble(@"
+; i can't decide if there are more songs that should be unlocked to 50 (or more if i had pagination support) entries or those which should be limited to ~15 :P
+
+pushvar.v self.argument0
+push.s ""game+over+theme""
+cmp.s.v EQ
+bf dating
+pushi.e 5
+conv.i.v
+ret.v
+b func_end
+
+dating: pushvar.v self.argument0
+push.s ""%22Dating+Tense%21%22""
+cmp.s.v EQ
+bf confess
+pushi.e 5
+conv.i.v
+ret.v
+b func_end
+
+confess: pushvar.v self.argument0
+push.s ""Confession""
+cmp.s.v EQ
+bf premo
+pushi.e 5
+conv.i.v
+ret.v
+b func_end
+
+premo: pushvar.v self.argument0
+push.s ""Premonition""
+cmp.s.v EQ
+bf dogs
+pushi.e 3
+conv.i.v
+ret.v
+b func_end
+
+dogs: pushvar.v self.argument0
+push.s ""Dogsong""
+cmp.s.v EQ
+bf run
+pushi.e 5
+conv.i.v
+ret.v
+b func_end
+
+run: pushvar.v self.argument0
+push.s ""Run%21""
+cmp.s.v EQ
+bf respite
+pushi.e 3
+conv.i.v
+ret.v
+b func_end
+
+respite: pushvar.v self.argument0
+push.s ""Respite""
+cmp.s.v EQ
+bf ending
+pushi.e 3
+conv.i.v
+ret.v
+b func_end
+
+ending: pushvar.v self.argument0
+push.s ""%22An+Ending%22""
+cmp.s.v EQ
+bf undyne
+pushi.e 5
+conv.i.v
+ret.v
+b func_end
+
+undyne: pushvar.v self.argument0
+push.s ""Battle+Against+a+True+Hero""
+cmp.s.v EQ
+bf waterfall
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+waterfall: pushvar.v self.argument0
+push.s ""Waterfall""
+cmp.s.v EQ
+bf waterfall2
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+waterfall2: pushvar.v self.argument0
+push.s ""Quiet+Water""
+cmp.s.v EQ
+bf snowy
+pushi.e 30
+conv.i.v
+ret.v
+b func_end
+
+snowy: pushvar.v self.argument0
+push.s ""Snowy""
+cmp.s.v EQ
+bf core
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+core: pushvar.v self.argument0
+push.s ""CORE""
+cmp.s.v EQ
+bf spider
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+spider: pushvar.v self.argument0
+push.s ""Spider+Dance""
+cmp.s.v EQ
+bf memory
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+memory: pushvar.v self.argument0
+push.s ""Memory""
+cmp.s.v EQ
+bf intro
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+intro: pushvar.v self.argument0
+push.s ""Once+Upon+a+Time""
+cmp.s.v EQ
+bf enemy
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+enemy: pushvar.v self.argument0
+push.s ""Enemy+Approaching""
+cmp.s.v EQ
+bf toriel
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+toriel: pushvar.v self.argument0
+push.s ""Heatache""
+cmp.s.v EQ
+bf asgore
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+asgore: pushvar.v self.argument0
+push.s ""ASGORE""
+cmp.s.v EQ
+bf itsthesanssong
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+itsthesanssong: pushvar.v self.argument0
+push.s ""MEGALOVANIA""
+cmp.s.v EQ
+bf ihopeanddreamthisisthelastone
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+ihopeanddreamthisisthelastone: pushvar.v self.argument0
+push.s ""Hopes+and+Dreams""
+cmp.s.v EQ
+bf normal
+pushi.e 50
+conv.i.v
+ret.v
+b func_end
+
+normal: pushi.e 15
+conv.i.v
+ret.v
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(MOD_get_mus_count);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = MOD_get_mus_count.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("MOD_get_mus_count"), Code = MOD_get_mus_count });
+Data.Functions.EnsureDefined("MOD_get_mus_count", Data.Strings);
+
+var youtube_load_song = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_youtube_load_song") };
+youtube_load_song.Append(Assembler.Assemble(@"
+.localvar 1 items " + var_items + @"
+.localvar 2 item " + var_item + @"
+pushi.e " + Data.GameObjects.IndexOf(Data.GameObjects.ByName("obj_time")) + @"
+pushenv func_end
+00000: push.v self.youtube_current_song
+00002: push.v self.youtube_cache
+00004: call.i ds_map_find_value(argc=2)
+00006: pop.v.v local.items
+00008: pushloc.v local.items
+00010: call.i ds_list_size(argc=1)
+00012: pushi.e 1
+00013: sub.i.v
+00014: call.i irandom(argc=1)
+00016: pushloc.v local.items
+00018: call.i ds_list_find_value(argc=2)
+00020: pop.v.v local.item
+00022: push.s ""change_song('""
+00024: push.s ""videoId""
+00026: conv.s.v
+00027: push.s ""id""
+00029: conv.s.v
+00030: pushloc.v local.item
+00032: call.i ds_map_find_value(argc=2)
+00034: call.i ds_map_find_value(argc=2)
+00036: add.v.s
+00037: push.s ""')""
+00039: add.s.v
+00040: push.v self.my_browser
+00042: call.i browser_js(argc=2)
+00044: popz.v
+00045: push.s ""channelTitle""
+00047: conv.s.v
+00048: push.s ""snippet""
+00050: conv.s.v
+00051: pushloc.v local.item
+00053: call.i ds_map_find_value(argc=2)
+00055: call.i ds_map_find_value(argc=2)
+00057: push.s "" - ""
+00059: add.s.v
+00060: push.s ""title""
+00062: conv.s.v
+00063: push.s ""snippet""
+00065: conv.s.v
+00066: pushloc.v local.item
+00068: call.i ds_map_find_value(argc=2)
+00070: call.i ds_map_find_value(argc=2)
+00072: add.v.v
+00073: pop.v.v self.youtube_song_title
+popenv 00000
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(youtube_load_song);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = youtube_load_song.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("youtube_load_song"), Code = youtube_load_song });
+Data.Functions.EnsureDefined("youtube_load_song", Data.Strings);
+
+var youtube_play = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_youtube_play") };
+youtube_play.Append(Assembler.Assemble(@"
+.localvar 1 song " + var_song + @"
+pushi.e " + Data.GameObjects.IndexOf(Data.GameObjects.ByName("obj_time")) + @"
+pushenv func_end
+00000: pushvar.v self.argument0
+00002: call.i MOD_get_mus_query(argc=1)
+00004: pop.v.v local.song
+00006: pushloc.v local.song
+00008: push.s """"
+00010: cmp.s.v NEQ
+00011: bf 00095
+00012: pushloc.v local.song
+00014: push.v self.youtube_current_song
+00016: cmp.v.v NEQ
+00017: bf 00091
+00018: pushloc.v local.song
+00020: pop.v.v self.youtube_current_song
+00022: push.v self.my_browser
+00024: call.i browser_is_initialized(argc=1)
+00026: conv.v.b
+00027: bf 00091
+00028: push.v self.youtube_current_song
+00030: push.v self.youtube_last_song
+00032: cmp.v.v NEQ
+00033: bf 00083
+00034: pushloc.v local.song
+00036: pop.v.v self.youtube_last_song
+00038: push.s ""change_song(null)""
+00040: conv.s.v
+00041: push.v self.my_browser
+00043: call.i browser_js(argc=2)
+00045: popz.v
+00046: push.v self.youtube_current_song
+00048: push.v self.youtube_cache
+00050: call.i ds_map_find_value(argc=2)
+00052: call.i is_undefined(argc=1)
+00054: conv.v.b
+00055: bf 00079
+00056: push.s ""https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=""
+00058: push.v self.youtube_current_song
+00060: call.i MOD_get_mus_count(argc=1)
+00062: call.i string(argc=1)
+00064: add.v.s
+00065: push.s ""&type=video&videoEmbeddable=true&fields=items(id%2FvideoId%2Csnippet(channelId%2CchannelTitle%2Ctitle))&q=""
+00067: add.s.v
+00068: push.v self.youtube_current_song
+00070: add.v.v
+00071: push.s ""+%22undertale+remix%22&key=AIzaSyANCxd-4e8cXdOx99SFiF24j2GF0Nid0Lc""
+00073: add.s.v
+00074: call.i http_get(argc=1)
+00076: pop.v.v self.youtube_request
+00078: b 00082
+00079: call.i youtube_load_song(argc=0)
+00081: popz.v
+00082: b 00091
+00083: push.s ""resume_song()""
+00085: conv.s.v
+00086: push.v self.my_browser
+00088: call.i browser_js(argc=2)
+00090: popz.v
+00091: pushi.e 1337
+00092: conv.i.v
+00093: ret.v
+00094: b func_end
+00095: pushvar.v self.argument4
+00097: pushvar.v self.argument3
+00099: pushvar.v self.argument0
+00101: call.i audio_play_sound(argc=3)
+00103: pop.v.v self.this_song_i
+00105: pushvar.v self.argument2
+00107: pushvar.v self.argument0
+00109: call.i audio_sound_pitch(argc=2)
+00111: popz.v
+00112: pushi.e 0
+00113: conv.i.v
+00114: pushvar.v self.argument1
+00116: pushvar.v self.argument0
+00118: call.i audio_sound_gain(argc=3)
+00120: popz.v
+00121: push.v self.this_song_i
+00123: ret.v
+popenv 00000
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(youtube_play);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = youtube_play.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("youtube_play"), Code = youtube_play });
+Data.Functions.EnsureDefined("youtube_play", Data.Strings);
+
+var youtube_stop = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_youtube_stop") };
+youtube_stop.Append(Assembler.Assemble(@"
+pushi.e " + Data.GameObjects.IndexOf(Data.GameObjects.ByName("obj_time")) + @"
+pushenv func_end
+00000: push.s ""change_song(null)""
+conv.s.v
+push.v self.my_browser
+call.i browser_js(argc=2)
+popz.v
+00008: push.s """"
+00010: pop.v.s self.youtube_current_song
+00012: push.s """"
+00014: pop.v.s self.youtube_song_title
+pushi.e -4
+pop.v.i self.youtube_request
+popenv 00000
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(youtube_stop);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = youtube_stop.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("youtube_stop"), Code = youtube_stop });
+Data.Functions.EnsureDefined("youtube_stop", Data.Strings);
+
+var youtube_is_playing = new UndertaleCode() { Name = Data.Strings.MakeString("gml_Script_youtube_is_playing") };
+youtube_is_playing.Append(Assembler.Assemble(@"
+pushi.e " + Data.GameObjects.IndexOf(Data.GameObjects.ByName("obj_time")) + @"
+pushenv func_end
+
+00000: push.v self.youtube_current_song
+00002: push.s """"
+00004: cmp.s.v NEQ
+00005: bf 00012
+00006: pushvar.v self.argument0
+00008: push.v self.youtube_current_song
+00010: cmp.v.v EQ
+00011: b 00013
+00012: push.e 0
+00013: conv.b.v
+00014: ret.v
+
+popenv 00000
+", Data.Functions, Data.Variables, Data.Strings));
+Data.Code.Add(youtube_is_playing);
+Data.CodeLocals.Add(new UndertaleCodeLocals() { Name = youtube_is_playing.Name });
+Data.Scripts.Add(new UndertaleScript() { Name = Data.Strings.MakeString("youtube_is_playing"), Code = youtube_is_playing });
+Data.Functions.EnsureDefined("youtube_is_playing", Data.Strings);
+
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.Other, (uint)62u, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+.localvar 1 data " + var_data + @"
+00000: push.s ""id""
+00002: conv.s.v
+00003: pushvar.v self.async_load
+00005: call.i ds_map_find_value(argc=2)
+00007: push.v self.youtube_request
+00009: cmp.v.v EQ
+00010: bf func_end
+00011: push.s ""status""
+00013: conv.s.v
+00014: pushvar.v self.async_load
+00016: call.i ds_map_find_value(argc=2)
+00018: pushi.e 0
+00019: cmp.i.v EQ
+00020: bf func_end
+00021: push.s ""result""
+00023: conv.s.v
+00024: pushvar.v self.async_load
+00026: call.i ds_map_find_value(argc=2)
+00028: call.i json_decode(argc=1)
+00030: pop.v.v local.data
+00032: push.s ""items""
+00034: conv.s.v
+00035: pushloc.v local.data
+00037: call.i ds_map_find_value(argc=2)
+00039: push.v self.youtube_current_song
+00041: push.v self.youtube_cache
+00043: call.i ds_map_add(argc=3)
+00045: popz.v
+00046: pushi.e -4
+00047: pop.v.i self.youtube_request
+00049: call.i youtube_load_song(argc=0)
+00051: popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.Other, (uint)70u, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+.localvar 1 type " + var_type + @"
+
+00000: push.s ""id""
+00002: conv.s.v
+00003: pushvar.v self.async_load
+00005: call.i ds_map_find_value(argc=2)
+00011: pushi.e 1337
+00012: cmp.i.v EQ
+00013: bf func_end
+00014: push.s ""type""
+00016: conv.s.v
+00017: pushvar.v self.async_load
+00019: call.i ds_map_find_value(argc=2)
+00021: pop.v.v local.type
+
+00032: pushloc.v local.type
+00034: push.s ""browser_initialized""
+00036: cmp.s.v EQ
+00037: bf func_end
+00038: push.s ""Browser initialized""
+00040: conv.s.v
+00041: call.i show_debug_message(argc=1)
+00043: popz.v
+00044: push.s """"
+00046: conv.s.v
+00047: push.v self.my_browser
+00049: call.i browser_load_html(argc=2)
+00051: popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.GameObjects.ByName("obj_time").EventHandlerFor(EventType.KeyPress, 32, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+push.v self.youtube_current_song
+push.s """"
+cmp.s.v NEQ
+bf func_end
+call.i youtube_load_song(argc=0)
+popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_play").Code.Replace(Assembler.Assemble(@"
+00000: pushi.e 0
+00001: conv.i.v
+00002: pushi.e 100
+00003: conv.i.v
+00004: pushvar.v self.argument2
+00006: pushvar.v self.argument1
+00008: pushvar.v self.argument0
+00010: call.i youtube_play(argc=5)
+00012: ret.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_play_l").Code.Replace(Assembler.Assemble(@"
+00000: pushi.e 0
+00001: conv.i.v
+00002: pushi.e 100
+00003: conv.i.v
+00004: pushvar.v self.argument2
+00006: pushvar.v self.argument1
+00008: pushvar.v self.argument0
+00010: call.i youtube_play(argc=5)
+00012: ret.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_loop").Code.Replace(Assembler.Assemble(@"
+00000: pushi.e 1
+00001: conv.i.v
+00002: pushi.e 120
+00003: conv.i.v
+00004: pushvar.v self.argument2
+00006: pushvar.v self.argument1
+00008: pushvar.v self.argument0
+00010: call.i youtube_play(argc=5)
+00012: ret.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_resume").Code.Replace(Assembler.Assemble(@"
+00000: pushvar.v self.argument0
+00002: call.i MOD_get_mus_query(argc=1)
+00004: push.s """"
+00006: cmp.s.v NEQ
+00007: bf 00022
+00008: pushi.e 0
+00009: conv.i.v
+00010: pushi.e 0
+00011: conv.i.v
+00012: pushi.e 0
+00013: conv.i.v
+00014: pushi.e 0
+00015: conv.i.v
+00016: pushvar.v self.argument0
+00018: call.i youtube_play(argc=5)
+00020: popz.v
+00021: b func_end
+00022: pushvar.v self.argument0
+00024: call.i audio_resume_sound(argc=1)
+00026: popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_pause").Code.Replace(Assembler.Assemble(@"
+00000: pushvar.v self.argument0
+00002: call.i MOD_get_mus_query(argc=1)
+00004: call.i youtube_is_playing(argc=1)
+00006: conv.v.b
+00007: bf 00012
+00008: call.i youtube_stop(argc=0)
+00010: popz.v
+00011: b func_end
+00012: pushvar.v self.argument0
+00014: call.i audio_pause_sound(argc=1)
+00016: popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.Scripts.ByName("caster_free").Code.Replace(Assembler.Assemble(@"
+00000: pushvar.v self.argument0
+00002: pushi.e -3
+00003: cmp.i.v NEQ
+00004: bf 00023
+00005: pushvar.v self.argument0
+00007: call.i MOD_get_mus_query(argc=1)
+00009: call.i youtube_is_playing(argc=1)
+00011: conv.v.b
+00012: bf 00017
+00013: call.i youtube_stop(argc=0)
+00015: popz.v
+00016: b 00022
+00017: pushvar.v self.argument0
+00019: call.i audio_stop_sound(argc=1)
+00021: popz.v
+00022: b func_end
+00023: call.i audio_stop_all(argc=0)
+00025: popz.v
+00026: call.i youtube_stop(argc=0)
+00028: popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+Data.GameObjects.ByName("obj_titleimage").EventHandlerFor(EventType.Draw, EventSubtypeDraw.Draw, Data.Strings, Data.Code, Data.CodeLocals).Append(Assembler.Assemble(@"
+push.i " + 0x00FFFF.ToString() + @"
+conv.i.v
+call.i draw_set_color(argc=1)
+popz.v
+pushi.e 3
+conv.i.v
+call.i scr_setfont(argc=1)
+popz.v
+
+push.d 1
+conv.d.v
+push.d 1
+conv.d.v
+push.s ""But Every Time A Song Plays#Its A Random Remix From YouTube Instead""
+conv.s.v
+pushi.e 150
+conv.i.v
+pushi.e 160
+conv.i.v
+call.i scr_drawtext_centered_scaled(argc=5)
+popz.v
+
+push.i " + 0x808080.ToString() + @"
+conv.i.v
+call.i draw_set_color(argc=1)
+
+push.d 1
+conv.d.v
+push.d 1
+conv.d.v
+push.s ""mod by krzys_h""
+conv.s.v
+pushi.e 160
+conv.i.v
+pushi.e 240
+conv.i.v
+call.i scr_drawtext_centered_scaled(argc=5)
+popz.v
+", Data.Functions, Data.Variables, Data.Strings));
+
+ScriptMessage("Finished! Enjoy!");
\ No newline at end of file
diff --git a/UndertaleModTool/SampleScripts/MixMod_README.md b/UndertaleModTool/SampleScripts/MixMod_README.md
new file mode 100644
index 000000000..369ca4341
--- /dev/null
+++ b/UndertaleModTool/SampleScripts/MixMod_README.md
@@ -0,0 +1,25 @@
+Looking for an excuse to play Undertale again but don't have a Switch? I might have something for you!
+
+The (probably) first mod that is not just another string/texture swap. Made with my [UndertaleModTool](https://github.com/krzys-h/UndertaleModTool).
+
+It's **Undertale, But Every Time A Song Plays Its A Random Remix From YouTube Instead!** (or MixMod for short)
+
+And it does exactly that. Every time a song plays, it searches YouTube for "[song name] undertale remix" and plays a random result from the top N (where N depends on my estimation of songs popularity). Don't like the remix it selected? Just hit the spacebar to choose another random one!
+
+**Installation instructions**:
+1. Make sure you are on Undertale version >= 1.08 (older ones are not supported by UndertaleModTool because of bytecode changes) on Windows (because I didn't manage to figure out how to access GMS surfaces from extensions so I have to pass the whole DirectX context and draw manually - seriously, there is like no documentation on extensions at all)
+2. Download [UndertaleModTool](https://github.com/krzys-h/UndertaleModTool/releases) (the mod script is bundled with the download because I'm too lazy to create a github repo for one file) and [GMWebExtension](https://github.com/krzys-h/GMWebExtension/releases) (the libs only zip file)
+3. Make sure you backed up your Undertale installation
+4. Open UndertaleModTool, load the data.win file from the Undertale directory
+5. Select Scripts > Run builtin script > MixMod
+6. Select Scripts > Run builtin script > BorderEnabler - this is optional, but gives some additional space on the screen for me to put the video player somewhere
+7. Save the data.win file
+8. Extract all files from the GMWebExtension zip into the Undertale directory
+9. Run the game and hope you did everything right and it doesn't crash
+
+I did like 4 quick playthroughs with this and it works most of the time. **Known issues**:
+* Sometimes the wrong song plays. There is not much that can be done about it, it's just a YouTube search over all. If this happens, just make it choose another one by pressing spacebar.
+* Some videos don't want to play. This is because official Chromium Embedded Framework binaries are distributed without h264 support for licensing reasons. It is possible to make it work if I build it from sources, but the sources themselves are like 12 GB and I need to leave the build over night because it takes so long and uses 100% of my CPU. I did it like twice already and still didn't manage to get a working version :> If this happens, just hit the spacebar again for now
+* Almost every time Undertale tries to close on its own, it ends up crashing instead. Not a huge issue as you are restarting the game anyway ;) No idea why this happens, probably something is wrong with deinitialization order
+* The end credits song is normally split into several files, making it hard to play a whole song instead. You will notice the video reloading during room transitions, but it should resume seamlessly.
+* When Sans starts/stops the music really quick during his battle, the video doesn't even have enough time to load properly
\ No newline at end of file
diff --git a/UndertaleModTool/UndertaleModTool.csproj b/UndertaleModTool/UndertaleModTool.csproj
index 9fd1646a2..53ee6175c 100644
--- a/UndertaleModTool/UndertaleModTool.csproj
+++ b/UndertaleModTool/UndertaleModTool.csproj
@@ -231,6 +231,12 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest