Aktuelle Zeit: 19.09.2018 06:05

Alle Zeiten sind UTC + 1 Stunde




 Seite 6 von 7 [ 100 Beiträge ]  Gehe zu Seite Vorherige  1 ... 3, 4, 5, 6, 7  Nächste
Autor Nachricht
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 01.04.2013 09:45 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Und? Gehts hier endlcih weiter?

Nö.

Ich habe gerade ein hübsches Zitat gelesen, das ich hier posten möchte.

Geäußert von Jez San, dem Entwickler von Starglider für u. a. Amstrad CPC, über Spieleentwicklung früher (mit Assembler) im Vergleich zu heute:

Retrogamer 2/2013, S. 25, Image Publishing / eMedia GmbH hat geschrieben:
Die Spieleprogrammierung war zu der Zeit nichts für schwache Nerven. In der guten alten Zeit mussten die Programmierer ihren Erfindergeist anstrengen und die Limitierungen der Computer überlisten, wie sich Jez mit einem Glitzern in den Augen erinnert. "Du hattest volle Kontrolle über den Computer. Programmiert wurde in Maschinensprache, du hattest also direkten Zugang zur Hardware. Heutzutage geht das gar nicht mehr, da nutzt du irgendwelche Bibliotheken und Schnittstellen, die die ganze harte Arbeit für dich erledigen. Anstatt in Assemblersprache wird in C programmiert, womit man nur sehr wenig Kontrolle über den Mikroprozessor hat. Damals wusste ich genau, was sich in welchen Registern befand - eine sehr effiziente Art des Programmierens. Dadurch lief mein Code auch viel schneller; kein Compiler jener Zeit hätte meinen Code auf diese Art und Weise übersetzen können. Ich bin mir nicht mal sicher, ob ein heutiger Compiler dazu in der Lage wäre."



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 16.04.2013 20:24 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Projekttage: Frisieren für Kapuzineräffchen

Heute machen wir... nix!

Wir werden Veränderungen im Code vornehmen, deren Ziel es ist, am Ende dennoch nur dasselbe wie jetzt auf den Bildschirm zu zaubern. Dazu werden wir uns maßgeblich um eine Subroutine kümmern. Wir haben aus unserer letzten praktischen Unterrichtsstunde ("Projekttage: Subroutinen und Stack") noch unser Programm, indem wir den DMA in eine Subroutine ausgelagert haben. Diese Subroutine wollen wir flexibler machen.
Wozu der Aufwand?
An dieser Stelle möchte ich gern einen Gedanken vom großen d4s anführen: Man sollte, bevor man ein größeres Projekt beginnt, sich gut organisiert haben, ansonsten wächst der Code geschwulstartig und wird selbst für den schreibenden Programmierer immer unübersichtlicher, bis sich jegliche Motivation gebunden an die Möglichkeit der Übersicht auf Nimmerwiedersehen verabschiedet. Sinngemäß sagte er mal sowas.
Folglich gilt auch hier: Vorbereitung ist alles. Wenn man sich einen guten Satz an flexiblen Subroutinen schreibt, die alle immer wiederkehrenden Wehwehchen meistern, spart man in der "heißen Phase" der Entwicklung viel Zeit; außerdem könnte man sicherlich auch solche Werkzeuge aus einem Projekt nehmen und sie in ein neues Projekt mitnehmen.

Jetzt beginnen wir mit der Automatisierung.

Zur Zeit ist es in dem Projekt so, dass die Subroutine "TilemapDMA" einen festen DMA durchführt. So oft ich sie aufrufe, transferiert sie immer wieder dieselbe Tilemap an dieselbe Stelle. Was wir jetzt tun werden ist: Wir werden Variablen einsetzen, die die Subroutine laden und in die DMA-Register speichern wird.
Da wir zur Zeit keine Variablen nutzen, können wir sie frei wählen. Aber -es tut mir leid- bevor wir ins Programmieren kommen, muss ich noch einmal einen theoretischen Teil erschlagen:

Direct Page, Direct Bank, RAM
Der Arbeitsspeicher, der RAM, liegt beim SNES zwischen #$7E0000 und #$7FFFFF. Im Englischen wird er oft als "WRAM" statt "RAM" bezeichnet, das "W" steht, glaube ich, für "Work RAM" oder "Working RAM". Vermutlich bezeichnet man ihn deshalb als "WRAM", um ihn von anderen RAMs unterscheiden können - den batteriegeschützten Speicher (SRAM), dem Palettenspeicher (CGRAM), dem Arbeitsspeicher des Videospeichers (VRAM) etc.
Jetzt könnte man bei jedem Mal, wenn man mit dem WRAM arbeitet, die 24-Bit-Adressen verwenden: LDA $7E0042.l, AND #$0F.b, STA $7F5000.l usw.
Zum Glück gibt es da zwei Vereinfachungen:
Erstens: Bei LoROM sind auf jeder Bank die Adressen $0000 bis $1FFF gleichzusetzen mit $7E0000 bis $7E1FFF. Das heißt, "LDA $0042.w" und "LDA $7E0042.l" laden dasselbe. Es gibt nur drei Unterscheide: Der erste ist: Man spart sich Tipparbeit (ganz wichtig). Der zweite ist: Man spart einen Byte im Programm (was natürlich bei der Menge der derartigen Befehle sich aufsummiert). Der dritte ist: Man spart pro Durchlauf dieses Befehls einen Cycle, was sich noch mehr aufsummiert (da mit Vorliebe viele Programmpassagen mehr als einmal durchlaufen werden).
Aber, es geht noch besser. Wir haben noch die Möglichkeit, die Direct Page Register zu nutzen. Mit der Direct Page kann man einen Bereich auf Bank $00 festsetzen, den man mit 8-Bit-Adressen ansprechen kann. In unserer InitSNES.asm finden wir "LDA #$0000.w" und "TCD", was ich auch schon im vorigen Artikel ("Projekttage: Stackbefehle (Push/Pull= und CPU-Register)") angesprochen habe. Das bedeutet, dieser Bereich beginnt bei $0000. Das heißt: "LDA $42.b" ist dasselbe wie "LDA $0042.w" ist dasselbe wie "LDA $7E0042.l" ist nicht dasselbe wie "LDA #$42.b". Obacht Doppelkreuz. Mind the Number Sign. Gare! Croisillon! ヘルメットの法律! hãy cẩn thận! Dê ruột!
Wichtig: Der Bereich, den man mit $0000 bis $1FFF ansprechen kann, kann man nicht variieren. Der Bereich, den man mit der Direct Page ansprechen kann, bezieht sich immer auf Bank $00. Das heißt, mache ich "LDA #$1F80.w" und "TCD", kann ich mit $00 bis $7F noch WRAM-Adressen ansprechen (logischerweise $7E1F80 bis $7E1FFF), mit $80 würde man in eins der Input-/Output-Register schreiben, das, sofern man nicht gerade ein MSU1-Programm schreibt, noch nicht mal unbedingt irgendwie belegt sein würde, und ich keine Ahnung hätte, was dann da passiert. Logischerweise wäre man mit "LDA #$8000.w" und "TCD" mit der Direct Page direkt am Anfang der eigenen ROM.
Folglich bietet es sich an, alle Werte, die man viel bearbeitet, in das Fenster zwischen $0000 und $1FFF zu packen, und die Wichtigsten der Wichtigsten im Rahmen eines dieser "Direct-Page-Fenster" zu behalten. Übrigens gibt es auch einige Spiele, die je nach Anlass die Direct Page ändern. Z. B. wird bei Squares Satellaview-Flugschiffspiel Treasure Conflix in Soundbelangen die Direct Page auf $1E00 gesetzt. Das Switchen kostet 4 Byte und 5 Cycles, das heißt, ab mehr als zehn solcher Befehle hat sich das Hin- und Herstellen rentiert.
Soweit hierzu. Ende theoretischer Teil.

