Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Clarification using _MEM
#1
In the wiki under _MEM is this:

TYPE memory_type
  OFFSET AS _OFFSET      'start location of block(changes with byte position)
  SIZE AS _OFFSET        'size of block remaining at offset(changes with position)
  TYPE AS _OFFSET        'type description of variable used(never changes)
  ELEMENTSIZE AS _OFFSET  'byte size of values inside the block(never changes)
  IMAGE AS LONG          'the image handle used when _MEMIMAGE(handle) is used
  SOUND AS LONG          'the sound handle used when _MEMSOUND(handle) is used
END TYPE

I'm interested in using SIZE to determine how much of the memory block is left to process, if that's possible.

I'm getting an image's memory location:

MemBlock = _MEMIMAGE(ImageHandle)

Then getting its offset:

Offset = MemBlock.OFFSET

Then iterating through the memory block:

DO
    _MEMGET MemBlock, Offset, Pixel
    'other code here
    _MEMPUT Memblock, Offset, Pixel
    Offset = Offset + 4
LOOP UNTIL MemBlock.SIZE = 4 ' (or perhaps 0?)

However MemBlock.SIZE never changes in value as I navigate through the memory block. What does the wiki mean by stating " size of block remaining at offset(changes with position) "?

Any help would be appreciated. I'm delving into the MEM statements and making great progress but this has me baffled.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply
#2
The OFFSET is the location of the MEM block. The SIZE is how big the MEM block is at that OFFSET. Think of OFFSET doing the same thing as _OFFSET(yourMemBlock). You could take your current position and subtract it from the size to see how much you have left. If the offset is 62349, for instance, and the size is 32, you can know that 62381 should be the end of the MEM block. I'm probably not explaining this coherently, but I hope it helps a bit. I don't think size is supposed to be marked as something that changes. That might be a typo.
Tread on those who tread on you

Reply
#3
(01-23-2024, 06:52 PM)TerryRitchie Wrote: However MemBlock.SIZE never changes in value as I navigate through the memory block. What does the wiki mean by stating " size of block remaining at offset(changes with position) "?

Any help would be appreciated. I'm delving into the MEM statements and making great progress but this has me baffled.
The comment on the definition is a little odd, maybe there's a situation where you can get a new _MEM that is offset from the original but I don't know of it.

That said I wouldn't read into it too much, `_MEM` works like any regular UDT except that the it's read-only. The logic `Offset = MemBlock.OFFSET` and `Offset = Offset + 4` only modifies the `Offset` variable you created, it has no impact on the original `_MEM` variable.
Reply
#4
Try this out and see if it doesn't help you figure out what's going on:

Code: (Select All)
Dim m As _MEM
Dim a(100) As Long '404 byte
m = _Mem(a()) 'mem pointed at a()

For i = 0 To 10
Print i, m.SIZE 'note that this never changes
Next
Sleep

For i = 0 To 10
m = _Mem(a(i)) 'but now notice what we see here
Print i, m.SIZE
Next


the SIZE is basically how much reserved space is available at that point where you're referencing it.

Now, if m is always pointing to offset 0, then you will always have the full size returned to you.

But now, if you notice what happens when I moved the offset to various positions via _MEM(a(i)), you'll see that value changes.

Honestly, I don't know *why* I'd ever want to get the mem.SIZE from element 4 to the end, but that's how it works. Seems like all I'd ever work with would either be mem.ELEMENTSIZE for a particular element, or else I'd just calculate that figure myself.

To tell the truth, I don't think I'd ever even noticed that it behaves the way it actually does here. LOL -- It's not something I've ever made use of, that's for certain! Wink

(01-23-2024, 07:12 PM)DSMan195276 Wrote:
(01-23-2024, 06:52 PM)TerryRitchie Wrote: However MemBlock.SIZE never changes in value as I navigate through the memory block. What does the wiki mean by stating " size of block remaining at offset(changes with position) "?

Any help would be appreciated. I'm delving into the MEM statements and making great progress but this has me baffled.
The comment on the definition is a little odd, maybe there's a situation where you can get a new _MEM that is offset from the original but I don't know of it.

That said I wouldn't read into it too much, `_MEM` works like any regular UDT except that the it's read-only. The logic `Offset = MemBlock.OFFSET` and `Offset = Offset + 4` only modifies the `Offset` variable you created, it has no impact on the original `_MEM` variable.

With arrays.   Point to an element in an array and the SIZE changes depending upon that element.  Seems odd to me, but that's just the way it's always been.  /shrug   See my demo above.  Wink
Reply
#5
(01-23-2024, 07:21 PM)SMcNeill Wrote: With arrays.   Point to an element in an array and the SIZE changes depending upon that element.  Seems odd to me, but that's just the way it's always been.  /shrug   See my demo above.  Wink
I suppose I was picturing the `_OFFSET` and `SIZE` in the existing `_MEM` being changed (since the comment says "changes"). Your code example doesn't change the original `_MEM` instance, it's creating new ones for each `_Mem()` call that you will then have to then `_MemFree`.
Reply
#6
Ok, thank for the replies guys, that does make sense. I wrote a subroutine the makes a negative image (inspired by another recent post) and wanted to see how small and fast I could make it. Here is what I have:

Code: (Select All)
' _______________________________________________________________________________________________________
'/                                                                                                       \
SUB __Negative (i AS LONG) '                                                                  __Negative |
    ' ___________________________________________________________________________________________________|___
    '/                                                                                                       \
    '| Creates a negative image                                                                              |
    '|                                                                                                       |
    '| i - the image to work with                                                                            |
    '\_______________________________________________________________________________________________________/

    DIM MemBlock AS _MEM '           memory block holding image data
    DIM Offset AS _OFFSET '          pixel location within memory block
    DIM Pixel AS _UNSIGNED LONG '    pixel data at pixel location
    DIM Size AS LONG '               total number of pixels

    Size = _WIDTH(i) * _HEIGHT(i) '       calculate number of total pixels
    MemBlock = _MEMIMAGE(i) '             set memory block to image data
    Offset = MemBlock.OFFSET '            get start position of memory block
    $CHECKING:OFF
    DO '                                  begin pixel count
        _MEMGET MemBlock, Offset, Pixel ' get pixel data from memory block
        Pixel = 16777215 XOR Pixel '      make negative (only RGB is affected, not alpha)
        _MEMPUT MemBlock, Offset, Pixel ' update pixel color in memory block
        Offset = Offset + 4 '             next pixel location in buffer
        Size = Size - 1 '                 decrement pixels remaining
    LOOP UNTIL Size = 0 '                 leave when no pixels remain
    _MEMFREE MemBlock '                   free memory block
    $CHECKING:ON

END SUB
As you can see I use a variable named Size that calculates the total number of pixels and then use that as a count down within the loop. I thought I could use .SIZE to achieve this same result and remove another variable from my subroutine.
There are two ways to write error-free programs; only the third one works.
QB64 Tutorial
Reply




Users browsing this thread: 1 Guest(s)