diff --git a/src/l4/pkg/pong/Control b/src/l4/pkg/pong/Control new file mode 100644 index 00000000..93347793 --- /dev/null +++ b/src/l4/pkg/pong/Control @@ -0,0 +1,2 @@ +requires: l4sys l4re crtn stdlibs libpthread libstdc++ libc_be_mem +maintainer: warg@os.inf.tu-dresden.de diff --git a/src/l4/pkg/pong/Makefile b/src/l4/pkg/pong/Makefile new file mode 100644 index 00000000..10c2d55e --- /dev/null +++ b/src/l4/pkg/pong/Makefile @@ -0,0 +1,6 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +TARGET = include server example + +include $(L4DIR)/mk/subdir.mk diff --git a/src/l4/pkg/pong/example/Makefile b/src/l4/pkg/pong/example/Makefile new file mode 100644 index 00000000..f3bfdd75 --- /dev/null +++ b/src/l4/pkg/pong/example/Makefile @@ -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 diff --git a/src/l4/pkg/pong/example/main.cc b/src/l4/pkg/pong/example/main.cc new file mode 100644 index 00000000..bdb6b5f8 --- /dev/null +++ b/src/l4/pkg/pong/example/main.cc @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +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().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 s = L4Re::Env::env()->get_cap("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; +}; diff --git a/src/l4/pkg/pong/include/Makefile b/src/l4/pkg/pong/include/Makefile new file mode 100644 index 00000000..481eb873 --- /dev/null +++ b/src/l4/pkg/pong/include/Makefile @@ -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 later. +# No need to list them in this Makefile. + +include $(L4DIR)/mk/include.mk diff --git a/src/l4/pkg/pong/include/logging.h b/src/l4/pkg/pong/include/logging.h new file mode 100644 index 00000000..ad005288 --- /dev/null +++ b/src/l4/pkg/pong/include/logging.h @@ -0,0 +1,57 @@ +// -*- C++ -*- + +#pragma once + +#include + +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 +class Log_Buffer : public std::basic_streambuf +{ +private: + std::string buffer; + +public: + using Base = std::basic_streambuf; + 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(256); + auto old_buf = os.rdbuf(buf); + // I guess we should delete this here? + delete old_buf; +} diff --git a/src/l4/pkg/pong/server/Makefile b/src/l4/pkg/pong/server/Makefile new file mode 100644 index 00000000..16ccaf1e --- /dev/null +++ b/src/l4/pkg/pong/server/Makefile @@ -0,0 +1,4 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/src/l4/pkg/pong/server/src/Makefile b/src/l4/pkg/pong/server/src/Makefile new file mode 100644 index 00000000..a14a41cc --- /dev/null +++ b/src/l4/pkg/pong/server/src/Makefile @@ -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:$@ + diff --git a/src/l4/pkg/pong/server/src/PosixThread.h b/src/l4/pkg/pong/server/src/PosixThread.h new file mode 100644 index 00000000..7b6f8bce --- /dev/null +++ b/src/l4/pkg/pong/server/src/PosixThread.h @@ -0,0 +1,54 @@ +/* + * (c) 2012 Nils Asmussen + * 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 +#include +#include + +namespace L4 +{ + +class PosixThread +{ +public: + PosixThread() : _thread(){}; + virtual ~PosixThread(){}; + + L4::Cap + self() const + { + return L4::Cap(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(arg)->run(); + return NULL; + }; + +private: + pthread_t _thread; +}; + +} // namespace L4 diff --git a/src/l4/pkg/pong/server/src/ball.bmp b/src/l4/pkg/pong/server/src/ball.bmp new file mode 100644 index 00000000..f2644322 Binary files /dev/null and b/src/l4/pkg/pong/server/src/ball.bmp differ diff --git a/src/l4/pkg/pong/server/src/ball.cc b/src/l4/pkg/pong/server/src/ball.cc new file mode 100644 index 00000000..58a195a8 --- /dev/null +++ b/src/l4/pkg/pong/server/src/ball.cc @@ -0,0 +1,126 @@ +#include "ball.h" +#include + +#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 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 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); +} diff --git a/src/l4/pkg/pong/server/src/ball.h b/src/l4/pkg/pong/server/src/ball.h new file mode 100644 index 00000000..bcc11e89 --- /dev/null +++ b/src/l4/pkg/pong/server/src/ball.h @@ -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 const &s); + void del(Gfx 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__ diff --git a/src/l4/pkg/pong/server/src/env.cc b/src/l4/pkg/pong/server/src/env.cc new file mode 100644 index 00000000..376c8f3c --- /dev/null +++ b/src/l4/pkg/pong/server/src/env.cc @@ -0,0 +1,111 @@ +#include "env.h" +#include + +Obstacle::~Obstacle() {} + +void +Obstacle::del(Gfx &) 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 & /*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 &buf, Gfx &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; +} diff --git a/src/l4/pkg/pong/server/src/env.h b/src/l4/pkg/pong/server/src/env.h new file mode 100644 index 00000000..c51cc4f5 --- /dev/null +++ b/src/l4/pkg/pong/server/src/env.h @@ -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 &gfx) const = 0; + /// Delete this obstacle + virtual void del(Gfx &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 &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 &buf, Gfx &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 &buf; + Gfx &scr; + int xo, yo; + Ball &ball; +}; + +#endif // PONG_ENV_H__i diff --git a/src/l4/pkg/pong/server/src/gfx-drv.cc b/src/l4/pkg/pong/server/src/gfx-drv.cc new file mode 100644 index 00000000..57cce7a8 --- /dev/null +++ b/src/l4/pkg/pong/server/src/gfx-drv.cc @@ -0,0 +1,103 @@ +#include "gfx-drv.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +Screen::Screen() +{ + + L4::Cap video; + try + { + video = L4Re::Env::env()->get_cap("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 fb = L4Re::Util::cap_alloc.alloc(); + 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"; +} diff --git a/src/l4/pkg/pong/server/src/gfx-drv.h b/src/l4/pkg/pong/server/src/gfx-drv.h new file mode 100644 index 00000000..40aa02f4 --- /dev/null +++ b/src/l4/pkg/pong/server/src/gfx-drv.h @@ -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 +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 + void blind_copy(Gfx const &gfx, int x1, int y1, int x2, int y2, int xd, + int yd) const; + + template + void blt(Gfx 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 + void draw(Gfx 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 +void +Gfx::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 +void +Gfx::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 +void +Gfx::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 +void +Gfx::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 +template +void +Gfx::blind_copy(Gfx 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 +template +void +Gfx::blt(Gfx 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 +void +Bitmap::draw(Gfx 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__ diff --git a/src/l4/pkg/pong/server/src/main.cc b/src/l4/pkg/pong/server/src/main.cc new file mode 100644 index 00000000..507924ef --- /dev/null +++ b/src/l4/pkg/pong/server/src/main.cc @@ -0,0 +1,84 @@ +#include +#include +#include +#include + +#include "ball.h" +#include "env.h" +#include "gfx-drv.h" +#include "paddle-server.h" + +#include +#include +#include + +#include + +// offscreen buffer for drawing operations +Gfx screen; +// real frame buffer +Gfx 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, <), + 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(<); + 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); + }; +} diff --git a/src/l4/pkg/pong/server/src/math.h b/src/l4/pkg/pong/server/src/math.h new file mode 100644 index 00000000..731ced4d --- /dev/null +++ b/src/l4/pkg/pong/server/src/math.h @@ -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__ diff --git a/src/l4/pkg/pong/server/src/maths.txt b/src/l4/pkg/pong/server/src/maths.txt new file mode 100644 index 00000000..9f9734d9 --- /dev/null +++ b/src/l4/pkg/pong/server/src/maths.txt @@ -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 + + diff --git a/src/l4/pkg/pong/server/src/obj_reg.h b/src/l4/pkg/pong/server/src/obj_reg.h new file mode 100644 index 00000000..fc5a02fd --- /dev/null +++ b/src/l4/pkg/pong/server/src/obj_reg.h @@ -0,0 +1,12 @@ +#ifndef ROOT_OBJ_REG_H__ +#define ROOT_OBJ_REG_H__ + +#include +#include +#include +#include +#include +#include + + +#endif diff --git a/src/l4/pkg/pong/server/src/paddle-server.cc b/src/l4/pkg/pong/server/src/paddle-server.cc new file mode 100644 index 00000000..3569a5df --- /dev/null +++ b/src/l4/pkg/pong/server/src/paddle-server.cc @@ -0,0 +1,159 @@ +#include "paddle-server.h" + +#include +#include + + +static Paddle_server *the_paddle_server; + +template +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(ios)); + return L4_EOK; + case 2: + set_lifes(extract(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 +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::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; +} diff --git a/src/l4/pkg/pong/server/src/paddle-server.h b/src/l4/pkg/pong/server/src/paddle-server.h new file mode 100644 index 00000000..c89de9dc --- /dev/null +++ b/src/l4/pkg/pong/server/src/paddle-server.h @@ -0,0 +1,96 @@ +#ifndef PADDLE_THREAD_H__ +#define PADDLE_THREAD_H__ + +#include "env.h" +#include "obj_reg.h" +#include "paddle.h" + +#include +#include + +#include "PosixThread.h" + +struct Paddle_if : L4::Kobject_t +{ +}; +class Paddle_so : public L4::Server_object_t +{ +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 +{ +}; +class Paddle_server : public L4::PosixThread, + public L4::Server_object_t +{ +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 connect(); + + void handle_collision(Obstacle *o); + +private: + char str[60]; + + Paddle_so _pad[2]; + + Env &env; +}; + + +#endif // PADDLE_THREAD_H__ diff --git a/src/l4/pkg/pong/server/src/paddle.bmp b/src/l4/pkg/pong/server/src/paddle.bmp new file mode 100644 index 00000000..48cde7b2 Binary files /dev/null and b/src/l4/pkg/pong/server/src/paddle.bmp differ diff --git a/src/l4/pkg/pong/server/src/paddle.cc b/src/l4/pkg/pong/server/src/paddle.cc new file mode 100644 index 00000000..63ebb056 --- /dev/null +++ b/src/l4/pkg/pong/server/src/paddle.cc @@ -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 &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 &gfx) const +{ + gfx.rect(oxo, oyo, oxo + bm.xres(), oyo + bm.yres(), 0); +} + +Area const & +Paddle::blt_area() const +{ + return ua; +} diff --git a/src/l4/pkg/pong/server/src/paddle.h b/src/l4/pkg/pong/server/src/paddle.h new file mode 100644 index 00000000..77dc7e16 --- /dev/null +++ b/src/l4/pkg/pong/server/src/paddle.h @@ -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 &gfx) const; + void del(Gfx &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__ diff --git a/src/l4/pkg/pong/server/src/sintab.cc b/src/l4/pkg/pong/server/src/sintab.cc new file mode 100644 index 00000000..d83ad62a --- /dev/null +++ b/src/l4/pkg/pong/server/src/sintab.cc @@ -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); +}