Also fange ich mal an und kopiere den Inhalt der TilemapDMA-Subroutine (bis auf das RTS) und füge ihn überhalb des JSR-Tilemap ein. Dort fange ich jetzt an und ersetze die Register bei den STA- und STX-Befehlen durch Direct-Page-Register. Dann sieht das ganze so aus:
   LDX #$1000.w
   STX VMADDL.w

   LDA #DMAP_2_REG_WRITE_ONCE.b
   STA $00.b
   LDA #$18.b
   STA $01.b
   LDX #Tilemap.w
   STX $02.b
   LDA #:Tilemap.b
   STA $04.b
   LDX #$0800.w
   STX $05.b
   LDA #DMA_CHANNEL0_ENABLE.b
   STA $07.b
   JSR TilemapDMA

   LDA #$0F.b
   STA INIDSP.w

forever:
    jmp forever

TilemapDMA:
   LDA #DMAP_2_REG_WRITE_ONCE.b
   STA DMAP0.w
   LDA #$18.b
   STA DMADEST0.w
   LDX #Tilemap.w
   STX DMASRC0L.w
   LDA #:Tilemap.b
   STA DMASRC0B.w
   LDX #$0800.w
   STX DMALEN0L.w
   LDA #DMA_CHANNEL0_ENABLE.b
   STA MDMAEN.w
   RTS
.ENDS


Was macht das Programm jetzt? Bevor es die Subroutine aufruft und den DMA wie gewohnt durchführt, speichert es dieselben DMA-Variablen in die Direct Page Register. Natürlich ist das gerade noch vollends sinnlos, also frisieren wir noch unsere Subroutine, dass die Direct-Page-Register statt der festen Werte geladen werden. Dann sieht die Subroutine so aus:

TilemapDMA:
   LDA $00.b
   STA DMAP0.w
   LDA $01.b
   STA DMADEST0.w
   LDX $02.b
   STX DMASRC0L.w
   LDA $04.b
   STA DMASRC0B.w
   LDX $05.b
   STX DMALEN0L.w
   LDA $07.b
   STA MDMAEN.w
   RTS


Zunächst ein paar Fragen, die ich beantworten sollte. Erstens:

Warum benutze ich nicht Register $03 und $06?
Tue ich. Indirekt. Das sind beides 16-Bit-Werte, und die Direct-Page-Register sind alle 8 Bit groß. Folglich, wenn ich
   LDX #Tilemap.w
   STX $02.b

mache, speichere ich in $02 und alles, was da nicht herein passt (50%, 8 Bit), kommt in $03. Andersrum, wenn ich
   LDX $02.b
   STX DMASRC0L.w

befehle, lädt er $03 gleich zusätzlich, da er sieht, dass in X noch 8 Bit Platz sind.

Wenn das aber 16-Bit-Werte, also "Words" sind, warum schreibe ich dann noch ein ".b" hinter "$02"?
Das ".b" bezieht sich niemals auf die Größe des Inhalts, sondern auf die Länge der Adresse.
Beispiel:
Ich könnte auch "LDX 2" statt "LDX $02.b" schreiben. Das Ergebnis wäre dasselbe. Der Punkt ist: Erstens ist die Adresse keine Hexzahl, was ich schonmal kacke finde, und zweitens überlasse ich dem Compiler zu entscheiden, was für eine Adresse er daraus bildet, ob er nun "LDX $02" als "LDX $02" oder "LDX $0002" interpretiert. Letztere Interpretation kann man z. B. erzwingen, würde man "LDX $02.w" schreiben.
In diesem Fall ist es vollends wurscht, allerdings wäre es natürlich Mist, wenn man die Direct Page auf etwas anderes als $0000 gesetzt hat, und der Compiler sich entscheidet, ein "LDX $02" als "LDX $0002" misszuinterpretieren, da er dann nämlich das falsche Register lädt. Folglich entscheidet sich das ".b", ".w" oder ".l" niemals am enthaltenen Wert, sondern immer an der Länge der vorangehenden Hexzahl.

Jetzt haben wir das umgestellt, und es ist flexibler. Wir können jetzt immer wieder dieselbe Subroutine aufrufen, wenn wir vorher unterschiedliche Werte in die entsprechenden Variablen speichern. Wir können uns sogar gegebenenfalls das Updaten einzelner Variablen sparen, wenn dort der richtige Wert bereits drinsteht.

Allerdings ist das jetzt keine wirkliche Vereinfachung, sondern speziell für den Prozessor ist eine Zusatzbelastung, da wir ja einen Schritt dazwischen gefügt haben (Trotzdem war es nicht vollends sinnlos; da das hier ein Tutorial ist, haben wir damit schon wieder ein wenig Praxiserfahrung sammeln können).
Was wir als nächstes machen, ist ein bisschen was verrücktes. Der Aufwand für den Prozessor wird zwar immer noch mehr sein als beim "direkten" DMA, den wir am Anfang hatten. Dafür ist das System ebenfalls flexibel und sogar noch bequemer zu bedienen als die anderen beiden Varianten.

