News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

A game in graphic mode

Started by amrac, December 28, 2009, 03:50:31 PM

Previous topic - Next topic

FORTRANS

#30
Hi,

   As Dave says, you can have many segments in your
program.  Normally you will have one data segment for a
small program.  I defined "ClockTic" as a location in the
BIOS data segment, as that was a way I like.  Dave has
showed how to access that location without a segment
declared in a SEGMENT directive.  If you want to have
more than one data segment, you declare them with
different names.


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants.  Data segment:
DATASEG SEGMENT PUBLIC
...
DATASEG ENDS

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants.  Data segment 2:
EXTRASG  SEGMENT PUBLIC
... 
EXTRASG  ENDS
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set up the code definitions the operating system wants.  Data segment 3:
MORESEG  SEGMENT PUBLIC
... 
MORESEG  ENDS



   You can specify the BIOS data segment and the video
display segment in SEGMENT AT directives to give them
names, or just set the segment register directly.  If using
a name makes things clearer, use that.  If the extra level
of indirection is confusing, then just set the registers as
needed.

   A minor "advantage" of using the SEGMENT way of doing
things, is that you then have to use the ASSUME directive to
tell MASM what is going on, or it will generate an error message.
That is either extra work, or a way to check that you have
correctly set the segment registers.

   So an amendment/correction to my code snippit.


; - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BIOSSEG SEGMENT AT 40H  ; BIOS Data area
        ORG    6CH
ClockTic LABEL DWORD    ; 55 ms timer ticks since CPU reset
BIOSSEG ENDS

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        PUSH    DS              ; Save data segment pointer.
        MOV     AX,SEG BIOSSEG
        MOV     DS,AX           ; Point data references to the BIOS.
        ASSUME DS:BIOSSEG       ; And tell MASM what we are doing.
        MOV     AX,WORD PTR [ClockTic]
        POP     DS              ; Restore data segment, so we can access our data.
        ASSUME DS:MYDATA        ; Use the name you have set up.
        MOV     [TestTic],AX

DoWork:
        ; Insert your routine here.
        PUSH    DS
        MOV     AX,SEG BIOSSEG
        MOV     DS,AX
        ASSUME DS:BIOSSEG
        MOV     AX,WORD PTR [ClockTic]
        POP     DS
        ASSUME DS:MYDATA
        CMP     [TestTic],AX    ; Have we used enough time to quit?
        JE      DoWork          ; No, continue.
        RET


   A side note:  van Gilluwe in "The Undocumented PC" says
that the Int 1aH function 0 should be used only by the OS.
This is because if it is used, it clears the "24-hour overrun
flag", and if you manage to do that, instead of the os doing
it, you have caused the OS to lose a day.  Seems unlikely?

Regards,

Steve N.
Edit: Fix dumb error...
SRN

dedndave

you're absolutely right about the rollover flag, Steve
i had never thought much about it - always ignored the flag
that means there is a lot of broken software out there - lol
of course, you can set the flag at 0040:0070, but, if you are doing that, you may as well get the tick count from 006C   :bg

MichaelW

amrac,

As a test I threw together an app that does what I think you are describing. I ended up with ~200 lines of code, not including the comments, blank lines, etc. While I am not going to post the complete source, the attachment does contain the EXE. I tested only under Windows 2000, where the app had to be run full-screen. There is only one ball in flight at a time. For the ball paths the x coordinates are random. I set the ball animation speed so it starts out slow, and then speeds up every 10 balls, to the point of becoming completely unplayable in the vicinity of 50 balls. Under DOS or Windows 9x the animation speed should be about 1/3 of what it is under Windows NT/2000/XP. Use the left and right cursor-control keys to move the paddle. The ball number is displayed in the upper-left corner and the current score in the upper-right corner. Intercepting a ball with the paddle will increment the score, and missing it will decrement the score. Press Escape to exit at any time.

In case you are not already aware of the feature of the Interrupt 10h, Function 0Ch that allows it to XOR the pixel onto the screen, I included a demo app.

eschew obfuscation

dedndave

#33
amrac - i was playing around with some code
at the same time, thinking about what the best approach to your problem is   BigGrin
i think the best way to go might be to write your own keyboard driver
the keyboard, by design, sends a signal whenever a key is pressed and again when it is released
the BIOS driver converts this into scan codes and key codes and handles the repeat delay and rate - all that
the repeat delay and rate are not desirable for what you want to do
i have done this kind of thing in the past (many years ago - lol)
it is a bit involved - but, i can do it again
the thing is - it will take me some time
right now, i had promised Zulfi i would work on a boot-sector for him
(another little thing i have wanted to do for a long time)
let me take care of that project, then come back to this one
that will give me some time to toss it around in my head for a while and let it ferment   BigGrin

in the mean time, i wrote this little quicky demo for video mode 13h that you might like
when we employ a keyboard driver, we may want to use that mode to get 256 colors   ThumbsUp

oh - press any key to exit the program
then, you can use Alt-Enter to toggle between full-screen and normal dos window

dedndave

#34
i like it Michael   :U

it looks like the makings of single-player pong, breakout, centipede or even space invaders - lol
i don't know what he has in mind when the ball hits the paddle

i don't know how many hours i spent playing "Digger" - a DigDug knockoff   :P


amrac

Hi Michael
Yes, that's exactly what I'm looking for. Thanks!


