Added pong

This commit is contained in:
Martin Kuettler
2023-10-23 14:05:47 +02:00
committed by vreusch
parent 20d8c2c149
commit ccd7c4a959
26 changed files with 1991 additions and 0 deletions

2
src/l4/pkg/pong/Control Normal file
View File

@@ -0,0 +1,2 @@
requires: l4sys l4re crtn stdlibs libpthread libstdc++ libc_be_mem
maintainer: warg@os.inf.tu-dresden.de

6
src/l4/pkg/pong/Makefile Normal file
View File

@@ -0,0 +1,6 @@
PKGDIR = .
L4DIR ?= $(PKGDIR)/../..
TARGET = include server example
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,12 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
vpath %.bmp ..
MODE = static
#MODE = shared
TARGET = pong-client
SRC_CC = main.cc
REQUIRES_LIBS = cxx_libc_io cxx_io libpthread libc_be_mem libstdc++
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,179 @@
#include <l4/cxx/iostream>
#include <l4/cxx/l4iostream>
#include <l4/re/env>
#include <l4/re/namespace>
#include <l4/util/util.h>
#include <l4/pong/logging.h>
#include <l4/cxx/exceptions>
#include <l4/cxx/ipc_stream>
#include <l4/re/util/cap_alloc>
#include <pthread-l4.h>
#include <iostream>
class Paddle
{
public:
Paddle(int speed, unsigned long svr);
void run();
int connect();
int lifes();
void move(int pos);
private:
unsigned long svr;
unsigned long pad_cap;
int speed;
};
static void *
thread_fn(void *ptr)
{
Paddle *pd = (Paddle *)ptr;
pd->run();
return 0;
}
class Main
{
public:
void run();
};
int
Paddle::connect()
{
L4::Ipc::Iostream s(l4_utcb());
pad_cap = L4Re::Util::cap_alloc.alloc<void>().cap();
while (1)
{
L4::cout << "PC: connect to " << L4::hex << svr << "\n";
s << 1UL;
s << L4::Ipc::Small_buf(pad_cap);
l4_msgtag_t err = s.call(svr);
l4_umword_t fp;
s >> fp;
L4::cout << "FP: " << fp << " err=" << err << "\n";
if (!l4_msgtag_has_error(err) && fp != 0)
{
L4::cout << "Connected to paddle " << (unsigned)fp << '\n';
return pad_cap;
}
else
{
switch (l4_utcb_tcr()->error)
{
case L4_IPC_ENOT_EXISTENT:
L4::cout << "No paddle server found, retry\n";
l4_sleep(1000);
s.reset();
break;
default:
L4::cout << "Connect to paddle failed err=0x" << L4::hex
<< l4_utcb_tcr()->error << '\n';
return l4_utcb_tcr()->error;
};
}
}
return 0;
}
int
Paddle::lifes()
{
L4::Ipc::Iostream s(l4_utcb());
s << 3UL;
if (!l4_msgtag_has_error((s.call(pad_cap))))
{
int l;
s >> l;
return l;
}
return -1;
}
void
Paddle::move(int pos)
{
L4::Ipc::Iostream s(l4_utcb());
s << 1UL << pos;
s.call(pad_cap);
l4_sleep(10);
}
Paddle::Paddle(int speed, unsigned long svr) : svr(svr), speed(speed) {}
void
Paddle::run()
{
L4::cout << "Pong client running...\n";
int paddle = connect();
if (paddle == -1)
return;
int pos = 180;
int c = 0;
while (1)
{
if (c++ >= 500)
{
c = 0;
L4::cout << '(' << pthread_self() << ") Lifes: " << lifes() << '\n';
}
move(pos);
pos += speed;
if (pos < 0)
{
pos = 0;
speed = -speed;
}
if (pos > 1023)
{
pos = 1023;
speed = -speed;
}
}
}
static l4_cap_idx_t
server()
{
L4::Cap<void> s = L4Re::Env::env()->get_cap<void>("PongServer");
if (!s)
throw L4::Element_not_found();
return s.cap();
}
Paddle p0(-10, server());
Paddle p1(20, server());
void
Main::run()
{
L4::cout << "Hello from pong example client\n";
pthread_t p, q;
pthread_create(&p, NULL, thread_fn, (void *)&p0);
pthread_create(&q, NULL, thread_fn, (void *)&p1);
L4::cout << "PC: main sleep......\n";
l4_sleep_forever();
}
int
main()
{
redirect_to_log(std::cout);
redirect_to_log(std::cerr);
Main().run();
return 0;
};

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
# All header files found in this directory tree will be automatically
# installed in a way that they can be included with
# #include <l4/pkgname/yourfile.h> later.
# No need to list them in this Makefile.
include $(L4DIR)/mk/include.mk

View File

@@ -0,0 +1,57 @@
// -*- C++ -*-
#pragma once
#include <ostream>
void send_ipc(std::string const &msg);
void redirect_to_log(std::ostream &os);
void
send_ipc(std::string const &msg)
{
printf("%s", msg.data());
}
template <typename CharT = char>
class Log_Buffer : public std::basic_streambuf<CharT>
{
private:
std::string buffer;
public:
using Base = std::basic_streambuf<CharT>;
using char_type = typename Base::char_type;
using int_type = typename Base::int_type;
Log_Buffer(std::size_t size) : buffer(size, '\0')
{
Base::setp(&buffer.front(), &buffer.back());
}
int_type
overflow(int_type ch) override
{
Log_Buffer::sync();
Base::sputc(ch);
return ch;
}
int
sync() override
{
send_ipc(buffer);
Base::setp(this->pbase(), this->epptr());
return 0;
}
};
void
redirect_to_log(std::ostream &os)
{
// The basic_ios interface expectes a raw pointer...
auto buf = new Log_Buffer<char>(256);
auto old_buf = os.rdbuf(buf);
// I guess we should delete this here?
delete old_buf;
}

View File