Wir werden folgendes machen: Die Daten für die Register schreiben wir in einer Kette hintereinanderweg als Bytes in unser Programm. Der Subroutine übergeben wir nur die Adresse dieser Kette, und die Subroutine geht dann zu dieser Adresse und verteilt dann selbstständig deren Inhalt auf die Register.

Machen wir das Einfache zuerst. Machen wir zunächst das, was jeweils außerhalb der Subroutine machen. Wir schreiben zunächst unsere Datenkette. Damit die nicht mit dem Code in die Quere kommt, schreiben wir sie unten in die Sektion "Bilddaten". Denn, wir erinnern uns, setzen wir das irgendwo ins Programm, nimmt der Prozessor an, das wären Befehle, interpretiert sie so, und verhält sich dann wie an Karneval im Rheinland. Und danach sieht alles aus wie Bierzeltgarnitur.
Dazu benutzen wir die Befehle ".DB" und ".DW". Die dienen dazu, dass die nachfolgenden Bytes (.DB) oder "Words", also Doppelbytes (.DW), so eins zu eins in das Programm geschrieben werden. Diese Befehle sind nun wieder, man kann es sich denken, keine Assembler-, sondern WLA-DX-Befehle. WLA-DX bietet auch einige andere Befehle, die genau dasselbe bewirken, aber ich benutze jetzt hier nur die und stelle die anderen Schreibweisen nicht dar. Wen es interessiert, der kann es in der WLA-DX-Dokumentation nachschauen. Wichtig dabei ist: Keine Raute davor. Wenn ".DB" oder ".DW" davor steht, weiß WLA DX sofort, dass das nachfolgende keine Adresse ist.
Also. Das Geschriebene sieht dann so aus:
(...)
.SECTION "Bilddaten"

.DB DMAP_2_REG_WRITE_ONCE.b
.DB $18.b
.DW Tilemap.w
.DB :Tilemap.b
.DW $0800.w
.DB DMA_CHANNEL0_ENABLE.b

Tileset:
(...)


Falls Klärungsbedarf besteht:
Ich kann natürlich auch statt der festen Zahlen auch hier die definierten Konstanten aus d4s' Datei verwenden.
Beim dritten Eintrag sehen wir, dass wir ".DW" statt ".DB" verwenden müssen, da es sich ja um eine 16-Bit-Adresse handelt.
Beim vierten Eintrag sehen wir, dass wir auch den Doppelpunkt-Befehl in diesem Zusammenhang nutzen können, damit die Bankadresse hier eingetragen wird.
Jetzt fügen wir noch unter dem ".SECTION" und über dem ".DB DMAP..." eine Sprungmarke für diesen Byte-Schlauch ein:

.SECTION "Bilddaten"

Data_Tilemap:
.DB DMAP_2_REG_WRITE_ONCE.b


Jetzt gehen wir an die Stelle im Hauptprogramm, bevor wir zur Subroutine springen. Dort löschen wir den Kram, in dem wir die DMA-Daten in die Register $00 bis $07 speichern, und speichern die 24-Bit-Adresse in die Direct Page Register $00 bis $02.

(...)
   STX VMADDL.w

   LDX #Data_Tilemap.w
   STX $00.b
   LDA #:Data_Tilemap.b
   STA $02.b
   JSR TilemapDMA
(...)


Es ist hier egal, welche Register man nimmt, es müssen allerdings (Merke 1!) Direct Page-Register sein und (Merke 2!) drei aufeinanderfolgende sein.
Jetzt kommt der knackige Teil!

Und dazu verwenden wir einen neuen ASM-Befehl...

...namens...

LDA!
Ja, in der Tat. Es gibt viele LDAs. Und wir kennen auch schon viele. Zum Beispiel wird ein "LDA #$0300.w" in die drei Bytes "$A9 $00 $03" zerlegt, das heißt, LDA ist $A9. In diesem Fall. Gucken wir uns "LDA $00.b" an. LDA in Verbindung mit einem Direct Page Register führt zu $A5. LDA in Verbindung mit einem 16-Bit-Register führt zu $AD. Das heißt, wir kennen schon mindestens drei Befehle, unter diesem Kürzel.
Bevor ich jetzt weitergehe, verweise ich wieder einmal auf das WLA-Handbuch (aber ich suche dieses Mal nicht nochmal den Link raus. Warum auch? Wenn du bis jetzt alle meine Ratschläge in den Wind geschlagen hast, dann kannst du jetzt auch ein bisschen arbeiten, um das Ding zu finden! :P) oder aber auch gern diese Seite, die ich des Öfteren nutze. Sie enthält dieselben Daten wie das Handbuch, ich meine auch, dass eine Aufstellung, die dieser sehr ähnlich ist, weiter hinten im Handbuch ist. Allerdings ist diese Aufstellung direkt digital und erspart mir das Blättern, wenn es mal ganz schnell gehen muss, um den Faden nicht zu verlieren.
Gut. Wir gebrauchen jetzt LDA im Sinne von $B7, das wird auf dieser Seite so schön "DP Indirect Long Indexed, Y" betitelt. Dieser Titel bedeutet: "DP" = Direct Page --- "Indirect" Indirekte Adressierung; wir geben dem Befehl nicht die Zieladresse, sondern eine Adresse, in der die Zieladresse steht --- "Long" = 24 Bit --- "Indexed" = Wir nehmen eins der Index-Register und zählen das auf die Adresse drauf. "Y" = Wir nehmen das Y-Register als Index (wir hätten ja auch X zur Auswahl).

Das Ganze sieht dann praktisch so aus:
MOI ERINNER MICH HIER MAL EIN BILDLI ZU MALEN
Wir speichern in Y "$0000.w" und in $10 bis $12 eine Adresse. Der Verständlichkeit halber nehme ich jetzt einen festen Wert, zum Beispiel $018980. Das heißt: $10 enthält #$80, $11 enthält #$89, $12 enthält #$01 (Low Byte zuerst, wie man sieht). Wenn ich jetzt Besagten "DP Indirect Long Indexed, Y"-LDA-Befehl nutze, der im Code so aussieht:
LDA [$10], Y

