+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Thread: Bouncing Ball

  1. #1
    Wire Noob BODYPRINT's Avatar
    Join Date
    Mar 2007
    Posts
    11

    Default

    I learned a lot from the simple screen tutorial. So I thought I'd complicate it a little and try to help more of you.

    This tutorial will draw 4 walls on a digital screen then draw a ball bouncing around.

    Here are the steps.
    1. Spawn 1 CPU, 1 Digital Screen (Preferably large monitor), 1 input and 1 Arithmetic Add
    2. Attach Screen Clk to Add
    3. Attach Add (A) to CPU Port 3
    4. Attach Screen Pixel G to CPU Port 2
    5. Attach Screen Pixel X to CPU Port 0
    6. Attach Screen Pixel Y to CPU Port 1
    7. Attach CPU Clk to Input
    The reason I used an arithmetic add chip is because going straight from the screen clk to the CPU port 3 doesn't work for me. I think there are a few bugs still floating around after the latest updates. So if you are trying something and it doesn't work, try experiment with different chips to get different results.

    Now here's the Assembly code for the CPU. You can enter this in game or save it as a txt file and load it into the CPU list.
    Save location for CPU files is in the directory Steam\steamapps\%username%\garrysmod\garrysmod\dat a\CPUChip\

    Code:
    //OUTPUTS
    //PORT 0 - PIXEL X coord to screen
    //PORT 1 - PIXEL Y coord
    //PORT 2 - PIXEL G 0=off 255=on
    //PORT 3 - SCREEN CLOCK=1 to enable drawing
    //-----------------------
    //DEFINE VARIABLES
    //-----------------------
    DATA;
    alloc cx;********//Clear X coord
    alloc cy;********//Clear Y coord
    //-----------------------
    //START PROGRAM
    //-----------------------
    CODE;
    //Draw Border Lines
    mov eax,0;********//Initial X Coord
    mov ebx,2;********//Y Border Coord 1
    mov ecx,29;********//Y Border Coord 2
    mov port0,eax;********//Output X to screen
    mov port1,ebx;********//Output Y1 to screen
    mov port2,255;********//Draw pixels
    mov port3,1;********//Allow Screen drawing
    lineloop1:
    ****mov port0,eax;****//Output X to screen
    ****mov port1,ebx;****//Output Y1 to screen
    ****mov port1,ecx;****//Output Y2 to screen
    ****inc eax;****//increase X Coord
    ****cmp eax,32;****// are we at 32? X range is 0-31
    jne lineloop1;********// loop until we are at 32
    mov eax,2;********//Initial Y Coord
    mov ebx,0;********//X Border Coord 1
    mov ecx,31;********//X Border Coord 2
    lineloop2:
    ****mov port1,eax;****//Output Y to screen
    ****mov port0,ebx;****//Output X1 to screen
    ****mov port0,ecx;****//Output X2 to screen
    ****inc eax;****//increase Y Coord
    ****cmp eax,29;****// are we at 29? Y range is 2-29
    jne lineloop2;********// loop until we are at 29
    //Init Ball
    mov eax,10;********//Ball X Coord
    mov ebx,10;********//Ball Y Coord
    mov ecx,1;********//Ball X direction
    mov edx,1;********//Ball Y direction
    mov esi,0;********//Store 0 into Registry esi
    dec esi;********//esi=-1 for reversing ball movements later
    //----------------------------------
    //We need to disable screen drawing 
    //while moving pixels diagonally to
    //avoid left over pixels on sides
    //----------------------------------
    mov port3,0;********//Disable Screen drawing
    mov port0,eax;********//Output X coord
    mov port1,ebx;********//Output Y coord
    //----------------------------------
    //Now the pixel is moved to its
    //final location we can start
    //drawing again.
    //----------------------------------
    mov port3,1;********//Allow Screen drawing
    //Main Loop
    loop:
    ****mov #cx,eax;****//Store coords for clearing
    ****mov #cy,ebx;
    ****add eax,ecx;****//calculate new x coord
    ****add ebx,edx;****//calculate new y coord
    ****cmp eax,30;****//is x=30 /on border
    ****je revx;****//yes? reverse x
    ****cmp eax,1;****//is x=1 /on border
    ****je revx;****//yes? reverse x
    retx:************//return from reverse x
    ****cmp ebx,28;****//is y=28 /on border
    ****je revy;****//yes? reverse y
    ****cmp ebx,3;****//is y=3 /on border
    ****je revy;****//yes? reverse y
    rety:************//return from reverse y
    ****mov port3,0;****//Disable Screen drawing
    //----------------------------------
    //We need to disable screen drawing 
    //while moving pixels diagonally to
    //avoid left over pixels on sides
    //----------------------------------
    ****mov port0,eax;****//Update X coord
    ****mov port1,ebx;****//Update Y coord
    ****mov port2,255;****//draw pixel at new coords
    //----------------------------------
    //Now the pixel is moved to its
    //final location we can start
    //drawing again.
    //----------------------------------
    ****mov port3,1;****//Allow Screen drawing
    ****mov port3,0;****//Disable Screen drawing
    ****mov port0,#cx;****//move to old X coord
    ****mov port1,#cy;****//move to old Y coord
    ****mov port2,0;****//Clear pixels
    ****mov port3,1;****//Allow Screen drawing
    jmp loop;
    revx:
    ****mul ecx,esi;****//Reverse X
    jmp retx;
    revy:
    ****mul edx,esi;****//Reverse Y
    jmp rety;
    After the code is entered or loaded in the Wire CPU menu, compile the code by updating the spawned CPU with the new code and check it has compiled OK in the console. If you are getting a huge amount of errors in the console, update the CPU again with the same code and recheck the console.

    It helps when starting to run a debugger on the CPU to watch the error numbers and watch the port outputs.

    Now enable the input to run the CPU.
    If all goes well you should see the walls appear then the ball starts moving on the screen.

    Any errors, feedback, tips, code optimization etc is greatly welcome as I am still learning this as well.

    Hope this helps some of you.

  2. #2
    Wire Amateur Neotracer's Avatar
    Join Date
    Mar 2007
    Location
    Germany
    Posts
    75

    Default

    Thaks for the tip with the add gate!!!
    i tryed other gates as "bridge" because i noticed the same bug, but they dosn´t worked
    (console returns error "compare string with number" or somthing like that)
    Es gibt genau 10 Typen von Menschen auf der Welt. Welche die Binär verstehen und Welche die nicht.
    (german)
    STOP USING BMP FILES! USE JPEG FOR YOUR SAKE!!

  3. #3
    Wire Noob BODYPRINT's Avatar
    Join Date
    Mar 2007
    Posts
    11

    Default

    (console returns error "compare string with number" or somthing like that)[/b]
    Yeah, just recompile again by updating the CPU with the same code. Another bug I think.
    Let me know if it works and I'll add this to the tutorial.

    Thanks.

  4. #4
    Wire Amateur conman420's Avatar
    Join Date
    Feb 2007
    Location
    UK
    Posts
    98

    Default

    I can't get any arithmetic functions to work
    How did you do it?

    Nice code, maybe soon a physics engine in Garry's mod?!?!?

  5. #5
    That furred thing Black Phoenix's Avatar
    Join Date
    Feb 2007
    Location
    Kyiv, Ukraine
    Posts
    3,565

    Default

    Code:
    //OUTPUTS
    //PORT 0 - PIXEL X coord to screen
    //PORT 1 - PIXEL Y coord
    //PORT 2 - PIXEL G 0=off 255=on
    //PORT 3 - SCREEN CLOCK=1 to enable drawing
    //DEFINE VARIABLES
    alloc cx;********//Clear X coord
    alloc cy;********//Clear Y coord
    //Draw Border Lines
    mov eax,0;********//Initial X Coord
    mov ebx,2;********//Y Border Coord 1
    mov ecx,29;********//Y Border Coord 2
    mov port0,eax;********//Output X to screen
    mov port1,ebx;********//Output Y1 to screen
    mov port2,255;********//Draw pixels
    mov port3,1;********//Allow Screen drawing
    Are you aware that you should place "DATA" before variables, and "CODE" before the code, or else you will have to put the allocation on the end. The alloc macro writes zero on current address, and that may screw up your code
    I'm a wire-crazy person with a tail.

    Take a daily journey into my brain

    D2K5

  6. #6
    That furred thing Black Phoenix's Avatar
    Join Date
    Feb 2007
    Location
    Kyiv, Ukraine
    Posts
    3,565

    Default

    Zero means program end opcode.

    Also awesome program, why don't you make pong game with it?
    I'm a wire-crazy person with a tail.

    Take a daily journey into my brain

    D2K5

  7. #7
    Wire Noob BODYPRINT's Avatar
    Join Date
    Mar 2007
    Posts
    11

    Default

    Zero means program end opcode.

    Also awesome program, why don't you make pong game with it?[/b]
    Ah, thanks for your help Black. I love this mod of a mod of a mod !! Awesome

    Is the lack of DATA and CODE the reason the program ends as soon as I run it the first time?
    I'll fix it in the tutorial.

    A question for you Black. When I store -1 in a registry (mov eax,-1, when I go to compile it says 'no such label on program line xx. It thinks the -1 is a reference to a label. Is there an easy way to store negative numbers. Or should I just use the method I have in my program?
    Also, in the jump op-codes is there a Jump Subroutine op-code?

    My aim is to make a pong eventually, but it will be pretty slow and difficult with the Digital Screen plugin as it is. If I increase the CPU frequency to 5000 as the program is now, the Digital Screen can't keep up and leaves pixels behind. I could increase program speed by spreading the pixel commands over the code to seperate them. That will give the screen time to recieve the data from the CPU.
    Does anybody know if there is documentation for the digital screens? There may be some functions that I don't know about that could make it easier to program for.

    @conman420, I don't quite understand what problem you are having. Do you mean with the CPU op-codes or the arithmetic add chip?
    If you mean op-code arithmetic, it's quite simple.

    There are 4 main registries in the CPU that can hold numbers...

    eax ebx ecx edx

    These can store numbers for use in arithmetic fuctions.

    So to add 1 to eax just use inc eax;
    To add 62 to eax use add eax,62;
    To add 2 registries together use add ecx,eax;
    The result is always stored in the first registry. So in the above example ecx gets the result of the add ecx and eax function.

  8. #8
    Wire Amateur conman420's Avatar
    Join Date
    Feb 2007
    Location
    UK
    Posts
    98

    Cool

    Thanks I figured it out eventually, I was trying to add to ports together and eventually came up with this:

    <div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-spacere;overflow:auto'>loop:
    mov eax,port1
    add eax,port2
    mov port0,eax
    jmp loop</div>

    Thanks for your help. Also Gmod pong would be awesome! Though I do agree about the limitations of the screen may make it difficult.

  9. #9
    That furred thing Black Phoenix's Avatar
    Join Date
    Feb 2007
    Location
    Kyiv, Ukraine
    Posts
    3,565

    Default

    There is an error in assembler, when it thinks that -1 is a reference to label. Right now no negative numbers are supported, and easiest way is to
    Code:
    mov eax,0; sub eax,63;
    etc. This will be fixed in next version.

    Yes, the lack of code and data made your program to stop as soon as it was executed. But because errors do not trigger RESET, CPU state is saved, and it would execute at next opcode when run again. Thats why usually few more power ons, and it works.

    There will be something new soon - programmable screen/GPU. In fact thats screen, which you can draw on, clientside. It will support direct memory access from CPU, so speed is not a problem.

    BODYPRINT, there is a sub-routine call, it works like this:
    Code:
    call something; //Execute function "something"
    -----some code------
    something:
    **-----some code------
    ret; //Return from call
    Each time you do "CALL" it pushes current program location (IP) into stack. So beware of screwing up stack in function call, or before it.
    I'm a wire-crazy person with a tail.

    Take a daily journey into my brain

    D2K5

  10. #10
    Wire Noob BODYPRINT's Avatar
    Join Date
    Mar 2007
    Posts
    11

    Default

    BODYPRINT, there is a sub-routine call, it works like this:
    Code:
    call something; //Execute function "something"
    -----some code------
    something:
    **-----some code------
    ret; //Return from call
    Each time you do "CALL" it pushes current program location (IP) into stack. So beware of screwing up stack in function call, or before it.[/b]
    Yeah, I saw the &#39;CALL&#39; op-code, but i was thinking more along the lines of...

    Code:
    cmp eax,10;**** //compare eax with 10
    jsre function;****//if equal then jump to subroutine labeled function
    -----continue code----
    
    function:
    -----func code here-----
    ret; //Return to code after jump sub routine call

+ Reply to Thread
Page 1 of 2 12 LastLast

Similar Threads

  1. Bouncing Ball (ConsoleScreen + Egate)
    By 3dfactor in forum Finished contraptions
    Replies: 3
    Last Post: 09-05-2008, 07:31 PM
  2. Bouncing with a vector thruster...
    By iMagUdspEllr in forum Installation and Malfunctions Support
    Replies: 6
    Last Post: 07-01-2008, 01:59 PM
  3. Hover-Ball
    By paal in forum Ideas & Suggestions
    Replies: 5
    Last Post: 06-26-2008, 03:24 AM
  4. Huge Ball Machine
    By _Kilburn in forum Finished contraptions
    Replies: 15
    Last Post: 12-17-2007, 01:35 AM
  5. Ball balancer
    By Solidacid in forum Finished contraptions
    Replies: 11
    Last Post: 10-12-2007, 03:42 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
proceed-collector
proceed-collector
proceed-collector
proceed-collector
linguistic-parrots
linguistic-parrots
linguistic-parrots
linguistic-parrots