@@ -0,0 +1,4 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,36 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
include $(L4DIR)/mk/Makeconf
#MODE = shared
MODE = static
TARGET = pong-server
OBJS += ball.img.o paddle.img.o
SRC_CC = main.cc gfx-drv.cc ball.cc env.cc sintab.cc paddle.cc \
paddle-server.cc
CXXFLAGS += -Wall -Wreorder
REQUIRES_LIBS = cxx_libc_io cxx_io libpthread libc_be_mem libstdc++
include $(L4DIR)/mk/prog.mk
CHECKCXX = $(shell if $(CXX) $(1) -S -o /dev/null -xc++ /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
CXXFLAGS += $(call CHECKCXX,-fno-threadsafe-statics,)
%.img.o: %.img
$(OBJCOPY) -B $(BFD_ARCH) -I binary -O $(OFORMAT) $< $@
paddle.img: $(SRC_DIR)/paddle.bmp
tail -c 3600 $< >$@
ball.img: $(SRC_DIR)/ball.bmp
tail -c 1200 $< >$@
#%.img: $(SRC_DIR)/%.bmp
# convert $< rgb:$@

View File

@@ -0,0 +1,54 @@
/*
* (c) 2012 Nils Asmussen <nils@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/re/error_helper>
#include <pthread-l4.h>
#include <pthread.h>
namespace L4
{
class PosixThread
{
public:
PosixThread() : _thread(){};
virtual ~PosixThread(){};
L4::Cap<L4::Thread>
self() const
{
return L4::Cap<L4::Thread>(pthread_l4_cap(pthread_self()));
};
void
start()
{
L4Re::chksys(pthread_create(&_thread, NULL, &PosixThread::start_run, this));
};
private:
virtual void run() = 0;
PosixThread(const PosixThread &);
PosixThread &operator=(const PosixThread &);
static void *
start_run(void *arg)
{
static_cast<PosixThread *>(arg)->run();
return NULL;
};
private:
pthread_t _thread;
};
} // namespace L4

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,126 @@
#include "ball.h"
#include <l4/cxx/iostream>
#include "math.h"
extern char _binary_ball_img_start;
Ball::Ball(unsigned fg, unsigned bg)
: x(50 * 512),
y(150 * 512),
s(0 * 512),
vx(4 * 512),
vy(3 * 512),
ox(50),
oy(50),
rad(10),
fg(fg),
bg(bg),
bm(20, 20, 3, 0, 8, 8, 8, 16, 8, Bitmap::CW0, &_binary_ball_img_start)
{
}
void
Ball::restart()
{
x = 270 * 512;
y = 120 * 512;
s = 0;
vy = -vx;
vx = -vy;
}
int
Ball::distance(int x1, int y1, int x2, int y2) const
{
int vx = x_speed();
int vy = y_speed();
int x = (this->x + vx) / 512;
int y = (this->y + vy) / 512;
int m = (x2 - x1);
int n = (y2 - y1);
// check ball direction (only one side of the mirror is reflective)
if ((vy * m - vx * n) > 0)
return rad * rad + 10;
int z = (x - x1);
int v = (y - y1);
int r = m * z + n * v;
int b = m * m + n * n;
int g = (r * 512) / b;
// check whether the ball hits the mirror
if (g < 0 || g > 512)
return rad * rad + 10;
// calculate the squre of the distance (enough to compare)
signed long long a = n * z - m * v;
signed long long l = a * a / b;
return l;
}
bool
Ball::collide(int x1, int y1, int x2, int y2)
{
// check the distance to the mirror
if (distance(x1, y1, x2, y2) > (rad * rad))
return false;
// collosion: calculate the new velocity
int aax = x2 - x1;
int aay = y2 - y1;
#ifdef BALL_SPIN
int ax = (aax * cos(s) - aay * sin(s)) / 512;
int ay = (aay * cos(s) + aax * sin(s)) / 512;
#else
int ax = aax;
int ay = aay;
#endif
int x = (2 * (vx * ax + vy * ay)) * 512 / (ax * ax + ay * ay);
vx = x * ax / 512 - vx;
vy = x * ay / 512 - vy;
if (abs(vx) < 20)
vx = sign(vx) * 20;
if (abs(vy) < 20)
vy = sign(vy) * 20;
return true;
}
void
Ball::draw(Gfx<Screen_buffer> const &s)
{
int X = x_pos();
int Y = y_pos();
if (ox == X && oy == Y)
return;
unsigned xx = bm.xres() / 2;
unsigned yy = bm.yres() / 2;
ux1 = ((X < ox) ? X : ox) - xx;
ux2 = ((X < ox) ? ox : X) + xx;
uy1 = ((Y < oy) ? Y : oy) - yy;
uy2 = ((Y < oy) ? oy : Y) + yy;
bm.draw(s, X - xx, Y - yy);
// s.rect( X-8, Y-8, X+8, Y+8, fg );
ox = X;
oy = Y;
}
void
Ball::del(Gfx<Screen_buffer> const &s)
{
int X = x_pos();
int Y = y_pos();
if (ox == X && oy == Y)
return;
unsigned xx = (bm.xres() + 1) / 2;
unsigned yy = (bm.yres() + 1) / 2;
s.rect(ox - xx, oy - yy, ox + xx, oy + yy, bg);
}

View File

@@ -0,0 +1,95 @@
#ifndef PONG_BALL_H__
#define PONG_BALL_H__
#include "gfx-drv.h"
// Simply the ball
class Ball
{
public:
Ball(unsigned fg, unsigned bg);
int
x_pos() const
{
return x / 512;
}
int
y_pos() const
{
return y / 512;
}
int
spin() const
{
return s / 512;
}
int
x_speed() const
{
return vx;
}
int
y_speed() const
{
return vy;
}
bool collide(int x1, int y1, int x2, int y2);
void draw(Gfx<Screen_buffer> const &s);
void del(Gfx<Screen_buffer> const &s);
void
move()
{
x += x_speed();
y += y_speed();
#ifdef BALL_SPIN
int const step = 50;
if ((s < step) && (s > -step))
s = 0;
else if (s <= -step)
s += step;
else
s -= step;
#endif
}
int
u_x1() const
{
return ux1;
}
int
u_x2() const
{
return ux2;
}
int
u_y1() const
{
return uy1;
}
int
u_y2() const
{
return uy2;
}
void restart();
private:
int distance(int x1, int y1, int x2, int y2) const;
int x, y, s, vx, vy;
int ox, oy;
int ux1, ux2, uy1, uy2;
int rad;
unsigned fg, bg;
Bitmap bm;
};
#endif // PONG_BALL_H__

View File

@@ -0,0 +1,111 @@
#include "env.h"
#include <l4/cxx/iostream>
Obstacle::~Obstacle() {}
void
Obstacle::del(Gfx<Screen_buffer> &) const
{
}
Area const &
Obstacle::blt_area() const
{
static Area a(0, 0, 0, 0);
return a;
}
bool
Line::collide(Ball &b) const
{
if (valid())
return b.collide(x1, y1, x2, y2);
else
return false;
}
void
Line::draw(Gfx<Screen_buffer> & /*gfx*/) const
{
}
void
Env::draw_field() const
{
buf.hline(10, 0, buf.width() - 10, buf.color(0xff, 0, 0));
buf.hline(10, buf.height() - 1, buf.width() - 10, buf.color(0xff, 0, 0));
buf.vline(10, 0, buf.height() - 1, buf.color(0xff, 0, 0));
buf.vline(buf.width() - 10, 0, buf.height() - 1, buf.color(0xff, 0, 0));
}
Env::Env(Gfx<Screen_buffer> &buf, Gfx<Screen> &scr, Ball &ball)
: last(Max_obstacles), buf(buf), scr(scr), ball(ball)
{
buf.fill(buf.color(0, 0, 0x0));
xo = (scr.width() - buf.width()) / 2;
yo = (scr.height() - buf.height()) / 2;
draw_field();
scr.blind_copy(buf, 0, 0, buf.width(), buf.height(), xo, yo);
}
void
Env::add(Obstacle *_o)
{
for (unsigned i = 0; i < Max_obstacles; ++i)
if (o[i] == 0)
{
o[i] = _o;
break;
}
}
void
Env::draw()
{
ball.del(buf);
for (unsigned i = 0; i < Max_obstacles; ++i)
if (o[i] != 0)
o[i]->del(buf);
draw_field();
for (unsigned i = 0; i < Max_obstacles; ++i)
if (o[i] != 0)
o[i]->draw(buf);
ball.draw(buf);
for (unsigned i = 0; i < Max_obstacles; ++i)
if (o[i] != 0)
scr.blt(buf, o[i]->blt_area(), xo, yo);
scr.blind_copy(buf, ball.u_x1(), ball.u_y1(), ball.u_x2(), ball.u_y2(),
ball.u_x1() + xo, ball.u_y1() + yo);
#if 0
real_screen.blind_copy(buf,
lpad.u_x1(), lpad.u_y1(),
lpad.u_x2(), lpad.u_y2(),
lpad.u_x1()+xo, lpad.u_y1()+yo);
real_screen.blind_copy(buf,
rpad.u_x1(), rpad.u_y1(),
rpad.u_x2(), rpad.u_y2(),
rpad.u_x1()+xo, rpad.u_y1()+yo);
#endif
}
Obstacle *
Env::collide() const
{
Obstacle *ob = 0;
for (unsigned i = 0; i < Max_obstacles; ++i)
if (/*last != i &&*/ o[i] && o[i]->collide(ball))
{
last = i;
// if (o[i]->out())
ob = o[i];
}
return ob;
}

