├── UberASMTool.suo ├── UberASMTool ├── asar.dll ├── uber.ico ├── Model │ ├── UberAssemblyFile.cs │ ├── Code.cs │ └── UberConfig.cs ├── UberASMTool.csproj.user ├── Logger.cs ├── Properties │ ├── AssemblyInfo.cs │ └── app.manifest ├── UberAssemblyProcessor.cs ├── FileUtils.cs ├── SNES.cs ├── DataCollector.cs ├── ROM.cs ├── UberASMTool.csproj ├── UberConfigProcessor.cs ├── asar.cs └── Program.cs ├── assets ├── asm │ ├── work │ │ └── readme.txt │ ├── base │ │ ├── statusbar.asm │ │ ├── main.asm │ │ ├── sprites.asm │ │ ├── overworld.asm │ │ ├── gamemode.asm │ │ ├── level.asm │ │ └── global.asm │ └── readme.txt ├── other │ ├── status_code.asm │ ├── global_code.asm │ └── macro_library.asm ├── level │ └── example.asm ├── gamemode │ └── example.asm ├── overworld │ └── example.asm ├── readme - library.txt ├── list.txt └── readme.txt ├── examples ├── powerup-cycling.asm ├── conditional-map16.asm └── readme.txt ├── .gitattributes ├── README.md ├── UberASMTool.sln ├── .gitignore ├── Specifications └── UberAssemblyFile.txt └── LICENSE /UberASMTool.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorVilela7/UberASMTool/HEAD/UberASMTool.suo -------------------------------------------------------------------------------- /UberASMTool/asar.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorVilela7/UberASMTool/HEAD/UberASMTool/asar.dll -------------------------------------------------------------------------------- /UberASMTool/uber.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorVilela7/UberASMTool/HEAD/UberASMTool/uber.ico -------------------------------------------------------------------------------- /assets/asm/work/readme.txt: -------------------------------------------------------------------------------- 1 | This is the work folder of UberASM Tool. Currently inserted files are placed here. -------------------------------------------------------------------------------- /examples/powerup-cycling.asm: -------------------------------------------------------------------------------- 1 | ; Example code for levels. Makes Mario "crazy". 2 | 3 | main: 4 | inc $19 5 | rtl 6 | -------------------------------------------------------------------------------- /assets/other/status_code.asm: -------------------------------------------------------------------------------- 1 | ; Note that since status bar code is just a single file, the code below should return with RTS. 2 | ; There is no such init or nmi label either. 3 | 4 | main: 5 | RTS 6 | -------------------------------------------------------------------------------- /assets/other/global_code.asm: -------------------------------------------------------------------------------- 1 | ; Note that since global code is a single file, all code below should return with RTS. 2 | 3 | load: 4 | rts 5 | init: 6 | rts 7 | main: 8 | rts 9 | ;nmi: 10 | ; rts 11 | -------------------------------------------------------------------------------- /examples/conditional-map16.asm: -------------------------------------------------------------------------------- 1 | ; Example code for levels. Set Conditional DM16 flag 0 if the player has either Cape or Fire power-up. 2 | 3 | load: 4 | lda $19 5 | lsr 6 | and #$01 7 | sta $7FC060 8 | rtl 9 | -------------------------------------------------------------------------------- /assets/asm/base/statusbar.asm: -------------------------------------------------------------------------------- 1 | ORG $008E1A 2 | autoclean JML statusbar_main 3 | NOP 4 | 5 | freecode 6 | 7 | statusbar_main: 8 | JSR status_bar_main 9 | LDA $1493|!addr 10 | ORA $9D 11 | JML $008E1F|!bank 12 | -------------------------------------------------------------------------------- /assets/asm/base/main.asm: -------------------------------------------------------------------------------- 1 | !previous_mode = !sprite_RAM+(!sprite_slots*3) 2 | 3 | incsrc level.asm 4 | incsrc overworld.asm 5 | incsrc gamemode.asm 6 | incsrc global.asm 7 | incsrc sprites.asm 8 | incsrc statusbar.asm 9 | 10 | -------------------------------------------------------------------------------- /examples/readme.txt: -------------------------------------------------------------------------------- 1 | This folder contains some simple examples on how to use UberASM Tool and some of its features. This is intended to stay on the GitHub page only. 2 | 3 | If you would like to add some interesting use case for UberASM Tool, pull requests are more than welcome! -------------------------------------------------------------------------------- /assets/level/example.asm: -------------------------------------------------------------------------------- 1 | ; This is an example code file for UberASMTool. 2 | ; The code in this file does nothing. 3 | ; By default, it runs in level 105, because of the entry "105 example.asm" in the "level" list (in the list.txt file). 4 | ; You can safely remove that entry. After you do that, you can also safely remove this file. 5 | 6 | main: 7 | rtl 8 | -------------------------------------------------------------------------------- /assets/gamemode/example.asm: -------------------------------------------------------------------------------- 1 | ; This is an example code file for UberASMTool. 2 | ; The code in this file does nothing. 3 | ; By default, it runs everywhere on the overworld, because of the entry "0E example.asm" in the "gamemode" list (in the list.txt file). 4 | ; You can safely remove that entry. After you do that, you can also safely remove this file. 5 | 6 | main: 7 | rtl 8 | -------------------------------------------------------------------------------- /assets/overworld/example.asm: -------------------------------------------------------------------------------- 1 | ; This is an example code file for UberASMTool. 2 | ; The code in this file does nothing. 3 | ; By default, it runs on the Yoshi's Island map, because of the entry "1 example.asm" in the "overworld" list (in the list.txt file). 4 | ; You can safely remove that entry. After you do that, you can also safely remove this file. 5 | 6 | main: 7 | rtl 8 | -------------------------------------------------------------------------------- /assets/asm/readme.txt: -------------------------------------------------------------------------------- 1 | This folder contains all .asm files inserted by Asar. 2 | 3 | base folder contains the base ASM files which the tools edits and 4 | moves them to the work folder. You don't need to edit any of the 5 | files unless you are a programmer. 6 | 7 | work folder contains the edited base ASM files which are inserted 8 | on the ROM. They're generated by the tool during at runtime. -------------------------------------------------------------------------------- /assets/readme - library.txt: -------------------------------------------------------------------------------- 1 | This is the library folder. Feel free to add any file here. 2 | The system is pretty simple. Each file will have its own freecode bank. 3 | All labels created with this system will appear on all relevant level/game mode/overworld 4 | codes. 5 | You can also add whatever non-asm file you want. They will be included as binary file and 6 | their name will be the label used. -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /UberASMTool/Model/UberAssemblyFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UberASMTool 7 | { 8 | /* 9 | * Specialized UberASM Tool assembly file 10 | */ 11 | class UberAssemblyFile 12 | { 13 | public string ProcessedContents { get; set; } 14 | public string FilePath { get; set; } 15 | public bool IsLibrary { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /UberASMTool/Model/Code.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UberASMTool.Model 7 | { 8 | class Code 9 | { 10 | public Code(string path) 11 | { 12 | this.Path = path; 13 | this.Inserted = false; 14 | this.Main = -1; 15 | this.Init = -1; 16 | this.Nmi = -1; 17 | this.Load = -1; 18 | } 19 | 20 | public string Path; 21 | public bool Inserted; 22 | public int Main; 23 | public int Init; 24 | public int Nmi; 25 | public int Load; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /UberASMTool/UberASMTool.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | publish\ 9 | 10 | 11 | 12 | 13 | 14 | en-US 15 | false 16 | 17 | -------------------------------------------------------------------------------- /assets/asm/base/sprites.asm: -------------------------------------------------------------------------------- 1 | sprite_code: 2 | LDX.b #!sprite_slots 3 | - 4 | DEX 5 | LDA !sprite_RAM,x 6 | ORA !sprite_RAM+(!sprite_slots),x 7 | ORA !sprite_RAM+(!sprite_slots*2),x 8 | BNE + 9 | CPX #$00 10 | BNE - 11 | BRA .return 12 | + 13 | if !sa1 14 | LDA $3242,x 15 | else 16 | LDA $14C8,x 17 | endif 18 | BEQ .clear 19 | LDA !sprite_RAM,x 20 | STA $00 21 | LDA !sprite_RAM+(!sprite_slots),x 22 | STA $01 23 | LDA !sprite_RAM+(!sprite_slots*2),x 24 | STA $02 25 | PHK 26 | PEA.w .next 27 | JMP [!dp] 28 | .next 29 | CPX #$00 30 | BNE - 31 | .return 32 | RTS 33 | .clear 34 | LDA #$00 35 | STA !sprite_RAM,x 36 | STA !sprite_RAM+(!sprite_slots),x 37 | STA !sprite_RAM+(!sprite_slots*2),x 38 | BRA - 39 | -------------------------------------------------------------------------------- /UberASMTool/Model/UberConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using UberASMTool.Model; 6 | 7 | namespace UberASMTool 8 | { 9 | class UberConfig 10 | { 11 | public bool VerboseMode { get; set; } 12 | public string ROMPath { get; set; } 13 | public string GlobalFile { get; set; } 14 | public string StatusBarFile { get; set; } 15 | public string MacroLibraryFile { get; set; } 16 | public int[][][] FileASMList { get; set; } 17 | public int[][] GlobalASMList { get; set; } 18 | public int SpriteCodeFreeRAM { get; set; } 19 | public int SpriteCodeFreeBWRAM { get; set; } 20 | public Code[] CodeList { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UberASM Tool 2 | ============ 3 | 4 | "UberASM Tool" is a tool that allows to insert common codes without relying to 5 | patches. The main objective is reducing the number of patches and at the same 6 | time allow for inserting ASM file easier and develop new codes quicker compared 7 | to other approaches. 8 | 9 | ## Building 10 | How to make the ZIP file for uploading a release: 11 | 12 | 1. Compile the C# source code using Visual Studio Community. 13 | 2. Copy UberASMTool.exe and UberASMTool.pdb from UberASMTool/bin/Release to the 14 | assets folder. 15 | 3. Copy asar.dll from the UberASMTool folder to the assets folder. 16 | 4. Create a ZIP file from all files inside assets. 17 | 18 | ## Examples 19 | 20 | At [examples] there is some ASM files that can be used for testing and/or for 21 | figuring out some specific UberASM Tool features. -------------------------------------------------------------------------------- /assets/asm/base/overworld.asm: -------------------------------------------------------------------------------- 1 | ORG $00A1C3 2 | autoclean JML main_ow 3 | 4 | ORG $00A18F 5 | autoclean JML init_ow 6 | NOP #2 7 | 8 | freecode 9 | 10 | ; Do not touch, nor move that. 11 | db "uber" 12 | OW_asm_table: 13 | OW_init_table: 14 | OW_nmi_table: 15 | db "tool" 16 | 17 | main_ow: 18 | PHB 19 | JSL $7F8000 20 | 21 | LDX $0DB3|!addr 22 | LDA $1F11|!addr,x 23 | ASL 24 | ADC $1F11|!addr,x 25 | TAX 26 | REP #$20 27 | LDA.l OW_asm_table,x 28 | STA $00 29 | LDA.l OW_asm_table+1,x 30 | JSL run_code 31 | PLB 32 | JML $00A1C7|!bank 33 | 34 | init_ow: 35 | PHK 36 | PEA.w .return-1 37 | PEA.w $84CE 38 | JML $0092A0|!bank 39 | .return 40 | PHB 41 | LDX $0DB3|!addr 42 | LDA $1F11|!addr,x 43 | ASL 44 | ADC $1F11|!addr,x 45 | TAX 46 | REP #$20 47 | LDA.l OW_init_table,x 48 | STA $00 49 | LDA.l OW_init_table+1,x 50 | JSL run_code 51 | PLB 52 | JML $0093F4|!bank 53 | -------------------------------------------------------------------------------- /UberASMTool.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C# Express 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UberASMTool", "UberASMTool\UberASMTool.csproj", "{B17060A9-56FF-49C8-9182-A46BD4185544}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x86 = Debug|x86 9 | Release|x86 = Release|x86 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {B17060A9-56FF-49C8-9182-A46BD4185544}.Debug|x86.ActiveCfg = Debug|x86 13 | {B17060A9-56FF-49C8-9182-A46BD4185544}.Debug|x86.Build.0 = Debug|x86 14 | {B17060A9-56FF-49C8-9182-A46BD4185544}.Release|x86.ActiveCfg = Release|x86 15 | {B17060A9-56FF-49C8-9182-A46BD4185544}.Release|x86.Build.0 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /assets/asm/base/gamemode.asm: -------------------------------------------------------------------------------- 1 | org $009322 2 | autoclean JML gamemode_main 3 | 4 | freecode 5 | 6 | db "uber" ; Don't touch or move these tables. 7 | gamemode_main_table: 8 | gamemode_init_table: 9 | gamemode_nmi_table: 10 | db "tool" 11 | 12 | 13 | gamemode_main: 14 | LDA $0100|!addr 15 | CMP #$2A 16 | BCS new_mode 17 | PHK 18 | PEA.w return-1 19 | BRA do_game_mode 20 | 21 | new_mode: 22 | LDA #$00 23 | PHA 24 | PEA $9311 25 | 26 | do_game_mode: 27 | PHB 28 | PHK 29 | PLB 30 | LDA $0100|!addr 31 | CMP !previous_mode 32 | STA !previous_mode 33 | REP #$30 34 | PHP 35 | AND #$00FF 36 | ASL 37 | ADC !previous_mode 38 | TAX 39 | PLP 40 | BNE + 41 | LDA gamemode_main_table,x 42 | STA $00 43 | LDA gamemode_main_table+1,x 44 | BRA ++ 45 | + 46 | LDA gamemode_init_table,x 47 | STA $00 48 | LDA gamemode_init_table+1,x 49 | ++ 50 | JSL run_code 51 | PLB 52 | RTL 53 | 54 | return: 55 | LDA $0100|!addr 56 | ASL 57 | TAX 58 | LDA $9329,x 59 | STA $00 60 | LDA $932A,x 61 | STA $01 62 | if !bank8 != $00 63 | LDA #!bank8 64 | STA $02 65 | else 66 | STZ $02 67 | endif 68 | JML [!dp] 69 | -------------------------------------------------------------------------------- /UberASMTool/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UberASMTool 7 | { 8 | class Logger 9 | { 10 | private StringBuilder aggregator; 11 | 12 | public static Logger GetLogger() 13 | { 14 | return new Logger(new StringBuilder()); 15 | } 16 | 17 | private Logger(StringBuilder baseBuilder) 18 | { 19 | this.aggregator = baseBuilder; 20 | } 21 | 22 | public string GetOutput() 23 | { 24 | return aggregator.ToString(); 25 | } 26 | 27 | public void Error(string description, int line = -1) 28 | { 29 | WriteLog(description, line, true); 30 | } 31 | 32 | public void Warning(string description, int line = -1) 33 | { 34 | WriteLog(description, line, false); 35 | } 36 | 37 | public void WriteLog(string description, int line = -1, bool error = true) 38 | { 39 | if (line == -1) 40 | { 41 | this.aggregator.AppendLine($"{(error ? "Error" : "Warning")}: {description}"); 42 | } 43 | else 44 | { 45 | this.aggregator.AppendLine($"{(error ? "Error" : "Warning")}: line {line + 1} - {description}"); 46 | } 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /UberASMTool/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UberASM Tool")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Vitor Vilela")] 12 | [assembly: AssemblyProduct("UberASM Tool")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ca32f2f6-4dd8-4bee-a2e2-79ff047646ff")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.5.0.0")] 36 | [assembly: AssemblyFileVersion("1.5.0.0")] 37 | -------------------------------------------------------------------------------- /assets/asm/base/level.asm: -------------------------------------------------------------------------------- 1 | !level = $010B|!addr ;Patches rely on this, changing this is bad. Don't. 2 | 3 | ORG $05D8B7 4 | BRA + 5 | NOP #3 ;the levelnum patch goes here in many ROMs, just skip over it 6 | + 7 | REP #$30 8 | LDA $0E 9 | STA !level 10 | ASL 11 | CLC 12 | ADC $0E 13 | TAY 14 | LDA.w $E000,Y 15 | STA $65 16 | LDA.w $E001,Y 17 | STA $66 18 | LDA.w $E600,Y 19 | STA $68 20 | LDA.w $E601,Y 21 | STA $69 22 | BRA + 23 | ORG $05D8E0 24 | + 25 | 26 | ORG $00A242 27 | autoclean JML main 28 | NOP 29 | 30 | ORG $00A295 31 | NOP #4 32 | 33 | ORG $00A5EE 34 | autoclean JML init 35 | 36 | freecode 37 | 38 | ;Editing or moving these tables breaks things. don't. 39 | db "uber" 40 | level_asm_table: 41 | level_init_table: 42 | level_nmi_table: 43 | level_load_table: 44 | db "tool" 45 | 46 | main: 47 | PHB 48 | LDA $13D4|!addr 49 | BNE + 50 | JSL $7F8000 51 | + 52 | REP #$30 53 | LDA !level 54 | ASL 55 | ADC !level 56 | TAX 57 | LDA.l level_asm_table,x 58 | STA $00 59 | LDA.l level_asm_table+1,x 60 | JSL run_code 61 | PLB 62 | 63 | LDA $13D4|!addr 64 | BEQ + 65 | JML $00A25B|!bank 66 | + 67 | JML $00A28A|!bank 68 | 69 | init: 70 | PHB 71 | LDA !level 72 | ASL 73 | ADC !level 74 | TAX 75 | LDA.l level_init_table,x 76 | STA $00 77 | LDA.l level_init_table+1,x 78 | JSL run_code 79 | PLB 80 | 81 | PHK 82 | PEA.w .return-1 83 | PEA $84CE 84 | JML $00919B|!bank 85 | .return 86 | JML $00A5F3|!bank 87 | 88 | run_code: 89 | STA $01 90 | PHA 91 | PLB 92 | PLB 93 | SEP #$30 94 | JML [!dp] 95 | 96 | null_pointer: 97 | RTL 98 | -------------------------------------------------------------------------------- /UberASMTool/UberAssemblyProcessor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UberASMTool 7 | { 8 | /* 9 | * Specialized in processing input assembly files and generating UberAssemblyFile 10 | */ 11 | class UberAssemblyProcessor 12 | { 13 | public UberAssemblyFile LoadAndProcessFile(string input, bool library, string fileName, string directoryBase, string macroLibraryFile) 14 | { 15 | var processed = ProcessAndGenerateFile(input, library, fileName, directoryBase, macroLibraryFile); 16 | 17 | return new UberAssemblyFile 18 | { 19 | ProcessedContents = processed, 20 | IsLibrary = library, 21 | FilePath = fileName 22 | }; 23 | } 24 | 25 | private string ProcessAndGenerateFile(string input, bool library, string fileName, string directoryBase, string macroLibraryFile) 26 | { 27 | string fix = FileUtils.FixPath(fileName, directoryBase); 28 | StringBuilder output = new StringBuilder(); 29 | 30 | if (library) 31 | { 32 | output.AppendFormat("incsrc \"{1}{0}\" : ", Program.LabelLibraryFile, fix); 33 | } 34 | output.AppendFormat("incsrc \"{1}{0}\" : ", macroLibraryFile, fix); 35 | output.Append("freecode cleaned : "); 36 | output.AppendLine("print \"_startl \", pc"); 37 | output.AppendLine(input); 38 | output.AppendLine("print \"_endl \", pc"); 39 | return output.ToString(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /UberASMTool/FileUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | 8 | namespace UberASMTool 9 | { 10 | static class FileUtils 11 | { 12 | const int maxAttempts = 1000; 13 | const int idleTimeBetweenAttempt = 10; 14 | 15 | public static bool ForceCreate(string fileName, string contents) 16 | { 17 | for (int i = 0; i < maxAttempts; ++i) 18 | { 19 | try 20 | { 21 | File.WriteAllText(fileName, contents); 22 | return true; 23 | } 24 | catch 25 | { 26 | Thread.Sleep(idleTimeBetweenAttempt); 27 | } 28 | } 29 | 30 | return false; 31 | } 32 | 33 | public static bool ForceDelete(string fileName) 34 | { 35 | if (!File.Exists(fileName)) 36 | { 37 | return true; 38 | } 39 | 40 | for (int i = 0; i < maxAttempts; ++i) 41 | { 42 | try 43 | { 44 | File.Delete(fileName); 45 | return true; 46 | } 47 | catch 48 | { 49 | Thread.Sleep(idleTimeBetweenAttempt); 50 | } 51 | } 52 | 53 | return false; 54 | } 55 | 56 | public static int DirectoryDepth(string fileName, string directoryBase) 57 | { 58 | string path1 = Path.GetFullPath(directoryBase); 59 | string path2 = Path.GetFullPath(fileName); 60 | char[] separators = new[] { Path.PathSeparator, Path.AltDirectorySeparatorChar, 61 | Path.DirectorySeparatorChar, Path.VolumeSeparatorChar }; 62 | 63 | return path2.Substring(path1.Length).Split(separators, StringSplitOptions.RemoveEmptyEntries).Length; 64 | } 65 | 66 | public static string FixPath(string fileName, string directoryBase) 67 | { 68 | int depth = DirectoryDepth(fileName, directoryBase); 69 | return String.Join("", Enumerable.Repeat("../", depth)); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /UberASMTool/Properties/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 47 | -------------------------------------------------------------------------------- /assets/list.txt: -------------------------------------------------------------------------------- 1 | verbose: on 2 | 3 | 4 | 5 | # UBERASM TOOL: LIST FILE 6 | # This is a list of all the code files you're using, and when to run them. 7 | 8 | 9 | 10 | # LEVEL CODE 11 | # Code files in this list will be run in specific levels. 12 | 13 | # EXAMPLE: 14 | # To run the code from the file "mycode.asm" in level 105, 15 | # put "mycode.asm" in the "level" folder 16 | # and add an entry to this list saying "105 mycode.asm" 17 | # (without the quotes, and without # in front). 18 | 19 | # - You can use the same code file in multiple levels! 20 | # - If you want to use multiple code files in the same level, 21 | # check https://www.smwcentral.net/?p=faq&page=1515827-uberasm . 22 | # - To run the same code in every level, apply it to game mode 14 (see below). 23 | 24 | level: 25 | 105 example.asm 26 | 27 | 28 | 29 | 30 | 31 | # OVERWORLD CODE 32 | # Code files in this list will be run on specific overworld maps. 33 | 34 | # Each map has a number: 35 | # 0: Main Map 36 | # 1: Yoshi's Island 37 | # 2: Vanilla Dome 38 | # 3: Forest of Illusion 39 | # 4: Valley of Bowser 40 | # 5: Special World 41 | # 6: Star Road 42 | 43 | # EXAMPLE: 44 | # To run the code from the file "mycode.asm" on the Vanilla Dome map, 45 | # put "mycode.asm" in the "overworld" folder 46 | # and add an entry to this list saying "2 mycode.asm" 47 | # (without the quotes, and without # in front). 48 | 49 | overworld: 50 | 1 example.asm 51 | 52 | 53 | 54 | 55 | 56 | # GAME MODE CODE 57 | # Code files in this list will be run during specific game modes. 58 | 59 | # Some common game modes are: 60 | # 01: "Nintendo Presents" screen 61 | # 07: Title Screen 62 | # 08: Title Screen (File select) 63 | # 0E: Overworld 64 | # 14: Level 65 | # You can also define your own (from 2A to FF). 66 | 67 | # EXAMPLE: 68 | # To run the code from the file "mycode.asm" in game mode 14 (i.e. in all levels), 69 | # put "mycode.asm" in the "gamemode" folder 70 | # and add an entry to this list saying "14 mycode.asm" 71 | # (without the quotes, and without # in front). 72 | 73 | gamemode: 74 | 0E example.asm 75 | 76 | 77 | 78 | 79 | 80 | # OTHER OPTIONS 81 | 82 | # Global code - this will be run all the time. 83 | global: other/global_code.asm 84 | 85 | # Status bar code - this will be run when the status bar is drawn to the screen. 86 | statusbar: other/status_code.asm 87 | 88 | # A file containing macros. 89 | macrolib: other/macro_library.asm 90 | 91 | # Sprite-related RAM (see README). You probably don't need to change this. 92 | sprite: $7FAC80 # 38 (SNES) or 68 (SA-1) bytes of free RAM. 93 | sprite-sa1: $41AC80 # Optional for SA-1 ROMs. 94 | 95 | # The name of your ROM file - this will be used if you don't specify a ROM name 96 | # when running UberASM Tool. 97 | rom: SMW.smc 98 | -------------------------------------------------------------------------------- /UberASMTool/SNES.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UberASMTool 4 | { 5 | static class SNES 6 | { 7 | public static int[] snesbanks = new int[] { 8 | // banks to be mapped for each megabyte 9 | // sa1rom : 0x00, 0x20, 0x80, 0xA0 10 | // lorom : 0x00, 0x20, 0x40, 0x60 11 | // fastrom: 0x80, 0xA0, 0xC0, 0xE0 12 | 0x80, 0xA0, 0xC0, 0xE0, 13 | 0, 0, 0, 0, // 8mb roms 14 | }; 15 | 16 | public static int[] pcbanks = new int[] { 17 | // inversed to return to pc address 18 | 0, // banks 00-1F 19 | 1, // banks 20-3F 20 | 2, // banks 40-5F 21 | 3, // banks 60-7F 22 | 0, // banks 80-9F 23 | 1, // banks A0-BF 24 | 2, // banks C0-DF 25 | 3, // banks E0-FF 26 | }; 27 | 28 | public static void DetectAddressing(int romheader) 29 | { 30 | switch (romheader) 31 | { 32 | case 0x23: 33 | // SA-1 34 | snesbanks[0] = 0x00; 35 | snesbanks[1] = 0x20; 36 | snesbanks[2] = 0x80; 37 | snesbanks[3] = 0xA0; 38 | snesbanks[4] = 0xA0; // map rest to 0xA0, but i'm not sure... 39 | snesbanks[5] = 0xA0; 40 | snesbanks[6] = 0xA0; 41 | snesbanks[7] = 0xA0; 42 | pcbanks[0] = 0; // 0-1F 43 | pcbanks[1] = 1; // 20-3F 44 | pcbanks[2] = 0; // 40-5F \ this is SA-1/SNES RAM 45 | pcbanks[3] = 0; // 60-7F / 46 | pcbanks[4] = 2; // 80-9F 47 | pcbanks[5] = 3; // A0-BF <-- May variable. 48 | pcbanks[6] = 0; // C0-DF \ this is SA-1 HiROM 49 | pcbanks[7] = 0; // E0-FF / 50 | break; 51 | 52 | default: 53 | // FastROM 54 | snesbanks[0] = 0x80; 55 | snesbanks[1] = 0xA0; 56 | snesbanks[2] = 0xC0; 57 | snesbanks[3] = 0xE0; 58 | snesbanks[4] = 0x00; // a... FastROM don't go up to 8MB... 59 | snesbanks[5] = 0x00; 60 | snesbanks[6] = 0x00; 61 | snesbanks[7] = 0x00; 62 | pcbanks[0] = 0; 63 | pcbanks[1] = 1; 64 | pcbanks[2] = 2; 65 | pcbanks[3] = 3; 66 | pcbanks[4] = 0; 67 | pcbanks[5] = 1; 68 | pcbanks[6] = 2; 69 | pcbanks[7] = 3; 70 | break; 71 | } 72 | } 73 | 74 | public static int ToPC(int snes) 75 | { 76 | return ((pcbanks[(snes & 0xe00000) >> 21]) << 20) | ((snes & 0x1f0000) >> 1) | (snes & 0x7fff); 77 | } 78 | 79 | public static int ToPCHeadered(int snes, bool header) 80 | { 81 | int val = ((pcbanks[(snes & 0xe00000) >> 21]) << 20) | ((snes & 0x1f0000) >> 1) | (snes & 0x7fff); 82 | return val + (header ? 512 : 0); 83 | } 84 | 85 | public static int FromPC(int pc) 86 | { 87 | return (snesbanks[(pc & 0xe00000) >> 20] << 16) | ((pc & 0x1f8000) << 1) | (pc & 0x7fff) | 0x8000; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /assets/asm/base/global.asm: -------------------------------------------------------------------------------- 1 | ORG $00804E 2 | autoclean JML clear_pointers 3 | 4 | ORG $00806B 5 | autoclean JML _global_main 6 | 7 | ORG $008176 8 | autoclean JML nmi_hijack 9 | NOP #2 10 | 11 | ORG $05808C 12 | JML load 13 | NOP 14 | 15 | freecode 16 | 17 | ; Do not edit nor move that. 18 | ; That's a special prot table for cleaning external data and codes. 19 | db "uber" 20 | prot_table: 21 | db "tool" 22 | 23 | clear_pointers: 24 | STA $7F8182 25 | LDA #$00 26 | LDX #!sprite_slots*3-1 27 | - 28 | STA !sprite_RAM,x 29 | DEX 30 | BPL - 31 | 32 | LDA #$00 33 | STA !previous_mode+1 34 | DEC 35 | STA !previous_mode 36 | 37 | if !sa1 38 | LDA #$60 39 | STA $1E93 ; edit SA-1 main loop to allow simple usage of it 40 | endif 41 | 42 | JSR global_init 43 | JML $008052|!bank 44 | 45 | _global_main: 46 | if !sa1 47 | JSR $1E8F 48 | else 49 | LDA $10 50 | BEQ _global_main 51 | endif 52 | JSR global_main 53 | 54 | LDA $0100|!addr 55 | CMP #$14 56 | BNE + 57 | JSR sprite_code 58 | + 59 | 60 | JML $00806F|!bank 61 | 62 | load: 63 | PHB 64 | SEP #$30 65 | JSR global_load 66 | REP #$30 67 | LDA !level 68 | ASL 69 | ADC !level 70 | TAX 71 | LDA.l level_load_table,x 72 | STA $00 73 | LDA.l level_load_table+1,x 74 | JSL run_code 75 | PLB 76 | REP #$10 77 | PHK 78 | PEA.w .return-1 79 | PEA.w $058125-1 80 | JML $0583AC|!bank 81 | .return 82 | SEP #$30 83 | JML $058091|!bank 84 | 85 | 86 | nmi_hijack: 87 | LDA $4210 ; This is SNES hardware stuff, so don't remove it please. 88 | 89 | PHB 90 | 91 | ; Include various probabilities for optimal performance. 92 | if !global_nmi == 1 93 | JSR global_nmi 94 | endif 95 | 96 | ; I guess I could have done this better, like pre-storing the tables into RAM during INIT or like, 97 | ; however I wanted to all hacks have minimum safetly to this run properly, so I decided to use 98 | ; temporary memory instead. 99 | if !gamemode_nmi == 1 || !level_nmi == 1 || !overworld_nmi == 1 100 | PEI ($6E) 101 | PEI ($70) 102 | endif 103 | 104 | if !gamemode_nmi == 1 105 | REP #$20 106 | LDA $0100|!addr 107 | AND #$00FF 108 | STA $6E 109 | ASL 110 | ADC $6E 111 | TAX 112 | LDA gamemode_nmi_table,x 113 | STA $6E 114 | LDA gamemode_nmi_table+1,x 115 | JSL nmi_run_code 116 | endif 117 | 118 | if !level_nmi == 1 && !overworld_nmi == 0 119 | ; LevelNMI only. 120 | LDA $0100|!addr 121 | CMP #$13 122 | BEQ ++ 123 | CMP #$14 124 | BNE + 125 | ++ REP #$30 126 | LDA !level 127 | ASL 128 | ADC !level 129 | TAX 130 | LDA.l level_nmi_table,x 131 | STA $6E 132 | LDA.l level_nmi_table+1,x 133 | JSL nmi_run_code 134 | + 135 | endif 136 | 137 | if !level_nmi == 1 && !overworld_nmi == 1 138 | ; Level NMI + Overworld NMI 139 | LDA $0100|!addr 140 | CMP #$13 141 | BEQ ++ 142 | CMP #$14 143 | BNE + 144 | ++ REP #$30 145 | LDA !level 146 | ASL 147 | ADC !level 148 | TAX 149 | LDA.l level_nmi_table,x 150 | STA $6E 151 | LDA.l level_nmi_table+1,x 152 | JSL nmi_run_code 153 | 154 | REP #$20 155 | PLA 156 | STA $70 157 | PLA 158 | STA $6E 159 | SEP #$20 160 | 161 | PLB 162 | LDA $1DFB|!addr ; return 163 | JML $00817C|!bank 164 | 165 | + CMP #$0D 166 | BEQ ++ 167 | CMP #$0E 168 | BNE + 169 | 170 | ++ LDX $0DB3|!addr 171 | LDA $1F11|!addr,x 172 | ASL 173 | ADC $1F11|!addr,x 174 | TAX 175 | REP #$20 176 | LDA.l OW_nmi_table,x 177 | STA $6E 178 | LDA.l OW_nmi_table+1,x 179 | JSL nmi_run_code 180 | + 181 | endif 182 | 183 | if !level_nmi == 0 && !overworld_nmi == 1 184 | ; Overworld NMI only. 185 | LDA $0100|!addr 186 | CMP #$0D 187 | BEQ ++ 188 | CMP #$0E 189 | BNE + 190 | 191 | ++ LDX $0DB3|!addr 192 | LDA $1F11|!addr,x 193 | ASL 194 | ADC $1F11|!addr,x 195 | TAX 196 | REP #$20 197 | LDA.l OW_nmi_table,x 198 | STA $6E 199 | LDA.l OW_nmi_table+1,x 200 | JSL nmi_run_code 201 | + 202 | endif 203 | 204 | if !gamemode_nmi == 1 || !level_nmi == 1 || !overworld_nmi == 1 205 | REP #$20 206 | PLA 207 | STA $70 208 | PLA 209 | STA $6E 210 | SEP #$20 211 | endif 212 | 213 | PLB 214 | LDA $1DFB|!addr 215 | JML $00817C|!bank 216 | 217 | nmi_run_code: 218 | STA $6F 219 | PHA 220 | PLB 221 | PLB 222 | SEP #$30 223 | JML [$006E|!dp] 224 | 225 | -------------------------------------------------------------------------------- /UberASMTool/DataCollector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace UberASMTool 7 | { 8 | class DataCollector 9 | { 10 | private readonly ROM rom; 11 | private readonly List freespacePointerList; 12 | 13 | public DataCollector(ROM romData) 14 | { 15 | rom = romData; 16 | freespacePointerList = new List(); 17 | } 18 | 19 | public int[] GetCollectedPointers() 20 | { 21 | int[] list = freespacePointerList.ToArray(); 22 | freespacePointerList.Clear(); 23 | 24 | return list; 25 | } 26 | 27 | public void CheckPreviousUberData() 28 | { 29 | //gamemode - $009322+1 30 | //levelASM - $00A242+1 31 | //overworld - $00A1C3+1 32 | //global - $00804E+1 33 | 34 | CleanPointerTable(0x1323, 256, false); 35 | CleanPointerTable(0x2243, 512, true); 36 | CleanPointerTable(0x21C4, 7, false); 37 | 38 | // clear external pointer table 39 | int ptr = CheckPointer(0x4F); 40 | 41 | if (ptr == -1) 42 | { 43 | return; 44 | } 45 | 46 | ptr -= 3; 47 | 48 | while (!CheckForUberSignature(ptr - 1)) 49 | { 50 | int pointer = rom.Read24(ptr); 51 | if (!freespacePointerList.Contains(pointer)) 52 | { 53 | freespacePointerList.Add(pointer); 54 | } 55 | ptr -= 3; 56 | } 57 | } 58 | 59 | private bool CheckForUberSignature(int ptr) 60 | { 61 | var str = rom.ReadBlock(ptr, 4); 62 | return (str[0] == (byte)'u' && str[1] == (byte)'b' && str[2] == (byte)'e' && str[3] == (byte)'r'); 63 | } 64 | 65 | private int CheckPointer(int offset) 66 | { 67 | int ptr = SNES.ToPC(rom.Read24(offset)); 68 | 69 | if (ptr < 0x80000 || ptr > rom.romSize) 70 | { 71 | // does not seem to be a valid pointer. 72 | return -1; 73 | } 74 | 75 | ptr -= 4; 76 | 77 | var str = rom.ReadBlock(ptr, 4); 78 | if (!(str[0] == (byte)'t' && str[1] == (byte)'o' && str[2] == (byte)'o' && str[3] == (byte)'l')) 79 | { 80 | // okay, does not seem legit. 81 | return -1; 82 | } 83 | 84 | return ptr; 85 | } 86 | 87 | private void CleanPointerTable(int offset, int pointerCount, bool ext) 88 | { 89 | int ptr = CheckPointer(offset); 90 | 91 | if (ptr == -1) 92 | { 93 | return; 94 | } 95 | 96 | ptr -= pointerCount * 6; 97 | 98 | bool nmi = false; 99 | bool load = false; 100 | 101 | scan: 102 | if (!CheckForUberSignature(ptr - 4)) 103 | { 104 | if (load) 105 | { 106 | // does not seem legit. 107 | return; 108 | } 109 | else if (nmi) 110 | { 111 | if (ext) 112 | { 113 | load = true; 114 | ptr -= pointerCount * 3; 115 | goto scan; 116 | } 117 | else 118 | { 119 | //does not seem legit.. 120 | return; 121 | } 122 | } 123 | else 124 | { 125 | nmi = true; 126 | ptr -= pointerCount * 3; 127 | goto scan; 128 | } 129 | } 130 | 131 | int total = pointerCount * (load ? 4 : (nmi ? 3 : 2)); 132 | 133 | for (int i = 0; i < total; ++i, ptr += 3) 134 | { 135 | int pointer = rom.Read24(ptr); 136 | if (!freespacePointerList.Contains(pointer)) 137 | { 138 | freespacePointerList.Add(pointer); 139 | } 140 | } 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /UberASMTool/ROM.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | // This controls ROM operations 5 | // Read/Write, RATS, FreeSpace Detection, 6 | // etc. 7 | 8 | 9 | namespace UberASMTool 10 | { 11 | class ROM 12 | { 13 | const int maxRomSize = 8389120; // 8mb + header 14 | const int minRomSize = 524288; // 512kb 15 | const int minRomExSize = 1048576; // 1mb 16 | 17 | public byte[] romData; 18 | public byte[] header; 19 | 20 | public bool canOperate; 21 | public ushort romType; 22 | public bool containsHeader; 23 | public string romLocation; 24 | public int romSize; 25 | public bool sa1; 26 | 27 | public ROM(string filename) 28 | { 29 | this.romData = File.ReadAllBytes(filename); 30 | this.canOperate = false; 31 | this.romType = 0; 32 | this.containsHeader = false; 33 | this.romLocation = filename; 34 | } 35 | 36 | public void Init() 37 | { 38 | int romLength = romData.Length; 39 | 40 | if (romLength > maxRomSize) throw new Exception("ROM too large!"); 41 | if (romLength < minRomSize) throw new Exception("ROM too small for Super Mario World!"); 42 | if (romLength < minRomExSize) throw new Exception("ROM must be expanded to 1MB first!"); 43 | 44 | this.containsHeader = (romLength % 0x8000) == 512; 45 | 46 | if ((romLength % 0x8000) != 0 && !this.containsHeader) 47 | throw new Exception("Invalid ROM block align! ROM corrupted?"); 48 | 49 | // 21 bytes long 50 | // aaaaaaaaaaa123456789012345678901 51 | string smw = "SUPER MARIOWORLD "; 52 | 53 | int position = 0x7FC0 + (this.containsHeader ? 512 : 0); 54 | 55 | foreach (char character in smw) 56 | { 57 | if (romData[position++] != character) 58 | throw new Exception("This isn't a Super Mario World ROM!"); 59 | } 60 | 61 | romType &= 0xffff; 62 | romType |= romData[position++]; 63 | romType |= (ushort)(romData[position++] << 8); 64 | 65 | romSize = romLength - (this.containsHeader ? 512 : 0); 66 | header = new byte[512]; 67 | 68 | if (this.containsHeader) 69 | { 70 | byte[] dupe = new byte[romSize]; 71 | Array.Copy(romData, 0, header, 0, 512); 72 | Array.Copy(romData, 512, dupe, 0, romSize); 73 | romData = null; 74 | romData = dupe; 75 | } 76 | 77 | canOperate = true; 78 | sa1 = (romType & 255) == 0x23; 79 | } 80 | 81 | public void Close() 82 | { 83 | romData = null; 84 | romType = 0; 85 | canOperate = false; 86 | containsHeader = false; 87 | romLocation = ""; 88 | romSize = 0; 89 | } 90 | 91 | public void Save() 92 | { 93 | byte[] final = new byte[romSize + (containsHeader ? 512 : 0)]; 94 | Array.Copy(romData, 0, final, containsHeader ? 512 : 0, romSize); 95 | 96 | if (containsHeader) 97 | { 98 | Array.Copy(header, romData, 512); 99 | } 100 | 101 | File.WriteAllBytes(romLocation, final); 102 | } 103 | 104 | public bool WriteBlock(byte[] block, int position) 105 | { 106 | try 107 | { 108 | if (!this.canOperate) throw new ArgumentNullException(); 109 | Array.Copy(block, 0, romData, position, block.Length); 110 | block = null; 111 | return true; 112 | } 113 | 114 | catch 115 | { 116 | return false; 117 | } 118 | } 119 | 120 | public int Read24(int pos) 121 | { 122 | try 123 | { 124 | if (!this.canOperate) throw new ArgumentNullException(); 125 | return romData[pos] | (romData[pos + 1] << 8) | (romData[pos + 2] << 16); 126 | } 127 | 128 | catch 129 | { 130 | return 0; 131 | } 132 | } 133 | 134 | public byte[] ReadBlock(int position, int length) 135 | { 136 | try 137 | { 138 | if (!this.canOperate) throw new ArgumentNullException(); 139 | byte[] output = new byte[length]; 140 | Array.Copy(romData, position, output, 0, length); 141 | return output; 142 | } 143 | 144 | catch 145 | { 146 | return null; 147 | } 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Visual Studio 2015 cache/options directory 14 | .vs/ 15 | # Uncomment if you have tasks that create the project's static files in wwwroot 16 | #wwwroot/ 17 | 18 | # MSTest test Results 19 | [Tt]est[Rr]esult*/ 20 | [Bb]uild[Ll]og.* 21 | 22 | # NUNIT 23 | *.VisualState.xml 24 | TestResult.xml 25 | 26 | # Build Results of an ATL Project 27 | [Dd]ebugPS/ 28 | [Rr]eleasePS/ 29 | dlldata.c 30 | 31 | # DNX 32 | project.lock.json 33 | artifacts/ 34 | 35 | *_i.c 36 | *_p.c 37 | *_i.h 38 | *.ilk 39 | *.meta 40 | *.obj 41 | *.pch 42 | *.pdb 43 | *.pgc 44 | *.pgd 45 | *.rsp 46 | *.sbr 47 | *.tlb 48 | *.tli 49 | *.tlh 50 | *.tmp 51 | *.tmp_proj 52 | *.log 53 | *.vspscc 54 | *.vssscc 55 | .builds 56 | *.pidb 57 | *.svclog 58 | *.scc 59 | 60 | # Chutzpah Test files 61 | _Chutzpah* 62 | 63 | # Visual C++ cache files 64 | ipch/ 65 | *.aps 66 | *.ncb 67 | *.opendb 68 | *.opensdf 69 | *.sdf 70 | *.cachefile 71 | *.VC.db 72 | *.VC.VC.opendb 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | *.sap 79 | 80 | # TFS 2012 Local Workspace 81 | $tf/ 82 | 83 | # Guidance Automation Toolkit 84 | *.gpState 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper*/ 88 | *.[Rr]e[Ss]harper 89 | *.DotSettings.user 90 | 91 | # JustCode is a .NET coding add-in 92 | .JustCode 93 | 94 | # TeamCity is a build add-in 95 | _TeamCity* 96 | 97 | # DotCover is a Code Coverage Tool 98 | *.dotCover 99 | 100 | # NCrunch 101 | _NCrunch_* 102 | .*crunch*.local.xml 103 | nCrunchTemp_* 104 | 105 | # MightyMoose 106 | *.mm.* 107 | AutoTest.Net/ 108 | 109 | # Web workbench (sass) 110 | .sass-cache/ 111 | 112 | # Installshield output folder 113 | [Ee]xpress/ 114 | 115 | # DocProject is a documentation generator add-in 116 | DocProject/buildhelp/ 117 | DocProject/Help/*.HxT 118 | DocProject/Help/*.HxC 119 | DocProject/Help/*.hhc 120 | DocProject/Help/*.hhk 121 | DocProject/Help/*.hhp 122 | DocProject/Help/Html2 123 | DocProject/Help/html 124 | 125 | # Click-Once directory 126 | publish/ 127 | 128 | # Publish Web Output 129 | *.[Pp]ublish.xml 130 | *.azurePubxml 131 | # TODO: Comment the next line if you want to checkin your web deploy settings 132 | # but database connection strings (with potential passwords) will be unencrypted 133 | *.pubxml 134 | *.publishproj 135 | 136 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 137 | # checkin your Azure Web App publish settings, but sensitive information contained 138 | # in these scripts will be unencrypted 139 | PublishScripts/ 140 | 141 | # NuGet Packages 142 | *.nupkg 143 | # The packages folder can be ignored because of Package Restore 144 | **/packages/* 145 | # except build/, which is used as an MSBuild target. 146 | !**/packages/build/ 147 | # Uncomment if necessary however generally it will be regenerated when needed 148 | #!**/packages/repositories.config 149 | # NuGet v3's project.json files produces more ignoreable files 150 | *.nuget.props 151 | *.nuget.targets 152 | 153 | # Microsoft Azure Build Output 154 | csx/ 155 | *.build.csdef 156 | 157 | # Microsoft Azure Emulator 158 | ecf/ 159 | rcf/ 160 | 161 | # Windows Store app package directories and files 162 | AppPackages/ 163 | BundleArtifacts/ 164 | Package.StoreAssociation.xml 165 | _pkginfo.txt 166 | 167 | # Visual Studio cache files 168 | # files ending in .cache can be ignored 169 | *.[Cc]ache 170 | # but keep track of directories ending in .cache 171 | !*.[Cc]ache/ 172 | 173 | # Others 174 | ClientBin/ 175 | ~$* 176 | *~ 177 | *.dbmdl 178 | *.dbproj.schemaview 179 | *.pfx 180 | *.publishsettings 181 | node_modules/ 182 | orleans.codegen.cs 183 | 184 | # Since there are multiple workflows, uncomment next line to ignore bower_components 185 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 186 | #bower_components/ 187 | 188 | # RIA/Silverlight projects 189 | Generated_Code/ 190 | 191 | # Backup & report files from converting an old project file 192 | # to a newer Visual Studio version. Backup files are not needed, 193 | # because we have git ;-) 194 | _UpgradeReport_Files/ 195 | Backup*/ 196 | UpgradeLog*.XML 197 | UpgradeLog*.htm 198 | 199 | # SQL Server files 200 | *.mdf 201 | *.ldf 202 | 203 | # Business Intelligence projects 204 | *.rdl.data 205 | *.bim.layout 206 | *.bim_*.settings 207 | 208 | # Microsoft Fakes 209 | FakesAssemblies/ 210 | 211 | # GhostDoc plugin setting file 212 | *.GhostDoc.xml 213 | 214 | # Node.js Tools for Visual Studio 215 | .ntvs_analysis.dat 216 | 217 | # Visual Studio 6 build log 218 | *.plg 219 | 220 | # Visual Studio 6 workspace options file 221 | *.opt 222 | 223 | # Visual Studio LightSwitch build output 224 | **/*.HTMLClient/GeneratedArtifacts 225 | **/*.DesktopClient/GeneratedArtifacts 226 | **/*.DesktopClient/ModelManifest.xml 227 | **/*.Server/GeneratedArtifacts 228 | **/*.Server/ModelManifest.xml 229 | _Pvt_Extensions 230 | 231 | # Paket dependency manager 232 | .paket/paket.exe 233 | paket-files/ 234 | 235 | # FAKE - F# Make 236 | .fake/ 237 | 238 | # JetBrains Rider 239 | .idea/ 240 | *.sln.iml 241 | *.suo 242 | 243 | # obj directory 244 | obj/ 245 | 246 | # Debug builds 247 | Debug/ 248 | 249 | # Release builds 250 | Release/ 251 | -------------------------------------------------------------------------------- /Specifications/UberAssemblyFile.txt: -------------------------------------------------------------------------------- 1 | UberASM v2.0 Assembly Specification File 2 | 3 | ============= 4 | = A: syntax = 5 | ============= 6 | 7 | 1- All .asm files are pre-processed by UberASM Tool before getting patched with Asar. 8 | ======== 9 | 10 | The files are read by a processor which changes the file contents and load additional required 11 | resources before the file can get correctly assembled by Asar. 12 | 13 | Example: library dependencies. 14 | 15 | 2- Special UberASM Tool commands start with ;> at the beginning of a line. 16 | ======== 17 | 18 | UberASM Tool will detect for ";>" and process only if it's on the beginning of a line. 19 | 20 | This is needed to keep compilant with Asar ASM syntax, so situations such as this: 21 | 22 | db "Test ;>file" 23 | 24 | Won't result in ambiguity, since UberASM can mistakenly interpret ;>file as a command while it's 25 | inside a string. This can apply to other situations where Asar doesn't understand ";" as a comment. 26 | 27 | 3- It's required to the command start as soon as prefix is present, with optional unlimited amount 28 | of parameters. 29 | ======== 30 | 31 | Example of UberASM special commands: 32 | ;>import my_library 33 | 34 | In case there is a non-alphanumeric character after ";>", the command is ignored. 35 | 36 | Example: 37 | 38 | ;> this appears to be a regular comment. 39 | ; > this appears to be a regular comment. 40 | ;>$FF this appears to be something else 41 | ;>7 this appears to be something else 42 | 43 | 4- There is no escaping characters. 44 | ======== 45 | 46 | Situations where it's expected a new line or a special between arguments should never happen and 47 | can be considered a design fault if some command ends up requiring it. 48 | 49 | Example - hypothetical alias command that references a file with spaces: 50 | ;>alias my file.asm my_file 51 | 52 | It's not clear if "my file.asm" is part of a first command or not and how to proceed with my_file 53 | 2nd paramter. 54 | 55 | 5- Some commands may required to be declared at top of the file. 56 | ======== 57 | 58 | Commands such as "import" can only be declared at the beginning of the file. Beginning of the 59 | file means empty, white-space, comment-only or begging-only UberASM commands. 60 | 61 | ======================================== 62 | = B: List of UberASM Assembly Commands = 63 | ======================================== 64 | 65 | 1- 'import' command. 66 | ======== 67 | File-beginning command only. 68 | 69 | The import command is used for telling UberASM Tool that the currently being processed file depends 70 | on a specific library and the library labels must be available before proceeding, if not available 71 | already. 72 | 73 | The command is required if the currently processing .asm file is part of the library. For other 74 | .asm files such as level ASM, overworld ASM, etc., it's optional unless if strict space saving mode 75 | is enabled. 76 | 77 | IMPORTANT: Cyclic references are not allowed. 78 | 79 | Example - a library file that requires math related commands on another library: 80 | 81 | == START OF FILE 82 | 83 | ;>import math 84 | 85 | ; outputs A = A*A 86 | power: 87 | STA $00 88 | STA $01 89 | 90 | ; call library to multiply $00 = $00 * $01 91 | JSL math_multiply 92 | 93 | LDA $00 94 | RTL 95 | 96 | == END OF FILE 97 | 98 | A wildcard "*" can be used to import all libraries prefixed before "*". It can only be used at the 99 | end of the file. 100 | 101 | Example: 102 | We have libraries hdma_gradient_layer, hdma_wavy_layer, and hdma_windowing available. 103 | It's suggested that they are from these files: 104 | 105 | hdma_gradient_layer.asm 106 | hdma_wavy_layer.asm 107 | hdma_windowing.asm 108 | 109 | We need all three imports, so instead of doing: 110 | 111 | ;>import hdma_gradient_layer 112 | ;>import hdma_wavy_layer 113 | ;>import hdma_windowing 114 | 115 | You can do: 116 | 117 | ;>import hdma_* 118 | 119 | alternatively: 120 | 121 | ;>import hdma* 122 | 123 | However, you CANNOT do: 124 | 125 | ;>import hdma_*_layer 126 | 127 | For this case, it would theorically import hdma_gradient_layer and hdma_wavy_layer. But "*" is 128 | only allowed at the end of library name reference. 129 | 130 | WARNING: when using "import" command, you are also telling UberASM Tool that only the imports 131 | specified are needed, so other unspecified libraries labels won't be included. 132 | 133 | 2- 'import' command with alias: 134 | ======== 135 | File-beginning command only. 136 | 137 | The import command can also create aliases. This can be useful for not having to reference long 138 | label names. For example, a library file hdma_gradient_layer.asm has the following labels: 139 | 140 | init: 141 | ;*insert code here* 142 | 143 | scroll: 144 | ;*insert code here* 145 | 146 | On your main code, you would need to reference them using the labels "hdma_gradient_layer_init" and 147 | "hdma_gradient_layer_scroll". However, to not have to write a such long label, you can use the "as" 148 | keyword on the import command for creating your own alias. 149 | 150 | Example: 151 | 152 | ;>import hdma_gradient_layer as gradient 153 | 154 | With such command, instead of referencing "hdma_gradient_layer_init" you can use "gradient_init" 155 | and instead of "hdma_gradient_layer_scroll" you can use "gradient_scroll" 156 | 157 | You can also completely inline the import, making the labels stay in the same "namespace" as your 158 | code, using the "inline" command instead of "as". 159 | 160 | Example: 161 | 162 | ;>import hdma_gradient_layer inline 163 | 164 | For this case, instead of referencing "hdma_gradient_layer_init", you can simply use "init" 165 | and for "hdma_gradient_layer_scroll" you can use "scroll". 166 | 167 | IMPORTANT: if some inlined label collides with a definition label (such as init, main, nmi, load, 168 | etc.) UberASM Tool will throw an error. This also applies when inlining or aliasing two libraries 169 | and they end up with exact label names. 170 | 171 | For this situation, you can use the RENAME command to rename label names before conflicting. 172 | 173 | Example: 174 | ;>import hdma_gradient_layer inline 175 | ;>rename hdma_gradient_layer_init as ginit 176 | 177 | Fun fact: import with alias or import with inline is basically an import with implied rename 178 | commands. 179 | 180 | 3- 'rename' command 181 | ======== 182 | File-beginning command only. 183 | 184 | TBD 185 | -------------------------------------------------------------------------------- /UberASMTool/UberASMTool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {B17060A9-56FF-49C8-9182-A46BD4185544} 9 | Exe 10 | Properties 11 | UberASMTool 12 | UberASMTool 13 | v4.0 14 | Client 15 | 512 16 | false 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 1 28 | 1.0.0.%2a 29 | false 30 | true 31 | true 32 | 33 | 34 | x86 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | prompt 41 | 4 42 | true 43 | 44 | 45 | x86 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | true 53 | false 54 | 55 | 56 | UberASMTool.Program 57 | 58 | 59 | uber.ico 60 | 61 | 62 | 787095019311569D0AAC199C1FF21BEF9A4C990E 63 | 64 | 65 | UberASMTool_TemporaryKey.pfx 66 | 67 | 68 | false 69 | 70 | 71 | false 72 | 73 | 74 | LocalIntranet 75 | 76 | 77 | Properties\app.manifest 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Always 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | False 115 | Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 116 | true 117 | 118 | 119 | False 120 | .NET Framework 3.5 SP1 Client Profile 121 | false 122 | 123 | 124 | False 125 | .NET Framework 3.5 SP1 126 | false 127 | 128 | 129 | False 130 | Windows Installer 3.1 131 | true 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 146 | -------------------------------------------------------------------------------- /assets/other/macro_library.asm: -------------------------------------------------------------------------------- 1 | ; This file is automatically included into all other UberASM Tool files. 2 | ; Useful for putting macros, defines, etc. 3 | ; Putting code or data is NOT recommend though or you will end up wasting lot of space. 4 | ; Put data or code at library folder instead. 5 | 6 | !sa1 = 0 ; 0 if LoROM, 1 if SA-1 ROM. 7 | !dp = $0000 ; $0000 if LoROM, $3000 if SA-1 ROM. 8 | !addr = $0000 ; $0000 if LoROM, $6000 if SA-1 ROM. 9 | !bank = $800000 ; $80:0000 if LoROM, $00:0000 if SA-1 ROM. 10 | !bank8 = $80 ; $80 if LoROM, $00 if SA-1 ROM. 11 | 12 | !sprite_slots = 12 ; 12 if LoROM, 22 if SA-1 ROM. 13 | 14 | ; Check if SA-1 is present. 15 | if read1($00ffd5) == $23 16 | !sa1 = 1 17 | !dp = $3000 18 | !addr = $6000 19 | !bank = $000000 20 | !bank8 = $00 21 | 22 | !sprite_slots = 22 23 | 24 | sa1rom 25 | endif 26 | 27 | ; Protect binary file. 28 | macro prot_file(file, label) 29 | pushpc 30 | freedata cleaned 31 | print "_prot ", pc 32 | 33 |