News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

replies to 'DrawBitmap procedure' and other meanderings

Started by NoCforMe, August 30, 2022, 06:30:24 AM

Previous topic - Next topic

NoCforMe

Quote from: Swordfish on August 30, 2022, 04:12:13 AM
Now I will work on making a nifty procedure to get the mouse coordinates and convert them to "square" x/y coordinates or better still the index to the game board.

You're talking about "hit testing". Here's the procedure in pseudocode:


Hit Testing
-----------

row=0
col=o

getMouseX, getMouseY

hitTestTop = 0
hitTestLeft= 0
hitTestBottom = $cellHeight
hitTestRight = $cellWidth

loop count = $total # of cells
loopTop:
   if MouseX < hitTestLeft
      break
   if MouseY < hitTestTop
      break

   if MouseX > hitTestRight
      break
   if MouseY > hitTestBottom
      break

; At this point, we have a hit:
; exit with (row, col)

   row++
   hitTestTop += $cellHeight
   hitTestBottom += $cellHeight
   if row > $maxRow
      hitTestTop = 0
      hitTestBottom = $cellHeight
      hitTestLeft += $cellWidth
      hitTestRight += $cellWidth
      row=0
      col++
LOOP loopTop

; Sadly, at this point we have no hit ...



Items starting with "$" are constants (the width & height of your "cells", the on-screen areas you want to hit-test for).

You're basically constructing a rectangle (the RECT structure comes in handy here) that you slide around the screen until the mouse coords. fall within it. Easy peasy.

When you find a hit, the row and col variables will tell you which "cell" was hit.
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on August 30, 2022, 06:30:24 AM
You're talking about "hit testing"...
Yes. But too late, I've got code:


    GetIndex proc lParam:dword ; convert mouse coordinates to index value
        mov eax, -1
        mov ecx, lParam
        mov edx, ecx
        movzx ecx, cx
        shr edx, 16
        ; convert mouse coordinates to square x/y coordinates
      .if ecx     >= col1x && ecx <= col1x+imgw
        mov ecx, col1x
      .elseif ecx >= col2x && ecx <= col2x+imgw
        mov ecx, col2x
      .elseif ecx >= col3x && ecx <= col3x+imgw
        mov ecx, col3x
      .endif
      .if edx     >= row1y && edx <= row1y+imgh
        mov edx, row1y
      .elseif edx >= row2y && edx <= row2y+imgh
        mov edx, row2y
      .elseif edx >= row3y && edx <= row3y+imgh
        mov edx, row3y
      .endif
       ; convert square x/y coordinates to index value
      .if     ecx == col1x && edx == row1y
        mov eax, 0
      .elseif ecx == col2x && edx == row1y
        mov eax, 1
      .elseif ecx == col3x && edx == row1y
        mov eax, 2
      .elseif ecx == col1x && edx == row2y
        mov eax, 3
      .elseif ecx == col2x && edx == row2y
        mov eax, 4
      .elseif ecx == col3x && edx == row2y
        mov eax, 5
      .elseif ecx == col1x && edx == row3y
        mov eax, 6
      .elseif ecx == col2x && edx == row3y
        mov eax, 7
      .elseif ecx == col3x && edx == row3y
        mov eax, 8
      .endif
        ret
    GetIndex endp

And


      .elseif uMsg == WM_LBUTTONUP
        invoke GetIndex, lParam
        mov indx, eax
        lea ecx, board
      .if byte ptr [ecx+eax] == 0
        mov byte ptr [ecx+eax], 1
      .endif
      .if indx != -1
        invoke InvalidateRect, hWin, 0, 0
      .endif
Using lParam from WM_LBUTTONUP but thanks for the offer.
At this rate, Ill have finished writing Tic Tac Toe here in this thread.  :toothy:

NoCforMe

OK, you like the "if ... elseif ... elseif ... elseif ...", ad infinitum approach. I prefer a nice clean block of code with a looping construct, without all those conditionals. More generalized (i.e., no need to rewrite substantially if the size of your grid changes).

Different stroke for different folks ...
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on August 30, 2022, 06:42:37 AM
Different stroke for different folks ...
I tend to stick with things I know. Yes I'm kinda .iffy...  :tongue:

jj2007

Quote from: NoCforMe on August 30, 2022, 06:42:37 AMI prefer a nice clean block of code

Switch_

The Masm32 switch macro is also pretty powerful.

daydreamer

Quote from: jj2007 on August 30, 2022, 07:14:45 AM
Quote from: NoCforMe on August 30, 2022, 06:42:37 AMI prefer a nice clean block of code