Geht der Prozessor zu $10 hin, guckt welche 24-Bit-Adresse in diesem Register und in dessen zwei Nachbarn ($11 und $12) liegt (du ahnst es schon: $018980), geht dann an diese Stelle (das heißt... $018980! Überrascht?) und zählt dann soviele Bytes weiter, wie in Y steht (in diesem Fall... null! Überrascht!?!) und lädt dann den nachfolgenden Byte (oder Doppelbyte, je nach Größe von A).
Wenn ich jetzt Y inkrementiere und denselben Befehl noch einmal aufrufe, lädt er logischerweise den Byte daneben, da zwar die indirekte Adresse (in $10 bis $12) dieselbe ist, aber der Index inkrementiert wurde. Verständlich?

Übrigens: Dieser Befehl funktioniert nur mit LDA und nur mit Y als Index. Andere Befehle gibt es in mehreren Ausführungen mit verschiedenen Lade-Registern und verschiedenen Indizes, z. B. das indizierte Direct-Page-Laden gibt es als "LDA $10.b, X", "LDX $10.b, Y" oder "LDY $10.b, X", diesen obenbeschriebenen Fall gibt es nur in einer Variante, nämlich -oh-oh!- in der oben Beschriebenen.

Verwirrt? Ich hoffe nicht. Bringen wir das neu erworbene, duselig machende Wissen jetzt gleich in die Praxis. Diesen Befehl müssen wir jetzt immer wieder aufrufen, und zwischendrin müssen wir nur den Index inkrementieren. Und, ach ja, vorher sollten wir den Index auch auf null setzen.

Wichtig! Sorry, das hier ist nicht ganz die einfache Einsteiger-Übung, wie ich dachte; wir hatten in der alten Subroutine auch noch einige Stellen, wo wir 16 Bit auf einmal eingelesen und abgespeichert haben. Wir haben aber, wie ich oben beschrieben habe, nur einen einzigen dieser "DP Indirect Long Indexed"-Befehle, und der speichert in A, was wir zur Zeit auf 8 Bit Größe eingestellt haben. Da könnten wir jetzt mittendrin für die zwei Doppelbytes die Größe von A switchen, das finde ich aber doof, deswegen schreiben wir das, was wir vorhin auf einmal übertragen haben, jetzt hier in zwei Einzelbytes. Dann sieht das Ganze so aus:

TilemapDMA:
   LDY #$0000.w
   LDA [$00.b], Y
   STA DMAP0.w
   INY
   LDA [$00.b], Y
   STA DMADEST0.w
   INY
   LDA [$00.b], Y
   STA DMASRC0L.w
   INY
   LDA [$00.b], Y
   STA DMASRC0H.w
   INY
   LDA [$00.b], Y
   STA DMASRC0B.w
   INY
   LDA [$00.b], Y
   STA DMALEN0L.w
   INY
   LDA [$00.b], Y
   STA DMALEN0H.w
   INY
   LDA [$00.b], Y
   STA MDMAEN.w
   RTS


Chic, was? Als Übung kannst du ja jetzt mal für das Tileset und die Palette die Daten-Bytes in die Sektion "Bilddaten" schreiben und das ganze Programm soweit verschlanken, dass dann die drei DMAs über die Subroutine laufen. Ich schmeiß dir dann die Lösung hier als Anhang untendran. Da werde ich dann auch mal unsere Subroutine passender umbenennen.

Oh, kleiner Tipp: Den Byte für das DMA-Aktivieren musst du im Paletten-DMA mit dazuschreiben. Erinnerst du dich? Wir hatten die ersten beiden DMAs über zwei verschiedene Channels gemacht, mit unserer Subroutine können wir aber immer nur den Channel 0 benutzen.

Okay, nächstes Mal wirds wieder einfacher. Versprochen.









~~~~~~~~~~~

An alle, die das hier noch wirklich lesen. Bei dem Ding hier brauche ich wirklich eure Hilfe. Gegen Ende empfinde ich, dass das Ding leider viel zu verwirrend geworden ist, einfach, weil mir aufgefallen war, wie viele dieser blöden Sonderregeln ich wieder beachten musste, deshalb konnte ich dem Leser nicht, wie ich wollte, einen einfachen Raum zum Üben geben, ohne ihn sicherheitshalber auf die ganzen Tücken hinzuweisen, die mir in letzter Sekunde auffielen.

Also, bitte: Fragt, fragt, fragt, und sagt mir, ab wo ihr mir nichtmehr folgen konntet. Nur durch Kritik kann das hier besser werden! ;)


Dateianhänge:
autodma.rar [9.55 KiB]
117-mal heruntergeladen

_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 28.01.2014 17:57 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
super Geil :) habs bis hierhin alles nachgecodet und glaube auch dass ich fast alles verstanden habe.
super Schwierig war diese Stelle
Lytron hat geschrieben:
Ja, in der Tat. Es gibt viele LDAs. Und wir kennen auch schon viele. Zum Beispiel wird ein "LDA #$0300.w" in die drei Bytes "$A9 $00 $03" zerlegt, das heißt, LDA ist $A9. In diesem Fall. Gucken wir uns "LDA $00.b" an. LDA in Verbindung mit einem Direct Page Register führt zu $A5. LDA in Verbindung mit einem 16-Bit-Register führt zu $AD. Das heißt, wir kennen schon mindestens drei Befehle, unter diesem Kürzel.
[...]
Gut. Wir gebrauchen jetzt LDA im Sinne von $B7 [...]


Hier wäre ein Hinweis darauf, dass das Opcodes sind, und was Opcodes sind, ganz gut.. vielleicht hattest du das auch schon erklärt und ich habs nur verdrängt. Ich saß hier jedenfalls nur und hab mich gefragt was das für komische Register sein sollen und wo du die jetzt wieder her hast x)
letztlich ist die Erklärung die dannach kommt viel wichtiger..
Vielleicht machts sinn den Absatz zu Verstecken und "zur Verwirrung" dran zu schreiben ;)

auch etwas undurchsichtig fand ich (und ich bin nichtmal sicher, dass ich das so richtig verstehe jetzt ist diese 24bit geschichte.. wenn ich das richtig sehe liegt im DPR ein Byte:

;   Im Direct Page Register liegt ein BitString der die folgenden Informationen enthaelt

;    DMA Mode       + 1 bit
;   DMA Destination    + 1 bit
;   TileMap       + 2 bit
;   TileMap Bank    + 1 bit
;   Transfer Size    + 2 bit
;   DMA toggle    + 1 bit
;             --------------
;            = 8 bit
das hab ich mir selbst ausgedacht.. ob es stimmt weiss ich nicht!


und mit diesem einen byte wird eine 24bit Adresse aufgerufen.. oderso?


nja, alles in allem jedenfalls großartige Leistung Lytron!

Jetzt würd ich als nächstes gern wissen wie ich unterschiedliche Sprites auf die verschiedenen BGs male..
lieber Herr Oberlehrer! Das kommt doch sicherlich als nächstes dran oder ;) ?