View File

@@ -0,0 +1,106 @@
#ifndef PONG_ENV_H__
#define PONG_ENV_H__
#include "ball.h"
#include "gfx-drv.h"
/**
* An obstacle that the ball may collide with.
*/
class Obstacle
{
public:
/// Is there a collision ?
virtual bool collide(Ball &b) const = 0;
/// Collision means out ?
virtual bool out() const = 0;
/// Draw this obstacle
virtual void draw(Gfx<Screen_buffer> &gfx) const = 0;
/// Delete this obstacle
virtual void del(Gfx<Screen_buffer> &gfx) const;
/// which area must be copied to the real frame buffer
virtual Area const &blt_area() const;
virtual ~Obstacle();
};
/**
* Just a line a obstacle. This obstacle is invisible.
*/
class Line : public Obstacle
{
public:
Line(int x1 = -1, int y1 = -1, int x2 = -1, int y2 = -1, bool out = false)
: x1(x1), y1(y1), x2(x2), y2(y2), _out(out)
{
}
bool
out() const
{
return _out;
}
bool
valid() const
{
return x1 != -1 || x2 != -1 || y1 != -1 || y2 != -1;
}
void draw(Gfx<Screen_buffer> &gfx) const;
bool collide(Ball &b) const;
int x1, y1, x2, y2;
bool _out;
};
/**
* A point.
*/
struct Point
{
int x, y;
};
/**
* The play field environment. Contains the obstacles and the ball.
* - frame buffer updates are handled by the environment.
*/
class Env
{
public:
/**
* Create a new environment.
* @param buf the off-screen buffer
* @param scr the frame buffer
* @param ball the ball
*/
Env(Gfx<Screen_buffer> &buf, Gfx<Screen> &scr, Ball &ball);
/// Add an obstacle
void add(Obstacle *o);
/// check for collisions
Obstacle *collide() const;
/// draw the play field
void draw_field() const;
/// draw the contents (obstacles and ball)
void draw();
private:
enum
{
Max_obstacles = 20,
};
Obstacle *o[Max_obstacles];
mutable unsigned last;
Gfx<Screen_buffer> &buf;
Gfx<Screen> &scr;
int xo, yo;
Ball &ball;
};
#endif // PONG_ENV_H__i

View File