Switch_

The Masm32 switch macro is also pretty powerful.
prefer the masm32 switch without needing lots of breaks;

mov ebx,x
mov edi,y
Switch alpha ;0-7
case 0
add ebx,cellxsize
case 1
add ebx,cellxsize
add edi,cellysize
case 2
add edi,cellysize
case 3
sub ebx,cellxsize
add edi,cellysize
case 4
sub ebx,cellxsize
case 5
sub ebx,cellxsize
sub edi,cellysize
case 6
sub edi,cellysize
case 7
add ebx,cellxsize
sub edi,cellysize
endsw
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

zedd151

#6

"A conditional expression by any other name still resolves to jumps n calls"
- dedndave


*Okay he never actually said that.
But he also wasn't a huge fan of .if blocks either iirc. He mentioned that in a post somewhere in the forum. I came across it recently while browsing some of the older threads. Can't remember the topic though.


Edit = I found it the Real quote from dedndave tm:
Quote from: dedndave on June 11, 2012, 11:31:41 AM
i prefer to write code "old style"
i am not too fond of .if/.else or .while/.endw stuff
but - the members don't like it when i write code that way - lol
so - to make code that i like - and that makes them happy,
i have had to learn how the statements work - in reverse
in other words, i write some code, disassemble it, and learn what code is generated
then - i write code they like - that more or less does what i wanted, to begin with
I miss Dave. He was my "go to guy" when I didn't understand the 'how and why' of a particular concept, piece of code, obscure (to me anyway) instructions, etc. He would give in depth explanations with examples. I hope he's doing well.

jj2007

QuoteSoftware coders: What is a programming language that you hope never to work in again, and why?
* COBOL. Verbose like no other, excess structure, unproductive, obtuse, limited, rigid.
* JavaScript. Insane semantics, weak typing, silent failure.
* BASIC. Mandatory line numbering. Zero standardization. Not even a structured language — you've never seen that much spaghetti code.

Strangely enough, "pure MASM" does not appear in the list. If you refuse .if ... .endif constructs, you vote for the worst variant of spaghetti code, worse than what BASIC abandoned 30 years ago by introducing structured programming.

The Masm32 SDK switch macro is a fine animal. It's much better than its C/C++ equivalent, basically because Hutch came from PowerBasic and laughed at Kernighan & Ritchie's break nonsense.

