Versuch SDL von C nach PB "Invalid Memory Access"

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
PureProgger
Beiträge: 40
Registriert: 19.12.2006 18:38

Versuch SDL von C nach PB "Invalid Memory Access"

Beitrag von PureProgger »

Hallo,

folgendes Problem

Möchte folgende Pixelroutine mit Hilfe der SDL in PB darstellen
Gerüsst stammt aus einem Tutorial

Code: Alles auswählen

Structure SDL_Rect
  x.w
  y.w
  w.w
  h.w
EndStructure

Structure SDL_Color
 r.c
 g.c
 b.c
 unused.c
EndStructure

Structure SDL_Palette
 ncolors.l
 *colors.SDL_Color
EndStructure

; Everything in the pixel format Structure is read-only

Structure SDL_PixelFormat
 *palette.SDL_Palette
 BitsPerPixel.c
 BytesPerPixel.c
 Rloss.c
 Gloss.c
 Bloss.c
 Aloss.c
 Rshift.c
 Gshift.c
 Bshift.c
 Ashift.c
 Rmask.l
 Gmask.l
 Bmask.l
 Amask.l
 colorkey.l
 alpha.c
EndStructure

Structure SDL_Surface
 flags.l                      
 *format.SDL_PixelFormat      
 w.l
 h.l  
 pitch.w    
 pixels.l    
 offset.l    
 clip_rect.SDL_Rect   
 unused1.l    
 locked.l    
 *map.SDL_BlitMap
 format_version.l
 refcount.l
EndStructure

;These are the currently supported flags For the SDL_surface
;Available For SDL_CreateRGBSurface() Or SDL_SetVideoMode()

#SDL_SWSURFACE = $00000000 ;Surface is in system memory
#SDL_HWSURFACE = $00000001 ;Surface is in video memory
#SDL_ASYNCBLIT = $00000004 ;Use asynchronous blits If possibleProcedure.l SDL_SetVideoMode(width.l, height.l, bpp.l, flags.l)

;Available For SDL_SetVideoMode()

#SDL_ANYFORMAT  = $10000000 ;Allow any video depth/pixel-format
#SDL_HWPALETTE  = $20000000 ;Surface has exclusive palette
#SDL_DOUBLEBUF  = $40000000 ;Set up double-buffered video mode
#SDL_FULLSCREEN = $80000000 ;Surface is a full screen display
#SDL_OPENGL     = $00000002  ;Create an OpenGL rendering context
#SDL_OPENGLBLIT = $0000000A  ;Create an OpenGL rendering context And use it For blitting
#SDL_RESIZABLE  = $00000010 ;This video mode may be resized
#SDL_NOFRAME    = $00000020 ;No window caption Or edge frame

;Used internally (read-only)

#SDL_HWACCEL     = $00000100 ;Blit uses hardware acceleration
#SDL_SRCCOLORKEY = $00001000 ;Blit uses a source color key
#SDL_RLEACCELOK  = $00002000 ;Private flag
#SDL_RLEACCEL    = $00004000 ;Surface is RLE encoded
#SDL_SRCALPHA    = $00010000 ;Blit uses source alpha blending
#SDL_PREALLOC    = $01000000 ;Surface uses preallocated memory

; -----------------------------

#SDL_INIT_TIMER       = $00000001
#SDL_INIT_AUDIO       = $00000010
#SDL_INIT_VIDEO       = $00000020
#SDL_INIT_CDROM       = $00000100
#SDL_INIT_JOYSTICK    = $00000200
#SDL_INIT_NOPARACHUTE = $00100000 ; Don't catch fatal signals
#SDL_INIT_EVENTTHREAD = $00000000 ;Not supported on all OS's
#SDL_INIT_EVERYTHING  = $0000FFFF

; ------------------------------



#SDL_LIB = 0