@@ -0,0 +1,103 @@
#include "gfx-drv.h"
#include <l4/cxx/exceptions>
#include <l4/cxx/iostream>
#include <l4/re/env>
#include <l4/re/error_helper>
#include <l4/re/util/cap_alloc>
#include <l4/re/video/goos>
#include <l4/sys/kdebug.h>
#include <cstring>
#include <typeinfo>
Screen::Screen()
{
L4::Cap<L4Re::Video::Goos> video;
try
{
video = L4Re::Env::env()->get_cap<L4Re::Video::Goos>("vesa");
if (!video)
throw L4::Element_not_found();
}
catch (L4::Base_exception const &e)
{
L4::cout << "Error looking for vesa device: " << e.str() << '\n';
return;
}
catch (...)
{
L4::cout << "Caught unknown exception \n";
return;
}
if (!video.is_valid())
{
L4::cerr << "No video device found\n";
return;
}
L4Re::Video::Goos::Info gi;
video->info(&gi);
L4::Cap<L4Re::Dataspace> fb = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
video->get_static_buffer(0, fb);
if (!fb.is_valid())
{
L4::cerr << "Invalid frame buffer object\n";
return;
}
void *fb_addr = (void *)0x10000000;
L4Re::chksys(L4Re::Env::env()->rm()->attach(
&fb_addr, fb->size(), L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(fb)));
if (!fb_addr)
{
L4::cerr << "Cannot map frame buffer\n";
return;
}
L4Re::Video::View v = video->view(0);
L4Re::Video::View::Info vi;
L4Re::chksys(v.info(&vi));
_base = (unsigned long)fb_addr + vi.buffer_offset;
_line_bytes = vi.bytes_per_line;
_width = vi.width;
_height = vi.height;
_bpp = vi.pixel_info.bytes_per_pixel();
if (!vi.pixel_info.r().size() || !vi.pixel_info.g().size()
|| !vi.pixel_info.b().size())
{
L4::cerr << "Something is wrong with the color mapping\n"
"assume rgb 5:6:5\n";
_red_shift = 11;
_red_size = 5;
_green_shift = 5;
_green_size = 6;
_blue_shift = 0;
_blue_size = 5;
}
else
{
_red_shift = vi.pixel_info.r().shift();
_green_shift = vi.pixel_info.g().shift();
_blue_shift = vi.pixel_info.b().shift();
_red_size = vi.pixel_info.r().size();
_green_size = vi.pixel_info.g().size();
_blue_size = vi.pixel_info.b().size();
}
L4::cout << "\nFramebuffer: base = 0x" << L4::hex << _base
<< "\n width = " << L4::dec << (unsigned)_width
<< "\n height = " << (unsigned)_height
<< "\n bpl = " << _line_bytes
<< "\n bpp = " << _bpp << "\n mode = ("
<< _red_size << ':' << _green_size << ':' << _blue_size << ")\n";
}

View File

