Shop Learn P1 Docs P2 Docs Events
a (try) version of pong and solved video driver issue — Parallax Forums

a (try) version of pong and solved video driver issue

ReinhardReinhard Posts: 464
edited 2023-01-14 20:01 in Propeller 2
I have never read an implementation of Pong and have wanted to work on it for a long time.
In principle, it works the way I thought it would. At times strange effects occur, but on the whole it is stable.
After the weekend, I can continue to take care of it.
At this version of pong the propeller plays against itself. The paddle position is calculated to hit the ball.
An expansion to several cogs is planned.

nice weekend
Reinhard

Comments

  • I believe the strange effect are gone with this workaround,
    but I have not a long time observed.
    LINE175		if(ym < 20 || ym > 470)
    
  • roglohrogloh Posts: 4,688
    edited 2020-07-17 11:28
    Hi Reinhard,

    I've modified your pong code to speed it up and it runs smoother now. Not so much flicker.
    You can use the fillCircle routine I included to draw circles of any colour and size, as well as
    syncing up to the blanking period to avoid tearing etc. Clearing the entire screen
    is slow, so you can erase just the ball and paddle. Take a look at what I changed.

    By the way, no need to distribute the entire video folder, just p2videodrv.spin2 is enough.

    Cheers,
    Roger.
    *
    +--------------------------------------------------------------------
    | TERMS OF USE: MIT License
    +--------------------------------------------------------------------
    Permission is hereby granted, free of charge, to any person obtaining
    a copy of this software and associated documentation files
    (the "Software"), to deal in the Software without restriction,
    including without limitation the rights to use, copy, modify, merge,
    publish, distribute, sublicense, and/or sell copies of the Software,
    and to permit persons to whom the Software is furnished to do so,
    subject to the following conditions:
    
    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    +--------------------------------------------------------------------
    */
    
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <math.h>
    
    #include <propeller2.h>
    #define P2_TARGET_MHZ 160
    #include "sys/p2es_clock.h"
    
    #define BAUD 230400
    
    // screen size
    #define SCRN_WIDTH 640
    #define SCRN_HEIGHT 480
    
    // VGA definitions
    #define VGA_BASE_PIN 48
    #define VGA_VSYNC_PIN (VGA_BASE_PIN + 4)
    
    // enough room for a scanline at full colour bit depth
    #define LINEBUFSIZE (1920*4)
    
    // RGBI8 colortable with full luminance
    #define ORANGE	0b000_11111
    #define BLUE	0b001_11111
    #define	GREEN	0b010_11111
    #define	CYAN	0b011_11111
    #define RED		0b100_11111
    #define	MAGENTA	0b101_11111
    #define	YELLOW	0b110_11111
    #define	WHITE	0b111_11111
    #define	BLACK	0
    
    // the video object
    struct __using("video/p2videodrv.spin2") vid;
    
    // space for video driver display and region info
    int display1[14];
    int first[14];
    
    // the actual frame and line buffer
    char frameBuffer[SCRN_WIDTH*SCRN_HEIGHT];
    int lineBuffer[LINEBUFSIZE];
    
    
    void Setup_Video()
    {
        vid.initDisplay(@display1, vid.VGA, VGA_BASE_PIN, VGA_VSYNC_PIN, vid.RGBHV, @lineBuffer, LINEBUFSIZE, 0);
    
        vid.initRegion(@first, vid.RGBI, 480, 0, 0, 0, 8, &frameBuffer[0], 0);
      
        // enable display list
        vid.setDisplayRegions(display1, first);
    }
    
    void line( int x0, int y0, int x1, int y1,int color)
    {
      int dx =  abs(x1-x0), sx = x0<x1 ? 1 : -1;
      int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
      int err = dx+dy, e2; /* error value e_xy */
    
      for(;;){  /* loop */
        plot(x0,y0,color);
        if (x0==x1 && y0==y1) break;
        e2 = 2*err;
        if (e2 > dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
        if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
      }
    }
    
    // routine to plot a point at screen coordinate (x,y) and color "color"
    void plot(int x, int y, int color)
    {
        frameBuffer[y*SCRN_WIDTH+x] = color;
    }
    
    void clearscreen (int color)
    {
    	// clear the screen
        memset(frameBuffer, color , SCRN_WIDTH*SCRN_HEIGHT);	
    }
    
    // Function for circle-generation
    // using Bresenham's algorithm
    void fillCircle(void *screen, int width, int xc, int yc, int r, int colour, int bpp)
    { 
        int x, y, d;
        x = 0;
        y = r;
        d = 3 - 2 * r;
        horizLine(screen, width, xc+x, yc+y, xc-x, yc+y, colour, bpp);
        horizLine(screen, width, xc+x, yc-y, xc-x, yc-y, colour, bpp);
        horizLine(screen, width, xc+y, yc+x, xc-y, yc+x, colour, bpp);
        horizLine(screen, width, xc+y, yc-x, xc-y, yc-x, colour, bpp);
        while (x <= y)
        {
            horizLine(screen, width, xc+x, yc+y, xc-x, yc+y, colour, bpp);
            horizLine(screen, width, xc+x, yc-y, xc-x, yc-y, colour, bpp);
            horizLine(screen, width, xc+y, yc+x, xc-y, yc+x, colour, bpp);
            horizLine(screen, width, xc+y, yc-x, xc-y, yc-x, colour, bpp);
            if (d > 0)
            {
                d = d + 4 * (x - y) + 10;
                y--;
            }
            else
                d = d + 4 * x + 6;
            x++;
        }
    }
    
    
    void horizLine(void *buf, int width, int x1, int y1, int x2,int y2, int c, int bpp)
    { 
        int  len = x1-x2 + 1;
        switch(bpp)
        {
        case 8:
          bytefill(buf + x2+y1*width, c, len);
          break;
        case 16:
          wordfill(buf + 2*(x2+y1*width), c, len);
          break;
        case 32:
          longfill(buf + 4*(x2+y1*width), c, len);
          break;
         default: return; // unhandled for now
       }
    }
              
    void ball(int x0,int y0, int radius, int color)
    {
    /*
    	int x,y,t;
    	unsigned int phi = 0;
    	for(t = 0; t < 2048; t++ )
    	{
    		__asm {
    			qrotate	#5, phi
    			getqx	x
    			getqy	y
    		};	
    		line(x0,y0,x0+x,y0+y,WHITE);
    		//plot(x0+x,y0+y,WHITE);
    		phi += 0x200000}
    */
    	fillCircle(&frameBuffer, SCRN_WIDTH*8/8, x0, y0, radius, color, 8); // 8bpp
    }
    
    void paddle (int ym, int colour)
    {
    	int yo = ym - 10;
    	int yu = ym + 10;
    	line(610,yu,610,yo,colour);
    }
    
    void main()
    {
         int i;
    	
        _clkset(_SETFREQ, _CLOCKFREQ);
        Setup_Video();
        _setbaud(BAUD);
        
        int xx = 20;
        int yy = 20;
        int dx = 5;
        int dy = 5;
        int ym = 230;
        float r;
        clearscreen(BLUE);
        for (;;)
        {
    //		clearscreen(BLUE);
    		ball(xx, yy, 5, WHITE);
    		paddle(ym, WHITE);
                    vid.waitforblanking(&display1);
                    ball(xx,yy, 5, BLUE);
    		paddle(ym, BLUE);
    		
    		//usleep(10000);
    		xx += dx;
    		yy += dy;
    		// check limits
    		if(xx < 20) dx = -dx;
    		if(xx > 620) dx = -dx;
    		if(yy < 20) dy = -dy;
    		if(yy > 460) dy = -dy;
    		
    		// check relation from ball to paddle
    		if ( ((xx+5) == 610) && 
    		     (((yy) < (ym-10)) || ((yy) < (ym+10)))  
    		   )
    			dx = -dx;
    			
    		if(dx > 0)
    		{
    			r = (float)((610 - xx) / dx);
    			ym = yy + (int)r * dy;
    		}
    		else
    			ym = ym;
    		
    		if(ym < 20 || ym > 460)
    		  ym = 230;
    	}
    
    
        	
    }
    
  • @rogloh
    Thanks for the many tips. I am currently out of my home and will only have my hardware again on Monday. I can't wait to try your version!
  • @rogloh
    Your improvements are great. I now have 2 players. Is it an advantage if I split that over 2 cogs (?).
    A sound output during ping would also be interesting.

    cheers
    Reinhard
  • Cool. You could split into two Cogs but it might be harder to write the overall logic that way. As long as both Cogs don't write to the same frame buffer address it could be done. There's so much power in a single Cog for this application its not really going to be worth doing. A separate Cog like what Ahle2 has written (or the P2 port of SIDCOG) would be good for your sound effects.

    You might like to figure out a way to slide your paddles up and down on each side more smoothly too (interpolate) when they figure out the final position instead of jumping, although the jumping effect still looks okay.

    This sort of makes a good screensaver.
  • Hello,
    I tried to complle this sourcecode, without changes in the c-file(s), but with the newest version of flexspin.
    It is unsuccessful, I get Error in the spin part.

    reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/spin2cpp-5.9.24/build/flexspin -2b -Wall pingpong.c graphictools.c
    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2023 Total Spectrum Software Inc. and contributors
    Version 5.9.24-- Compiled on: Jan 13 2023
    pingpong.c
    |-p2videodrv.spin2
    home/reinhard/Schreibtisch/Propeller2/testbench2/pong/video/p2videodrv.spin2:363: error: assignment to constant `GRAPHICS_MODE'


    With the old version of fastspin I can compile:
    reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/spin2cpp-4.2.6/build/fastspin -2b -Wall pingpong.c graphictools.c
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2020 Total Spectrum Software Inc.
    Version 4.2.6 Compiled on: Jul 30 2020
    pingpong.c
    |-p2videodrv.spin2
    graphictools.c
    |-p2videodrv.spin2
    memset.c
    pingpong.p2asm
    Done.
    Program size is 347248 bytes

    and download:
    reinhard@reinhard-TUXEDO:~/Schreibtisch/Propeller2/testbench2/pong$ /home/reinhard/Schreibtisch/Propeller2/p2gcc-master/bin/loadp2 -b 230400 -p /dev/ttyUSB0 -t pingpong.binary


    Is this a issue from flexspin or a bug in the spin - graphic driver and the new flexspin in not so tolerant like the old one?

    Regards Reinhard

  • ersmithersmith Posts: 5,618

    In all the versions of p2videodrv.spin2 that I've seen, GRAPHICS_MODE is a constant (defined in the CON section) and so if the code in line 363 really is modifying it that's an error and flexspin should never have accepted it. The p2videodrv.spin2 that comes with FlexProp (in the Multi-Language/video folder; admittedly it's an old version!) does not have any such assignment. Could you share your code?

  • Thank you for the fast answer.
    Here is the zip file with all sources.
    It is the same as I posted above.
    The p2videodrv.spin2 is in the subfolder video.

  • ersmithersmith Posts: 5,618

    Line 363 of your p2videodrv.spin2 currently reads:

            byte[region][5] &= ~GRAPHICS_MODE 
    

    it should read

            byte[region][5] &= !GRAPHICS_MODE 
    

    The ~ operator modifies its argument. In fact ~ isn't even legal in Spin2, but flexspin accepts it as a hold-over from Spin1. I think older versions of flexspin incorrectly did not modify x in ~x, which may be why your code worked with the old flexspin.

  • I remember the whole thing about incorrect ~ operator behaviours ;P

  • ReinhardReinhard Posts: 464
    edited 2023-01-14 20:04

    @ersmith
    Cool, this is the solution. My skill in SPIN is not so great. I didn't find it out by myself.
    Thank you
    Reinhard

  • roglohrogloh Posts: 4,688
    edited 2023-01-15 00:12

    Must have been an old version as ersmith mentioned. Versions of my P2 video driver since v0.92 had that issue fixed. Versions are posted here in the first post...
    https://forums.parallax.com/discussion/170676/p2-dvi-vga-driver

Sign In or Register to comment.