bis dahin werd ich mich mal wieder selbst bemühen müssen *grml ;)


Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 28.01.2014 18:02 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
ach! Und was ich dringend bräuchte wäre eine Erläuterung zur DMA Transfersize..

Mache ich den immer exakt so groß wie die zu transferierende Datenmenge?
Ergo sollte ich deshalb darauf achten, meine Sprites alle in der selbe Größe abzulegen?
Alte Wahrheit neu entdeckt?


Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 28.01.2014 18:18 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Du kannst den DMA auch größer anlegen, als die Daten sind. Dann transferiert er die danachliegenden Daten mit (z. B. andere Grafikdaten, oder was auch immer du nach den Grafikdaten machst).

Chic ist das nich', aber machbar.

~~~

*blätter* Oh, das war ein Doppel-Post, da waren ja noch mehr fragen. :D

Das Direct Page-Register/Direct Bank musst du dir so vorstellen:

Eigentlich kann der Prozessor nur mit 24-Bit-Adressen umgehen. Wann immer ich eine 16-Bit-Adresse benutze, sage ich ihm: "Die restlichen acht Bit kannste dir selber ausm Direct Bank Register puhlen." Er komplettiert sich die Adresse dann damit selbst. Soll heißen:

LDA $8012.w

Lädt Byte $8012 der aktuellen ROM-Direct-Bank. Normalerweise ist das Bank $00. Wenn ich jetzt aber die Direct Bank umswitche, weil ich viel auf Bank $04 arbeite, und dann LDA $8012.w sage, lädt er logischerweise von Bank $04 (weil ich es vorher umgestellt habe).

Alle Klarheiten beseitigt? ;)
Ansonsten frag gern weiter, bis ich es anständig erklärt kriege. :D ;)

Ich weiß nicht, ob das deine Probleme löst, aber Sprites sind etwas anders als BGs. Die Tiles *müssen* 16 Farben haben, und die Paletten müssen in die obere Hälfte des CGRAMs gespeichert werden. Soll heißen: Palette 0 bei BGs beginnt bei Farbe 0 von 255, Palette 0 für Sprites bei Farbe 128.



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 29.01.2014 01:42 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
herrlich x) ich hab grad 2h versucht einen Fehler in meinem Code zu finden..
aber jetzt funktioniert alles wie es soll und damit mir das auch alle glauben sind im Anhang ROM und Sources.. wobei sich bei den Sources nicht viel geändert hat gegenüber der Version von Lytron, und dass ich einige Teile des Codes probehalber in eigene Files verfrachtet und ein paar comments geschrieben hab.

yeah.. gut gemacht, ich :applaus:


Dateianhänge:
dprStack0r.zip [11.84 KiB]
94-mal heruntergeladen
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 29.01.2014 06:40 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Hah, nice! Ich schätze, ich muss dann wirklich mal ein weiteres Tutorial schreiben. ;)



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 29.01.2014 16:40 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
ja! ..dieses forum braucht einen *like button ;)

Ohne das jetzt als dreiste Aufforderung zu meinen liste ich mal auf was mich momentan am meisten interessiert:
    - wie bringe ich Tiles auf die unterschiedelichen Backgrounds
    - gibt es einen seperaten Layer für zB Playersprites, oder nutzt man einen der vier Backgrounds?
    - wie realisiere ich sinnvollerweise einen Loop für Sprite Animation, vor allem wenn es eine endlos animation sein soll?
    - allgemeines zu Interrupts, führt dann ja zu controller implementierung


    - ORA does...exactly what?
LDA $4212       ; $4212  |Status register [HVBJOY]
         ; xy00000a         x:   0 = Not in VBlank state.
         ;            1 = In VBlank state.
         ;         y:    0 = Not in HBlank state
         ;            1 = In HBlank state.
         ;         a:    0 = Joypad not ready. 
         ;            1 = Joypad ready.
ORA #$01

$4212 wird in den Akkumulator A geladen
ich glaube ORA #$01 prüft, ob der in A gespeicherte wert $01 = % 0000 0001 ist und schreibt, wenn das der Fall ist eine 1 in A

ja? ne?


Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 29.01.2014 19:47 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Sorry, ich werde das jetzt eher in Kurzform erklären, weil ich heute abend nicht viel Zeit habe... und würde ich es ausführlich erklären, wäre ich schon gleich beim Tutorial Schreiben. ;)

ORA:
ORA ist ein "Mach ein Logisches 'Oder' zwischen dem Inhalt von A und dem Wert/Register, das ich dir übergebe". Lies dir dazu am Besten die Erklärung zu ORA im WDC Handbuch durch, Seite 370.
Ein aus der Luft gegriffenes Beispiel: LDA $15, ORA #$80, STA $15.
Das lädt den Wert in Register $15, setzt den höchsten Bit (MSB), lässt die anderen Bits unberührt und speichert den Kram wieder zurück in Reg. %15.

Sprites/BGs:
Ja, Sprites sind losgelöst von den BGs. Näheres zu den Sprites mach ich mal wann anders, das ist eine eigene Wissenschaft für sich. Da steckt ein etwas anderes System hinter als bei den BGs.

Zweiter BG:
Also. Du musst den BG aktivieren, dass er auf dem Bildschirm erscheint, dazu schreibst du:

LDA #T_BG1_ENABLE|T_BG2_ENABLE.b
STA TMAIN.w

sofern du d4s' define.asm benutzt, ansonsten: LDA #$03.b STA $212C.w (anstelle des LDA #$01.b STA $212C.w, das du derzeit haben müsstest).

Irgendwas speichest du auch zur Zeit in das Register BG12NBA/$210B. Z. B. könntest du derzeit #$01.b dort hineinspeichern. Das sagt dem Dingens, dass es die Tiles für BG1 ab Adresse $1000 im VRAM sucht. Würdest du #$02.b reinspeichern, suchte es die Tiles ab $2000, bei #$05 bei $5000 usw.
Der vordere, hohe Nybble ist für BG2. Das heißt, wenn du #$43.b in $210B speicherst, nimmt das SNES die Daten ab $3000 im VRAM für die Tiles für BG1 und ab $4000 für BG2.
Du kannst natürlich auch #$33.b in $210B speichern, dann verwenden beide BGs dasselbe Tileset - was wiederum ebenfalls ggf. nützlich sein kann.
Jetzt hast du ihm gesagt, wo das Tileset für BG2 liegt. Die Tilemap speicherst du bei BG2SC/$2108 ab. Der Einfachheit halber würde ich dir empfehlen, die Tilemaps zu runden-Tausender-Adressen zu transferieren, das würde sonst ein bisschen zu kopfschmerzig. Jedenfalls, sagen wir, du transferierst die Tilemap für BG2 nach $5000. Dann speicherst du #$50.b in $2108.