@@ -0,0 +1,462 @@
#ifndef PONG_GFX_H__
#define PONG_GFX_H__
class Area
{
public:
Area(int x0, int y0, int x1, int y1) : x0(x0), y0(y0), x1(x1), y1(y1) {}
int x0, y0, x1, y1;
};
class Screen_buffer
{
public:
Screen_buffer() {}
unsigned
line_bytes() const
{
return Line_bytes;
}
int
width() const
{
return Width;
}
int
height() const
{
return Height;
}
unsigned
bpp() const
{
return 2;
}
unsigned
red_shift() const
{
return 11;
}
unsigned
red_size() const
{
return 5;
}
unsigned
green_shift() const
{
return 5;
}
unsigned
green_size() const
{
return 6;
}
unsigned
blue_shift() const
{
return 0;
}
unsigned
blue_size() const
{
return 5;
}
unsigned long
base() const
{
return (unsigned long)buffer;
}
unsigned long
addr(unsigned x, unsigned y) const
{
return base() + y * line_bytes() + x * bpp();
}
private:
enum
{
Line_bytes = 1280,
Height = 480,
Width = 640,
};
mutable char buffer[Line_bytes * Height];
};
class Screen
{
public:
Screen();
unsigned
line_bytes() const
{
return _line_bytes;
}
int
width() const
{
return _width;
}
int
height() const
{
return _height;
}
unsigned
bpp() const
{
return _bpp;
}
unsigned
red_shift() const
{
return _red_shift;
}
unsigned
red_size() const
{
return _red_size;
}
unsigned
green_shift() const
{
return _green_shift;
}
unsigned
green_size() const
{
return _green_size;
}
unsigned
blue_shift() const
{
return _blue_shift;
}
unsigned
blue_size() const
{
return _blue_size;
}
unsigned long
base() const
{
return _base;
}
unsigned long
addr(unsigned x, unsigned y) const
{
return _base + y * line_bytes() + x * bpp();
}
private:
unsigned long _base;
unsigned _line_bytes;
int _width;
int _height;
unsigned _bpp;
unsigned _red_shift, _green_shift, _blue_shift;
unsigned _red_size, _green_size, _blue_size;
};
template <typename Scr>
class Gfx : public Scr
{
public:
unsigned
color(unsigned r, unsigned g, unsigned b) const
{
return (((r & 0xff) >> (8 - this->red_size())) << this->red_shift())
| (((g & 0xff) >> (8 - this->green_size())) << this->green_shift())
| (((b & 0xff) >> (8 - this->blue_size())) << this->blue_shift());
}
void vline(unsigned x, unsigned y1, unsigned y2, unsigned c) const;
void hline(unsigned x1, unsigned y, unsigned x2, unsigned color) const;
void rect(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
unsigned c) const;
template <typename OScr>
void blind_copy(Gfx<OScr> const &gfx, int x1, int y1, int x2, int y2, int xd,
int yd) const;
template <typename OScr>
void blt(Gfx<OScr> const &gfx, Area const &src, int xd, int yd) const;
void fill(unsigned c) const;
};
class Bitmap
{
public:
enum
{
CW0,
CW90,
CW180,
CW270
};
Bitmap(unsigned xr, unsigned yr, unsigned bpp, unsigned rs, unsigned _rs,
unsigned gs, unsigned _gs, unsigned bs, unsigned _bs, unsigned _o,
void *data)
: _red_shift(rs),
_green_shift(gs),
_blue_shift(bs),
_red_size(_rs),
_green_size(_gs),
_blue_size(_bs),
_bpp(bpp),
_orientation(_o),
xr(xr),
yr(yr),
data(data)
{
}
int
xres() const
{
return xr;
}
int
yres() const
{
return yr;
}
unsigned
bpp() const
{
return _bpp;
}
unsigned
red_shift() const
{
return _red_shift;
}
unsigned
green_shift() const
{
return _green_shift;
}
unsigned
blue_shift() const
{
return _blue_shift;
}
unsigned
red_size() const
{
return _red_size;
}
unsigned
green_size() const
{
return _blue_size;
}
unsigned
blue_size() const
{
return _blue_size;
}
unsigned
red(unsigned pix) const
{
return (pix >> _red_shift) & ((1 << _red_size) - 1);
}
unsigned
green(unsigned pix) const
{
return (pix >> _green_shift) & ((1 << _green_size) - 1);
}
unsigned
blue(unsigned pix) const
{
return (pix >> _blue_shift) & ((1 << _blue_size) - 1);
}
unsigned
pix(unsigned /*x*/, unsigned y) const
{
unsigned long s = (unsigned long)data;
s += (y * xr + y) * _bpp;
return *(unsigned *)s;
}
template <typename Scr>
void draw(Gfx<Scr> const &gfx, int x, int y) const;
private:
unsigned char _red_shift, _green_shift, _blue_shift;
unsigned char _red_size, _green_size, _blue_size;
unsigned char _bpp;
unsigned char _orientation;
unsigned xr, yr;
void *data;
};
template <typename Scr>
void
Gfx<Scr>::hline(unsigned x1, unsigned y, unsigned x2, unsigned c) const
{
unsigned long a = this->addr(x1, y);
unsigned long e = this->addr(x2, y);
switch (this->bpp())
{
case 2:
for (; a <= e; a += 2)
*((unsigned short *)a) = c;
break;
case 4:
for (; a <= e; a += 4)
*((unsigned *)a) = c;
break;
}
}
template <typename Scr>
void
Gfx<Scr>::rect(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
unsigned c) const
{
for (unsigned y = y1; y <= y2; ++y)
hline(x1, y, x2, c);
}
template <typename Scr>
void
Gfx<Scr>::vline(unsigned x, unsigned y1, unsigned y2, unsigned c) const
{
unsigned long a = this->addr(x, y1);
unsigned long e = this->addr(x, y2);
switch (this->bpp())
{
case 2:
for (; a <= e; a += this->line_bytes())
*((unsigned short *)a) = c;
break;
case 4:
for (; a <= e; a += this->line_bytes())
*((unsigned *)a) = c;
break;
}
}
template <typename Scr>
void
Gfx<Scr>::fill(unsigned c) const
{
unsigned long a = this->base();
unsigned long e = this->base() + this->line_bytes() * this->height();
switch (this->bpp())
{
case 2:
for (; a <= e; a += 2)
*((unsigned short *)a) = c;
break;
case 4:
for (; a <= e; a += 4)
*((unsigned *)a) = c;
break;
}
}
template <typename Scr>
template <typename OScr>
void
Gfx<Scr>::blind_copy(Gfx<OScr> const &gfx, int x1, int y1, int x2, int y2,
int xd, int yd) const
{
if (y2 < 0 || x2 < 0)
return;
if (y1 >= gfx.height() || x1 >= gfx.width())
return;
if (y1 < 0)
{
yd -= y1;
y1 = 0;
}
if (x1 < 0)
{
xd -= x1;
x1 = 0;
}
if (yd < 0)
{
y1 -= yd;
yd = 0;
}
if (xd < 0)
{
x1 -= xd;
xd = 0;
}
if (y2 > gfx.height())
{
y2 = gfx.height();
}
if (x2 > gfx.width())
{
x2 = gfx.width();
}
if (yd + (y2 - y1) > this->height())
{
y2 = this->height() - yd + y1;
}
if (xd + (x2 - x1) > this->width())
{
x2 = this->width() - xd + x1;
}
for (int y = y1; y < y2; ++y, ++yd)
{
unsigned long oa = gfx.addr(x1, y);
unsigned long oe = gfx.addr(x2, y);
unsigned long a = this->addr(xd, yd);
for (; oa < oe; oa += gfx.bpp(), a += this->bpp())
*((unsigned short *)a) = *((unsigned short *)oa);
}
}
template <typename Scr>
template <typename OScr>
void
Gfx<Scr>::blt(Gfx<OScr> const &gfx, Area const &src, int xo, int yo) const
{
if (src.x0 == src.x1)
return;
blind_copy(gfx, src.x0, src.y0, src.x1, src.y1, src.x0 + xo, src.y0 + yo);
}
template <typename Scr>
void
Bitmap::draw(Gfx<Scr> const &gfx, int x, int y) const
{
unsigned long s = (unsigned long)data;
for (unsigned ay = 0; ay < yr; ++ay)
{
unsigned long d = gfx.addr(x, y + ay);
for (unsigned ax = 0; ax < xr; ++ax)
{
unsigned v = *((unsigned *)s);
unsigned n = gfx.color(red(v), green(v), blue(v));
if (n)
*((unsigned short *)d) = n;
s += _bpp;
d += gfx.bpp();
}
}
}
#endif // PONG_GFX_H__

View File

