Code archives/Miscellaneous/PeekPoke Module for B3D/B+

This code has been declared by its author to be Public Domain code.

Download source code

PeekPoke Module for B3D/B+ by markcw
(Posted 20 years ago)
I was using BLTZMEM.dll by zjpierre until I read jfk's post about RtlMoveMemory and wrote this. The main advantages of using this module are no need for an extra dll and shorter function names.

Create a file in your userlibs folder called "peekpoke.decls"
.lib "Kernel32.dll"

;Win32 Decls, Memory Management Functions
Api_RtlMoveToBank(Destination*,Source,Length):"RtlMoveMemory"
Api_RtlMoveToMemory(Destination,Source*,Length):"RtlMoveMemory"
;Api_RtlFillMemory(Destination,Length,Fill):"RtlFillMemory"
;Api_RtlZeroMemory(Destination,Length):"RtlZeroMemory"

;PeekPoke Module Decls
PeekB%(address)
PeekS%(address)
PeekI%(address)
PeekF#(address)
PokeB(address,value)
PokeS(address,value)
PokeI(address,value)
PokeF(address,value#)
MemoryLog(address,ByteLength,filename$)

Save this code entry as "peekpoke.bb" and then include it in your main program. Examples are shown below.
;PeekPoke Module for B3D/B+
;Author: markcw, edited 15 Mar 2008
;Allows direct memory access via Kernel32.dll
;Create a file in your userlibs folder called "peekpoke.decls"

;.lib "Kernel32.dll"
;
;;Win32 Decls, Memory Management Functions
;Api_RtlMoveToBank(Destination*,Source,Length):"RtlMoveMemory"
;Api_RtlMoveToMemory(Destination,Source*,Length):"RtlMoveMemory"
;;Api_RtlFillMemory(Destination,Length,Fill):"RtlFillMemory"
;;Api_RtlZeroMemory(Destination,Length):"RtlZeroMemory"
;
;;PeekPoke Module Decls
;PeekB%(address)
;PeekS%(address)
;PeekI%(address)
;PeekF#(address)
;PokeB(address,value)
;PokeS(address,value)
;PokeI(address,value)
;PokeF(address,value#)
;MemoryLog(address,ByteLength,filename$)

;This global has a long name to avoid a conflict
Global Kernel32PeekPokeBank=CreateBank(4) ;Bank for memory access

Function PeekB(address) ;PeekByte
 Api_RtlMoveToBank(Kernel32PeekPokeBank,address,1)
 Return PeekByte(Kernel32PeekPokeBank,0)
End Function

Function PeekS(address) ;PeekShort
 Api_RtlMoveToBank(Kernel32PeekPokeBank,address,2)
 Return PeekShort(Kernel32PeekPokeBank,0)
End Function

Function PeekI(address) ;PeekInteger
 Api_RtlMoveToBank(Kernel32PeekPokeBank,address,4)
 Return PeekInt(Kernel32PeekPokeBank,0)
End Function

Function PeekF#(address) ;PeekFloat
 Api_RtlMoveToBank(Kernel32PeekPokeBank,address,4)
 Return PeekFloat(Kernel32PeekPokeBank,0)
End Function

Function PokeB(address,value) ;PokeByte
 PokeByte Kernel32PeekPokeBank,0,value
 Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,1)
End Function

Function PokeS(address,value) ;PokeShort
 PokeShort Kernel32PeekPokeBank,0,value
 Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,2)
End Function

Function PokeI(address,value) ;PokeInteger
 PokeInt Kernel32PeekPokeBank,0,value
 Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,4)
End Function