Den Endlosloop mit dem Sprite, äh, ist schon so ne Sache... wenn du willst, kann ich dir den Code für die ROM geben, mit der ich neulich ChronoMoogles Sprite zum Laufen gebracht habe (das war in meinem Fragerunden-Thread, glaube ich). Da arbeite ich nicht mit einem Sprite, sondern habe die Animation über einen BG laufen lassen, aber zumidnest die Animation ist drin. ;)



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 31.01.2014 21:57 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
uff ey.. ich bin einfach zu blöd..

obwohl ich mir einbilde die Situation soweit erfasst zu haben, sowohl Speicheradressen, offsets und transfermodi kriege ich grad ziemlich einen zuviel..
Egal da muss ich jetzt erstmal durch, aber mal so als ausblick frage ich mich,
ob man längerfristig weiterhin bei jedem DMA händisch den speicher zuweisen muss, oder ob ich mit etwas Glück und Gottes Segen eines Tages dazu in der Lage sein könnte, den Speicher automatisch zuzuweisen.

Also.. ja oder? Da muss man sich irgendwann nicht mehr drum kümmern oder? *hoff


Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 01.02.2014 08:53 
Mr SNES
Mr SNES
Benutzeravatar

Registriert: 06.12.2011 17:05
Beiträge: 1668
Wohnort: Freiburg
+Positive Tradingpoints+: 40 von 40
Ich verstehe in diesem Thread so gut wie Nichts! Trotzdem toll wieviel Herzblut hier rein gesteckt wird! Respekt!



_________________
Bild
Mein Youtube-Channel!....UMBENANNT! -> Snes Heaven
http://www.youtube.com/user/papierkorb91
Gamefakt!
https://www.facebook.com/pages/Gamefakt/514091018689173
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 01.02.2014 09:34 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
Jein.

Wenns dich nervt, schreib dir ne Subroutine, die dir die Arbeit abnimmt.

Ich glaube, ich habe in meinem letzten Tutorial schon eine "einfache" Art der Erleichterung geschrieben, aber du kannst das je nach Belieben ändern.

Wenn ich mich recht erinnere, willst du ein Jump'n'Run basteln. Mein Rat wäre, dass zu zunächst ein paar kleinere Sachen bastelst, um dich ins Programmieren reinzufuchsen (z. B. Slideshows. lytron liebt Slideshows. :ugly: ), und dann anfängst, dich an dein Lebenswerk zu machen. Denn, wie d4s es mal sagte und ich nicht müde werde, es zu zitieren: Zunächst muss man die Struktur schaffen, ansonsten verheddert man sich auf kurz oder lang.

Bei einem Platformer wäre das, für deinen Fall, z. B. eine supergroße "Lade den nächsten Screen"-Subroutine. Eine Automatisierung würde so aussehen, dass du der Subroutine nur einen Zahlenwert übergibst, die dem zu ladenden Level/Raum entspricht, und das Dingens dann alles andere automatisch macht. In Bezug auf die DMAs könnte die Subroutine so aussehen:

  • Der übergebene Zahlenwert wird als Index für eine Liste umgerechnet, die Liste enthält die Adresse des dazugehörigen Datensatzes für den Raum
  • Der erste (Doppel)byte wird geladen
  • Der erste (Doppel)byte wird verarbeitet
  • Der zweite (Doppel)byte wird geladen
  • ...

Auf meiner Page habe ich eine meiner letzten Fassungen von DotT mitsamt Sourcecode hochgeladen, schau da mal nach, da habe ich angefangen, eine solche Automatik einzubauen.

In deinem Fall könntest du es z. B. so machen, dass diese Datensätze aus drei Source-Adressen von Grafikdaten bestehen, und die Subroutine dann drei DMAs durchführt, in denen diese Source-Daten an festbestimmte Stellen im VRAM transferiert werden. Das hätte dann den Vorteil, dass du bei jedem neuen Raum dich mit wenig Fitzelkram aufhalten musst, sondern nur einen neuen Datensatz schreiben musst, die Subroutine aufrufst, und damit der ganze Schrott von selbst funktioniert.
Ersteres ist der Hack-Style - und bei allem nötigen Respekt den Leistungen gegenüber, die auf erstere Weise entstanden sind-, letzteres hingegen ist wirkliches professionelles Programmieren. Weil man da sich vorher überlegt, was man machen will, statt in den Blauen Dunst codet.

