Kleine Einführung in die Dreamcast-Programmierung mit SDL

Die Programmierecke: Hier könnt ihr euch über alles was mit der (Dreamcast-)Programmierung zusammenhängt austauschen. C/C++, SDL, Assembler, KallistiOS und mehr
Antworten
Benutzeravatar
Maturion
sega-dc.de-Team
sega-dc.de-Team
Kontaktdaten:

Kleine Einführung in die Dreamcast-Programmierung mit SDL

Beitrag von Maturion »

Kleine Einführung in die Dreamcast-Programmierung mit SDL
von Maturion

An wen richtet sich diese Anleitung?
Diese Anleitung richtet sich an alle, die grundlegende Kenntnisse in der Programmierung mit C oder C++ haben und ihre Dreamcast-Entwicklungsumgebung bereits konfiguriert haben. Eure Kenntnisse müssen nicht überragend sein, es reicht völlig, wenn ihr wisst was Variablen, Klassen, Header, Zeiger und Funktionen sind. In dieser Anleitung lernt ihr, wie man mit Hilfe von SDL für die Dreamcast-Konsole programmiert.

Fangen wir mit ein paar Headerdateien an:

Code: Alles auswählen

#include <kos.h>
#include <stdio.h>
#include <SDL.h>
#include <SDL_dreamcast.h>
kos.h ist der Standard-Header von KallistiOS, stdio.h ist eion Header aus der C-Standardbibliothek, SDL.h ist der Header der SDL-Bibliothek und SDL_dreamcast.h enthält Dreamcast-spezifische Teile von SDL. Das ganze ist also nichts wirklich neues.

Code: Alles auswählen

SDL_Surface *screen = NULL;
SDL_Surface *bild= NULL;
Hier deklarieren wir 2 Objekte der Klasse SDL_Surface. SDL_Surface ist eine Klasse aus SDL und kann Bilder und Ähnliches enthalten. Die gesamte Anzeige des Bildschirms wird auch als ein Objekt gesehen. Auf dieser screen-Variable werdet ihr die Variable "bild" auch später "blitten" - sprich in die screen-Variable laden. Dazu aber später.

Hier erstellen wir eine Funktion, die für uns später eine Datei "hallo_welt.bmp" ausliest, in das aktuelle Anzeigeformat konvertiert und dann diese in das Objekt "bild" speichert.

Code: Alles auswählen

SDL_Surface *bild_laden( const char* dateiname)  {
    
    SDL_Surface* BildGeladen = NULL;
    SDL_Surface* optimiertesBild = NULL;

    BildGeladen = SDL_LoadBMP( filename );
    
    if( BildGeladen != NULL ) {

        optimiertesBild = SDL_DisplayFormat( BildGeladen );
        

        SDL_FreeSurface( BildGeladen );
        
    }
    
    return optimiertesBild;
}
Diese Funktion gibt ein SDL_Surface zurück - was nötig ist, damit das ganze auch in die bild-Variable geladen werden kann. Die ersten zwei Variablen, die wir hier definieren sind nur ein Zwischenspeicher. Richtig interessant wird's erst hier: BildGeladen = SDL_LoadBMP( dateiname );.
Hier wird in die weiter oben definierte Variable Bild mit Hilfe der Funktion SDL_LoadBMP ein Bild geladen. dateiname ist hierbei das Argument vom char-Typ, das der Funktion bild_laden am Anfang übergeben wird. SDL_LoadBMP lädt nur Bitmaps, andere Dateiformate können mit Hilfe einer weiteren Funktion aus einer weiteren Header-Datei der SDL-Bibliothek benutzt werden, allerdings werden wir in dieser kleinen Einführung vorerst nicht darauf zu sprechen kommen. In der nächsten if-Abfrage prüfen wir, ob in BildGeladen erfolgreich ein Bild gespeichert werden konnte. Falls ja wird mit Hilfe von SDL_DisplayFormat das Bild, das momentan in BildGeladen gespeichert ist, in das Format der aktuellen Anzeige umgewandelt und dann in optimiertesBild gespeichert. Sprich: Wenn das Bild ein 24bit-Bitmap ist und das Zielsystem auf 32bit-Auflösung läuft, dann erledigt diese Funktion die Umwandlungs-Arbeit für euch. Mit SDL_FreeSurface( BildGeladen ); löschen wir das alte Objekt, das nun nicht mehr gebraucht wird. Zu guter letzt geben wir das optimierte Objekt als Rückgabewert der Funktion bild_laden mit return optimiertesBild; zurück. Jetzt ist unsere Funktion einsatzbereit.

Jetzt kümmern wir uns mal um die Hauptunkfunktion:

Code: Alles auswählen

int main(int narg,char**arg) {

	SDL_Init( SDL_INIT_EVERYTHING );
	screen = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );
	
	bild = bild_laden("hallo_welt.bmp");
	
	SDL_Rect offset;
	
    offset.x = 0;
    offset.y = 0;
    
    SDL_BlitSurface( bild, NULL, screen, &offset );
	
	SDL_Flip( screen );
}
Die main()-Funktion wird ganz normal wie auf dem PC aufgerufen. mit SDL_Init( SDL_INIT_EVERYTHING ); initialisieren wir die SDL-Bibliothek und mit screen = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE ); setzten wir den Video-Modus. Die Argumente, die an die Funktion übergeben werden sind: Breite, Höhe, Bit und um das letzte Argument müsst ihr euch vorerst gar nicht kümmern.