Function PokeF(address,value#) ;PokeFloat
 PokeFloat Kernel32PeekPokeBank,0,value#
 Api_RtlMoveToMemory(address,Kernel32PeekPokeBank,4)
End Function

;MemoryLog Functions

Function MemoryLog(address,ByteLength,filename$="memorylog.txt")
 ;Writes a memory log text file, useful if you're searching for offsets
 ;address -> where to start from, ByteLength -> length to copy
 Local file,id,value,count,array$
 file=WriteFile(filename$)
 For id=0 To (ByteLength/4)-1 ;Write the line
  MemoryLogValue(file,address) : WriteByte(file,43) ;Write "address+"
  MemoryLogValue(file,id Shl 2) : WriteByte(file,32) ;Write "offset "
  WriteByte(file,123) : WriteByte(file,32) ;Write "{ "
  value=PeekI(address)
  MemoryLogValue(file,value) : WriteByte(file,32) ;Write "Int "
  WriteByte(file,58) : WriteByte(file,32) ;Write ": "
  For count=0 To 3 Step 2 ;2 shorts
   value=PeekS(address+count)
   MemoryLogValue(file,value) ;Write "Short"
   If count=0 Then WriteByte(file,44) ;Write ","
   If count=2 Then WriteByte(file,32) ;Write " " if last
  Next
  WriteByte(file,58) : WriteByte(file,32) ;Write ": "
  For count=0 To 3 ;4 bytes
   value=PeekB(address+count)
   MemoryLogValue(file,value) ;Write "Byte"
   If count<3 Then WriteByte(file,44) ;Write ","
   If count=3 Then WriteByte(file,32) ;Write " " if last
  Next
  WriteByte(file,58) : WriteByte(file,32) ;Write ": "
  For count=0 To 3 ;4 chars
   value=PeekB(address+count)
   WriteByte(file,value) ;Write "Char"
  Next
  WriteByte(file,32) : WriteByte(file,58) ;Write " :"
  array$=Str(PeekF(address))
  WriteByte(file,32) : MemoryLogString(file,array$) ;Write " Float"
  WriteByte(file,32) : WriteByte(file,125) ;Write " }"
  WriteByte(file,13) : WriteByte(file,10) ;Write "EOL"
  address=address+4 ;Get the next 4 bytes
 Next
 array$="Address  { Int : Short : Byte : Char : Float }"
 MemoryLogString(file,array$) ;Write info string
 WriteByte(file,13) : WriteByte(file,10) ;Write "EOL"
 CloseFile file
End Function

Function MemoryLogValue(file,value)
 ;Writes an ascii byte, short or integer
 Local stringarray$,id,char$
 stringarray$=Str(value)
 For id=1 To Len(stringarray$)
  char$=Mid(stringarray$,id,1)
  WriteByte(file,Asc(char$))
 Next
End Function

Function MemoryLogString(file,stringarray$)
 ;Writes an ascii string
 Local id,char$
 For id=1 To Len(stringarray$)
  char$=Mid(stringarray$,id,1)
  WriteByte(file,Asc(char$))
 Next
End Function

Comments

markcw
(Posted 20 years ago)
This example is for b3d. It looks at the structure of an image in memory and then pokes the pixels with random colors.

I have done a speed test with this method versus WritePixelFast and it is twice as slow. I assume this is because you need to pass the value to a bank and then to memory. I also tested passing to a bank per pixel and then passing the whole image in one go with RTL_MoveMemory and it still wasn't as fast as WritePixelFast although it was very close.

;PeekPoke Example, for Blitz3D

Include "peekpoke.bb" ;PeekPoke Module

Graphics 640,480,0,2
SetBuffer BackBuffer()

load=0 ;Flag to load or create an image
If load=1
 image=LoadImage("test.bmp")
Else
 width=100
 height=63
 frames=1
 image=CreateImage(width,height,frames)
EndIf

BufferList=PeekI(image+4) ;pImageBufferList
BufferListEnd=PeekI(image+8) ;pImageBufferListEnd
numframes=(BufferListEnd-BufferList)/4 ;Number of image frames

buffer=ImageBuffer(image,0)
pImageBuffer=PeekI(BufferList+(0*4)) ;pImageBuffer[frame]

LockBuffer buffer ;LockBuffer to return a pointer to the pixels
UnlockBuffer buffer
DDSurface7=PeekI(buffer+12) ;pImageDDSurface7
PixelData=PeekI(buffer+72) ;pImagePixelData
WidthImage=PeekI(buffer+92) ;ImageWidth
HeightImage=PeekI(buffer+96) ;ImageHeight

DrawImageText(Str(0),image,0)

If GraphicsDepth()=32
 pitch=(((width*8)+127)/128)*16 ;16 bit-aligned
 For iy=1 To height-2
  offset=(pitch*iy) Shl 2
  For ix=1 To width-2
   pixel=BGRA(Rand(255),Rand(255),Rand(255))
   PokeI(PixelData+offset+(ix Shl 2),pixel)
  Next
 Next
ElseIf GraphicsDepth()=16
 pitch=(((width*8)+255)/256)*32 ;32-bit aligned
 For iy=1 To height-2
  offset=(pitch*iy) Shl 1
  For ix=1 To width-2
   pixel=BGR16(Rand(255),Rand(255),Rand(255))
   PokeS(PixelData+offset+(ix Shl 1),pixel)
  Next
 Next
EndIf

While Not KeyDown(1) ;Esc key
 Cls

 Text 0,0,"width="+width+" height="+height+" frames="+frames
 Text 0,12,"image="+image
 Text 0,36,"BufferList="+BufferList
 Text 0,48,"BufferListEnd="+BufferListEnd
 Text 0,60,"numframes="+numframes
 Text 0,84,"buffer="+buffer
 Text 0,96,"pImageBuffer="+pImageBuffer
 Text 0,120,"DDSurface7="+DDSurface7
 Text 0,132,"PixelData="+PixelData
 Text 0,144,"WidthImage="+WidthImage
 Text 0,156,"HeightImage="+HeightImage
 Text 0,168,"pitch="+pitch

 DrawImage image,MouseX()-width,MouseY()-height

 Flip
Wend
End

Function BGRA(blue,green,red,alpha=$FF)
 ;Converts BGRA to a 32-bit value, alpha is optional
 Return ((alpha Shl 24) Or (red Shl 16) Or (green Shl 8) Or blue)
End Function

Function BGR16(blue,green,red)
 ;Converts BGR to a 16-bit value
 Return ((red Shr 3 Shl 11) Or (green Shr 2 Shl 5) Or (blue Shr 3))
End Function

Function DrawImageText(textstr$,image,frame=0)
 ;Draw frame number on image
 Local buffer=GraphicsBuffer()
 SetBuffer ImageBuffer(image,frame)
 ClsColor 255,255,255 : Cls
 Color 255,0,0 : Text 0,0,textstr$
 ClsColor 0,0,0 : Color 255,255,255
 SetBuffer buffer
End Function


markcw
(Posted 20 years ago)
This example is for b+. It does the same as the b3d example above. You can see the structure of a b+ image is different to b3d.

;PeekPoke Example, for BlitzPlus

Include "peekpoke.bb" ;PeekPoke Module

windowx=(ClientWidth(Desktop())-640)/2
windowy=(ClientHeight(Desktop())-480)/2
window=CreateWindow("",windowx,windowy,640,480,0,1+2+32)
canvas=CreateCanvas(0,0,640,480,window)
SetBuffer CanvasBuffer(canvas)

load=0 ;Flag to load or create an image
If load=1
 image=LoadImage("test.bmp")
Else
 width=100
 height=63
 frames=1
 image=CreateImage(width,height,frames)
EndIf

BufferList=PeekI(image+28) ;pImageBufferList
NumFrames=PeekI(image+52) ;ImageFrames

buffer=ImageBuffer(image,0)
pImageBuffer=PeekI(BufferList+(0*4)) ;pImageBuffer[frame]

LockBuffer buffer ;LockBuffer to return a pointer to the pixels
UnlockBuffer buffer
WidthImage=PeekI(buffer+172) ;ImageWidth
HeightImage=PeekI(buffer+176) ;ImageHeight
DDSurface7=PeekI(buffer+192) ;pImageDDSurface7
PixelData=PeekI(buffer+220) ;pImagePixelData

DrawImageText(Str(0),image,0)

If GraphicsDepth()=32
 pitch=(((width*8)+127)/128)*16 ;16 bit-aligned
 For iy=1 To height-2
  offset=(pitch*iy) Shl 2
  For ix=1 To width-2
   pixel=BGRA(Rand(255),Rand(255),Rand(255))
   PokeI(PixelData+offset+(ix Shl 2),pixel)
  Next
 Next
ElseIf GraphicsDepth()=16
 pitch=(((width*8)+255)/256)*32 ;32-bit aligned
 For iy=1 To height-2
  offset=(pitch*iy) Shl 1
  For ix=1 To width-2
   pixel=BGR16(Rand(255),Rand(255),Rand(255))
   PokeS(PixelData+offset+(ix Shl 1),pixel)
  Next
 Next
EndIf

While Not KeyDown(1) ;Esc key
 If WaitEvent(0)=$803 Then End ;Close button
 Cls

 Text 0,0,"width="+width+" height="+height+" frames="+frames
 Text 0,12,"image="+image
 Text 0,36,"BufferList="+BufferList
 Text 0,48,"NumFrames="+NumFrames
 Text 0,72,"buffer="+buffer
 Text 0,84,"pImageBuffer="+pImageBuffer
 Text 0,108,"WidthImage="+WidthImage
 Text 0,120,"HeightImage="+HeightImage
 Text 0,132,"DDSurface7="+DDSurface7
 Text 0,144,"PixelData="+PixelData
 Text 0,156,"pitch="+pitch

 DrawImage image,MouseX(canvas)-width,MouseY(canvas)-height

 FlipCanvas canvas
Wend
End

Function BGRA(blue,green,red,alpha=$FF)
 ;Converts BGRA to a 32-bit value, alpha is optional
 Return ((alpha Shl 24) Or (red Shl 16) Or (green Shl 8) Or blue)
End Function

Function BGR16(blue,green,red)
 ;Converts BGR to a 16-bit value
 Return ((red Shr 3 Shl 11) Or (green Shr 2 Shl 5) Or (blue Shr 3))
End Function

Function DrawImageText(textstr$,image,frame=0)
 ;Draw frame number on image
 Local buffer=GraphicsBuffer()
 SetBuffer ImageBuffer(image,frame)
 ClsColor 255,255,255 : Cls
 Color 255,0,0 : Text 0,0,textstr$
 ClsColor 0,0,0 : Color 255,255,255
 SetBuffer buffer
End Function


Code Archives Forum