Sprites definieren



  • hallo,

    bin grad am überlegen, wie ich in assembler sprites anlegen kann ...
    d.h. in der sprache c mit SDL zum beispiel hab ich immer bitmaps genommen und
    diese bitmaps dann in mein programm eingeladen und als "surface" abgelegt...

    aber wie geht das in assembler wenn man jetz gar keine externe bitmap-dateien
    verwenden will.. also das heisst kein os verwenden möchte um irgendwie auf
    externe dateien zugreifen zu wollen

    also ich möchte z.b. sagen wir einen kleinen kreis in der farbe blau als sprite
    ablegen, der aus etwa 20 pixel besteht und ich arbeite im mode13h ...
    wie gehe ich vor ?
    muss ich dann im programmcode jeden pixel selbst definieren ?, also
    mir zum beispiel ein 2dimenionales array anlegen aus 20*20 bytes (sofern der kreis einen durchmesser von 20 pixel haben soll) und dann jeden blauen pixel
    vom kreis von hand setzen ?
    wenn ja, wie würde das etwa dann im code aussehen ?

    oder kann ich mir da doch das leben mit einem editor ( malprogramm ) einfacher machen ? nur wie verwende ich dann diese pixelinformationen, wenn ich komplett
    von jeglichen betriebssystemen unabhängig bleiben möchte..

    sagen wirs mal so..
    die alten AMIGA-spiele haben es ja irgendwie auch hinbekommen..
    ich will nich wissen wieviel sprites da pro spiel im programmimage
    abgelegt sind...

    bin für jeden gedankenanreiz dankbar ..

    mfg haMMer



  • Moin, Moin...

    Wenn Du tatsächlich keine Grafik von Festplatte laden möchtest, ist Deine bereits angedeutete Lösung das Richtige. Du definierst ein Array mit den 8-Bit-Farbwerten Deines Bildes.

    bild    db 0,0,9,9,9,9,0,0
            db 0,9,9,9,9,9,9,0
            db 9,9,9,9,9,9,9,9
            db 9,9,9,9,9,9,9,9
            db 9,9,9,9,9,9,9,9
            db 9,9,9,9,9,9,9,9
            db 0,9,9,9,9,9,9,0
            db 0,9,9,9,9,9,9,0
    

    Nun musst Du die einzelnen Farbwerte in den Grafikspeicher schreiben. Für jede Zeile kannst Du dafür die Stringbefehle des Prozessors nutzen(rep movsb). Dieses Schreiben in den Grafikspeicher hängt natürlich vom Betriebssystem ab. Unter DOS geht das direkt. Unter einem 32-Bit-OS benötigst Du entsprechende Befehle einer Grafikbibliothek, wie z.B. SDL oder DirectX. Beide unterstützen ja direkten Zugriff auf den Grafikspeicher.

    Ciao...



  • ey cool !

    ich werd mich mal an die arbeit machen und bischen rumprobieren
    ...

    danke danke !

    wenn in laufe der zeit noch was unklares auftreten sollte, meld ich mich nochmal..

    btw.: verdammt, ich hab immernoch kein buch für assembler .. 😞 !

    mfg haMMer

    [ Dieser Beitrag wurde am 03.06.2003 um 21:24 Uhr von Hammer editiert. ]



  • nochmal ne frage zur ergänzung :

    wenn ich jetz ein programm in asm schreibe ohne treiber zu verwenden und ich es
    von diskette mit einem selbstgebastelten bootloader starte, kann ich dann
    auch die bilddaten einer 8-bit-bitmap binär auf die diskette kopieren und dann
    vom programmcode aus diese daten von diskette ins RAM verschieben...?
    also ich hätte dann ein komplettes image auf diskette, welches 1. aus dem bootloader besteht, 2. aus dem programmcode und 3. aus den binären bildinformationen ..
    is das möglich ?
    wenn ja, wie greif ich dann vom code aus auf diese bilddaten zu ?
    weil ich müsste ja dann genau die stelle kennen, wo dieses bild auf der diskette abgelegt ist... so wie z.b. der bootloader inerhalb der ersten 512bytes liegt

    mfg haMMer



  • Moin, Moin...

    Natürlich ist das möglich. Der Bootloader lädt den Programmcode in den Speicher. Die Speicheradresse bestimmst Du. Also kannst Du auch die Bilddaten an eine definierte Speicheradresse schreiben. Ich kenne nun nicht die genaue Größe Deines Images, also mach ich mal so ein Beispiel:

    Nehmen wir mal an, der Programmcode ist auch 512 Byte lang. Dann liegt der Bootloader im 1. Sektor und der Programmcode in 2. Sektor. Die Bilddaten könntest Du nun in den 3. Sektor schreiben.

    Programmcode wird z.B. nach 010000h geladen (1000:0000h). Die Bilddaten könntest Du dann an Adresse 010200h (1000:0200h) schreiben. Dann bräuchtest Du keine FAR-Zeiger, um die Bilddaten zu adressieren.

    Wenn die Bilddaten Bestandteil Deines Programmcodes sind, so kannst Du sie einfach im Programm normal adressieren. Sie werden dann ja automatisch mitgeladen.

    Ciao...



  • servus nochmal..

    also ich hab jetz mal n unterprogramm hinbekommen, welches mir ein bild im
    8bit bereich an einer beliebigen stelle aufmalt .. 😉
    ich paste hier mal den code und dann wollte ich wissen, ob man den code so lassen kann oder ob das einfacher geht .. :

    SetSprite proc near
    
        push bp
        mov bp, sp
        push es
        push ax
        push bx
        push di
        push cx
    
        mov ax, 0A000h
        mov es, ax
    
        mov ax, [bp+4]          ; y-koord.
        mov bx, 320
        mul bx
        add ax, [bp+6]          ; x-koord.
        mov di, ax
        mov si, [bp+8]          ; offset vom bild
        mov bx, [bp+12]         ; länge vom bild
    
      sprite:
        mov cx, [bp+10]         ; breite vom bild
        rep movsb                    ; schiebe byte von [si] nach [di]
        cmp bx, 0
        je finish                    ; wenn bx = 0
        add di, 320                  ; springe auf nächste zeile
        sub di, [bp+10]              ; breite vom bild
        dec bx
        ja sprite                    ; wenn bx > 0
    
      finish:
        pop cx
        pop di
        pop bx
        pop ax
        pop es
        mov sp, bp
        pop bp
        ret
    
    SetSprite endp
    

    also dieses unterprogramm erhält 5 parameter:
    x- und y-koordinate, wo das bild hinkommt (upperleftcorner)
    länge vom bild
    breite vom bild
    und der offset, wo das bild im RAM steht !

    nur ich hatte das problem, wie ich 2 ineinander verschachtelte "for"-schleifen machen soll, da das cx register zum zählen verwendet wird und ich ja nur eins davon habe.. also musste ich auf cmp umsteigen und mit ja und jb weitere anweisungen geben..

    was haltet ihr von dem code..? was kann, sollte und muss man verändern ?

    desweiteren wäre ich noch dankbar wenn mir jemand einen gedankenstoss geben kann für folgende zwei probleme :

    1. wie schneide ich den hintergrund eines bildes weg, sodass er nur die figur malt und nich das komplette rechteck .. ?
    2. durch was wird die geschwindigkeit einer animation festgelegt ?
    in hochsprachen hab ich das immer mit einem delay gemacht.. aber
    wie muss ich bei asm vorgehen ?

    mfg haMMer



  • Original erstellt von Hammer:
    **1. wie schneide ich den hintergrund eines bildes weg, sodass er nur die figur malt und nich das komplette rechteck .. ?
    **

    Am einfachsten ists, wenn du eine spezielle Farbe als durchsichtig definierst. Dein Programm checkt dann halt, ob das aktuell zu zeichnende Pixel diese Farbe hat, wenn ja, wird das Pixel einfach nicht dargestellt.



  • Original erstellt von Hammer:
    **... und dann wollte ich wissen, ob man den code so lassen kann oder ob das einfacher geht ..

    1. wie schneide ich den hintergrund eines bildes weg, sodass er nur die figur malt und nich das komplette rechteck .. ?
    **

    Wie schon gesagt wurde: eine Farbe als durchsichtig definieren...
    Ein Vorschlag: (durchsichtige Farbe ist 00)

    SetSprite proc near
    
        push es
    ;diverse push gespart...
        pusha
        mov bp, sp ;Argumente bei 16+2+2=>20
        mov ax, 0A000h
        mov es, ax
    
        mov ax, 320    
        ;ein mov gespart...
        mul [word ptr bp+20]    ; y-koord.
        add ax, [bp+22]         ; x-koord.
        mov si, [bp+24]         ; offset vom bild
        mov di, ax
        mov bx, [bp+28]         ; länge vom bild
        mov bp, [bp+26]
        mov dx, 320
        sub dx, bp
    
      sprite:
        mov cx, bp         ; breite vom bild
        PixelLoop:
          lodsb
          test al, al
          jz  NoPixel
          mov [es:di],al
        NoPixel:
          inc di
          dec cx
          jnz PixelLoop 
        ;ein cmp; jxx; sub gespart...
        add di, dx                  ; springe auf nächste zeile
        dec bx
        jnz sprite                    ; wenn bx != 0
    
        popa
    ;diverse pop gespart...
        pop es
        ret
    
    SetSprite endp
    

    Original erstellt von Hammer:
    durch was wird die geschwindigkeit einer animation festgelegt ?

    Eine einfache Moeglichkeit ist, den ueber IRQ0 gesteuerten Zeitgeber bei 0000:046C zu benutzen. Das byte an selbiger Addresse wird ca. 18 mal pro Sekunde inkrementiert.
    Du kannst dir natuerlich auch direkt den int8 (IRQ0 handler) greifen (Weiterleitung an den Original handler waere dabei zu empfehlen).
    Notfalls kannst du auch die Frequenz, mit der der IRQ0 aufgerufen wird, im PIT aendern. (siehe OS-Dev-Links in FAQ)



  • huch!!

    mein assembler sagt bei pusha / popa:

    illegal instruction for selected prozessor !

    kann das sein dass mein tasm 5.0 den befehl nicht übersetzen kann ? 😕



  • hupsalaaa ..!

    hab .386 vergessen .. 🙄

    d.h. aber dass es den befehl zu beginn nich gab ...
    welcher proz-typ ist denn standardmäßig aktiv ?



  • Laut Handbuch ist Standard P8086 (8086 Instructions - wer haette das gedacht 😉 )


Anmelden zum Antworten