amrac

Hi dedndave
Thanks for the file I liked it. I think I have the solution for my problem. I have to join the procedures altogether. I have to put the little balls falling and wait for the user to press the keys at the same time. I really don't want you to waist time with my project because I think I have the solution. I don't know if I'm going to find another problem because I'm going to try this other way of solving my problem. But anyway, thanks a lot! :U

dedndave

yes - you should be able to have a routine for each, then service them in "round robin" fashion
i.e. a loop where you call the keyboard routine, call the paddle routine, call the ball routine, then start at the top of the loop again

amrac

I've solved the problem and now I have another problem that has to do with preserving the values of registers.
My procedure is working like this:
-determine the column for the ball

-if the ball didn't rich the bottom

-1(true)make the ball fall

-2(true)draw the rectangle

-3(true)make the ball fall

-4(true) wait for a pressed key

-(false)determine the column of the ball

But the problem is that the first time the ball falls it falls correctly. The second time it falls, it jumps from one column to another. That is, it falls till the middle of the screen and then jumps to another column. And it falls always in the same columns (two columns alternately). And I know that the code that makes the balls fall randomly in several columns, work because I've already tested it. This means that it is getting the value for the column from some other procedure. My code that generates the columns randomly is:

push ax
   push bx
   push dx
   push cx
   mov quedas,180
   mov ah,2ch      ;para ir buscar as centésimas de segundo
      int 21h
      sub dh,dh
      mov ax,dx      ;para fazer a multiplicação do valor por ah
      mov cx,0ah
      mul cx
      ;mov aleatorio, ax   ;guarda os centesimos de segundo em aleatorio
      ;o resultado da multiplicação está em ax
      ;o resto fica em dx
      ;vai dividir ax por 2bch
      mov bx,2bch
      div bx
      cmp dx,12ch      ;verificar se o resto da divisao é maior q 300
      jg maior
      maior: mov coluna,12ch      ; se o resto da divisao for maior que 300 retorna a coluna 300
      mov coluna,dx            ;poe o resto da divisao na coluna
   pop cx
   pop dx
   pop bx
   pop ax   
   



Aren't those pushes enough to preserve the values of the registers? How to procede to preserve correctly the values of the registers?

dedndave

hiya amrac

first - this code can be simplified a little bit...

      sub dh,dh
      mov ax,dx      ;para fazer a multiplicação do valor por ah
      mov cx,0ah
      mul cx

MOV DH,0 is as small as SUB DH,DH
you might use that on a word register to make the code 1 byte smaller
MOV DX,0 is 3 bytes - SUB DX,DX is 2 bytes

but, just put 10 into the AL register and multiply it by DL - the result will be in AX, CX and DX won't be affected...

        mov     al,10
        mul     dl

as for the column jump, the code modifies the "coluna" value, whether the registers are pushed or not

      maior: mov coluna,12ch      ; se o resto da divisao for maior que 300 retorna a coluna 300
      mov coluna,dx            ;poe o resto da divisao na coluna

that code doesn't make sense   :bg

amrac

Quote from: dedndave on January 12, 2010, 12:21:24 PM

as for the column jump, the code modifies the "coluna" value, whether the registers are pushed or not

      maior: mov coluna,12ch      ; se o resto da divisao for maior que 300 retorna a coluna 300
      mov coluna,dx            ;poe o resto da divisao na coluna

that code doesn't make sense   :bg
I've runned this code and it runs fine. Sometimes I get a value in dx which is bigger than 12ch and in that case I want the value in coluna to be 12ch. That's because I want the ball to fall only in the left most 300 columns.
But I still don't know what is the right manner to preserve the registers in the procedures. That I think is the problem of my code. The random column code is running fine in another program without the rectangle.

dedndave

it looks like this code is used to generate a random column number for a new ball to drop
if it is causing the ball to jump columns, it is because it is being executed before the ball hits the last row
perhaps you are trying to have more than one ball at a time ?
i don't know, as i can't see the rest of the code   :P

if you want to replace that code with something a little nicer, try this code...

        mov     quedas,180     ;falls = 180
        push    ax
        push    bx
        push    dx
        push    es
        xor     ax,ax
        mov     es,ax
        les     ax,es:[46Ch]
        mov     dx,es
        mov     bx,301
        div     bx
        mov     coluna,dx
        pop     es
        pop     dx
        pop     bx
        pop     ax

one problem that your code has is something like this...
a new random column is selected from a range of 0 to 699
if it is over 300, you set it to the limit value of 300
the problem is - it will be 300 more often than any other value
just divide by 301 - the remainder can never be more than 300   :U

amrac

Hi dedndave
Thanks for your reply.
I've copied you're code and run it and the result is exactly the same. The ball falls and then jumps to another column. This only confirms what I suspected. I'm not preserving the registers the right way in another procedure.
One question. What does this code do:
les     ax,es:[46Ch]

dedndave

LES is really just a shortcut
i wanted to load the timer value from 0000:046C, which is a dword
LES AX,xxxx gets the dword, low order word into AX, high order word into ES
then, i put the high order word into DX, where i wanted it
you could do the same thing with this code...

        mov     ax,es:[46Ch]
        mov     dx,es:[46Eh]

dedndave

put your asm file into a zip
below the reply window is a link for Additional Options...
click that, and attach the zip file
i will look at the entire code and see if i can spot the problem   :U