@@ -0,0 +1,84 @@
#include <l4/pong/logging.h>
#include <l4/sys/factory.h>
#include <l4/sys/kip.h>
#include <l4/util/util.h>
#include "ball.h"
#include "env.h"
#include "gfx-drv.h"
#include "paddle-server.h"
#include <l4/cxx/iostream>
#include <l4/cxx/ipc_server>
#include <l4/cxx/l4iostream>
#include <iostream>
// offscreen buffer for drawing operations
Gfx<Screen_buffer> screen;
// real frame buffer
Gfx<Screen> real_screen;
// Instanciation of the ball
Ball ball(screen.color(0xff, 0xf0, 0x40), 0);
// Instanciation of the play field
Env env(screen, real_screen, ball);
// The playfield boundaries
Line ll(10, screen.height() - 2, 10, 2, false);
Line lt(2, 2, screen.width() - 2, 2, false);
Line lr(screen.width() - 10, 2, screen.width() - 10, screen.height() - 2,
false);
Line lb(screen.width() - 2, screen.height() - 2, 2, screen.height() - 2, false);
Paddle paddles[] = {Paddle(0, 0, &ll), Paddle(620, 0, &lr), Paddle(0, 0, &lt),
Paddle(0, 460, &lb)};
// Instanciation of the paddle server (own thread)
Paddle_server paddle_server(env, paddles);
// Main server function
int
main()
{
redirect_to_log(std::cout);
redirect_to_log(std::cerr);
L4::cout << "PS Hello here am I\n";
L4::cout << "KIP @ " << l4re_kip() << ": " << L4::n_hex(l4re_kip()->magic)
<< '\n';
// add the boundaries to the playfield
env.add(&ll);
env.add(&lt);
env.add(&lr);
env.add(&lb);
// start the paddle server (thread)
paddle_server.start();
Obstacle *o;
// main loop
while (1)
{
// draw the complete stuff (becomes visible on frame buffer)
env.draw();
// handle collisions
o = env.collide();
if (o)
paddle_server.handle_collision(o);
#if 0
if (o==&lpad)
L4::cout << "Left Points: " << ++lpp << '\n';
if (o==&rpad)
L4::cout << "Right Points: " << ++rpp << '\n';
#endif
// move the ball one step
ball.move();
l4_sleep(8);
};
}

View File

@@ -0,0 +1,25 @@
#ifndef PONG_MATH_H__
#define PONG_MATH_H__
int sin(int x);
int cos(int x);
inline int
sign(int x)
{
if (x < 0)
return -1;
else
return 1;
}
inline int
abs(int x)
{
if (x < 0)
return -x;
else
return x;
}
#endif // PONG_MATH_H__

View File

@@ -0,0 +1,30 @@
2
2 (m v + n z)
l = --------------
2 2
m + n
z = Px - Ax
v = Py - Ay
m = Bx - Ax
n = By - Ay
P
.
. | .
. |l .
. | .
A -------------------- B
L
-> ->
x AB = AL
x >= 0
x <= 1
m z + n v
x = -----------
2 2
m + n

View File

@@ -0,0 +1,12 @@
#ifndef ROOT_OBJ_REG_H__
#define ROOT_OBJ_REG_H__
#include <l4/cxx/ipc_stream>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/sys/factory>
#include <l4/sys/task>
#endif

View File

@@ -0,0 +1,159 @@
#include "paddle-server.h"
#include <l4/cxx/iostream>
#include <l4/cxx/l4iostream>
static Paddle_server *the_paddle_server;
template <typename T>
T
extract(L4::Ipc::Istream &i)
{
T v;
i >> v;
return v;
}
int
Paddle_so::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
unsigned long op;
ios >> op;
switch (op)
{
case 1:
move_to(extract<int>(ios));
return L4_EOK;
case 2:
set_lifes(extract<int>(ios));
return L4_EOK;
case 3:
ios << get_lifes();
return L4_EOK;
default:
L4::cout << "Invalid request for " << obj << '\n';
return -L4_ENOREPLY;
}
}
int
Paddle_server::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
unsigned long op;
ios >> op;
switch (op)
{
case 1:
ios << connect();
return L4_EOK;
default:
L4::cout << "Invalid request for " << obj << '\n';
return -L4_ENOREPLY;
}
}
Paddle_server::Paddle_server(Env &env, Paddle paddles[4])
: L4::PosixThread(), env(env)
{
_pad[0].set_paddle(&paddles[0]);
_pad[1].set_paddle(&paddles[1]);
_pad[0].paddle()->add(0, 60);
_pad[0].paddle()->add(16, 60);
_pad[0].paddle()->add(18, 55);
_pad[0].paddle()->add(20, 50);
_pad[0].paddle()->add(21, 40);
_pad[0].paddle()->add(21, 20);
_pad[0].paddle()->add(20, 10);
_pad[0].paddle()->add(18, 5);
_pad[0].paddle()->add(16, 0);
_pad[0].paddle()->add(0, 0);
_pad[1].paddle()->add(20, 60);
_pad[1].paddle()->add(20, 0);
_pad[1].paddle()->add(4, 0);
_pad[1].paddle()->add(2, 5);
_pad[1].paddle()->add(0, 10);
_pad[1].paddle()->add(-1, 20);
_pad[1].paddle()->add(-1, 40);
_pad[1].paddle()->add(0, 50);
_pad[1].paddle()->add(2, 55);
_pad[1].paddle()->add(4, 60);
}
void
Paddle_server::run()
{
L4::cerr << "------------------------------------------------------\n";
Server server(self(), L4Re::Env::env()->factory());
server.registry()->register_obj(this, "PongServer");
server.registry()->register_obj(&_pad[0]);
server.registry()->register_obj(&_pad[1]);
the_paddle_server = this;
L4::cerr << "Hello from svrloop\n";
server.loop(l4_utcb());
}
void
Paddle_server::handle_collision(Obstacle *o)
{
for (unsigned i = 0; i < 2; ++i)
if (_pad[i].connected() && o == _pad[i].paddle()->wall())
_pad[i].dec_lifes();
}
L4::Cap<void>
Paddle_server::connect()
{
for (unsigned i = 0; i < 2; ++i)
{
if (!_pad[i].connected())
{
_pad[i].connect(true);
env.add(_pad[i].paddle());
L4::cout << "MAP cap: " << _pad[i].obj_cap() << "\n";
return _pad[i].obj_cap();
}
}
return L4::Cap<void>::Invalid;
}
void
Paddle_so::move_to(int pos)
{
if (pos < 0 || pos > 1023)
return;
paddle()->move(0, pos * 420 / 1024);
}
int *
Paddle_so::lifes()
{
return &_points;
}
void
Paddle_so::set_lifes(int _lifes)
{
int *l = lifes();
if (l)
*l = _lifes;
}
int
Paddle_so::get_lifes()
{
int *l = lifes();
if (l)
return *l;
return -5000;
}

View File

