pointer mess (help, please!)

Windows specific forum
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by mindplay.

I'm writing a pattern system for a tracker, but something's not right with some of my pointer management ... could someone take a look at this please? I commented everything to give you an idea of what I'm trying to do - briefly explained:

"StepStruct" is the structure type for one step, i.e. one note + effect command + whatever else I decide to put in there ... for now, it's just one byte named "value", just for testing.

An ordinary array of "PatternStruct" structures is created to hold up to #MaxPatterns number of patterns. Each "PatternStruct" in this array contains a pointer to the "StepStruct" items of each pattern, and the number of rows (NumRows) - the number of channels is global for all patterns ("NumTracks") ...

When a pattern is initialized, memory is allocated for SizeOf(StepStruct) * number of tracks * number of rows.

The problem seems to be the SetNumTracks procedure, which is supposed to convert all the patterns in memory to a new number of tracks - something goes wrong here, as you can tell from the readout. Comment out the call to SetNumTracks, and it works fine - but that's not necessarily because the rest is correct, the StepPtr procedure could very well return bad pointers, or not return them the correct way, I don't know - I get very confused with all these pointers ...

anyway, here's the code...

Code: Select all

; Pattern Data Include

#BaseMemoryID.l = 1

#MaxPatterns.l = 256 ; max. possible number of patterns

NumTracks.l = 8 ; global number of tracks (for all patterns)

Structure StepStruct
  Value.b
EndStructure

Structure PatternStruct
  *DataPtr.l ; pointer to the memory area that contains StepStruct's
  NumRows.l ; number of rows in this pattern
EndStructure

Dim Patterns.PatternStruct(#MaxPatterns) ; the last pattern is reserved for 

Procedure InitPatternEx(aPatNum.l, aNumRows.l, aNumTracks.l)
  ; Allocate the required amount of memory for the StepStruct's of a pattern,
  ; using a given number of tracks, rather than the global NumTracks
  Global Patterns, StepStruct
  AllocateMemory(#BaseMemoryID+1+aPatNum, SizeOf(StepStruct)*NumRows*aNumTracks, 0)
  Patterns(aPatNum)\DataPtr = MemoryID()
  Patterns(aPatNum)\NumRows = aNumRows
EndProcedure

Procedure InitPattern(aPatNum.l, aNumRows.l)
  ; Allocate the required amount of memory for the StepStruct's of a pattern,
  ; using the global number of tracks (NumTracks)
  Global NumTracks
  InitPatternEx(aPatNum, aNumRows, NumTracks)
EndProcedure

Procedure.l StepPtr(aPatNum.l, aTrack.l, aRow.l)
  ; Calculates and returns a pointer to a specific StepStruct within a pattern
  Global Patterns, StepStruct, NumTracks
  Offset.l = SizeOf(StepStruct)*(aRow*NumTracks+aTrack)
  ProcedureReturn Patterns(aPatNum)\DataPtr + Offset
EndProcedure

Procedure.l StepPtrEx(aPatNum.l, aTrack.l, aRow.l, aNumTracks.l)
  ; Calculates and returns a pointer to a specific StepStruct within a pattern,
  ; using a specified number of tracks for calculation, rather than the global NumTracks
  Global Patterns, StepStruct
  Offset.l = SizeOf(StepStruct)*(aRow*aNumTracks+aTrack)
  ProcedureReturn Patterns(aPatNum)\DataPtr + Offset
EndProcedure

Procedure SetNumTracks(NewNumTracks.l)
  ; Change the number of tracks in all patterns
  Global Patterns, StepStruct, NumTracks
  DefType.StepStruct *src, *dst
  For PatNum = 0 To #MaxPatterns-1
    If Patterns(PatNum)\DataPtr  0
      ; create temporary work pattern with same number of rows as original pattern
      InitPattern(#MaxPatterns, Patterns(PatNum)\NumRows)
      ; copy original pattern into temporary work pattern
      CopyMemory(@Patterns(PatNum)\DataPtr, @Patterns(#MaxPatterns)\DataPtr, SizeOf(StepStruct) * Patterns(PatNum)\NumRows * NumTracks)
      ; resize original pattern
      InitPatternEx(PatNum, Patterns(PatNum)\NumRows, NewNumTracks)
      ; copy each step manually from temporary pattern into original pattern
      If NewNumTracks>NumTracks
        LastTrack = NumTracks-1
      Else ; If NewNumTracks

by the way, I'm very confused by the help files - the word "MemoryID" seems to be used both about memory handles and actual pointers! very confusing ... like in AllocateMemory, for example, you have to supply a "MemoryID" which is a memory handle (i.e. a number of your own choice, by which you will identify the memory block) - but at the same time, the function MemoryID() returns NOT a "MemoryID" as in the previous definition, but a POINTER to the ACTUAL memory block ... am I the only one who finds this really, really confusing?? :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

MemoryID() returns a pointer to the last allocated memory, it's not a handle.

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by mindplay.

Yeah, that's what I said - but it's confusing that a pointer is referred to as a "MemoryID", when obviously it's a pointer, and not an ID of any sort. The Memory# that you specify for AllocateMemory, for example, is an ID - an identifier, not a pointer. And MemoryID() returns a pointer - not an identifier. You see what I mean? :)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by mindplay.

okay, I debugged everything manually, by writing out every pointer in every routine to the debug output ... two solid hours of hard work - man, I'm an idiot when it comes to pointers :)
Post Reply