Damit komme ich jetzt auch zu dem Punkt, weshalb ich bisher noch kein großes Spiel in Angriff genommen habe:
Sorry, dass das schon wieder so ein langer Post wird. Ich habe eigentlich auch keinen Bock, so viel zu schreiben, gerade... :( Ich habe noch sooo viel anderes zu tun. >_<

Um es mal aphorismisch auszudrücken:
Wenn du dir große Automatiken mit Subroutinen schreibst, baust du dir deine Technical Restrictions selbst.

Kann ich an obigem Beispiel erklären: Wenn dein Datensatz nur die Source-Adressen der Grafikdaten für die DMAs enthält, sind die Ziel-Adressen der DMAs "hardwired", sie sind fixe Werte. Du kannst deine Automatisierungssubroutine natürlich flexibler Schreiben, aber das kostet Zeit und macht alles komplizierter.
Genauso: Du schreibst dir eine komplette Level-Lade-Subroutine (über Tage und Wochen), fängst an, dein Spiel zusammenzusetzen, und kommst nach drei Wochen Leveldesign dazu, dass du willst, dass in deinem London-Themsen-Level BG3 noch einen halbtransparenten Nebeleffekt auf das Bild draufhaut. Zu dumm, dass deine Level-Lade-Subroutine nur BG1 und BG2 bedient.
Also kannst du nun entweder deine Super-Subroutine ummodeln, wieder Stunden ins Debuggen reinstecken, und danach alle bisher erstellten Datensätze nochmal anfassen, um es anzupassen, oder du fängst an, für den Raum eine Sonderlösung zu schreiben, wobei du da hoffen musst, nicht irgendwie zufällig irgendwas anderes zu zerschießen. Und du musst hoffen, dass du damit nicht nachträglich anfängst, deinen schön sauber und professionell strukturierten Code nachträglich vollends unübersichtlich zu machen und damit zu verhunzen, weil du hier in den "Hacking-Style" gewechselt bist.

Ich weiß, dass d4s das mit diesen "Styles" niemals so binär gemeint hat, wie ich das jetzt interpretiere, dass man nur ENTWEDER Hack-alike pfuscht ODER super-awesome mastermindig halbgott-in-weißig seine Code-Magic praktiziert. Es ist absolut legitim, Sonderfälle gesondert abzuhandeln, und wahrscheinlich ist das auch der Grund, warum es noch keinen Game-Maker-Editor für das SNES gibt, weil man schwerlich eine ultimative Lösung für alle Anforderungen aus dem Hut zaubern kann, die der Prozessor in adäquater Zeit abhandeln kann.
Allerdings muss man aufpassen, dass man, wenn man einmal damit angefangen hat, sich zu sagen: "Ach, ich mach das jetzt einfach so, kurz und schmerzlos!", dass man nicht in das Fahrwasser kommt, das ständig zu machen und seine eigene Arbeit... up-zu-messen. Durchnander zu machn. Wie heißt es so schön? "Wer billig kauft, kauft zweimal"? Hier muss es heißen: Wer unüberlegt codet, codet zweimal.

Äh, ja. Jedenfalls. Was ich eigentlich sagen will, ist: Wenn man ein großes Spiel in Angriff nehmen will, sollte man erstmal ein paar Wochen lang planen. Einmal konzeptionell wissen, was für technische Anforderungen man an seine "Engine" stellen will. Eine perfekte Planung (d. h. ein komplettes Script mit allen Leveln, allen Grafiken, allen Endboss-Mechaniken, allen Gegner-Mechaniken, allen Items etc.) wäre der Idealfall für den Programmierer, weil er dann keine "bösen Überraschungen" (= Änderungen) befürchten muss. Es ist immer der Kampf zwischen Kreativität und Aufwandsminimierung. Die coolsten Ideen sind eben die, die aus dem Muster ausbrechen, und das ist immer eine Menge Zusatzarbeit. Wenn Programmierer und Künstler in Personalunion sind, besteht der Vorteil, dass über diese Differenzen im schlimmsten Fall keine Freundschaft kaputtgehen kann. ;)

Einige Sachen, die man z. B. für eine Jump'n'Run-Raum-Lade-Subroutine planen kann, ist:

  • Wie will ich die Grafiken organisieren? Sollen die Räume bestimmte BG-Sets haben, d. h. die Grafiken für BG1, BG2 und BG3 nur in bestimmten Kombinationen geladen werden können, die man dann in eine eigene Liste schreibt, oder soll man frei kombinieren können?
  • Soll die Subroutine immer für die gleiche Anzahl von BGs Daten laden, oder soll das flexibel sein?
  • Wie will ich den Musikwechsel machen (inkl. einem Test, ob die Musik gewechselt werden muss, oder die alte weiterlaufen soll)?
  • Wie mache ich das mit der Collision-Map? Schreibe ich eine eigenständige Liste dafür, oder mache ich das tileabhängig? Dann wiederum muss ich für jede Map (/ jedes Grafikset) eine eigenständige Liste schreiben, welche Tiles durchlässig sind und welche nicht.
  • Wie will ich mit dem Raum die Positionsliste der Gegner verknüpfen, wie will ich selbige aufbauen, etc.

Man sieht, das baut alles direkt aufeinander auf, und man verschachtelt eigentlich immer mehr kleine Helferlein ineinander, bis man ein richtiges Monstrum hat, das man selbst nur noch meistern kann.

Ich könnte jetzt ewig so weiterschreiben, aber ich denke, genug Dinge in dem Text oben sind schon redundant genug. ;)



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 01.02.2014 20:48 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
Hi Lytron,
ich hoffe du fühlst dich nicht zusehr genötigt mir zu antworten ':)
was du da ausführst klingt sinnig.. solange ich es aber nichteinmal auf die Reihe bekomme
ohne gravierende Denkfehler die basics anzuwenden, wage ich garnicht daran zu denken, dass eines Tages ein echtes Spiel dabei rumkommt.

So jetzt habe ich aber mal ein ganz konkretes Problem:
Tilesets und Tilemaps funtktionieren und die Palette hab ich auch hinter der ersten im CGRAM.
Wie kann ich für BG2 eine andere Palette verwenden als für BG1?

oder ist es so, dass ich eine 128 farben palette machen muss, auf die sich alle tiles beziehen? ..ne oder?
..oder doch? *kratz

EDIT:
..ach muss ich da mode3 benutzen?


Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 01.02.2014 22:30 
Code Bro
Code Bro
Benutzeravatar

Registriert: 12.08.2012 20:18
Beiträge: 2665
Wohnort: ハノーファー区
+Positive Tradingpoints+: 12 von 12
snoer hat geschrieben:
Hi Lytron,
ich hoffe du fühlst dich nicht zusehr genötigt mir zu antworten ':)


Never ever, dude.
Es freut mich, wenn hier mal technische Fragen kommen, und wenn es dann auch noch welche sind, zu denen ich was sagen kann, freut mich das noch mehr. ;)

snoer hat geschrieben:
was du da ausführst klingt sinnig.. solange ich es aber nichteinmal auf die Reihe bekomme
ohne gravierende Denkfehler die basics anzuwenden, wage ich garnicht daran zu denken, dass eines Tages ein echtes Spiel dabei rumkommt.


Huch, solche Sätze kennt man von mir von 2012. ;)

Gute Debugging-Tools sind immer hilfreich. Der Geiger-Debugger ist sehr cool (danke an dieser Stelle nochmals an Svambo für datt Dingens), die Log-Files, die das Ding erstellt, haben mir geholfen, viele Bugs aufzuspüren.
Weitere Hilfe ist der NO$SNS-Emulator (http://nocash.emubase.de/), der VRAM-Viewer ist sehr hilfreich um zu sehen, ob wenigstens die Grafikdaten korrekt übertragen wurden.

Und, eine weitere Hilfe, die man nicht unterschätzen darf, ist: ZSNES! Das Ding gilt als nicht-akkurater Emulator, und gerade deshalb ist er eine große Hilfe. Es ist für mich eine gute Hilfe zu sehen, ob meine ROM wenigstens unter ZSNES funktioniert oder nicht. Das teilt die Bugs schonmal in zwei Kategorien von etwa gleicher Größe, was das Fixen nochmal vereinfacht: Läuft die ROM unter ZSNES so, wie ich es will, ist es meist ein Bug, der auf irgendeiner Hardware-Spezialität des SNES beruht (z. B. ein VRAM-DMA, der zuspät während des VBLANKs gestartet wird und deshalb nicht komplett ausgeführt wird). Läuft es unter ZSNES auch nicht, dann weiß ich wenigstens, dass ich zu dämlich bin, anständig zu coden. ;)