Procedure.l Open_SDL()
    lib.l = OpenLibrary(#SDL_LIB, "SDL.dll")
    ProcedureReturn lib
EndProcedure

Procedure Close_SDL()
  CloseLibrary(#SDL_LIB)  
EndProcedure

Procedure.l SDL_Init(flags.l)
   ergebnis.l = CallCFunction(#SDL_LIB, "SDL_Init", flags)  
   ProcedureReturn ergebnis
EndProcedure

Procedure SDL_Quit()
  CallCFunction(#SDL_LIB, "SDL_Quit")  
EndProcedure

 Procedure.l SDL_SetVideoMode(width.l, height.l, bpp.l, flags.l)
   ProcedureReturn CallCFunction(#SDL_LIB, "SDL_SetVideoMode", width, height, bpp, flags)
EndProcedure
 
 
Procedure SDL_UpdateRect(*screen.SDL_Surface, x.l, y.l, w.l, h.l);
  CallCFunction(#SDL_LIB, "SDL_UpdateRect", *screen, x, y ,w, h)
EndProcedure

Procedure.l SDL_MUSTLOCK(*pSDL.SDL_Surface)  
  x = (*pSDL\offset|((*pSDL\offset & (#SDL_HWSURFACE|#SDL_ASYNCBLIT|#SDL_RLEACCEL)) <> 0))
  ProcedureReturn x
 EndProcedure
 
 Procedure.l SDL_MapRGB(*format.SDL_PixelFormat, r.c, g.c, b.c)
  ProcedureReturn CallCFunction(#SDL_LIB, "SDL_MapRGB", *format, r, g, b)
EndProcedure

Procedure.l SDL_LockSurface(*surface.SDL_Surface)
  ProcedureReturn CallCFunction(#SDL_LIB, "SDL_LockSurface", *surface)
EndProcedure

Procedure.l SDL_UnlockSurface(*surface.SDL_Surface)
  ProcedureReturn CallCFunction(#SDL_LIB, "SDL_UnlockSurface", *surface)
EndProcedure

Procedure.l SDL_Flip(*screen.SDL_Surface)
  ProcedureReturn CallCFunction(#SDL_LIB, "SDL_Flip", *screen)
EndProcedure


Procedure DrawPixel(*screen.SDL_Surface, x.l, y.l, r.c, g.c, b.c)

    bpp.c
    color = SDL_MapRGB(*screen\format, r, g, b)
          
    If SDL_MUSTLOCK(*screen) 
    
        If SDL_LockSurface(*screen) < 0 
            End
        EndIf
        
    EndIf
    
    bpp = *screen\format\BytesPerPixel
         
    Select bpp
    
        Case 1 ;vermutlich 8 Bit
            
            *bufp = (*screen\pixels) + y * (*screen\pitch) + x
            PokeB(*bufp,color)
       
        Case 2 ;/* vermutlich 15 Bit oder 16 Bit */
            
            *bufp = (*screen\pixels) + y * (*screen\pitch / 2) + x                     
            PokeW(*bufp,color)
       
        Case 4   ;/* vermutlich 32 Bit */
                    
            *bufp = (*screen\pixels) + y * (*screen\pitch / 4) + x                          
            PokeL(*bufp,color)             
                 
    EndSelect
    
    If SDL_MUSTLOCK(*screen)
    
        SDL_UnlockSurface(*screen)
        
    EndIf 
    
    SDL_UpdateRect(*screen, x, y, 1, 1);

EndProcedure

Open_SDL() 


If SDL_Init(#SDL_INIT_VIDEO|#SDL_INIT_AUDIO) = 0
 
  screen = SDL_SetVideoMode(800, 600, 32, #SDL_SWSURFACE)
  
  For y = 0 To 200
    Drawpixel(screen, 400, 300+y, 255,255,255)
  Next  
  
  Delay(1000) 

  SDL_Quit()
  
EndIf 
  
Close_SDL()
beim Zugriff auf die Speicheradresse gibt es einen "Invalid Memory Access"

in C++ sieht die Pixelfunction so aus

Code: Alles auswählen

void DrawPixel(SDL_Surface *screen, int x, int y,
Uint8 R, Uint8 G,
Uint8 B)
{
    Uint32 color = SDL_MapRGB(screen->format, R, G, B);

    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) < 0 ) {
            return;
        }
    }
    switch (screen->format->BytesPerPixel) {
        case 1: { /* vermutlich 8 Bit */
            Uint8 *bufp;

            bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
            *bufp = color;
        }
        break;

        case 2: { /* vermutlich 15 Bit oder 16 Bit */
            Uint16 *bufp;

            bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
            *bufp = color;
        }
        break;

        case 3: { /* langsamer 24-Bit-Modus, selten verwendet */
            Uint8 *bufp;

            bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3;
            if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {
                bufp[0] = color;
                bufp[1] = color >> 8;
                bufp[2] = color >> 16;
            } else {
                bufp[2] = color;
                bufp[1] = color >> 8;
                bufp[0] = color >> 16;
            }
        }
        break;

        case 4: { /* vermutlich 32 Bit */
            Uint32 *bufp;

            bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
            *bufp = color;
        }
        break;
    }
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
    }
    SDL_UpdateRect(screen, x, y, 1, 1);
}

dort wo ich mit den Poke-Befehlen auf den Speicher zugreife passiert der "Invalid Memory Access"

Jemand eine Idee, woran es liegt?

gruß Michael
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag von Kekskiller »

Könnte es vielleicht am Typ des Pointers liegen?

MSDN über UInt32:
Der Werttyp UInt32 stellt ganze Zahlen ohne Vorzeichen mit Werten zwischen 0 und 4.294.967.295 dar.
PB hats da viel eher mit Vorzeichen:
Long | .l | 4 Byte | -2147483648 bis +2147483647
Da dein nicht-deklarierter Pointer standartmäßig LONG ist, könnte das ev. ein paar Probleme geben. Ich bin mir nicht sicher, aber ev. kommst du irgendwie über das Problem weg, indem mit CopyMemory arbeitest (ja, ist langsam, aber so könnte mans besser testen).

Ich bin kein großer C++-Experte, as einmalige
(Uint32 *)screen->pixels
wundert mich ein wenig. Das sat C++ doch ohnehin nur, dass der Pointer auf UInt32-Struktur/-Class zeigt, oder? Ev. ist das auch der Fehler -> MSDN beschreibt UINT32 als Klasse, nicht als Struktur.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Lad dir mal die Demo der Linuxversion und kopiere "sdl.res" nach
/purebasic/Residents/. Kompiler neustarten und struckturviewer
benutzen, jetzt siehst du das in deiner SDL_Surface Struktur etwas
fehlt :D .

Ich tippe mal darauf das du ne alte Header Datei benutzt aber
sdl 1.2.xx
PureProgger
Beiträge: 40
Registriert: 19.12.2006 18:38

Beitrag von PureProgger »

Sorry,

möchte das unter Windows lösen und nicht extra Linux ziehen um dann die res zu durchsuchen /:->

Benutze Version 1.2.11 und habe auch die C-Headerdateien durchsucht!

Hatte einen Wert vergessen, aber trotzdem gleiches Problem
Er will nicht in den Speicherbereich schreiben!

Aber trotzdem danke für die bisherigen Antworten :)

Gruß Michael
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

>> möchte das unter Windows lösen und nicht extra Linux ziehen um dann die res zu durchsuchen
<offtopic>
Die SDL.dll unter Windows ist lediglich ein GDI Wrapper. Wenn Du also nicht
planst es irgendwann nach Linux zu portieren, stellt die Nutzung von SDL in
meinen Augen, nur ein kastrieren Deines Programmes dar :mrgreen:
</offtopic>
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

@PureProgger

Nein du hast mich falsch verstanden. Diese Datei solltest du unter
Windows installieren. Damit stehen dir saemtliche Konstanten und
Strukturen direkt unter PureBasic zur Verfuegung.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8814
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Muss das .c in der Struktur nicht .b heißen? Also statt Character ein Byte?
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Die SDL.dll unter Windows ist lediglich ein GDI Wrapper.

Wie sicher bist Du Dir da? Ich dachte eigentlich daß SDL auf DirectX zugreift, kann mich aber auch täuschen.

EDIT: Es gibt ja auch die Konstante #SDL_HWACCEL, da würde ich nicht vermuten, daß die mit GDI arbeitet... :?
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

@ZeHa
Hab das so im engl. Forum gelesen. Fred hat das Wohl geäußert, als die
Diskussion um SDL für PB unter Windows ging.
Im Grunde auch egal, die DLL bietet nichts, was nicht ohne sie schon in PB
(notfalls per API) verfügbar ist.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
PureProgger
Beiträge: 40
Registriert: 19.12.2006 18:38

Beitrag von PureProgger »

Hi Nic,

das .c ist ein char-type richtig, aber gleichzeitig liegt der als unsigned byte im Speicher!

ts-soft

Les mal hier nach

http://www.libsdl.org

gruß Michael
Antworten