Switch_ is more sophisticated (under the hood it's 264 lines, 5703 bytes of purest MASM code), but in real life you rarely need such luxury.

Btw for very simple, short hello world proggies you don't need switch or Switch_. Really, you might not even need .if ... endif or .While ... .Endw. Up to, say, 100 lines of code, it's fun to reflect every time whether jg or jb is the right mnemonic for your specific case. And given that nobody is interested in such short exercises, readability is not even an issue :cool:

NoCforMe

Quote from: jj2007 on August 31, 2022, 06:54:26 AM
QuoteSoftware coders: What is a programming language that you hope never to work in again, and why?
* COBOL. Verbose like no other, excess structure, unproductive, obtuse, limited, rigid.

I'm here to register a hearty rebuttal to that insult against COBOL. I actually was a COBOL programmer (got paid for it even) for a short while. It was the 2nd language I learned, after BASIC (on the first IBM PC).

COBOL is actually very well suited for its tasks. It's extremely easy to read, which is maybe even more important than being easy to write (have you ever heard of a little thing called "maintenance"?).

And I'd really like to see some snot-nosed, pimple-faced kid write a robust, reliable and maintainable payroll program--something that people rely on for their paychecks--in C++ or Python or Pascal or whatever.

I liked COBOL.
Assembly language programming should be fun. That's why I do it.

zedd151

#9
@jj lol.
I'll stick to my .iffy code. (Pun intended)  :biggrin:
Manually writing even the compares in WndProc would present a challenge in certain instances (multiple nested .if code for example) so, I don't want to go THAT far. Lol
I've seen plenty of code of that type in olly. What a mess. A lot of jumps that will never execute, etc. I did experiment whit discrete calls and jumps at various stages of my learning of assembly. The code ain't pretty no matter what lenses you look at it with.  :toothy:  Fortunately I removed all such code from my archives.


My very first piece of assembly code was a simple message box written in ollydbg. lol
I overwrote the original program, and figured out pointers, etc.  :nie:  this was long before I discovered masm32 btw, and that was a profound life changing moment.

daydreamer

There are alternatives to switch /case,
Lea pointer arithmetic and arrays of deltax, deltay,hicon,bitmap handle for  0-7 directions
Jumptable
But I choose switch /case because more readable easier to debug than array s
When using comisd it's simpler only zero flag and carry flag conditional jumps that's is used

my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

jj2007

Quote from: daydreamer on August 31, 2022, 08:34:32 PM
There are alternatives to switch /case,
Lea pointer arithmetic and arrays of deltax, deltay,hicon,bitmap handle for  0-7 directions
Jumptable

Under the hood of Switch_:
004011C6   .  83F9 10       cmp ecx, 10
004011C9   .^ 7E B1         jle short MbCase0_7
004011CB   >  83F9 FE       cmp ecx, -2                              ; Switch (cases -2..12, 5 exits)
004011CE   .^ 7C BB         jl short MbCase0_D
004011D0   .  83F9 12       cmp ecx, 12
004011D3   .^ 7F B6         jg short MbCase0_D
004011D5   .^ FF248D E41140 jmp near [ecx*4+4011E4]                  ;  ******* the jumptable ***********
004011DC   .  40114000      dd MbCase0_3
004011E0   .  8B114000      dd MbCase0_D
004011E4   .  4F114000      dd MbCase0_4
004011E8   .  8B114000      dd MbCase0_D
004011EC   .  8B114000      dd MbCase0_D
004011F0   .  8B114000      dd MbCase0_D
004011F4   .  8B114000      dd MbCase0_D
004011F8   .  8B114000      dd MbCase0_D


But a jumptable rarely makes sense, see Rem under Switch_

If you find jumptables interesting, see older threads here and here

zedd151

#12
.switch, switch, Switch, switch_, et. al.
Which switch?  :tongue:


.if
    Only one? (IF/IFNDEF,etc isnt the same, so not included) No confusion there.  :biggrin:
    Hmmm.


    I still prefer reading .iffy code. Not a commentary (yes it is  :tongue:  iffy code lol ) on coding styles.
    And I rarely use .while on purpose.

   At any rate, the "if/switch" debate should have its own thread imo.  :icon_idea:
.else
    I shall start posting all my code using cmp/jmp style coding  :badgrin: 
    and using push/call too for good measure.  :toothy:  I've got a qeditor plugin for that (invoke to push/call)
.endif
    edited for clarification. And indenting pseudo if block

NoCforMe

Quote from: swordfish on September 01, 2022, 02:07:55 AM
I shall start posting all my code using cmp/jmp style coding  :badgrin: 

You laugh, but some of us (me) actually prefer the cmp/jxx style. Here's how I like to lay out my message dispatchers:


MOV EAX, uMsg
CMP EAX, WM_COMMAND
JE do_command
CMP EAX, WM_LBUTTONDOWN
JE do_lbuttondown
CMP EAX, WM_NOTIFY
JE do_notify
CMP EAX, WM_PAINT
JE do_paint
. . .

do_command:
MOV AX, WORD PTR wParam
CMP AX, IDOK
JE do_processing
CMP AX, IDCANCEL
JE do_close
. . .

do_lbuttondown:
; (big block of code here)

do_notify:
; (another big block o'code)

do_paint:
; (more big blox of code)


Let's compare to the .if/.elseif style:


switch umsg
case WM_COMMAND
DO this
DO that
; (big block of code)

case WM_LBUTTONDOWN
DO this
DO that
DO the_other
; (another big block o'code)

case WM_NOTIFY
DO this
DO that
; you get the idea ...


Better? Worse? Six of one and half a dozen of the other? I'd say my method is nicer because it keeps those big blocks of code (like the WM_PAINT) handler out of the dispatcher code, which after all is just a dispatcher: "WM_CREATE, here's your paycheck, WM_PAINT, here's your mail, ...". If the blocks are small enough then maybe I could see putting them in .if blocks, nicely indented of course. (I don't use indentation in my code at all. After all, this ain't C, it's assembly language ...)

(You'll have to excuse the probably-incorrect syntax in the switch/case example, as I don't know the proper syntax offhand since I don't use it.)
Assembly language programming should be fun. That's why I do it.

zedd151

I have no problem with how anyone writes their conditional statements (if, while, switch, etc) Everyone has their own personal preferences sometimes due to their previous use of other programming languages. Just being a bit sarcastic in my last post. No worries, no discrete cmp and jxx in my code unless it provides a distinct advantage.


But indentation now is another topic (off topic too btw, but ok)
Indentation in the right places helps to clarify the code a bit, makes it more readable imo. Makes finding labels for example easier. Also easier to separate nested code (if, switch, while blocks, etc) Just another formatting preference, as is strategically placing an empty line in just the 'right' places.