@@ -0,0 +1,96 @@
#ifndef PADDLE_THREAD_H__
#define PADDLE_THREAD_H__
#include "env.h"
#include "obj_reg.h"
#include "paddle.h"
#include <l4/cxx/ipc_server>
#include <l4/sys/capability>
#include "PosixThread.h"
struct Paddle_if : L4::Kobject_t<Paddle_if, L4::Kobject>
{
};
class Paddle_so : public L4::Server_object_t<Paddle_if>
{
public:
explicit Paddle_so(Paddle *_pad = 0)
: _points(0), _py(0), _paddle(_pad), _connected(0)
{
}
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
void move_to(int pos);
void set_lifes(int lifes);
int get_lifes();
void
set_paddle(Paddle *pad)
{
_paddle = pad;
}
Paddle *
paddle() const
{
return _paddle;
}
bool
connected() const
{
return _connected;
}
void
connect(bool c = true)
{
_connected = c;
}
void
dec_lifes()
{
--_points;
}
private:
int *lifes();
int _points;
int _py;
Paddle *_paddle;
bool _connected;
};
struct Paddle_server_if : L4::Kobject_t<Paddle_server_if, L4::Kobject>
{
};
class Paddle_server : public L4::PosixThread,
public L4::Server_object_t<Paddle_server_if>
{
private:
typedef L4Re::Util::Registry_server<> Server;
public:
Paddle_server(Env &env, Paddle paddles[4]);
void run();
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
L4::Cap<void> connect();
void handle_collision(Obstacle *o);
private:
char str[60];
Paddle_so _pad[2];
Env &env;
};
#endif // PADDLE_THREAD_H__

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,71 @@
#include "paddle.h"
extern char _binary_paddle_img_start;
Paddle::Paddle(unsigned ox, unsigned oy, Obstacle *wall)
: num_points(0),
xo(ox),
yo(oy),
oxo(xo),
oyo(yo),
ua(0, 0, 0, 0),
bm(20, 60, 3, 0, 8, 8, 8, 16, 8, Bitmap::CW90, &_binary_paddle_img_start),
_wall(wall)
{
}
void
Paddle::add(int x, int y)
{
if (num_points < Max_points)
{
points[num_points].x = x;
points[num_points].y = y;
num_points++;
}
}
bool
Paddle::collide(Ball &b) const
{
if (num_points <= 1)
return false;
bool ret = false;
for (unsigned i = 0; i < num_points - 1; ++i)
{
if (b.collide(points[i].x + xo, points[i].y + yo, points[i + 1].x + xo,
points[i + 1].y + yo))
ret = true;
}
if (b.collide(points[num_points - 1].x + xo, points[num_points - 1].y + yo,
points[0].x + xo, points[0].y + yo))
ret = true;
return ret;
}
void
Paddle::draw(Gfx<Screen_buffer> &gfx) const
{
ua.x0 = xo > oxo ? oxo : xo;
ua.y0 = yo > oyo ? oyo : yo;
ua.x1 = xo > oxo ? xo + bm.xres() : oxo + bm.xres();
ua.y1 = yo > oyo ? yo + bm.yres() : oyo + bm.yres();
oxo = xo;
oyo = yo;
bm.draw(gfx, xo, yo);
}
void
Paddle::del(Gfx<Screen_buffer> &gfx) const
{
gfx.rect(oxo, oyo, oxo + bm.xres(), oyo + bm.yres(), 0);
}
Area const &
Paddle::blt_area() const
{
return ua;
}

View File

@@ -0,0 +1,54 @@
#ifndef PONG_PADDLE_H__
#define PONG_PADDLE_H__
#include "env.h"
#include "gfx-drv.h"
class Paddle : public Obstacle
{
public:
Paddle(unsigned ox, unsigned oy, Obstacle *wall);
bool collide(Ball &b) const;
bool
out() const
{
return true;
}
void add(int x, int y);
void draw(Gfx<Screen_buffer> &gfx) const;
void del(Gfx<Screen_buffer> &gfx) const;
Area const &blt_area() const;
void
move(unsigned /*x*/, unsigned y)
{ /*xo = x;*/
yo = y;
}
Obstacle *
wall() const
{
return _wall;
}
private:
enum
{
Max_points = 20,
};
unsigned num_points;
Point points[Max_points];
unsigned xo, yo;
mutable unsigned oxo, oyo;
mutable Area ua;
Bitmap bm;
Obstacle *_wall;
};
#endif // PONG_PADDLE_H__

View File

