The MASM Forum

General => The Campus => Topic started by: zedd151 on February 26, 2025, 03:08:52 PM

Title: FloodFill and ExtFloodFill
Post by: zedd151 on February 26, 2025, 03:08:52 PM
I have been working on using gdi32 drawing functions to use instead of bitmaps for my tic tac toe game.
I now have all of the bimaps removed from the game. All of the drawing issues have been resolved.

(https://i.postimg.cc/QxHTDF17/untitled.png)
No Title bar, no movable borders. You close the program with the ESC key.  :wink2:  Plain and simple.
I might add an ini file, for the user to select their own color for X and O. This image shows another variation of contrasting colors for X and O.
Title: Re: FloodFill and ExtFloodFill
Post by: sinsi on February 26, 2025, 03:31:30 PM
Can't you just draw a line using a wide pen? For the X.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 26, 2025, 03:39:36 PM
Quote from: sinsi on February 26, 2025, 03:31:30 PMCan't you just draw a line using a wide pen? For the X.
I have not.   :sad: I was spending way too much time trying to figure the FloodFill problems out.
What would the 'points' of the X look like, I hope not rounded.
I'll try that when I get back inside, to see how it looks.
Title: Re: FloodFill and ExtFloodFill
Post by: sinsi on February 26, 2025, 03:41:02 PM
Quote from: zedd151 on February 26, 2025, 03:39:36 PMWhat would the 'points' of the X look like
Think of a thick texta (sharpie?)
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 26, 2025, 03:44:54 PM
Quote from: sinsi on February 26, 2025, 03:41:02 PM
Quote from: zedd151 on February 26, 2025, 03:39:36 PMWhat would the 'points' of the X look like
Think of a thick texta (sharpie?)
Okay. If needed I could always put in a coupla lines to make the points less round and more square like the bitmap.
I'll post my progress in a little while.  :smiley:

It never dawned on me to try it. I did think about using extra large fonts though.
Speaking of fonts, I used to have a bootleg copy of Font Creator. You could design your own fonts, even from a bitmap.  :biggrin:  I might just explore that possibility, if this doesn't look very good using wide pen..
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 26, 2025, 04:03:38 PM
Dunno if it'll help, but I have my own flood-fill routine I could post that you could try. Works for me.
Title: Re: FloodFill and ExtFloodFill
Post by: sinsi on February 26, 2025, 04:25:57 PM
Quote from: zedd151 on February 26, 2025, 03:44:54 PMIt never dawned on me to try it.
First thing I thought of :biggrin:

Flashbacks to drawing on a 320x200x256 VGA screen on a 386sx. Everything.
None of this fancy Windows drawing stuff.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 26, 2025, 04:41:09 PM
It needs a little tweaking, but I can live with that.

Thanks, sinsi. That works much better, it will look even better after a few adjustments.


Quote from: sinsi on February 26, 2025, 04:25:57 PM
Quote from: zedd151 on February 26, 2025, 03:44:54 PMIt never dawned on me to try it.
First thing I thought of :biggrin:

Flashbacks to drawing on a 320x200x256 VGA screen on a 386sx. Everything.
None of this fancy Windows drawing stuff.
I never had to suffer such Phun.
Title: Re: FloodFill and ExtFloodFill
Post by: sinsi on February 26, 2025, 04:49:59 PM
The new X looks friendlier :badgrin:
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 26, 2025, 05:01:09 PM
Quote from: NoCforMe on February 26, 2025, 04:03:38 PMDunno if it'll help, but I have my own flood-fill routine I could post that you could try. Works for me.

I totally missed your post earlier. Sorry.
Sure, you only need to post the essential bits. I won't need a full blown example. At least I don't think I will.

Quote from: sinsi on February 26, 2025, 04:49:59 PMThe new X looks friendlier :badgrin:
Why do you fear the old style?  :greensml:
I still need to tweak it so it looks 'right' next to the O's.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 01:47:45 AM
I just had another overnight epiphany while I slept, sinsi.  :biggrin:

Why the hell don't I now use the thick pen to also draw the "O", so it will look much better when side by side with the new and improved "X".

Last night, I was thinking about making the X (created with a thick pen), look better and match it to the O, which was created using filled ellipses.

Kinda like making an apple look like an orange.  :joking:

Amazing what a little sleep can do, to restore common sense, or at least better thought processes.  :biggrin:

Title: Re: FloodFill and ExtFloodFill
Post by: daydreamer on February 27, 2025, 02:18:01 AM
Quote from: zedd151 on February 26, 2025, 03:44:54 PM
Quote from: sinsi on February 26, 2025, 03:41:02 PM
Quote from: zedd151 on February 26, 2025, 03:39:36 PMWhat would the 'points' of the X look like
Think of a thick texta (sharpie?)
Okay. If needed I could always put in a coupla lines to make the points less round and more square like the bitmap.
I'll post my progress in a little while.  :smiley:

It never dawned on me to try it. I did think about using extra large fonts though.
Speaking of fonts, I used to have a bootleg copy of Font Creator. You could design your own fonts, even from a bitmap.  :biggrin:  I might just explore that possibility, if this doesn't look very good using wide pen..
I am using code that changes font to bigger size in my unicode chess,so big 'X' and 'O' could be used
 
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 02:22:07 AM
Quote from: daydreamer on February 27, 2025, 02:18:01 AMI am using code that changes font to bigger size in my unicode chess,so big 'X' and 'O' could be used
 
I have considered that possibilty as well. I am currently working on a different approach, though.   :biggrin:
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 02:43:05 AM
YaY! I got 'er done.Thanks again sinsi for a simple solution. I like simplicity. But I still wonder why I had issues with FloodFill and ExtFloodFill.

    DrawX proc hDC:dword, color:dword, x:dword, y:dword
    local hPen:dword, hPenOld:dword
        invoke CreatePen, PS_SOLID, 20, red
        mov hPen, eax
        invoke SelectObject, hDC, hPen
        mov hPenOld, eax
        mov ecx, x
        mov edx, y
        add ecx, 26
        add edx, 26
        invoke MoveToEx, hDC, ecx, edx, 0
        mov ecx, x
        add ecx, 112
        mov edx, y
        add edx, 112
        invoke LineTo, hDC, ecx, edx
        mov ecx, x
        add ecx, 112
        mov edx, y
        add edx, 26
        invoke MoveToEx, hDC, ecx, edx, 0
        mov ecx, x
        mov edx, y
        add ecx, 26
        add edx, 112
        invoke LineTo, hDC, ecx, edx
        invoke SelectObject, hDC, hPenOld
        invoke DeleteObject, hPen
        ret
    DrawX endp

    DrawO proc hDC:dword, hback:dword, hfill:dword, x:dword, y:dword
    local hPen:dword
        invoke SelectObject, hDC, hback
        invoke CreatePen, PS_SOLID, 18, blue
        mov hPen, eax
        invoke SelectObject, hDC, hPen
        add x, 32
        mov eax, x
        add eax, 96
        add y, 32
        mov ecx, y
        add ecx, 96
        invoke Ellipse, hDC, x, y, eax, ecx
        ret
    DrawO endp

So that issue is still unresolved. I must have spent the better part of half a day messing around trying to get either of those to behave.
Title: Re: FloodFill and ExtFloodFill
Post by: raymond on February 27, 2025, 05:33:05 AM
Have you ever considered using the CreatePolygonRgn and FillRgn functions with two regions, one for each the oblique parts of the X.

It would fill the center part of the X twice but who cares!
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 05:34:18 AM
Quote from: raymond on February 27, 2025, 05:33:05 AMHave you ever considered using the CreatePolygonRgn and FillRgn functions with two regions, one for each the oblique parts of the X.

It would fill the center part of the X twice but who cares!

I had never used that, since I don't know how. I didn't fully understand the docs I read online about it. Simply using a thick pen seems to work sufficiently for my purposes. But thanks for the suggestion.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 11:01:02 AM
After making some pen size and positioning adjustments, I think it looks pretty good now.

I will proceed to replace that bitmap as well, with other gdi32 drawing functions.  :azn:
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 27, 2025, 04:17:51 PM
If you want to play around with my homebrew flood-fill code, it's attached here.

It's not ready to roll: it was created for an app of mine that used a bitmap consisting of 1-byte pixels (actually a cursor bitmap), so you'd have to adapt it to your usage.

And it operates on a bitmap in memory, not on a GDI "object", so you'd have to adapt that as well.

However, it does show the technique of flood-filling, which is actually pretty simple:
When I figure out how to post a damn picture here properly I'll do that.

Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 27, 2025, 05:54:56 PM
[quote author=NoCforMe link=msg=136367 date=1740633471]
And it operates on a bitmap in memory, not on a GDI "object", so you'd have to adapt that as well.
A bitmap created with CreateCompatibleBitmap? but that is a gdi object. what else is there? Load a bitmap using LoadBitmap and draw on it? I don't get it. Just draw to a correctly sized array, then blit it somehow onto the device context?

QuoteWhen I figure out how to post a damn picture here properly I'll do that.
This might help.
If not, what issues are you having posting pix?
https://masm32.com/board/index.php?msg=136368 (https://masm32.com/board/index.php?msg=136368)
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 28, 2025, 07:26:45 AM
OK, now that I've finally figured out how to properly post a pic:

Here's the flood-fill algo in nutshell:
You start at the starting pixel (x,y) passed in to the function.
For each pixel, you look at its four non-diagonal neighbors:

(https://i.postimg.cc/wvL6h5Fm/4-neighbors.gif)

If any of those pixels are not the fill color (the color you want the shape to be flooded with), you change them to that color and then you recursively process each of those pixels, looking at its four neighbors, and so on.

Since you're recursively processing pixels, the routine will automatically expand to fill the entire interior space of the shape you want to fill.

You stop when you reach a pixel that is already the fill color, which will be either just a stray interior pixel or one of the boundary pixels. Therefore, the routine will stop when it hits the boundary. (You also need to handle the "edge" cases, literally, where you're on the edge of the bitmap. This happens when either x or y is equal to zero or is equal to the size (horizontal or vertical) of the bitmap minus one.)

Since it's recursive, you need to make sure you have enough stack space available. This usually won't be a problem unless you're processing very large bitmaps.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 07:30:22 AM
That still doesn't tell me where and how to use this.  :undecided:
I just need a small code snippet, where your little function is called from.
And exactly what the flood fill will be applied to...
I barely grasp gdi32 stuff. This (what you posted) is unknown to me as well.

I'm all thumbs when working on unknown material.
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 28, 2025, 08:31:11 AM
OK, I'll make a post about GDI, bitmaps, etc.
Warning: it's a bit complicated.
However, it's not rocket surgery. Can be understood by the average programmer.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 08:32:46 AM
Quote from: NoCforMe on February 28, 2025, 08:31:11 AMOK, I'll make a post about GDI, bitmaps, etc.
Warning: it's a bit complicated.
However, it's not rocket surgery. Can be understood by the average programmer.
I think I could handle it.
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 08:46:50 AM
Quote from: zedd151 on February 28, 2025, 07:30:22 AMThat still doesn't tell me where and how to use this.  :undecided:
I just need a small code snippet, where your little function is called from.
And exactly what the flood fill will be applied to...
I barely grasp gdi32 stuff. This (what you posted) is unknown to me as well.

I'm all thumbs when working on unknown material.
Would you like to try drawing a window with something like DirectDraw?  It's only a couple of lines of code (especially with DDraw) and then the screen is yours and Windows behaves.  You can even write to the primary surface if you like, yet it is still just a window, with nothing to be wary of.

I am saying that if you want to get into it without all those costly GDI calls, the program seems to be a couple of nice hires shapes and nine coordinates, a call to create a primary surface, and a surface lock.  In essence this is a bitmap but without ANY calls to make it a bitmap.  Even your Xs and 0s are literally two simple shapes you could draw out on paper first.

This would probably cut the size of the program AND your effort significantly. It's not scary.  I even have easy boilerplate code if you would like.  Nothing tricky.

Let's turn those thumbs into coding shears!
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 28, 2025, 08:52:50 AM
DirectDraw? I guess I'm all ears.
This doesn't require COM or anything fancy like that, does it?
Is it a standard Windows API?
Yes, GDI is somewhat clunky and a pain in the ass.
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 09:14:59 AM
NoC,

COM is a Windows call with your interface pointer as the #1 parameter.  Literally, that's it!  I studied DirectDraw for over a year to find what makes it tick.  Most of it (almost all, actually) is nearly useless, but the thing it has is that primary surface screen access.  With screen access I can SSE or AVX-blit a 4k screen 60x/sec without even stressing the machine.  That's a 32-meg screen.

Also, DirectDraw is the last DirectX to let you do that.  With it you can do what Windows does.

GDI is really convoluted at times.  The technique I am talking about is not at all.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 09:38:11 AM
Quote from: satpro on February 28, 2025, 08:46:50 AMI even have easy boilerplate code if you would like.  Nothing tricky.
Okay, I'm game. Lets see your stuff.  :biggrin:
You must have been attaching that while I was posting.
; ==================================================================================================
;                                       DIRECTDRAW
; ==================================================================================================

align 16
EXPORT uhd_DDraw:       ; minimal DirectDraw startup to get at the primary surface

; -----

; create a stack frame
    sub rsp, 28h                        ; an aligned stack frame w/ pre-allocated param space

; -----  Enter  -----


    xor ecx, ecx                        ; p1: 0 (param1 for the DirectDrawCreateEx function)

; zero the DDraw interface pointers while there is a register = 0
    mov [pp_DD7], rcx                   ; + zero the top-level interface ptr
    mov [pp_Front], rcx                 ; + zero the front surface interface ptr

; create a DirectDraw7 COM instance 
    lea rdx, pp_DD7                     ; p2: address of the instance pptr
    lea r8, IID_DD7                     ; p3: address of the IDirectDraw7 interface GUID
    xor r9, r9                          ; p4: 0
    call DirectDrawCreateEx             ; creates the DDraw COM instance
        or eax, eax
        hint.nobranch jnz << Winc64Error

; set up to use as a windowed, borderless app with a system-memory Screenbuffer
    mov rcx, [pp_DD7]                   ; *this
    xor edx, edx                        ; p1: hWnd
    mov r8d, DDSCL_NORMAL               ; p2: dwFlags
   
    mov rax, [rcx]
    add eax, IDirectDraw7.SetCooperativeLevel
    call [rax]
        or eax, eax
        hint.nobranch jnz << Winc64Error
   
   
; --------------------
;   Frontbuffer only
; --------------------

; clear a DDSURFACEDESC2 structure for the front buffer
    lea rdx, ddsd
    xor eax, eax
    mov cl, sizeof(DDSURFACEDESC2 / 8)

:   mov [rdx], rax
    add edx, 8
    dec cl
    jnz <

; fill in a DDSURFACEDESC2 structure
  mov D[ddsd.dwSize], sizeof(DDSURFACEDESC2)  ; set the structure size field
  mov D[ddsd.dwFlags], DDSD_CAPS
  mov D[ddsd.ddsCaps.dwCaps], DDSCAPS_PRIMARYSURFACE

; create the front buffer surface
    mov rcx, [pp_DD7]                   ; *this
    lea rdx, ddsd                       ; p1:
    lea r8, pp_Front                    ; p2:
    xor r9d, r9d                        ; p3:

    mov rax, [rcx]
    add eax, IDirectDraw7.CreateSurface
    call [rax]
        or eax, eax
        hint.nobranch jnz << Winc64Error

; -----

; get the monitor frequency in Hz (frames per second)
    mov rcx, [pp_DD7]                   ; *this
    lea rdx, MonitorHz                  ; p1:

    mov rax, [rcx]
    add eax, IDirectDraw7.GetMonitorFrequency
    call [rax]
        or eax, eax
        hint.nobranch jnz << Winc64Error


; -----  Exit  -----

; destroy the stack frame
    add rsp, 28h

    ret

; ==================================================================================================
Okay.. bbbut I am working with 32 bit code. And some details are missing. Remember I am new to this stuff.  :smiley:
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 09:51:17 AM
I will create a 32-bit program to get you there.  It will be GoAsm, but not to worry; it is a very straight-forward assembler and will be easy to understand.  I will need a minute...
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 09:53:18 AM
Quote from: satpro on February 28, 2025, 09:51:17 AMI will need a minute...
Thanks, Bert. NoCforme might even be interested in it, too. (as well as others, I'd imagine.)
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 11:20:33 AM
Okay, here is what I could quickly convert to 32-bit.  I had to think a bit!

It is because I program exclusively in 64 bits these days and this old mind, well, you know.  The freedom and extra registers are wonderful, though.  Hope I got the stack right (converting back to 32-bit) and it might not be precise as I did it real fast.  I'm guessing an error or two somewhere...  :biggrin:

1.  Params can be entered in the natural order.
2.  COM is the same as Win32, except for the first param, which is the interface ptr (e.g. ppDD7).
3.  At the end of a program you do not need to clean anything.  Call ExitProcess and that's it.

It's long.  All told, over a meg of GoAsm source.  I could not upload this as 'code' because it is too much.  Attached is the video-creation part, some memory movers, part of WndProc, creating the main window, and a 1x & 2x blit to screen (still 64-bit) and there is much more if this does not make enough sense.  I didn't want to get too carried away.  lol

*****

This is from an emulator I am almost finished with.  If no one minds, the program is my attempt at a 32-bit version of the 65c02 in a program called WinC64.  WinC64 is an HD version of a very modern C64, one that has a 32-bit cpu and 32-bit graphics, and MANY x86 instructions (made into 32-bit 65c02) that run it.  I think it's cool, and if I count right has been a mere 12 years in the making.  :eusa_boohoo:
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 11:41:27 AM
Forgot this bit:

; ==================================================================================================
;                                       MESSAGE LOOP
; ==================================================================================================

align 16
EXPORT MessageLoop:
    xor ecx, ecx
    mov [esp], addr msg                 ; p1: addr msg
    mov [esp+4], edx                    ; p2: 0
    mov [esp+8], edx                    ; p3: 0
    mov [esp+12], edx                   ; p4: 0
    call GetMessage                     ; retrieve messages from the queue

    or eax, eax                         ; if message = 0 (WM_QUIT),
    jz >                                ; it's time to quit, so branch to Exit

    mov [esp], addr msg                 ; p1: addr msg
    call TranslateMessage               ; translate virtual-key messages into character messages

    mov [esp], addr msg                 ; p1: addr msg
    call DispatchMessage                ; send the message to WndProc for processing

    jmp < MessageLoop                   ; return to the message loop

:

; -----  Exit the program  -----

; exit properly thru Windows
    mov ecx, TRUE                             ; retval = TRUE (OKAY)
    call ExitProcess                          ; ends the process, quits


; ==================================================================================================
;                                       WNDPROC
; ==================================================================================================

; ---------
; on entry:
; ---------
; rcx: hwnd
; rdx: uMsg
; r8:  wParam
; r9:  lParam

align 16
EXPORT WndProc:         ; hwnd,uMsg,wParam,lParam

; create a stack frame
    sub esp, 14h

; -----
  mov edx, [esp+4]  ; uMsg
 
    cmp edx, WM_KEYDOWN                 ; check if a KEYDOWN message has arrived
    je >> .doKEYDOWN

    cmp edx, WM_PAINT                   ; check if a PAINT message has arrived
    je >> .doPAINT

    cmp edx, WM_DESTROY                 ; check if a DESTROY message has arrived
    je > .doDESTROY

    cmp edx, WM_CREATE                  ; check if a CREATE message has arrived
    je >> .doCREATE

    cmp edx, WM_NCCREATE                ; check if a NCCREATE message has arrived
    je >> .doNCCREATE                   ; CreateWindowExA fails if this is not here

    cmp edx, WM_CLOSE                   ; check if a CLOSE message has arrived
    je >> .doCLOSE

; go default for anything else, then fall thru & exit
    call DefWindowProcA

; -----
   
align 16
.GetOutRight
    add esp, 14h                            ; restore the stack

    xor eax, eax
    ret

; ==================================================================================================
; WM_DESTROY message handler

align 16
.doDESTROY
; exit via the message loop by posting WM_QUIT to queue
    mov [esp], 0                        ; p1: 0
    call PostQuitMessage
 
    jmp << .GetOutRight

; ==================================================================================================
; WM_PAINT message handler

align 16
.doPAINT
    mov ecx, [WindowHandle]
    mov [esp], ecx                      ; p1: hwnd
    mov [esp+4], addr ps                   
    call BeginPaint                     ; p2: addr ps

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

    mov ecx, [WindowHandle]
    mov [esp], ecx                      ; p1: hwnd
    mov [esp+4], addr ps                   
    call EndPaint                       ; p2: addr ps

    jmp << .GetOutRight


; ==================================================================================================
; WM_KEYDOWN message handler

align 16
.doKEYDOWN      ; respond to a keypress

;    cmp r8, VK_ESCAPE                   ; compare keypress to: "ESC KEY = Show/Hide fkey Menu"
;    je >> .doMENU                       ; go to MENU handler for this

;    cmp r8, VK_DOWN                     ; compare keypress to: "CURSOR DOWN KEY = Menu Go Down"
;    je >> .doMENUDOWN                   ; go to MENUDOWN handler for this

;    cmp r8, VK_UP                       ; compare keypress to: "CURSOR UP KEY = Menu Go Up"
;    je >> .doMENUUP                     ; go to MENUUP handler for this

    cmp r8, VK_F1                       ; compare keypress to: "F1 KEY = Go - Stop"
    je >> .doPAUSE                      ; go to PAUSE handler for this

    cmp r8, VK_F4                       ; compare keypress to: "F8 KEY = Exit"
    je >> .doCLOSE                      ; go to WM_CLOSE handler for this

    jmp << .GetOutRight                 ; any other key returns to WinC64


; ==================================================================================================
; WM_CREATE message handler

align 16
.doCREATE

    jmp << .GetOutRight

; ==================================================================================================
; WM_NCCREATE message handler

align 16
.doNCCREATE

    add esp, 14h                            ; restore the stack

    mov eax, 1
    ret

; ==================================================================================================
; WM_CLOSE message handler (alt-F4)

align 16
.doCLOSE

; disable the cpu thread
;    mov B[IsPowerOn], 0

; stop the timer for the cpu thread
;    xor ecx, ecx                        ; p1: HWND hWnd, handle of window that installed timer
;    mov edx, [hTimer1]                  ; p2: UINT uIDEvent, timer identifier
;    call KillTimer

; release front buffer interface
    mov ecx, [pp_Front]
    mov eax, [ecx]
    add eax, IDirectDrawSurface7.Release
    call [eax]
    or eax, eax
    jnz << Winc64Error

; release DirectDraw interface
    mov ecx, [pp_DD7]
    mov eax, [ecx]
    add eax, IDirectDraw7.Release
    call [eax]
    or eax, eax
    jnz << Winc64Error

; zero the interface ptrs
    xor eax, eax
    mov [pp_Front], eax
    mov [pp_DD7], eax

; destroy the window, send WM_DESTROY message to queue
    mov ecx, [WindowHandle]
    mov [esp], ecx
    call DestroyWindow                  ; destroy window, send WM_DESTROY msg


    jmp << .GetOutRight


; ==================================================================================================
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 11:57:36 AM
Thanks satpro, I will take a look at this later this evening.  :smiley:
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 12:10:07 PM
Great!  Watch out for uncorrected 64-bit.  I noticed something later in WndProc that still has r8 instead of a stack MOV [esp].
But you already have your WndProc, so that's not a big deal.  I am sorry I left those mem movers at 64-bit.  It would take some more work to make those x86-32, but even still in 32-bit, they work quick.

Please PM me if you need clarity.
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on February 28, 2025, 12:43:27 PM
Sorry, I don't use GoAsm and have no intention of doing so.
I don't have any of those include files (7 of 'em!) and don't want to have to acquire them.
Any chance of making this a plain old MASM (32 bit) program?

Just so you know, you don't need to do any of that stack "setup" stuff you're doing for a 32-bit program: it's already all set up for you by the loader. No need for the "align 16" and that other stack-manipulation code you have in there.

One thing I really really HATE is the use of addressing like mov [esp+n], eax, where[esp+n] points to a local variable. There's absolutely no justification at this late stage of the game (2025!) to use primitive, cryptic addressing like this. This is like the kind of programming that was used for the Apollo missions back in the 1970s.

Use named variables, man!
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 01:10:50 PM
Quote from: satpro on February 28, 2025, 12:10:07 PMGreat!  Watch out for uncorrected 64-bit.  I noticed something later in WndProc that still has r8 instead of a stack MOV [esp].
But you already have your WndProc, so that's not a big deal.  I am sorry I left those mem movers at 64-bit.  It would take some more work to make those x86-32, but even still in 32-bit, they work quick.

Please PM me if you need clarity.
No worries, satpro. It might take me some time, but I think I can handle a bit of housekeeping there in regards to 64 bit leftovers.
But we will see...
Title: Re: FloodFill and ExtFloodFill
Post by: sinsi on February 28, 2025, 01:42:42 PM
Is this bit of code right?
EXPORT MessageLoop:
    xor ecx, ecx
    mov [esp], addr msg                 ; p1: addr msg
    mov [esp+4], edx                    ; p2: 0
    mov [esp+8], edx                    ; p3: 0
    mov [esp+12], edx                   ; p4: 0
    call GetMessage                     ; retrieve messages from the queue
You zero ecx but then store edx, which could be anything.
Typo I assume?  :biggrin:
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 01:52:08 PM
Quote from: sinsi on February 28, 2025, 01:42:42 PMIs this bit of code right?
EXPORT MessageLoop:
    xor ecx, ecx
    mov [esp], addr msg                 ; p1: addr msg
    mov [esp+4], edx                    ; p2: 0
    mov [esp+8], edx                    ; p3: 0
    mov [esp+12], edx                   ; p4: 0
    call GetMessage                     ; retrieve messages from the queue
You zero ecx but then store edx, which could be anything.
Typo I assume?  :biggrin:
@ satpro: Upon a cursory inspection of the code, aside from what sinsi posted above, it leaves a lot to be desired. I'll probably postpone any attempted efforts on this piece of work.  I have many other things to do, but so little time. When I have a full free weekend, I might continue down this path.  :undecided:
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 09:04:52 PM
Quote from: sinsi on February 28, 2025, 01:42:42 PMIs this bit of code right?
EXPORT MessageLoop:
    xor ecx, ecx
    mov [esp], addr msg                 ; p1: addr msg
    mov [esp+4], edx                    ; p2: 0
    mov [esp+8], edx                    ; p3: 0
    mov [esp+12], edx                   ; p4: 0
    call GetMessage                     ; retrieve messages from the queue
You zero ecx but then store edx, which could be anything.
Typo I assume?  :biggrin:
Yes, a typo!.  I'm sorry.  This was all written as 64-bit.  I wasn't thinking 32-bit when I wrote the original and also, did the conversion fast.  When you program in 64-bit the four params generally form an automatic "flow" between subroutine calls.  In other words, the Windows API is set up so that you can let params and registers float from one call to the next.  x86 does not do this at all.  In an actual program this winds up making your calls to memory almost nil (what you want).  Once I started looking through and converting this code I realized what a job it would really be, especially in WndProc.  There you can let the registers do ALL the work with no stack involvement, but not in x86.

sinsi, if you want the original code, I can zip it up and send it to you.

zedd, NoC:  I am sorry this isn't what you guys were looking for.  From my perspective you two are killing your own programming effort by not moving "up" to 64 bits!  Pessimism and negativity are the two emotions that kill productivity and learning.  Granted, who wants to try to figure out how to convert from anything to anything???  I know I didn't like doing it here.  

As for GoAsm, I love it like a brother and always will.  Do you have ANY idea how much fun it is to program without LIB files???

If you want real help, you may wish to embrace what I am saying.  The alternative is that you may be arguing about the merits of macros forever.  The rest of the world has moved on from 32-bit programing and so have I.

So, if you need me, I'm here and WILL help you, but not for an argument about GoAsm or 32-bit.  
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on February 28, 2025, 09:32:35 PM
Quote from: NoCforMe on February 28, 2025, 12:43:27 PMSorry, I don't use GoAsm and have no intention of doing so.
I don't have any of those include files (7 of 'em!) and don't want to have to acquire them.
Any chance of making this a plain old MASM (32 bit) program?

Just so you know, you don't need to do any of that stack "setup" stuff you're doing for a 32-bit program: it's already all set up for you by the loader. No need for the "align 16" and that other stack-manipulation code you have in there.

One thing I really really HATE is the use of addressing like mov [esp+n], eax, where[esp+n] points to a local variable. There's absolutely no justification at this late stage of the game (2025!) to use primitive, cryptic addressing like this. This is like the kind of programming that was used for the Apollo missions back in the 1970s.

Use named variables, man!

This is precisely why you don't understand it.  It seems to me you want this to be easy.  Well, it's not.  I had to read a lot of those 1500-page programming books and most of that 3800-page Intel manual to get it.  Fake NASA has nothing to do with it.

Yes, I hastily whipped up 32-bit code.  I would rather use stack pushes and pulls, but you don't need those at all in x64.  Do you want pretty names for your TEMPORARY stack variables, or would you rather have a complete understanding of why they are just known offsets?

Asking the question and then arguing with the answer....
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on February 28, 2025, 09:43:40 PM
@satpro, I can and sometimes do write 64 bit masm code, even translate 32 bit -> 64 bit masm code. Your code doesn't look like masm that I am used to seeing. So, it will take me quite some time, to convert it to code more to my liking. :smiley:
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 01, 2025, 03:50:05 AM
:rolleyes:  um.... I found the problem with FloodFill.
My implementation of using a double buffer in WM__PAINT was not quite double buffering. And for some of my testing, I was not using double buffering at all. Some of the gdi32 drawing functions work fine without double buffering, but it seems that FloodFill and ExtFloodFill are not in that category.

Now that I have properly implemented a double buffer, FloodFill is now working 100% as expected.
...
I had borrowed fearless' double buffering code from here  (https://masm32.com/board/index.php?msg=135599)... I happened upon that thread while browsing the forum this morning, and noticed a slight difference in the implementation from mine.
I may have my own somewhere, but dozens of source I checked used the faulty painting scheme.  :rolleyes:

I guess I had never had any issues with it, until now, in the Tic Tac Toe game.  (Grumble, grumble)

      .elseif uMsg == WM_PAINT
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;
        ;;  WM_PAINT startup code
        ;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        invoke BeginPaint, hWin, addr ps
        mov hDC, eax
        invoke GetClientRect, hWin, addr rct
        invoke CreateCompatibleDC, hDC
        mov mDC, eax
        invoke CreateCompatibleBitmap, hDC, rct.right, rct.bottom
        mov hBmp, eax
        invoke SelectObject, mDC, hBmp
        mov hBmpOld, eax

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;
        ;;  draw background color
        ;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
       
        invoke CreateSolidBrush, 00FF7F3Fh
        mov hBrush, eax
        invoke SelectObject, mDC, hBrush
        mov hBrushOld, eax
        invoke FillRect, mDC, addr rct, hBrush
        invoke SelectObject, mDC, hBrushOld
        invoke DeleteObject, hBrush

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;
        ;;  drawing rectangle by drawing lines
        ;;  then use FloodFill to fill the rectangle
        ;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

       
        invoke CreatePen, 0, 6, 00000000h
        mov hPen, eax
        invoke SelectObject, mDC, hPen
        mov hPenOld, eax
        invoke CreateSolidBrush, 003F7FFFh
        mov hBrush, eax
        invoke SelectObject, mDC, hBrush
        mov hBrushOld, eax
        invoke MoveToEx, mDC, 100, 100, 0
        invoke LineTo,   mDC, 100, 200
        invoke LineTo,   mDC, 200, 200
        invoke LineTo,   mDC, 200, 100
        invoke LineTo,   mDC, 100, 100
        invoke FloodFill, mDC, 110, 110, 00000000h
        invoke SelectObject, mDC, hBrushOld
        invoke DeleteObject, hBrush
        invoke SelectObject, mDC, hPenOld
        invoke DeleteObject, hPen

        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
        ;;
        ;;  WM_PAINT ending code
        ;;
        ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

        invoke BitBlt, hDC, 0, 0, rct.right, rct.bottom, mDC, 0, 0, SRCCOPY
        invoke SelectObject, mDC, hBmpOld
        invoke DeleteObject, hBmp
        invoke DeleteDC, mDC
        invoke EndPaint, hWin, addr ps
        mov eax, 0
        ret
      .elseif uMsg == WM_SIZE


(https://i.postimg.cc/jdnVj9nj/untitled.png)


Later:
I found the source (literally) of the erroneous code. In a couple (not 1) of my 'template' files, it was there in WM_PAINT. Time to make new Window Templates.  :tongue:  ... and find all the asm sources that use the bad code.
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 01, 2025, 07:42:15 AM
Quote from: satpro on February 28, 2025, 09:32:35 PMI would rather use stack pushes and pulls, but you don't need those at all in x64.
And neither do you need them in 32-bit code; that's why god invented invoke.

QuoteDo you want pretty names for your TEMPORARY stack variables, or would you rather have a complete understanding of why they are just known offsets?

The former, obviously; I don't need a constant lesson in stack addressing when I look at my code; what I do need is to know which goddamn variable I'm looking at without having to consult a lookup table. Those variables may be "temporary" (active only within the scope of the subroutine they're in), but they're variables nonetheless, therefore it would be nice to know exactly which one you're dealing with by name.

Or would you rather we all go back to using numeric offsets for addressing all of our variables? Remember, the whole idea of an assembler is to make so-called machine language more manageable to the poor programmer. Which is why we have such luxuries as named variables, subroutine names, jump targets, etc.

Otherwise we might as well just go back to front-panel programming. (I'm guessing you might be a bit too young to remember what that was.)
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 01, 2025, 07:44:07 AM
Quote from: zedd151 on March 01, 2025, 03:50:05 AM:rolleyes:  um.... I found the problem with FloodFill.

I'm glad you found the problem. It would have taken a lot of re-jiggering to use my flood-fill routine.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 01, 2025, 07:58:29 AM
Quote from: NoCforMe on March 01, 2025, 07:44:07 AMI'm glad you found the problem.
Yeah, me too.

Quote from: NoCforMeIt would have taken a lot of re-jiggering to use my flood-fill routine.
I really didn't want to go that route, or any of the other work-arounds proposed here - unless as a last resort. I wanted the program to work as I intended, even if I had to beat it into submission.  :biggrin:

All I had to do was take a closer look at the rest of the WM_PAINT code.  :rolleyes:

Mission accomplished, problem solved, case closed, water under the bridge, etc., etc.  :tongue:
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 01, 2025, 08:43:05 AM
Quote from: satpro on February 28, 2025, 08:46:50 AMWould you like to try drawing a window with something like DirectDraw?  It's only a couple of lines of code (especially with DDraw) and then the screen is yours and Windows behaves.  You can even write to the primary surface if you like, yet it is still just a window, with nothing to be wary of.

@satpro: I am curious about DirectDraw, as I'm well acquainted with the hassles of using GDI (and even GDI+).

But looking at the stuff on Micro$oft Learn, I'm still pretty much in the dark as to what DirectDraw actually does or how to use it. I see you can create DD "objects", but I don't know what exactly those objects are, what they do, and how to get them to draw what you want on the screen. I don't see any primitives like GDI has (lines, ellipses, etc.)

And another mystery is the stuff I see that apparently gives you access to things like the horizontal and vertical retrace periods, which seems to be quite CRT-specific.

So could you possibly give a very brief overview of what DD does and how to use it? It might be worthwhile learning it, despite the barriers of having to deal with COM and "interfaces" intended for C++.

Thanks.
Title: Re: FloodFill and ExtFloodFill
Post by: satpro on March 01, 2025, 10:08:36 AM
Quote from: NoCforMe on March 01, 2025, 08:43:05 AMSo could you possibly give a very brief overview of what DD does and how to use it? It might be worthwhile learning it, despite the barriers of having to deal with COM and "interfaces" intended for C++.

Thanks.
I will be happy to, and thank you.  In my opinion DirectDraw is a gem from another time.  Nothing really works, but it does let you access screen ram like in the old days.  And that's big.  Microsoft (obviously) does not want us tinkering with the primary surface.

What I will do is write something separate and explain some things that are not necessarily in all of the docs.  In fact, the farther back you go in time, the more MS was willing to share.  Objects, how to call COM, video sync, what works and what doesn't -- all of it will be covered.

I will show you how to draw there -- it is liberating and so much faster than using the graphics card.  For example, you can fill a box or draw any line before equivalent DirectX COM code executes that does the same, exact thing!  I'll explain this more, but one thing I have found is that once I bypassed the card (I'm talking doing it all in system memory and then SSE-copying directly to video ram) cpu usage goes way down, and the program itself runs faster and smoother -- the exact opposite of what you might expect.

Again, thank you for wishing to give this a second look.  I'll get on that "write" away.
Title: Re: FloodFill and ExtFloodFill
Post by: jj2007 on March 01, 2025, 10:21:13 AM
Quote from: satpro on March 01, 2025, 10:08:36 AMcpu usage goes way down, and the program itself runs faster and smoother -- the exact opposite of what you might expect

That is indeed interesting, as we are always taught that graphics cards are so much faster than ordinary x86 cpus :cool:
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 01, 2025, 11:45:14 AM
Quote from: satpro on March 01, 2025, 10:08:36 AMAgain, thank you for wishing to give this a second look.  I'll get on that "write" away.

Well, thank you (in advance).
If you could, would you include at least a couple of drawing operations like lines, ellipses, maybe filled shapes?

Don't care about the programming style here, so don't worry about that. Just want to see how it works "under the hood".
Title: Re: FloodFill and ExtFloodFill
Post by: daydreamer on March 01, 2025, 07:04:49 PM
I have made several ddraw program and posted in forum before
But coding style more kinda dos style with library or own proc 's for draw different shapes
Fast speed write directly to vram,but the way graphics port worked oneway before 100 * slower reading vram
Isn't it replaced with newer interface ,alternative to GDI it draws hardware accelerated shapes ?

But don't forget d3d9 isn't only Poly's,you also have linelist, pointlist

Title: Re: FloodFill and ExtFloodFill
Post by: TimoVJL on March 01, 2025, 08:04:50 PM
Not so fun ?
Introduction to DirectWrite (http://www.nuonsoft.com/blog/2009/05/27/introduction-to-directwrite/)

Only two functions to import, D2D1CreateFactory() and DWriteCreateFactory()
so perhaps using dynamic way, so don't need those import libraries.
Title: Re: FloodFill and ExtFloodFill
Post by: jj2007 on March 02, 2025, 01:19:48 AM
Direct2D Tutorial Part 2: Basic Shapes (https://www.codeproject.com/Articles/5277136/Direct2D-Tutorial-Part-2-Basic-Shapes#round_rect)
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 01:40:56 AM
Suggestion:
Maybe someone can start a new topic dedicated to these Direct Draw discussions?

Perhaps not relevant in a thread where the topic was gdi32 FloodFill and ExtFloodFill. And the issue with those gdi32 functions has been resolved,  several posts ago. (https://masm32.com/board/index.php?msg=136444)
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 10:47:36 AM
Quote from: zedd151 on March 01, 2025, 03:50:05 AM:rolleyes:  um.... I found the problem with FloodFill.
Which worked fine in the example  Here (https://masm32.com/board/index.php?msg=136444).

However, after adding several drawing function then add the funtion that uses FloodFill, the drawing is not bothered by moving the window below the task bar anymore... but now when the window is minimized using the window borders similar issues with it:
(https://i.postimg.cc/wjg69Psm/untitled.png)

I had even tried breaking up the outline of the X into 5 pieces to FloodFill smaller sections but that did not help.

The only way I found to resolve this is to call InvalidateRect in WM_SIZE, which restores everything being painted, if the window gets resized using the window border.

Maybe it is better to stick with bitmap images?
Unless there is a way to create the X (using FloodFill) only once. And keep a memory bitmap of it, to be blitted when needed. I confess though, that I have no clue how to do that.  :sad:

Most likely I will revert to using bitmaps...
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 02, 2025, 11:00:37 AM
Quote from: zedd151 on March 02, 2025, 01:40:56 AMSuggestion:
Maybe someone can start a new topic dedicated to these Direct Draw discussions?
Your wish is my command.
I started a new thread (https://masm32.com/board/index.php?topic=12575.0). It's just a placeholder for now, to be fleshed out as more info comes in.
Speaking of which, @satpro, anytime you have some example code for us you can post it there.
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 02, 2025, 11:02:30 AM
Quote from: zedd151 on March 02, 2025, 10:47:36 AMThe only way I found to resolve this is to call InvalidateRect in WM_SIZE, which restores everything being painted, if the window gets resized using the window border.

Well, that's exactly what you should be doing. Does that solve the redrawing problem? If so, then, as they say, Bob's your uncle.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 11:13:07 AM
Quote from: NoCforMe on March 02, 2025, 11:00:37 AM
Quote from: zedd151 on March 02, 2025, 01:40:56 AMSuggestion:
Maybe someone can start a new topic dedicated to these Direct Draw discussions?
Your wish is my command.
...
Siekmanski will be around shortly to help you guys out... a little bird told me.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 11:16:32 AM
Quote from: NoCforMe on March 02, 2025, 11:02:30 AMWell, that's exactly what you should be doing. Does that solve the redrawing problem? If so, then, as they say, Bob's your uncle.
Just when I thought I had that problem knackered. Is that a legit way to handle it? And yes, it does resolve the drawing irregularities.  Under normal circumstances it was drawing fine otherwise, and no gdi leaks.

Much experimenting on my part to figure all of this out.
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 02, 2025, 12:12:34 PM
Quote from: zedd151 on March 02, 2025, 11:16:32 AM
Quote from: NoCforMe on March 02, 2025, 11:02:30 AMWell, that's exactly what you should be doing. Does that solve the redrawing problem? If so, then, as they say, Bob's your uncle.
Just when I thought I had that problem knackered. Is that a legit way to handle it? And yes, it does resolving the drawing irregularities.  Under normal circumstances it was drawing fine otherwise, and no gdi leaks.

Yes; the overall point is that you, the programmer, are responsible for making sure things are redrawn when certain events occur, like the window being resized. Not all of this is done automagically by Windows, as you discovered.

And it really has nothing to do with GDI leaks, which happen when you create objects and then forget to delete them. That's a separate issue.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 12:19:08 PM
Quote from: NoCforMe on March 02, 2025, 12:12:34 PM
Quote from: zedd151 on March 02, 2025, 11:16:32 AM
Quote from: NoCforMe on March 02, 2025, 11:02:30 AMWell, that's exactly what you should be doing. Does that solve the redrawing problem? If so, then, as they say, Bob's your uncle.
Just when I thought I had that problem knackered. Is that a legit way to handle it? And yes, it does resolving the drawing irregularities.  Under normal circumstances it was drawing fine otherwise, and no gdi leaks.

Yes; the overall point is that you, the programmer, are responsible for making sure things are redrawn when certain events occur, like the window being resized. Not all of this is done automagically by Windows, as you discovered.
okay.


QuoteAnd it really has nothing to do with GDI leaks, which happen when you create objects and then forget to delete them. That's a separate issue.
yes, I know is a separate issue. But it does happens a lot more than you would think it does.  And not just to me.   :badgrin:
Title: Re: FloodFill and ExtFloodFill
Post by: NoCforMe on March 02, 2025, 01:21:42 PM
Quote from: zedd151 on March 02, 2025, 12:19:08 PM
Quote from: NoCforMe on March 02, 2025, 12:12:34 PMAnd it really has nothing to do with GDI leaks, which happen when you create objects and then forget to delete them. That's a separate issue.
yes, I know is a separate issue. But it does happens a lot more than you would think it does.  And not just to me.  :badgrin:
Oh, yeah, I know all about GDI leaks. (Don't ask me how I know.)
That's why Task Manager is your friend.
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 02, 2025, 01:51:28 PM
Re: GDI leaks...
 :toothy:  Don't you hate it when that happens.   :biggrin:

Anyway I have updated the image in post #1. It closely resembles the original game graphics. Maybe not pixel for pixel in the "tic - tac - toe" banner, but most of the other graphics are a match. The O's might be a little off, though.  :smiley:

I am going to now integrate the drawing functions and WM_PAINT (in its entirety) into the original code.
Hopefully I can package it all up, and never need to look at its code again!  :greensml:
Title: Re: FloodFill and ExtFloodFill
Post by: zedd151 on March 03, 2025, 04:19:45 AM
Quote from: zedd151 on March 02, 2025, 01:51:28 PMI am going to now integrate the drawing functions and WM_PAINT (in its entirety) into the original code.
Nope. That had some issues. It appears that the window DC was getting corrupted somewhere, and I could not locate exactly where...
Sooooo.....  I am rewriting it from scratch, except for the new graphics stuff. I have updated the current code and attachment for tic-tac-toe Here (https://masm32.com/board/index.php?msg=136249)

The tic-tac-toe rewrite is about as close to finished as it needs to be... it wasn't all that hard to rewrite it.
Btw, no other issues found regarding FloodFill and/or ExtFloodFill. That issue is now fully resolved.