Programmieren für den GBA

    • [ASM]

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Programmieren für den GBA

      Inhaltsverzeichnis
      Vorwort
      Einige mögen vielleicht bemerkt haben, dass es zwar mittlerweile immer mehr Leute gibt, die sich mit Assembly, und Programmierung für den GBA im Allgemeinen beschäftigen, allerdings holt man sich dieses Wissen zumeist aus dem Englischen Bereich, ein wirklich modernes, deutsches, Tutorial dafür gibt es noch nicht. Dem möchte ich gerne Abhilfe schaffen und ein bisschen erklären, wie ich denn meine Projekte organisiere, und wie man es trotz riesengroßer Codemengen (Im Falle von Pokémon Sovereign of the Skies allein etwa 15000 Zeilen Reincode) schafft, ein solches Projekt zu verwalten. Ein paar User aus diesem Forum haben quasi unter sich, eine kleine Projektstruktur entwickelt, auf der zumindest 2 der größten Projekte auf diesem Forum basieren. (Naja, zumindest auf einer ähnlichen Struktur) - und um dieses Know-How einmal weiterzugeben, schreibe ich hier etwas darüber.

      Das Hauptproblem, wenn man einmal mehr als nur ein paar kleine ASM Hacks in seinem Projekt hat, ist die Übersicht. Wo habe ich Pointer geändert, wo steht welcher Code, Snippet XY fehlt in meiner Dokumentation, etc. - Was kann man also tun, naja, am schönsten wäre es, den Reincode, und die entsprechenden "Patchingstellen", also Addressen, an denen Bytes, Pointer etc. geändert werden, einfach in einem Projekt zu haben, und dieses Projekt dann einfügen zu können. Da diese Problematik nicht nur irgendwann bei Romhackern auftritt, sondern allgemein bei größeren Projekten, gibt es eine Auswahl an Programmen, die genau das ermöglichen. Welche das genau sind, und wie man sie verwendet, das soll dieses Tutorial behandeln. Eine kleine Randinfo: Wenn ihr Assembly oder C an sich lernen wollt, dann seit ihr hier nicht ganz richtig. Ich werde versuchen alle meine Beispielcodes zu erklären, aber ich glaube, diese Thematik lernt man am besten, indem man mit den Leuten redet, ihr könnt mich jederzeit Privat, oder in Skype/Discord anschreiben, und ich bin sicher, wenn man auf andere User zugeht, sind diese genau so hilfsbereit. Ich habe damals auch im direkten Gespräch gelernt wie der ganze Kram funktioniert, und ich habe viele Datenblätter gelesen. Einige Tutorials gibt es hier auch noch dazu, falls man sich das ganze einmal ansehen möchte. Wichtig für den GBA spezifisch ist natürlich die entsprechende Architektur, und die Grundlagenidee, wie so ein Prozessor überhaupt funktioniert. Ansonsten gilt: Wer Fragen hat, der soll Fragen stellen, und dämliche Fragen gibt es nicht.


      Was ist diese Toolchain, was brauchen wir überhaupt?



      Unix ist Liebe, Unix ist Leben

      Ich habe von einer Kollektion von Programmen gesprochen, die uns ermöglichen solche Projekte zu erstellen, hier treffen wir nun erst ein paar Vorbereitende Schritte, um diese Programme zu verwenden. First Things first: Wenn ihr unter Windows operiert, braucht ihr auf jedenfall eine Unixoide Umgebung, also ein Terminal, das ein wenig besser ist, als die "Eingabeaufforderung" von Windows. Dazu gibt es zum Beispiel cygwin - Einfach die Version für eure Architektur (32- oder 64Bit) herunterladen, und das Setup ausführen. Das Setup installiert das Grundpaket und ist gleichzeitig ein Paketmanager, kann also Programme für euch installieren. Im Setup könnt ihr euch durch die ersten paar Seiten klicken, und wenn es darum geht, einen Mirror auszuwählen, nehmt ihr am besten einen Server, der nahe bei euch ist. Für Österreicher zu empfehlen ist z.B. gd.tuwien.ac.at - Der Server der TU Wien. Es ist aber grundsätzlich egal, von wo ihr euch das Zeug ladet (Ihr schont nur das Internet ein wenig). Zusätzlich zum Standardpaket installieren müsst ihr das Programm "make", dazu in der Suchleiste "make" eingeben, das Tool mit der Beschreibung "make - The GNU Version of the 'make' Utility" suchen, und einmal auf "skip" drücken, sodass dort nicht mehr "skip" sondern eine Versionsnummer steht. Das ganze sieht dann in etwa so aus:



      Außerdem zu empfehlen, für die Versionskontrolle ist "git", das werde ich höchstwarscheinlich in einem späteren Teil behandeln. Die volle Bezeichnung dazu lautet "git: Distributed Version Control System"


      Compiler

      Um unseren Code in etwas für den GBA ausführbares zu übersetzen, brauchen wir einen Compiler, am besten einen Assembler noch dazu, weil wir ein paar Dinge nicht in C schreiben können. (Das meiste jedoch schon, und das ist ein Segen, man glaube mir) Eine gute Compiler Toolchain für den GBA ist "DevkitARM", ein Bestandteil von DevkitPro - Einfach herunterladen und installieren. Danach müsst ihr noch den Ordner "<DevkitProInstallation>/devkitARM/bin" zu eurer PATH Variable hinzufügen. Wie das auf eurem entsprechenden Betriebssystem geht, könnt ihr sicher im Internet nachlesen, hier wird zum Beispiel erklärt, wie das unter ein paar verschiedenen Systemen funktioniert: superuser.com/questions/284342…or-use-them/284351#284351

      Gut, testen, ob ihr den PATH richtig gesetzt habt, könnt ihr, indem ihr das zuvor installierte cygwin terminal öffnet (Das Programm heißt Cygwin Terminal, oder Cygwin64 Terminal) und einfach einmal
      arm-none-eabi-gcc --version

      eingebt. Das sieht dann z.B. so aus:

      $ arm-none-eabi-gcc --version
      arm-none-eabi-gcc.exe (devkitARM release 46) 6.3.0
      Copyright (C) 2016 Free Software Foundation, Inc.
      This is free software; see the source for copying conditions. There is NO
      warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


      Wenn ihr euch vertippt oder PATH nicht richtig gesetzt ist, bekommt ihr eine Fehlermeldung, die euch sagt, dass das Programm nicht gefunden wurde. Um auch zu testen, ob die anderen Programme installiert sind, könnt ihr respektive

      make --version

      git --version

      eingeben, und schauen, ob ihr eine sinnvolle Ausgabe, oder einen Fehler erhaltet.

      Nachdem ihr das alles erledigt habt, sind sowohl euer Compiler, als auch make und git Einsatzbereit. Als nächstes schauen wir uns an, wie man damit arbeiten kann.


      Ein Template für alle Fälle

      Weil das alles nicht unbedingt intuitiv ist, und ich selbst ein paar Monate an dem geschraubt habe, was ich euch hier als Template anbiete, und überhaupt, weil man das Rad nicht neu erfinden muss, ... TL;DR: Es gibt ein Template. Dieses beinhaltet ein wenig Beispielcode, und ist vollständig durchkommentiert, sodass man sich damit auskennen sollte. Hier erkläre ich euch, wie ihr dieses Template aufsetzt. Zuerst einmal, müsst ihr euch das Ding von meiner git Repository herunterladen. Wer will kann dazu die Konsole verwenden, oder einfach hier drauf kliTemplate Download. Anschließend müsst ihr euch eine Ordnerstruktur erstellen, die wie folgt aussieht

      Quellcode

      1. PROJECT_ROOT
      2. /tools
      3. /rhr_coding_template
      4. /src
      5. /base
      6. ...


      Für den Tools Ordner wichtig ist das Tool, armips, und ein (VBA) Emulator, um euer ROM zu starten. Ihr könnt euch den Inhalt dieses Ordners von unserer Filebase laden. Damit ist das Projekt auch schon vollständig aufgesetzt. Um das Template zu benutzt müsst ihr eine Rom, mit Namen "bpre0.gba" in den Ordner "base" legen. Diese wird dann beim einfügen des Codes verwendet.

      Ihr könnt den Beispielcode testen, indem ihr in eurem cygwin Terminal in den Ordner rhr_coding_template wechselt und
      make run

      ausführt. Als Ausgabe seht ihr, was die ganze Toolchain tut, welche Programme ausgeführt werden, und wie am Ende der Emulator gestartet wird. Das sieht zum Beispiel so aus:
      arm-none-eabi-gcc -mthumb -mthumb-interwork -g -mcpu=arm7tdmi -fno-inline -mlong-calls -march=armv4t -O0 -std=c99 -Wall -Wextra -Wunreachable-code -Iinclude -DBPRE -DSOFTWARE_VERSION=0 -c src/example.c -o object/src/example.o
      arm-none-eabi-gcc -mthumb -mthumb-interwork -g -mcpu=arm7tdmi -fno-inline -mlong-calls -march=armv4t -O0 -std=c99 -Wall -Wextra -Wunreachable-code -Iinclude -DBPRE -DSOFTWARE_VERSION=0 -c src/agb_debug/agb_debug.c -o object/src/agb_debug/agb_debug.o
      arm-none-eabi-ld -z muldefs -T linker.lsc -T bpre.sym --whole-archive -r -o object/linked.o --start-group object/src/example.o object/src/agb_debug/agb_debug.o --end-group
      armips main.asm
      arm-none-eabi-nm object/linked.o -n -g --defined-only | \
      sed -e '{s/^/0x/g};{/.*\sA\s.*/d};{s/\sT\s/ /g}' > build/__symbols.sym
      *** SUCCESSFULLY BUILT PROJECT ***

      Die kompilierte ROM liegt anschließend im Ordner "build", beachtet, dass sämtlicher Code an die Addresse 0x09000000, bzw. 0x1000000 geschrieben wird. Also nach den ersten 16MB. Wie man das ändert, zeige ich im nächsten Abschnitt. Im build Ordner liegt außerdem noch eine "__symbols.sym" Datei, welche euch genau zeigt, wo euer Code eigentlich liegt. Um zu testen, ob der Code, der eingebaut wurde funktioniert, müsst ihr nur ins hohe Gras gehen, und dabei das Log des VBA aufmachen, dort solltet ihr eine Ausgabe feststellen. (Für C versierte, ihr könnt euch natürlich den Code ansehen, und nachvollziehen versuchen, wieso das so ist) - Im letzten Abschnitt gehe ich einmal kurz durch den Code, und erkläre was dort so schönes passiert.


      Codeerläuterung

      Das ganze ist ja ganz nett und schön, aber irgendwie ist vieles davon eine ganze Menge an Kuhmagie? Nun, für die meisten Teile reicht es erst einmal zu glauben, dass es funktioniert. Wer daran interessiert ist, wie das Linker Script funktioniert, kann sich im Internet gerne weiter umsehen, erklären werde ich das hier nicht. (Schwer ist es allerdings keinesfalls).

      makefile

      Quellcode

      1. ### Heart of the toolchain, compiles your code, ###
      2. ### links it, and inserts it into the ROM ###
      3. ### ###
      4. AS := arm-none-eabi-as
      5. LD := arm-none-eabi-ld
      6. OBJCOPY := arm-none-eabi-objcopy
      7. CC := arm-none-eabi-gcc
      8. ARS := armips
      9. ### Other tools you might need at some point ###
      10. ### can be defined here as well ###
      11. GRIT := grit
      12. NM := arm-none-eabi-nm
      13. VBA := vba
      14. MAKE := make
      15. ### Define a standard path for make to look for ###
      16. ### your tools, as well as your standard path ###
      17. export PATH := $(realpath ../tools):$(PATH)
      18. ### Some arguments for gcc you can acces in ###
      19. ### your code, for example with #ifdef ###
      20. DEFINES := -DBPRE -DSOFTWARE_VERSION=0
      21. ### Flags to pass to your compilers, note ###
      22. ### that our include directory is "include", ###
      23. ### defined via -Iinclude if you wish to change ###
      24. ### it ###
      25. ASFLAGS := -mthumb
      26. CFLAGS := -mthumb -mthumb-interwork -g -mcpu=arm7tdmi -fno-inline -mlong-calls
      27. CFLAGS += -march=armv4t -O0 -std=c99 -Wall -Wextra -Wunreachable-code
      28. CFLAGS += -Iinclude $(DEFINES)
      29. GRITFLAGS := -ftc -fa
      30. LDFLAGS := -z muldefs
      31. ### Standard directories to put our files into ###
      32. ### or take the source files from ###
      33. BLDPATH := object
      34. OUTPATH := build
      35. SOURCEDIR := src
      36. LINKER := linker.lsc
      37. SYMBOLS := bpre.sym
      38. PROJECT_NAME := YOUR_PROJECT
      39. MAIN_OBJ := $(BLDPATH)/linked.o
      40. ### some commands to make enumerating files ###
      41. ### a bit easier ###
      42. rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
      43. ### lists of our source files, note that they ###
      44. ### have to be given unique extensions ###
      45. ### .S/.s for ASM, .c for C files, ###
      46. ### capitalization does matter here! ###
      47. ASM_SRC_PP := $(call rwildcard,src/,*.S)
      48. ASM_SRC := $(call rwildcard,src/,*.s)
      49. C_SRC := $(call rwildcard,src/,*.c)
      50. ASM_OBJ_PP := $(ASM_SRC_PP:%.S=$(BLDPATH)/%.o)
      51. ASM_OBJ := $(ASM_SRC:%.s=$(BLDPATH)/%.o)
      52. C_OBJ := $(C_SRC:%.c=$(BLDPATH)/%.o)
      53. ALL_OBJ := $(C_OBJ) $(ASM_OBJ_PP) $(ASM_OBJ)
      54. ### rules for making objects out of source ###
      55. ### we use gcc for all of our compilation, as ###
      56. ### it will call the assembler respectively ###
      57. ### and can resolve preprocessor commands ###
      58. $(BLDPATH)/%.o: %.c
      59. $(shell mkdir -p $(dir $@))
      60. $(CC) $(CFLAGS) -c $< -o $@
      61. $(BLDPATH)/%.o: %.S
      62. $(shell mkdir -p $(dir $@))
      63. $(CC) $(CFLAGS) -c $< -o $@
      64. $(BLDPATH)/%.o: %.s
      65. $(shell mkdir -p $(dir $@))
      66. $(AS) $(ASFLAGS) $< -o $@
      67. ### rules for building the whole project ###
      68. all: rom
      69. .PHONY: rom
      70. rom: main.asm $(MAIN_OBJ)
      71. $(ARS) $<
      72. $(NM) $(BLDPATH)/linked.o -n -g --defined-only | \
      73. sed -e '{s/^/0x/g};{/.*\sA\s.*/d};{s/\sT\s/ /g}' > $(OUTPATH)/__symbols.sym
      74. @echo "*** SUCCESSFULLY BUILT PROJECT ***"
      75. $(MAIN_OBJ): $(ALL_OBJ)
      76. $(LD) $(LDFLAGS) -T $(LINKER) -T $(SYMBOLS) --whole-archive -r -o $@ --start-group $^ --end-group
      77. .PHONY: clean
      78. clean:
      79. rm -f $(OUTPATH)/__symbols.sym $(OUTPATH)/build.gba
      80. rm -R -f object/*
      81. .PHONY: run
      82. run: rom
      83. $(VBA) "build/$(PROJECT_NAME).gba"
      Alles anzeigen
      Die wichtigen Sektionen wurden von mir bereits auf Englisch kommentiert. (Generell empfielt es sich, für sowohl Code als auch Kommentare die Englische Sprache zu verwenden, es ist technisch einfach einfacher zu verstehen und international lesbar. Ihr könnt hier zum Beispiel den Namen eures Projektes ändern, in dem ihr YOUR_PROJECT durch euren Projektnamen ersetzt. (Beachtet, dass ihr dann auch in main.asm den Namen ändern müsst) - Was hier sonst noch so passiert, naja, es werden Regeln erstellt um die ganzen Dateien von ASM/ zu Maschinencode zu übersetzen. Beachtet, dass alle eure source Dateien im Ordner src liegen müssen, und ASM Dateien die Erweiterung .S/.s haben müssen, C Dateien die Erweiterung .c (Groß und Kleinschreibung ist wichtig!) - Wenn ihr euch mit makefiles auskennt, könnt ihr euch hier weiter austoben, ansonsten meine Empfehlung: Nicht angreifen.

      main.asm

      C-Quellcode: main.asm

      1. //this file can access the ROM directly,
      2. //use it to place hooks, overwrite bytes etc.
      3. //open a gba file named bpre0.gba in the base folder
      4. //set the base symbol to 0x08000000, the ROM section
      5. .gba
      6. .thumb
      7. .open "base/bpre0.gba","build/YOUR_PROJECT.gba",0x08000000
      8. //you can include other files like so, the path is arbitrary
      9. //.include "patches/some_hooks.asm"
      10. //inside the file you only need to place instructions to override
      11. //locations in the rom like so
      12. //.org 0x08ABCDEF //some random address
      13. //ldr r0, =some_global_symbol_in_the_source+1
      14. //bx r0
      15. //this would create a hook over r0 to some_global_symbol_in_the_source
      16. //make sure the symbol is defined, and that it is thumb code
      17. //NOTE: All code we define should be thumb code with our compiler settings
      18. //You can also add hooks directly in here, this is an example which will
      19. //be compiled and can be tinkered with
      20. .org 0x0806D698
      21. ldr r1, =ex_per_step_scripts+1
      22. bx r1
      23. .pool
      24. //NOTE: We jump in r1 here because r0 is used by convention to pass the argument
      25. // We could also use r2-r3, those are caller-save convention registers as well
      26. // .pool indicates that armips may put symbolic constants here, so in this case
      27. // the address of ex_per_step_scripts will be located at the .pool pseudo-op
      28. //this needs to be done to include all our code
      29. //address of our code, I use a 32 MB rom, so I place it after the first
      30. //16 MB of our main output file, after the original code has ended
      31. .org 0x09000000
      32. .importobj "object/linked.o"
      33. .close
      Alles anzeigen

      Auch hier wurde das wichtigste bereits wieder in Kommentaren dazu geschrieben. Ihr könnt eure Hooks, sofern es nur wenige sind, einfach in diese Datei schreiben, und der Syntax folgen, die das Beispiel vorgibt. Ihr könnt aber auch wie oben beschrieben, andere Dateien inkludieren, um die Übersicht zu behalten. Für ein größeres Beispiel könnt ihr zum Beispiel den source Code von Pokémon SotS oder Pokémon Violet betrachten (In den respektiven Unterforen zu finden)

      bpre.sym

      C-Quellcode: bpre.sym

      1. /*
      2. * Define symbols in this file, which can be used in your C code as
      3. * method definitions to call internal functions, or access internal
      4. * memory areas (structures etc. )
      5. */
      6. script_reset_environments_and_start = 0x08069AE4|1;
      7. in_trade_center = 0x0811B0D0|1;
      8. happiness_algorithm_step = 0x0806D74C|1;
      9. is_tile_control_override = 0x08059D70|1;
      10. overworld_poison_step = 0x0806D79C|1;
      11. get_egg = 0x080463B8|1;
      12. sav_xor_increment = 0x08054E90|1;
      13. safari_step = 0x080A0F0C|1;
      14. script_walk_810c4ec = 0x0810C4EC|1;
      15. __aeabi_idiv = 0x081E4018|1;
      16. __aeabi_idivmod = 0x081E40F4|1;
      17. __aeabi_uidiv = 0x081E460C|1;
      18. __aeabi_uidivmod = 0x081E4684|1;
      19. memset = 0x081E5ED8|1;
      20. memcpy = 0x081E5E78|1;
      21. vram_decompress = 0x081E3B6C|1;
      22. wram_decompress = 0x081E3B70|1;
      23. random = 0x08044EC8|1;
      24. malloc = 0x08002BB0|1;
      25. free = 0x08002BC4|1;
      26. scr_overworld_poison_death = 0x081A8DFD;
      27. scr_egg_hatch = 0x081BF546;
      28. scr_unk_per_step_end = 0x081A8CED;
      29. prev_quest_mode = 0x0203ADFA;
      30. walkrun_state = 0x02037078|1;
      Alles anzeigen
      Hier passiert nicht viel, ihr könnt Addressen zu Spielinternen Funktionen angeben, die ihr verwenden könnt. Beispiele (Die wir alle im Beispielcode mehr oder weniger brauchen) sind auch schon angegeben. Außerdem könnt ihr natürlich auch RAM Addressen angeben, und diese dann verwenden. Ihr müsst dem C Compiler nur sagen, wie sie zu interpretieren sind.

      C-Quellcode: example.c

      1. /*
      2. * This is an example file to show you how to use the template
      3. */
      4. /* === INCLUDES === */
      5. #include <game_engine.h>
      6. #include <types.h>
      7. #include <agb_debug.h>
      8. /* === EXTERN SCRIPTS === */
      9. void* scr_overworld_poison_death;
      10. void* scr_egg_hatch;
      11. void* scr_unk_per_step_end;
      12. /* === PROTOTYPES === */
      13. /**
      14. * @brief executed each step, executes scripts based on steps
      15. * @param tile_to the behavior ID of the tile we walk towards
      16. */
      17. bool ex_per_step_scripts(u16 tile_to);
      18. /* === IMPLEMENTATIONS === */
      19. bool ex_per_step_scripts(u16 tile_to)
      20. {
      21. if(tile_to == 0x2)
      22. {
      23. /* this is custom added code, will be executed if we step on grass in
      24. * bpre vanilla, which has behavior id 0x2
      25. */
      26. dprintf("we just stepped on grass, tile_to is %d", tile_to);
      27. /* this also shows off the debug functionality of this template, the string
      28. * above will be printed to the vba log, if you are using vba
      29. */
      30. }
      31. if(in_trade_center() || prev_quest_mode == 2)
      32. {
      33. return false;
      34. }
      35. happiness_algorithm_step();
      36. if((walkrun_state.bitfield & 0x40) || is_tile_control_override(tile_to))
      37. {
      38. return safari_step();
      39. }
      40. if(!script_walk_810C4EC())
      41. {
      42. if(overworld_poison_step())
      43. {
      44. script_reset_environments_and_start(scr_overworld_poison_death);
      45. return true;
      46. }
      47. if(get_egg())
      48. {
      49. sav_xor_increment(0xD);
      50. script_reset_environments_and_start(scr_egg_hatch);
      51. return true;
      52. }
      53. return safari_step();
      54. }
      55. script_reset_environments_and_start(scr_unk_per_step_end);
      56. return true;
      57. }
      Alles anzeigen
      Okay, endlich ein wenig richtiger C Code, und eigentlich auch kein allzu schwierig zu lesender. Wir inkludieren uns zuerst ein paar Header Dateien (Die könnt ihr euch anschauen, dort seht ihr wie ihr Spielinterne Methoden deklariert) und definieren eine Methode, welche wir auch in main.asm referenzieren. Nämlich überschreiben wir dort eine Originalmethode, mit unserer eigenen. Im Endeffekt ist diese Methode ein Nachbau, der Spielinternen Methode "per_step_scripts", welche ich mit einem Disassembler und Decompiler analysiert habe. Wie man sieht, weiß ich bei einigen Funktionen nicht genau, was sie tun, weswegen sie diese komischen Namen haben. Hier passiert also alles, was möglicherweise einen Script ausführen könnte, wenn man einen Schritt im Spiel macht. Die ersten Zeilen sind dafür verantwortlich, dass auf dem Log eine Ausgabe getätigt wird, wenn man durch das hohe Gras läuft. Wir können also mit der bereitgestellten "agb_debug.h" einen string auf dem Log ausgeben, und so noch mehr Debugging im Spiel unterbringen. Wir könnten hier auch eine Funktion implementieren, die bei betreten eines bestimmten tiles (Welches wir als Parameter übergeben haben) einen Script ausführt. (z.b. allen Pokémon Schaden machen, wenn man auf Feuer tritt, oder ein Pokémon im Team zufällig einschlafen lassen) Die Methode, die wir hierzu sogar schon definiert haben ist "script_reset_environments_and_start" welche als Parameter einen Scriptpointer übergeben bekommt. Vielleicht zeige ich euch in einem späteren Abschnitt, wie man mit diesem System sogar einen kleinen Script Compiler erstellen kann, der wohl mächtiger ist als XSE. Ihr könnt aber auch mit einem anderen Script Compiler Scripts in die ROM schreiben und die Methode mit "script_reset_environments_and_start((void*)(0x08ABCDEF)); aufrufen, wenn ihr einen statischen Script habt. Spielt euch einfach ein wenig mit dieser Methode, ich glaube es ist ein sehr anschauliches Beispiel, und kann ein bisschen mehr, als einfach das klassische Rot Tinten von Palletten. Außerdem in dieser Routine zu finden ist: Die Funktionalität für das Schlüpfen von Eiern und vergiftete Pokémon (Die ja alle paar Schritte Schaden bekommen) - Recht umfangreich.

      Das soll es erstmals gewesen sein. In den Headern seht ihr noch, wie man dem Compiler beibringt, was z.b. an "walkrun_state" steht, nämlich eine Struktur. Für weiteres könnt ihr mich gerne fragen, was wie wo, und euch natürlich in die 2 großen Projekte hineinlesen, welche so ein System momentan verwenden.


      Schlusswort

      Das ist natürlich nicht das einzige, was man hiermit tun kann. Mit dem Tool "grit" lassen sich Bilder in ASM und C Code übersetzen, und mit ein paar hilfsmitteln kann man auch Musik und Texte mit dieser netten Toolchain einfügen. Dazu vielleicht mehr, in einem anderen Tutorial.

      ~Sturmvogel
      Wandering on Horizon Road
    • Ist das eigentlich Absicht, dass du bei den CFLAGS -O0 drin hast? Weil wirklich auf Source Code Ebene tut man aufm GBA ja eh nie debuggen und kanns sogesehen direkt auf O3/O2 schalten.
      Das -z muldefs sollte man eigentlich auch mal rausnehmen. Das macht einem idR auch mehr kaputt als richtig (wobei ich grade gar nicht weiß wie das bei SotS ist).
      Bitte keine Musikhacking Fragen an micht, in denen es um die Verwendung von Programmen geht oder ob ich euch nicht dies oder jenes beibringen kann (ich gebe keine Einzelschülerkurse die 50 Stunden dauern würden). Bitte keine Fragen an mich wie man Programme oder Computer benutzt.
    • Der Debug Code wollte früher ohne Optimierung nicht kompilieren, außerdem ist es manchmal schön zu sehen, was der Compiler mit dem Output eigentlich genau macht, um das ein wenig nachvollziehen zu können. Im Regelfall würde man wsl. mit -O3 kompilieren, aber das sind Dinge, die man im Endeffekt eh aus der Dokumentation des Compilers entsprechend einmal ablesen kann / wird.

      Bezüglich der muldefs: Das ist tatsächlich etwas altes aus SotS, viel kaputt machen tut das nicht, wenn man keine multiplen Definitionen verwendet.

      ~Sturmvogel
      Wandering on Horizon Road