@@ -0,0 +1,98 @@
#include "math.h"
short int sintab[] = {
0, 3, 6, 9, 12, 15, 18, 21, 25, 28, 31, 34, 37,
40, 43, 47, 50, 53, 56, 59, 62, 65, 68, 72, 75, 78,
81, 84, 87, 90, 93, 96, 99, 102, 106, 109, 112, 115, 118,
121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157,
160, 163, 166, 169, 172, 175, 178, 181, 184, 187, 190, 193, 195,
198, 201, 204, 207, 210, 213, 216, 218, 221, 224, 227, 230, 233,
235, 238, 241, 244, 246, 249, 252, 255, 257, 260, 263, 265, 268,
271, 273, 276, 279, 281, 284, 287, 289, 292, 294, 297, 299, 302,
304, 307, 310, 312, 314, 317, 319, 322, 324, 327, 329, 332, 334,
336, 339, 341, 343, 346, 348, 350, 353, 355, 357, 359, 362, 364,
366, 368, 370, 372, 375, 377, 379, 381, 383, 385, 387, 389, 391,
393, 395, 397, 399, 401, 403, 405, 407, 409, 411, 413, 414, 416,
418, 420, 422, 423, 425, 427, 429, 430, 432, 434, 435, 437, 439,
440, 442, 443, 445, 447, 448, 450, 451, 453, 454, 455, 457, 458,
460, 461, 462, 464, 465, 466, 468, 469, 470, 471, 473, 474, 475,
476, 477, 478, 479, 481, 482, 483, 484, 485, 486, 487, 488, 489,
489, 490, 491, 492, 493, 494, 495, 495, 496, 497, 498, 498, 499,
500, 500, 501, 502, 502, 503, 503, 504, 504, 505, 505, 506, 506,
507, 507, 508, 508, 508, 509, 509, 509, 510, 510, 510, 510, 511,
511, 511, 511, 511, 511, 511, 511, 511, 511, 512, 511, 511, 511,
511, 511, 511, 511, 511, 511, 511, 510, 510, 510, 510, 509, 509,
509, 508, 508, 508, 507, 507, 506, 506, 505, 505, 504, 504, 503,
503, 502, 502, 501, 500, 500, 499, 498, 498, 497, 496, 495, 495,
494, 493, 492, 491, 490, 489, 489, 488, 487, 486, 485, 484, 483,
482, 481, 479, 478, 477, 476, 475, 474, 473, 471, 470, 469, 468,
466, 465, 464, 462, 461, 460, 458, 457, 455, 454, 453, 451, 450,
448, 447, 445, 443, 442, 440, 439, 437, 435, 434, 432, 430, 429,
427, 425, 423, 422, 420, 418, 416, 414, 413, 411, 409, 407, 405,
403, 401, 399, 397, 395, 393, 391, 389, 387, 385, 383, 381, 379,
377, 375, 372, 370, 368, 366, 364, 362, 359, 357, 355, 353, 350,
348, 346, 343, 341, 339, 336, 334, 332, 329, 327, 324, 322, 319,
317, 314, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287,
284, 281, 279, 276, 273, 271, 268, 265, 263, 260, 257, 255, 252,
249, 246, 244, 241, 238, 235, 233, 230, 227, 224, 221, 218, 216,
213, 210, 207, 204, 201, 198, 195, 193, 190, 187, 184, 181, 178,
175, 172, 169, 166, 163, 160, 157, 154, 151, 148, 145, 142, 139,
136, 133, 130, 127, 124, 121, 118, 115, 112, 109, 106, 102, 99,
96, 93, 90, 87, 84, 81, 78, 75, 72, 68, 65, 62, 59,
56, 53, 50, 47, 43, 40, 37, 34, 31, 28, 25, 21, 18,
15, 12, 9, 6, 3, 0, -3, -6, -9, -12, -15, -18, -21,
-25, -28, -31, -34, -37, -40, -43, -47, -50, -53, -56, -59, -62,
-65, -68, -72, -75, -78, -81, -84, -87, -90, -93, -96, -99, -102,
-106, -109, -112, -115, -118, -121, -124, -127, -130, -133, -136, -139, -142,
-145, -148, -151, -154, -157, -160, -163, -166, -169, -172, -175, -178, -181,
-184, -187, -190, -193, -195, -198, -201, -204, -207, -210, -213, -216, -218,
-221, -224, -227, -230, -233, -235, -238, -241, -244, -246, -249, -252, -255,
-257, -260, -263, -265, -268, -271, -273, -276, -279, -281, -284, -287, -289,
-292, -294, -297, -299, -302, -304, -307, -310, -312, -314, -317, -319, -322,
-324, -327, -329, -332, -334, -336, -339, -341, -343, -346, -348, -350, -353,
-355, -357, -359, -362, -364, -366, -368, -370, -372, -375, -377, -379, -381,
-383, -385, -387, -389, -391, -393, -395, -397, -399, -401, -403, -405, -407,
-409, -411, -413, -414, -416, -418, -420, -422, -423, -425, -427, -429, -430,
-432, -434, -435, -437, -439, -440, -442, -443, -445, -447, -448, -450, -451,
-453, -454, -455, -457, -458, -460, -461, -462, -464, -465, -466, -468, -469,
-470, -471, -473, -474, -475, -476, -477, -478, -479, -481, -482, -483, -484,
-485, -486, -487, -488, -489, -489, -490, -491, -492, -493, -494, -495, -495,
-496, -497, -498, -498, -499, -500, -500, -501, -502, -502, -503, -503, -504,
-504, -505, -505, -506, -506, -507, -507, -508, -508, -508, -509, -509, -509,
-510, -510, -510, -510, -511, -511, -511, -511, -511, -511, -511, -511, -511,
-511, -512, -511, -511, -511, -511, -511, -511, -511, -511, -511, -511, -510,
-510, -510, -510, -509, -509, -509, -508, -508, -508, -507, -507, -506, -506,
-505, -505, -504, -504, -503, -503, -502, -502, -501, -500, -500, -499, -498,
-498, -497, -496, -495, -495, -494, -493, -492, -491, -490, -489, -489, -488,
-487, -486, -485, -484, -483, -482, -481, -479, -478, -477, -476, -475, -474,
-473, -471, -470, -469, -468, -466, -465, -464, -462, -461, -460, -458, -457,
-455, -454, -453, -451, -450, -448, -447, -445, -443, -442, -440, -439, -437,
-435, -434, -432, -430, -429, -427, -425, -423, -422, -420, -418, -416, -414,
-413, -411, -409, -407, -405, -403, -401, -399, -397, -395, -393, -391, -389,
-387, -385, -383, -381, -379, -377, -375, -372, -370, -368, -366, -364, -362,
-359, -357, -355, -353, -350, -348, -346, -343, -341, -339, -336, -334, -332,
-329, -327, -324, -322, -319, -317, -314, -312, -310, -307, -304, -302, -299,
-297, -294, -292, -289, -287, -284, -281, -279, -276, -273, -271, -268, -265,
-263, -260, -257, -255, -252, -249, -246, -244, -241, -238, -235, -233, -230,
-227, -224, -221, -218, -216, -213, -210, -207, -204, -201, -198, -195, -193,
-190, -187, -184, -181, -178, -175, -172, -169, -166, -163, -160, -157, -154,
-151, -148, -145, -142, -139, -136, -133, -130, -127, -124, -121, -118, -115,
-112, -109, -106, -102, -99, -96, -93, -90, -87, -84, -81, -78, -75,
-72, -68, -65, -62, -59, -56, -53, -50, -47, -43, -40, -37, -34,
-31, -28, -25, -21, -18, -15, -12, -9, -6,
};
int
sin(int x)
{
x = x / 180;
x &= 1023;
return sintab[x];
}
int
cos(int x)
{
x = x + 90 * 512;
return sin(x);
}