Als nächstes rufen wir unsere oben definierte Funktion auf.
SDL_Rect offset ist ein Rechteck, das wir brauchen, um festzulegen, ab welchen Koordinaten später das Bild angezeigt werden soll. Da das ganze ab dem oberen Bildschirmrand angezeigt werden soll, setzen wir die x- und y-Koordinaten auf 0. Mit SDL_BlitSurface( bild, NULL, screen, &offset ); "blitten" wir unser Objekt bild auf das Objekt screen.

Bild
screen beinhaltet also nun unser Objekt bild.

screen ist wie bereits oben gesagt, der gesamte Bildschirm. Das erste Argument von SDL_BlitSurface( bild, NULL, screen, &offset ); ist das Objekt, das in das andere Objekt kopiert bzw "geblittet" werden soll. Das zweite Argument würde angeben ob nur ein bestimmter Teil des im ersten Argument übergebenen Bildes kopiert werden soll. Da wir aber das gesamte Objekt kopieren möchten, nehmen wir hier NULL. Das dritte Objekt hier ist das Objekt, in das das erste Objekt kopiert werden soll. Das vierte Argument, vom Typ SDL_Rect, gibt an, an welcher Position das ganze dann angezeigt werden soll. Danach wäre das Objekt screen auch fertig. Doch dann müsst ihr mit SDL_Flip( screen ); noch den Bildschirm "aktualisieren". Dann ist euer Programm fertig und eure Dreamcast-Konsole zeigt ein schmuckes Bild aus der Datei hallo_welt.bmp an! Was ihr in diese Datei malt, bleibt letztendlich euch überlassen....

Dieses Programm wird sich leider auch nicht selbst beenden, dass heißt, wenn ihr genug von eurem Bild habt, dann müsst ihr eure Konsole mit einem Druck auf die Powertaste ausschalten.

Die Datei main.c, könnt ihr einfach erstellen, in dem ihr den Inhalt der mit "Code" markierten Beispiele einfach in eine Datei kopiert und diese dann main.c nennt.

Das Makefile, das ihr zum Kompilieren benötigt, ist hier:

Code: Alles auswählen

TARGET = main

OPTFLAGS=-O3 -fomit-frame-pointer

KOS_CFLAGS+= -I$(KOS_BASE)/../kos-ports/include/SDL-1.2.9 $(OPTFLAGS) 

all: $(TARGET).bin

include $(KOS_BASE)/Makefile.rules

.SRCS	=	main.c \

OBJS = $(.SRCS:.c=.o)

clean:
	rm -f $(OBJS) $(TARGET).elf $(TARGET).bin

$(TARGET).elf: $(OBJS)
	$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET).elf $(KOS_START) \
		$(OBJS) -lSDL_129 -lm $(OBJEXTRA) $(KOS_LIBS)

$(TARGET).bin: $(TARGET).elf
	$(KOS_OBJCOPY) -R .stack -O binary $(TARGET).elf $(TARGET).bin

run: $(TARGET).bin
	$(KOS_LOADER) $(TARGET).bin

Die Dateien "Makefile" und "main.c" müssen irgendwo in eurem Cygwin-Ordner sein. Öffnet einfach die Cygwin-Konsole, geht in den Ordner in dem ihr die beiden Dateien abgespeichert habt und gebt "make" ein. Kurz darauf dürftet ihr eine "main.elf"-Datei haben, eine ausführbare Dreamcast-Datei!
Dreamcast träumt weiter
Xbox Live GamerTag: Maturion
Benutzeravatar
TulleMulle
Dauergast
Dauergast

Re: Kleine Einführung in die Dreamcast-Programmierung mit SDL

Beitrag von TulleMulle »

Respekt für die lange anleitung!

leider funktioniert das nicht unter linux. es heißt die SDL_dreamcast.h fehlt. ich hab in meinem ganzen KOS-ordner danach gesucht und nix gefunden. Ich bin auf dem aktuellen SVN-stand.
Benutzeravatar
Maturion
sega-dc.de-Team
sega-dc.de-Team
Kontaktdaten:

Re: Kleine Einführung in die Dreamcast-Programmierung mit SDL

Beitrag von Maturion »

Tut mir Leid, dasss ich vergessen habe das zu sagen: Das ganze ist für Chuis SDL-Portierung gedacht. Standardmäßig ist die im DDE4 von fackue dabei. Im SVN ist der SDL-Port von bero, der leider veraltet ist. Da hier die meisten Windows und das DDE4 benutzen, habe ich vergessen, das dazu zu sagen - obwohl ich selber Linux-Nutzer bin. :lol:

Hier gibt es Chuis SDL, das kannste dir dann selber kompilieren - dann funktionierts auch unter Windows.
Dreamcast träumt weiter
Xbox Live GamerTag: Maturion
mr-edit
Neuling
Neuling

Re: Kleine Einführung in die Dreamcast-Programmierung mit SDL

Beitrag von mr-edit »

Dieses Beispiel kann leider gar nicht funktionieren :) denn es fehlt eine kleine aber wichtige Sache.
Und zwar das sich das bild "hallo_welt.bmp" in einem Romdisk Verzeichnis befinden muss.

Mit diesen Befehlen lädt man die Romdisk:

extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);

Die Befehle sollten unter den "Include" und "Define" Einträgen stehen, dann klappt auch dieses Beispiel :)
Musste ich selber hart erlernen. Ach und wichtig ist das das Romdisk dann auch korrekt in dem "makefile" angegeben ist.

mfg.
mr-edit
Antworten

Mitglieder in diesem Forum: 0 Mitglieder und 122 Gäste