Aber ansonsten mach dir keinen Kopp, ich kriege es auch nicht hin, so einen "simplen Showoff" wie diese Grafik-Demo mit ChronoMoogles Sprite aus dem Stand richtig hinzubekommen. Man lernt nur mit der Zeit und der Häufigkeit, mit der man was getan hat, was die Sachen sind, die man immer vergisst. Zumindest ist das bei mir so. Bei d4s nicht. d4s is f'kin' genius.

snoer hat geschrieben:
So jetzt habe ich aber mal ein ganz konkretes Problem:
Tilesets und Tilemaps funtktionieren und die Palette hab ich auch hinter der ersten im CGRAM.
Wie kann ich für BG2 eine andere Palette verwenden als für BG1?

oder ist es so, dass ich eine 128 farben palette machen muss, auf die sich alle tiles beziehen? ..ne oder?
..oder doch? *kratz

EDIT:
..ach muss ich da mode3 benutzen?


Ähm. Öh. Ähm.

Also, es kommt drauf an. Wenn du zwei BGs mit 16 Farben hast, benutzt du Mode 1. Ehrlich gesagt habe ich bisher nur mit Mode 1 gearbeitet, weil das immer meinen Bedürfnissen entsprochen hat. Also, erwarte keine Hilfe von mir bei Mode-7-Fragen. ;)
Davon habe ich ein grundlegendes Verständnis, wie der Kram funktioniert, ich war aber seit langem nicht mehr geneigt, mich daran ernsthaft zu versuchen.

Welche Palette ein Tile benutzen soll, legst du in der Tilemap fest. Eine ausführliche englische Erklärung findest du hier. Für dich in diesem Fall müsste es hilfreich sein, wenn du weißt, dass du, wenn ud in deiner Tilemap z. B. ein "$01 $00 $02 $00" hast, die beiden Tiles Palette 1 statt 0 benutzen, wenn du "$01 $04 $02 $04" draus machst.



_________________
pantalytron: ルトロンはくそのディスアセンブラだよ!

Perikles hat geschrieben:
Man muss sich das mal reinziehen: die Idee ist scheiße, die theoretische Ausarbeitung ist scheiße, die praktische Umsetzung ist scheiße und der so entstehende Anspruch noch beschissener.
Offline
 Profil  
 
 Betreff des Beitrags: Re: Maggi-Fix für SNES Programmierung
BeitragVerfasst: 02.02.2014 01:53 
SNES-Programmer
SNES-Programmer

Registriert: 27.01.2013 13:10
Beiträge: 229
+Positive Tradingpoints+: 5 von 5
ah super :) das funktioniert jetzt auch..

Nächste Frage gleich hinterher:
Ich versuche aus einer Ascii file mit fester Filezize und einem Paletten Offset
eine Tilemap zu erzeugen.
Dafür will ich einen String schreiben, in den immer Abwechselnd ein Bit aus der ASCII Datei und das PalettenOffset (zb. #$04) steht. Jetzt hab ich gedacht ich kann das mit diesem dubiosen .DB bewerkstelligen, aber erstens verstehe nicht wie genau sich der Befehl verhält
und zweitens check ich nicht, an welcher Adresse der so erzeugte String liegt.

ich hab sowas versucht das compiliert nichtmal x)
      TextMap_n_TextPal:
          LDX #$0000.w      ; clear X
          StringConstructor:
            LDY TextMap.w, X   ; lädt die ertsen beiden bytes
            LDY $04.b       ; Paletten Offset
;            .DB Y         ; [color=#BF0000]<--- geht nicht[/color]
            INX
            INX
            CPX #$0800.w
         BNE StringConstructor

Der String der dabei rauskommt stellt ja eine Tilemap dar, und um die in den Vram zu kriegen brauche ich ja die Adresse..

ist das nachvollziehbar *kratz ?


EDIT again:
oder macht man das indem man seine Daten auf den Stack wirft und dann wieder runter liest?

..momentan würde ich ja immer 1dbyte aus der datei lesen, weil ich im native mode bin, richtig? wenn ich jetzt nur 1byte haben will, muss ich dann auf emulation mode switchen?

ich habe das hier versucht aber bin kläglich gescheitert..
   BG2_TileMap:
      .INCBIN "text.1024"
      Data_BG2_TileMap:            
         ; This writes Data ...somewhere (?)
         ; so it can be fetched by the DMA subroutine
         .DB $01.b               ;    1 byte
         .DB $18.b                ;     1 byte
         .DW $1FFF.w            ;   this is the stack   ;2 bytes
         .DB $00.b               ;   this is bank 0      ;1byte
         .DW $0010.w            ;     2bytes
         .DB DMA_CHANNEL0_ENABLE.b   ;
;-------------------------------------------------------------
      TextMap_n_TextPal:
      
         sec   ;set carry flag
         xce   ;exchange carry flag -> switch to EMULATION mode
      
          LDA $04.b
          LDX #$00.b      ; clear X
      
          StringConstructor:         
            PHA            ; push A to stack
         ;   LDY #BG2_TileMap.b, X   ; lädt das erste byte also den ersten buchstaben ; 1;            
         ;   PHY            ; push Y to stack
         ;   INX
            INX
            CPX #$08.b
          BNE StringConstructor

         clc   ; clear carry flag
         xce   ; exchange carry flag -> switch to NATIVE mode


ich hätte jetzt gedacht, dass der 8 mal #$04 auf den stack legt.. naive mode ;D
..aber ich weiss nichtmal ob ich das mit dem mode wechsel richtig gemacht hab


Offline
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
 Seite 6 von 7 [ 100 Beiträge ]  Gehe zu Seite Vorherige  1 ... 3, 4, 5, 6, 7  Nächste

Alle Zeiten sind UTC + 1 Stunde


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:

Zurück zu Schreibfabrik