ImageGadgetEx()
Posted: Sat Sep 27, 2008 12:48 am
ImageGadgetEx is a PureBasic image gadget with an enhancement: It can contain a regular image or an image with alpha transparency. It works seamlessly for the programmer, you just use SetGadgetState as usual and pass either a normal image or an alpha image and the gadget does the rest. The DrawAlphaImage() command is not used here as I was able to achieve a faster alternative. iirc, (subject to correction by team) DrawAlphaImage takes a copy of the image, premultiplies the color bytes with the alpha values and passes the premultiplied copy to AlphaBlend_(), all of which takes time. In my solution, I'm keeping a list of previously-rendered images and saving the premultiplied copies. If the procedure receives an image to render that it has drawn before, the premultiplication step is skipped which results in a considerable saving in time. In speed tests where the same image is redrawn many times, my AlphaRender routine is approx. 8x faster than DrawAlphaImage (here, anyway.) It is an ideal approach for this application imho as an imagegadget gets repainted often and the repaints should happen as fast as possible. Another difference between my routine and DrawAlphaImage is that mine will handle a normal image as well. If you use DrawAlphaImage and pass it a 24-bit bmp, you will see nothing. Because I wanted my imagegadget to accept anything, I coded mine so that the AlphaRender routine would detect the lack of alpha values and switch to BitBlt_() where needed.
Use these images for the test: http://www.lloydsplace.com/chessimages.zip
It's early going, so please report any bugs or omissions.
Also, in testing the performance I found a huge difference between the debugger on and debugger off so if you have a large alpha image for the gadget and it feels a bit sluggish make sure you try with the debugger turned off, which is going to be the case for release software anyway.
Here it is:
Test program:
Use these images for the test: http://www.lloydsplace.com/chessimages.zip
It's early going, so please report any bugs or omissions.
Also, in testing the performance I found a huge difference between the debugger on and debugger off so if you have a large alpha image for the gadget and it feels a bit sluggish make sure you try with the debugger turned off, which is going to be the case for release software anyway.
Here it is:
Code: Select all
;==========================================================
; Library Command: ImageGadgetEx
; Author: Lloyd Gallant (netmaestro)
; Date: September 24, 2008
; Target OS: Microsoft Windows all
; Target Compiler: PureBasic 4.0 and later
; License: Free, unrestricted, no warranty
;==========================================================
Prototype AlphaBlend(hdcDest,DestX,DestY,DestW,DestH,hdcSrc,SrcX,SrcY,SrcW,SrcH,BLENDFUNCTION)
Procedure PreMultiply(image)
; netmaestro 2008
; Helper function for AlphaRender
imgout = CopyImage_(image, #IMAGE_BITMAP, 0, 0, #LR_CREATEDIBSECTION)
GetObject_(imgout, SizeOf(BITMAP), bmp.BITMAP)
If bmp\bmBitsPixel <> 32
ProcedureReturn image
ElseIf bmp\bmBits = 0
ProcedureReturn 0
EndIf
alphasfound=#False
*bits.RGBQUAD = bmp\bmBits
For i=0 To bmp\bmHeight-1
For j=0 To bmp\bmWidthBytes-1 Step 4
*px.RGBQUAD = *bits + bmp\bmWidthBytes * i + j
If *px\rgbReserved > 0: alphasfound=#True : EndIf
*px\rgbBlue = *px\rgbBlue & $FF * *px\rgbReserved & $FF / $FF
*px\rgbGreen = *px\rgbGreen & $FF * *px\rgbReserved & $FF / $FF
*px\rgbRed = *px\rgbRed & $FF * *px\rgbReserved & $FF / $FF
Next
Next
If alphasfound
ProcedureReturn imgout
Else
DeleteObject_(imgout)
ProcedureReturn image
EndIf
EndProcedure
Procedure AlphaRender(imgIn, imgDest, x, y)
; netmaestro 2008
; Alternative to DrawAlphaImage()
Structure Index
original.l ; contains handles of all previously-rendered images
premult.l ; contains handles of premultiplied copies
EndStructure
Static firstrun = 1
If firstrun
Static NewList image.Index()
firstrun = 0
EndIf
imgSrc = 0
ForEach image()
If image()\original = ImgIn
ImgSrc = image()\premult
Break
EndIf
Next
If Not imgSrc
imgSrc = Premultiply(imgIn)
AddElement(image())
image()\original = imgIn
image()\premult = imgSrc
EndIf
hdcScreen = CreateDC_("DISPLAY",0,0,0)
hdcDest = CreateCompatibleDC_(hdcScreen)
hdcSrc = CreateCompatibleDC_(hdcScreen)
SelectObject_(hdcSrc, imgSrc)
SelectObject_(hdcDest, imgDest)
GetObject_(imgSrc, SizeOf(BITMAP), bmpSrc.BITMAP)
msimg32 = OpenLibrary(#PB_Any, "msimg32.dll")
AlphaBlend_.AlphaBlend = GetFunction(msimg32, "AlphaBlend")
If msimg32=0 Or bmpSrc\bmBitsPixel < 32 Or imgIn = image()\premult
BitBlt_(hdcDest,x,y,bmpSrc\bmWidth,bmpSrc\bmHeight,hdcSrc,0,0,#SRCCOPY)
result = 2
Else
result=AlphaBlend_(hdcDest,x,y,bmpSrc\bmWidth,bmpSrc\bmHeight,hdcSrc,0,0,bmpSrc\bmWidth,bmpSrc\bmHeight,$1FF0000)
EndIf
DeleteObject_(bmpSrc)
DeleteDC_(hdcScreen)
DeleteDC_(hdcSrc)
DeleteDC_(hdcDest)
If IsLibrary(msimg32)
CloseLibrary(msimg32)
EndIf
ProcedureReturn result
EndProcedure
Procedure ige_ImageProc(hwnd, msg, wparam, lparam)
oldproc = GetProp_(hwnd, "ige_oldproc")
ctrlid = GetDlgCtrlID_(hwnd)
Select msg
Case #WM_NCDESTROY
RemoveProp_(hwnd, "ige_oldproc")
Case #WM_PAINT
dcParent = GetDC_(GetParent_(hwnd))
hdc = BeginPaint_(hwnd, ps.PAINTSTRUCT)
If GetGadgetState(ctrlid)
GetObject_(GetGadgetState(ctrlid),SizeOf(BITMAP), bmp.BITMAP)
w = bmp\bmWidth
h = bmp\bmHeight
base = CreateImage(#PB_Any,w,h,#PB_Image_DisplayFormat)
dcOut = StartDrawing(ImageOutput(base))
; take a snapshot of the window background where the image will show
If GetWindowLong_(hwnd, #GWL_EXSTYLE) & #WS_EX_CLIENTEDGE
offset = GetSystemMetrics_(#SM_CXEDGE)
Else
offset = 0
EndIf
BitBlt_(dcOut, 0,0,ImageWidth(base),ImageHeight(base),dcParent,GadgetX(ctrlid)+offset,GadgetY(ctrlid)+offset,#SRCCOPY)
StopDrawing()
ReleaseDC_(GetParent_(hwnd), dcParent)
; draw the alpha image onto it
AlphaRender(GetGadgetState(ctrlid),ImageID(base),0,0)
; render background & image together on the window
dcIn = StartDrawing(ImageOutput(base))
BitBlt_(hdc, 0,0,ImageWidth(base),ImageHeight(base),dcIn,0,0,#SRCCOPY)
StopDrawing()
FreeImage(base)
EndIf
EndPaint_(hwnd, ps)
ProcedureReturn 0
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure ImageGadgetEx(gadgetnumber,x,y,width,height,imageID=0,flags=0)
If gadgetnumber = #PB_Any
ige_ctrlid = ImageGadget(#PB_Any,x,y,width,height,0,flags)
ige_hwnd = GadgetID(ige_ctrlid)
result = ige_ctrlid
Else
ige_hwnd = ImageGadget(gadgetnumber,x,y,width,height,0,flags)
ige_ctrlid = gadgetnumber
result = ige_hwnd
EndIf
oldproc = SetWindowLong_(ige_hwnd,#GWL_WNDPROC,@ige_ImageProc())
SetProp_(ige_hwnd, "ige_oldproc", oldproc)
SetGadgetState(ige_ctrlid,imageID)
ProcedureReturn result
EndProcedure
Code: Select all
IncludeFile "imagegadgetex.pbi"
#offset = 34
#size = 64
Structure SQUARE
ctrlid.l ; gadget number
x.l ; x coordinate
y.l ; y coordinate
name.s{2} ; square name, e.g. "A1", etc.
EndStructure
Global rgn_bishop = ExtCreateRegion_(0,?rgn_bishopend-?rgn_bishop, ?rgn_bishop)
Global rgn_knight = ExtCreateRegion_(0,?rgn_knightend-?rgn_knight, ?rgn_knight)
Global hand = LoadCursor_(0, #IDC_HAND), arrow = LoadCursor_(0, #IDC_ARROW)
Global activeimage, activeregion, move_active, offs_x, offs_y, boardimage_in, boardimage_out, tid
boardimage_in = CreateImage(#PB_Any, 580, 580, #PB_Image_DisplayFormat)
UsePNGImageDecoder()
Global bkg = CatchImage(#PB_Any, ?bkg, ?bkgend-?bkg)
bishop = CatchImage(#PB_Any, ?bishop, ?bishopend-?bishop)
knight = CatchImage(#PB_Any, ?knight, ?knightend-?knight)
Global NewList squares.SQUARE()
For j=7 To 0 Step -1
For i=0 To 7
AddElement(squares())
With squares()
\ctrlid = 0
\x = #offset + (i*64)
\y = #offset + ((7-j)*64)
\name = Chr(65+i)+Chr(49+j)
EndWith
Next
Next
Procedure FindSquare(square$)
ForEach squares()
If squares()\name = square$
ProcedureReturn @squares()
EndIf
Next
ProcedureReturn -1
EndProcedure
Procedure GrabBoard(ctrlid)
tmp = GrabImage(bkg,#PB_Any,GadgetX(ctrlid),GadgetY(ctrlid),64,64)
hdcIn = GetDC_(WindowID(0))
hdcOut = StartDrawing(ImageOutput(boardimage_in))
BitBlt_(hdcOut,0,0,580,580,hdcIn,0,0,#SRCCOPY)
DrawImage(ImageID(tmp),GadgetX(ctrlid),GadgetY(ctrlid))
StopDrawing()
FreeImage(tmp)
ReleaseDC_(WindowID(0),hdcIn)
EndProcedure
Procedure PieceMove_Thread(ctrlid)
ExamineDesktops()
OptimalDelay = 1000/DesktopFrequency(0)
timeGetDevCaps_(tc.TIMECAPS, SizeOf(TIMECAPS))
timeBeginPeriod_(tc\wPeriodMin)
With boardrect.RECT
\left = WindowX(0)+#offset+5
\top = WindowY(0)+#offset+25
\right = \left+506
\bottom = \top+506
EndWith
ClipCursor_(boardrect)
SetGadgetState(ctrlid, 0)
While move_active
t1 = timeGetTime_()
mouse_x = lparam>>16
mouse_y = lparam&$FFFF
boardimage_out = GrabImage(boardimage_in,#PB_Any,0,0,580,580)
AlphaRender(activeimage,ImageID(boardimage_out),WindowMouseX(0)-offs_x,WindowMouseY(0)-offs_y)
StartDrawing(WindowOutput(0))
DrawImage(ImageID(boardimage_out),0,0)
StopDrawing()
FreeImage(boardimage_out)
drawingtime = timeGetTime_()-t1
Delay(Int(Abs(OptimalDelay-drawingtime)))
Wend
timeEndPeriod_(tc\wPeriodMin)
EndProcedure
Procedure ImageProc(hwnd, msg, wparam, lparam)
oldproc = GetProp_(hwnd, "oldproc")
ctrlid = GetDlgCtrlID_(hwnd)
Select msg
Case #WM_NCDESTROY
RemoveProp_(hwnd, "oldproc")
Case #WM_SETCURSOR
rgn = GetProp_(hwnd, "region")
GetCursorPos_(cp.point)
MapWindowPoints_(0,hwnd, cp,1)
If PtInRegion_(rgn, cp\x+4, cp\y)
SetCursor_(hand)
ProcedureReturn #True
Else
SetCursor_(arrow)
EndIf
Case #WM_LBUTTONDOWN
rgn = GetProp_(hwnd, "region") ; get the square's region for hittesting
GetCursorPos_(cp.point) ; do the hittest
MapWindowPoints_(0,hwnd, cp,1) ; "
If PtInRegion_(rgn, cp\x+4, cp\y) ; "
SetCapture_(WindowID(0)) ; transfer mouse messages to parent window for the move
offs_x = cp\x : offs_y = cp\y ; store cursor offsets for when parent draws the moved piece
activeimage = GetGadgetState(ctrlid) ; save imageid to drop on target square
activeregion = rgn ; save region to store in target square
SetProp_(hwnd, "region", 0) ; remove region from this square
GrabBoard(ctrlid) ; get current board image minus the moving piece
move_active = #True ; set global var to indicate a move in progress
tid = CreateThread(@PieceMove_Thread(),ctrlid) ; start the move thread
ThreadPriority(tid, 17) ; give it above-normal priority
EndIf
ProcedureReturn 0
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure WindowProc(hwnd, msg, wparam, lparam)
result = #PB_ProcessPureBasicEvents
Select msg
Case #WM_SETCURSOR
If move_active
SetCursor_(hand)
ProcedureReturn #True
EndIf
Case #WM_LBUTTONUP
If move_active
ReleaseCapture_()
move_active = #False
ClipCursor_(0)
targetsquare = GetDlgCtrlID_(ChildWindowFromPoint_(WindowID(0),WindowMouseX(0),WindowMouseY(0)))
WaitThread(tid)
StartDrawing(WindowOutput(0))
DrawImage(ImageID(boardimage_in),0,0)
StopDrawing()
SetGadgetState(targetsquare, 0)
SetGadgetState(targetsquare, activeimage)
SetProp_(GadgetID(targetsquare), "region", activeregion)
EndIf
EndSelect
ProcedureReturn result
EndProcedure
hBrush = CreatePatternBrush_(ImageID(bkg))
OpenWindow(0,0,0,580,580,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_Invisible)
SetWindowCallback(@WindowProc())
CompilerIf #PB_Compiler_Version <= 420 : CreateGadgetList(WindowID(0)) : CompilerEndIf
SetClassLong_(WindowID(0),#GCL_HBRBACKGROUND,hBrush)
InvalidateRect_(WindowID(0),0,1)
ForEach squares()
cc+1
With squares()
\ctrlid = cc: ImageGadgetEx(cc, \x, \y, #size, #size, 0)
SetProp_(GadgetID(cc), "oldproc", SetWindowLong_(GadgetID(cc),#GWL_WNDPROC,@ImageProc()))
EndWith
Next
; Place a bishop on C1
FindSquare("C1")
SetGadgetState(squares()\ctrlid, ImageID(bishop))
SetProp_(GadgetID(squares()\ctrlid), "region", rgn_bishop)
; Place a knight on B1
FindSquare("B1")
SetGadgetState(squares()\ctrlid, ImageID(knight))
SetProp_(GadgetID(squares()\ctrlid), "region", rgn_knight)
HideWindow(0,0)
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
DeleteObject_(hBrush)
DataSection
; Images
bishop: IncludeBinary "bishop.png" : bishopend:
knight: IncludeBinary "knight.png" : knightend:
bkg: IncludeBinary "board_grain.png" : bkgend:
; Regions
rgn_bishop:
Data.b $20,$00,$00,$00,$01,$00,$00,$00,$3D,$00,$00,$00,$D0,$03,$00,$00
Data.b $07,$00,$00,$00,$05,$00,$00,$00,$3E,$00,$00,$00,$3A,$00,$00,$00
Data.b $20,$00,$00,$00,$05,$00,$00,$00,$25,$00,$00,$00,$06,$00,$00,$00
Data.b $1F,$00,$00,$00,$06,$00,$00,$00,$26,$00,$00,$00,$07,$00,$00,$00
Data.b $1E,$00,$00,$00,$07,$00,$00,$00,$27,$00,$00,$00,$09,$00,$00,$00
Data.b $1D,$00,$00,$00,$09,$00,$00,$00,$28,$00,$00,$00,$0A,$00,$00,$00
Data.b $1E,$00,$00,$00,$0A,$00,$00,$00,$28,$00,$00,$00,$0B,$00,$00,$00
Data.b $1E,$00,$00,$00,$0B,$00,$00,$00,$27,$00,$00,$00,$0E,$00,$00,$00
Data.b $1D,$00,$00,$00,$0E,$00,$00,$00,$28,$00,$00,$00,$0F,$00,$00,$00
Data.b $1B,$00,$00,$00,$0F,$00,$00,$00,$1C,$00,$00,$00,$10,$00,$00,$00
Data.b $1D,$00,$00,$00,$0F,$00,$00,$00,$28,$00,$00,$00,$10,$00,$00,$00
Data.b $29,$00,$00,$00,$0F,$00,$00,$00,$2A,$00,$00,$00,$10,$00,$00,$00
Data.b $1B,$00,$00,$00,$10,$00,$00,$00,$2A,$00,$00,$00,$11,$00,$00,$00
Data.b $18,$00,$00,$00,$11,$00,$00,$00,$2C,$00,$00,$00,$12,$00,$00,$00
Data.b $18,$00,$00,$00,$12,$00,$00,$00,$2D,$00,$00,$00,$13,$00,$00,$00
Data.b $17,$00,$00,$00,$13,$00,$00,$00,$2E,$00,$00,$00,$14,$00,$00,$00
Data.b $16,$00,$00,$00,$14,$00,$00,$00,$2F,$00,$00,$00,$15,$00,$00,$00
Data.b $14,$00,$00,$00,$15,$00,$00,$00,$30,$00,$00,$00,$16,$00,$00,$00
Data.b $14,$00,$00,$00,$16,$00,$00,$00,$31,$00,$00,$00,$17,$00,$00,$00
Data.b $13,$00,$00,$00,$17,$00,$00,$00,$31,$00,$00,$00,$18,$00,$00,$00
Data.b $14,$00,$00,$00,$18,$00,$00,$00,$31,$00,$00,$00,$1A,$00,$00,$00
Data.b $13,$00,$00,$00,$1A,$00,$00,$00,$32,$00,$00,$00,$1B,$00,$00,$00
Data.b $14,$00,$00,$00,$1B,$00,$00,$00,$32,$00,$00,$00,$1C,$00,$00,$00
Data.b $14,$00,$00,$00,$1C,$00,$00,$00,$31,$00,$00,$00,$1D,$00,$00,$00
Data.b $13,$00,$00,$00,$1D,$00,$00,$00,$31,$00,$00,$00,$1E,$00,$00,$00
Data.b $14,$00,$00,$00,$1E,$00,$00,$00,$31,$00,$00,$00,$1F,$00,$00,$00
Data.b $15,$00,$00,$00,$1F,$00,$00,$00,$31,$00,$00,$00,$20,$00,$00,$00
Data.b $14,$00,$00,$00,$20,$00,$00,$00,$30,$00,$00,$00,$21,$00,$00,$00
Data.b $16,$00,$00,$00,$21,$00,$00,$00,$30,$00,$00,$00,$22,$00,$00,$00
Data.b $16,$00,$00,$00,$22,$00,$00,$00,$2F,$00,$00,$00,$23,$00,$00,$00
Data.b $18,$00,$00,$00,$23,$00,$00,$00,$2E,$00,$00,$00,$24,$00,$00,$00
Data.b $18,$00,$00,$00,$24,$00,$00,$00,$2D,$00,$00,$00,$25,$00,$00,$00
Data.b $19,$00,$00,$00,$25,$00,$00,$00,$2C,$00,$00,$00,$26,$00,$00,$00
Data.b $18,$00,$00,$00,$26,$00,$00,$00,$2D,$00,$00,$00,$27,$00,$00,$00
Data.b $16,$00,$00,$00,$27,$00,$00,$00,$2E,$00,$00,$00,$29,$00,$00,$00
Data.b $17,$00,$00,$00,$29,$00,$00,$00,$2F,$00,$00,$00,$2C,$00,$00,$00
Data.b $17,$00,$00,$00,$2C,$00,$00,$00,$2E,$00,$00,$00,$2D,$00,$00,$00
Data.b $0D,$00,$00,$00,$2D,$00,$00,$00,$0E,$00,$00,$00,$2E,$00,$00,$00
Data.b $12,$00,$00,$00,$2D,$00,$00,$00,$14,$00,$00,$00,$2E,$00,$00,$00
Data.b $19,$00,$00,$00,$2D,$00,$00,$00,$2D,$00,$00,$00,$2E,$00,$00,$00
Data.b $0C,$00,$00,$00,$2E,$00,$00,$00,$15,$00,$00,$00,$2F,$00,$00,$00
Data.b $1C,$00,$00,$00,$2E,$00,$00,$00,$2A,$00,$00,$00,$2F,$00,$00,$00
Data.b $30,$00,$00,$00,$2E,$00,$00,$00,$39,$00,$00,$00,$2F,$00,$00,$00
Data.b $09,$00,$00,$00,$2F,$00,$00,$00,$17,$00,$00,$00,$30,$00,$00,$00
Data.b $1B,$00,$00,$00,$2F,$00,$00,$00,$3B,$00,$00,$00,$30,$00,$00,$00
Data.b $09,$00,$00,$00,$30,$00,$00,$00,$3C,$00,$00,$00,$31,$00,$00,$00
Data.b $08,$00,$00,$00,$31,$00,$00,$00,$3D,$00,$00,$00,$32,$00,$00,$00
Data.b $08,$00,$00,$00,$32,$00,$00,$00,$3E,$00,$00,$00,$33,$00,$00,$00
Data.b $07,$00,$00,$00,$33,$00,$00,$00,$3D,$00,$00,$00,$34,$00,$00,$00
Data.b $09,$00,$00,$00,$34,$00,$00,$00,$3D,$00,$00,$00,$35,$00,$00,$00
Data.b $08,$00,$00,$00,$35,$00,$00,$00,$3C,$00,$00,$00,$36,$00,$00,$00
Data.b $0A,$00,$00,$00,$36,$00,$00,$00,$22,$00,$00,$00,$37,$00,$00,$00
Data.b $24,$00,$00,$00,$36,$00,$00,$00,$3C,$00,$00,$00,$37,$00,$00,$00
Data.b $09,$00,$00,$00,$37,$00,$00,$00,$11,$00,$00,$00,$38,$00,$00,$00
Data.b $16,$00,$00,$00,$37,$00,$00,$00,$21,$00,$00,$00,$38,$00,$00,$00
Data.b $25,$00,$00,$00,$37,$00,$00,$00,$2F,$00,$00,$00,$38,$00,$00,$00
Data.b $35,$00,$00,$00,$37,$00,$00,$00,$3B,$00,$00,$00,$38,$00,$00,$00
Data.b $0B,$00,$00,$00,$38,$00,$00,$00,$0F,$00,$00,$00,$39,$00,$00,$00
Data.b $19,$00,$00,$00,$38,$00,$00,$00,$1E,$00,$00,$00,$39,$00,$00,$00
Data.b $27,$00,$00,$00,$38,$00,$00,$00,$2C,$00,$00,$00,$39,$00,$00,$00
Data.b $37,$00,$00,$00,$38,$00,$00,$00,$3B,$00,$00,$00,$39,$00,$00,$00
Data.b $0B,$00,$00,$00,$39,$00,$00,$00,$0E,$00,$00,$00,$3A,$00,$00,$00
Data.b $38,$00,$00,$00,$39,$00,$00,$00,$3A,$00,$00,$00,$3A,$00,$00,$00
rgn_bishopend:
rgn_knight:
Data.b $20,$00,$00,$00,$01,$00,$00,$00,$43,$00,$00,$00,$30,$04,$00,$00
Data.b $08,$00,$00,$00,$04,$00,$00,$00,$3E,$00,$00,$00,$3A,$00,$00,$00
Data.b $14,$00,$00,$00,$04,$00,$00,$00,$15,$00,$00,$00,$05,$00,$00,$00
Data.b $1F,$00,$00,$00,$04,$00,$00,$00,$21,$00,$00,$00,$05,$00,$00,$00
Data.b $13,$00,$00,$00,$05,$00,$00,$00,$18,$00,$00,$00,$06,$00,$00,$00
Data.b $1E,$00,$00,$00,$05,$00,$00,$00,$23,$00,$00,$00,$06,$00,$00,$00
Data.b $13,$00,$00,$00,$06,$00,$00,$00,$19,$00,$00,$00,$07,$00,$00,$00
Data.b $1D,$00,$00,$00,$06,$00,$00,$00,$24,$00,$00,$00,$07,$00,$00,$00
Data.b $13,$00,$00,$00,$07,$00,$00,$00,$1A,$00,$00,$00,$08,$00,$00,$00
Data.b $1D,$00,$00,$00,$07,$00,$00,$00,$23,$00,$00,$00,$08,$00,$00,$00
Data.b $12,$00,$00,$00,$08,$00,$00,$00,$1B,$00,$00,$00,$09,$00,$00,$00
Data.b $1C,$00,$00,$00,$08,$00,$00,$00,$25,$00,$00,$00,$09,$00,$00,$00
Data.b $12,$00,$00,$00,$09,$00,$00,$00,$24,$00,$00,$00,$0A,$00,$00,$00
Data.b $13,$00,$00,$00,$0A,$00,$00,$00,$28,$00,$00,$00,$0B,$00,$00,$00
Data.b $13,$00,$00,$00,$0B,$00,$00,$00,$29,$00,$00,$00,$0C,$00,$00,$00
Data.b $2A,$00,$00,$00,$0B,$00,$00,$00,$2C,$00,$00,$00,$0C,$00,$00,$00
Data.b $14,$00,$00,$00,$0C,$00,$00,$00,$2E,$00,$00,$00,$0D,$00,$00,$00
Data.b $13,$00,$00,$00,$0D,$00,$00,$00,$30,$00,$00,$00,$0E,$00,$00,$00
Data.b $12,$00,$00,$00,$0E,$00,$00,$00,$31,$00,$00,$00,$0F,$00,$00,$00
Data.b $11,$00,$00,$00,$0F,$00,$00,$00,$32,$00,$00,$00,$10,$00,$00,$00
Data.b $11,$00,$00,$00,$10,$00,$00,$00,$33,$00,$00,$00,$11,$00,$00,$00
Data.b $10,$00,$00,$00,$11,$00,$00,$00,$33,$00,$00,$00,$12,$00,$00,$00
Data.b $10,$00,$00,$00,$12,$00,$00,$00,$34,$00,$00,$00,$13,$00,$00,$00
Data.b $10,$00,$00,$00,$13,$00,$00,$00,$35,$00,$00,$00,$14,$00,$00,$00
Data.b $0F,$00,$00,$00,$14,$00,$00,$00,$36,$00,$00,$00,$16,$00,$00,$00
Data.b $0F,$00,$00,$00,$16,$00,$00,$00,$37,$00,$00,$00,$17,$00,$00,$00
Data.b $0F,$00,$00,$00,$17,$00,$00,$00,$38,$00,$00,$00,$19,$00,$00,$00
Data.b $0E,$00,$00,$00,$19,$00,$00,$00,$39,$00,$00,$00,$1A,$00,$00,$00
Data.b $0D,$00,$00,$00,$1A,$00,$00,$00,$39,$00,$00,$00,$1C,$00,$00,$00
Data.b $0C,$00,$00,$00,$1C,$00,$00,$00,$3A,$00,$00,$00,$1D,$00,$00,$00
Data.b $0B,$00,$00,$00,$1D,$00,$00,$00,$3A,$00,$00,$00,$1E,$00,$00,$00
Data.b $0B,$00,$00,$00,$1E,$00,$00,$00,$3B,$00,$00,$00,$1F,$00,$00,$00
Data.b $0A,$00,$00,$00,$1F,$00,$00,$00,$3B,$00,$00,$00,$20,$00,$00,$00
Data.b $09,$00,$00,$00,$20,$00,$00,$00,$3B,$00,$00,$00,$21,$00,$00,$00
Data.b $09,$00,$00,$00,$21,$00,$00,$00,$3C,$00,$00,$00,$22,$00,$00,$00
Data.b $08,$00,$00,$00,$22,$00,$00,$00,$23,$00,$00,$00,$23,$00,$00,$00
Data.b $24,$00,$00,$00,$22,$00,$00,$00,$3C,$00,$00,$00,$23,$00,$00,$00
Data.b $08,$00,$00,$00,$23,$00,$00,$00,$21,$00,$00,$00,$24,$00,$00,$00
Data.b $24,$00,$00,$00,$23,$00,$00,$00,$3C,$00,$00,$00,$24,$00,$00,$00
Data.b $08,$00,$00,$00,$24,$00,$00,$00,$1F,$00,$00,$00,$25,$00,$00,$00
Data.b $24,$00,$00,$00,$24,$00,$00,$00,$3D,$00,$00,$00,$25,$00,$00,$00
Data.b $09,$00,$00,$00,$25,$00,$00,$00,$1D,$00,$00,$00,$26,$00,$00,$00
Data.b $23,$00,$00,$00,$25,$00,$00,$00,$3D,$00,$00,$00,$26,$00,$00,$00
Data.b $09,$00,$00,$00,$26,$00,$00,$00,$1C,$00,$00,$00,$27,$00,$00,$00
Data.b $1D,$00,$00,$00,$26,$00,$00,$00,$1F,$00,$00,$00,$27,$00,$00,$00
Data.b $23,$00,$00,$00,$26,$00,$00,$00,$3D,$00,$00,$00,$27,$00,$00,$00
Data.b $09,$00,$00,$00,$27,$00,$00,$00,$1B,$00,$00,$00,$28,$00,$00,$00
Data.b $1C,$00,$00,$00,$27,$00,$00,$00,$1D,$00,$00,$00,$28,$00,$00,$00
Data.b $21,$00,$00,$00,$27,$00,$00,$00,$3D,$00,$00,$00,$28,$00,$00,$00
Data.b $08,$00,$00,$00,$28,$00,$00,$00,$1C,$00,$00,$00,$29,$00,$00,$00
Data.b $20,$00,$00,$00,$28,$00,$00,$00,$3D,$00,$00,$00,$29,$00,$00,$00
Data.b $08,$00,$00,$00,$29,$00,$00,$00,$1A,$00,$00,$00,$2A,$00,$00,$00
Data.b $1F,$00,$00,$00,$29,$00,$00,$00,$3D,$00,$00,$00,$2A,$00,$00,$00
Data.b $09,$00,$00,$00,$2A,$00,$00,$00,$19,$00,$00,$00,$2B,$00,$00,$00
Data.b $1E,$00,$00,$00,$2A,$00,$00,$00,$3E,$00,$00,$00,$2B,$00,$00,$00
Data.b $0B,$00,$00,$00,$2B,$00,$00,$00,$18,$00,$00,$00,$2C,$00,$00,$00
Data.b $1D,$00,$00,$00,$2B,$00,$00,$00,$3E,$00,$00,$00,$2C,$00,$00,$00
Data.b $0B,$00,$00,$00,$2C,$00,$00,$00,$17,$00,$00,$00,$2D,$00,$00,$00
Data.b $18,$00,$00,$00,$2C,$00,$00,$00,$19,$00,$00,$00,$2D,$00,$00,$00
Data.b $1C,$00,$00,$00,$2C,$00,$00,$00,$3E,$00,$00,$00,$2D,$00,$00,$00
Data.b $0C,$00,$00,$00,$2D,$00,$00,$00,$16,$00,$00,$00,$2E,$00,$00,$00
Data.b $1B,$00,$00,$00,$2D,$00,$00,$00,$3E,$00,$00,$00,$2E,$00,$00,$00
Data.b $0F,$00,$00,$00,$2E,$00,$00,$00,$14,$00,$00,$00,$2F,$00,$00,$00
Data.b $1A,$00,$00,$00,$2E,$00,$00,$00,$3E,$00,$00,$00,$2F,$00,$00,$00
Data.b $1A,$00,$00,$00,$2F,$00,$00,$00,$3E,$00,$00,$00,$31,$00,$00,$00
Data.b $19,$00,$00,$00,$31,$00,$00,$00,$3E,$00,$00,$00,$33,$00,$00,$00
Data.b $18,$00,$00,$00,$33,$00,$00,$00,$3E,$00,$00,$00,$37,$00,$00,$00
Data.b $17,$00,$00,$00,$37,$00,$00,$00,$3E,$00,$00,$00,$39,$00,$00,$00
Data.b $18,$00,$00,$00,$39,$00,$00,$00,$3E,$00,$00,$00,$3A,$00,$00,$00
rgn_knightend:
EndDataSection