Skip to content

DreamNik/pg_doom

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

7 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

English version below.


ЦСль

Π—Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Doom Π½Π° PostgreSQL.

ΠŸΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ

Для удобства вСсь процСсс Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ Π² Π²ΠΈΠ΄Π΅ Docker ΠΎΠ±Ρ€Π°Π·Π°, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ.

НСобходимо Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ ΠΏΠΎΠ΄Π»ΠΎΠΆΠΈΡ‚ΡŒ Ρ„Π°ΠΉΠ» doom.wad, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π·Π°Ρ‰ΠΈΡ‰Ρ‘Π½ авторским ΠΏΡ€Π°Π²ΠΎΠΌ ΠΈ Π½Π΅ являСтся свободно распространяСмым.

git clone https://github.com/DreamNik/pg_doom
cd pg_doom
<Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ помСститС Π’Π°Ρˆ Ρ„Π°ΠΉΠ» doom.wad Π² Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡŽ pg_doom>
docker build --tag pg_doom --file docker/Dockerfile .
docker run --rm --interactive --tty pg_doom

screenshot

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ - ΠΊΠ½ΠΎΠΏΠΊΠ°ΠΌΠΈ A, S, D, W, F, E.

АрхитСктура Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ

РСшСниС Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ·:

  • Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ "pg_doom", ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€ΠΈ Π‘Π£Π‘Π”;
  • bash-скрипта, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ интСрфСйс Π²Π²ΠΎΠ΄Π° Π²Ρ‹Π²ΠΎΠ΄Π°.

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ Π΄Π²Π΅ Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² языкС SQL. ΠŸΠ΅Ρ€Π²Π°Ρ - Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Π²Π°Ρ‚ΡŒ Π½Π°ΠΆΠ°Ρ‚Ρ‹Π΅ клавиши, вторая - ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ "ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ" для отобраТСния. А скрипт Π±ΡƒΠ΄Π΅Ρ‚, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½Π°ΠΆΠ°Ρ‚Ρ‹Π΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ, пСрСдавая ΠΈΡ… ΠΊΠ°ΠΊ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π° послС Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Π²Ρ‚ΠΎΡ€ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Π΅Ρ‘ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚.

ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ°

Для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Π½Π°ΠΌ ΠΏΠΎΡ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ:

  • ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€ с ОБ Debian;
  • установлСнный PostgreSQL с Π½Π°Π±ΠΎΡ€ΠΎΠΌ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ;
  • компилятор языка C ΠΈ Π½Π°Π±ΠΎΡ€ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ GNU Make.

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ОБ Debian, Π½ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ Π»ΡŽΠ±ΡƒΡŽ Π΄Ρ€ΡƒΠ³ΡƒΡŽ ОБ сСмСйства Linux с ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ Π°Π΄Π°ΠΏΡ‚Π°Ρ†ΠΈΠ΅ΠΉ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… шагов. Windows Ρ‚ΠΎΠΆΠ΅ ΠΏΠΎΠ΄ΠΎΠΉΠ΄Ρ‘Ρ‚, Π½ΠΎ Ρ‚Π°ΠΌ шаги ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠΈ совсСм Π΄Ρ€ΡƒΠ³ΠΈΠ΅. Π˜Ρ‚Π°ΠΊ, ΠΎΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ консоль ΠΈ ставим Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹:

export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
	git \
	build-essentials \
	postgresql

Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ

Π˜ΡΡ…ΠΎΠ΄Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ для PostgreSQL Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ·:

  • Ρ„Π°ΠΉΠ»Π° с ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹ΠΌΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ - "pg_doom.control".
  • Ρ„Π°ΠΉΠ»ΠΎΠ² с SQL ΠΊΠΎΠ΄ΠΎΠΌ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Π² Π±Π°Π·Π΅ - "pg_doom.sql";
  • Ρ„Π°ΠΉΠ»Π° сборки Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ - "Makefile";
  • Ρ„Π°ΠΉΠ»ΠΎΠ² с исходным ΠΊΠΎΠ΄ΠΎΠΌ - "pg_doom.c" ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅.

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½ Π΄Π°Π»Π΅ΠΊΠΎ Π½Π΅ вСсь исходный ΠΊΠΎΠ΄. Π’Π΅ΡΡŒ исходный ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ pg_doom

Π€Π°ΠΉΠ» pg_doom.control

Π­Ρ‚ΠΎΡ‚ Ρ„Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ PostgreSQL для опрСдСлСния состава Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ ΠΈ ΠΊΡƒΠ΄Π° ΠΈ ΠΊΠ°ΠΊ Π΅Π³ΠΎ Π·Π°Π³Ρ€ΡƒΠΆΠ°Ρ‚ΡŒ.

comment         = 'Provides ability to play the game.'
default_version = '1.0'
relocatable     = false
module_pathname = '$libdir/pg_doom'
schema          = doom

Из интСрСсного здСсь это module_pathname - ΠΏΡƒΡ‚ΡŒ, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ Π½Π° собранный Π±ΠΈΠ½Π°Ρ€Π½Ρ‹ΠΉ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ.

Π€Π°ΠΉΠ» pg_doom--1.0.sql

Π­Ρ‚ΠΎΡ‚ Ρ„Π°ΠΉΠ» выполняСтся ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ Π² Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…. ΠŸΡ€ΠΈ нСобходимости Π² Ρ‚Π°ΠΊΠΈΡ… Ρ„Π°ΠΉΠ»Π°Ρ… ΡΠΎΠ·Π΄Π°ΡŽΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, прСдставлСния, Ρ‚Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ структуры, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ. Нам Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π² схСмС Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ - Π²Π²ΠΎΠ΄Π° ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π° Π΄Π°Π½Π½Ρ‹Ρ…:

CREATE PROCEDURE doom.input(
    IN  chars      TEXT,
    IN  duration   INTEGER)
AS 'MODULE_PATHNAME', 'pg_doom_input' LANGUAGE C;

CREATE FUNCTION doom.screen(
    IN  width      INTEGER DEFAULT 320,
    IN  height     INTEGER DEFAULT 200,
    OUT lineNumber INTEGER,
    OUT lineText   TEXT)
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_doom_screen' LANGUAGE C;

Π’ Ρ„Π°ΠΉΠ»Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΊΠ»ΡŽΡ‡Π΅Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ MODULE_PATHNAME Π² качСствС ΠΈΠΌΠ΅Π½ΠΈ модуля Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ подмСняСтся Π½Π° фактичСский адрСс Π·Π°Π³Ρ€ΡƒΠΆΠ°Π΅ΠΌΠΎΠ³ΠΎ модуля (Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ), ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΡƒΠΊΠ°Π·Π°Π½ΠΎ Π² control Ρ„Π°ΠΉΠ»Π΅.

Π€Π°ΠΉΠ» Makefile

Π€Π°ΠΉΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для компиляции ΠΈ установки Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ. Π’ Π½Π°Ρ‡Π°Π»Π΅ Ρ„Π°ΠΉΠ»Π° Π·Π°Π΄Π°ΡŽΡ‚ΡΡ имя ΠΈ описаниС Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ:

MODULE_big = pg_doom
EXTENSION  = pg_doom
PGFILEDESC = pg_doom

Π”Π°Π»Π΅Π΅ задаётся список Ρ„Π°ΠΉΠ»ΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄ΡƒΡ‚ установлСны вмСстС с Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ

DATA = pg_doom--1.0.sql pg_doom.control

Π”Π°Π»Π΅Π΅, Π·Π°Π΄Π°Ρ‘ΠΌ список ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ. Π’ΠΎ Π΅ΡΡ‚ΡŒ, задаётся Π½Π΅ список исходных Ρ„Π°ΠΉΠ»ΠΎΠ², Π° список Π°Ρ€Ρ‚Π΅Ρ„Π°ΠΊΡ‚ΠΎΠ² сборки. Из пСрСчислСнных ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹Ρ… Ρ„Π°ΠΉΠ»ΠΎΠ² ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ собрана Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°.

OBJS = pg_doom.c ...

Π’Ρ‹Π·ΠΎΠ² компилятора ΠΈ скрипты сборки установлСны Π² систСмС ΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° PGXS. Для получСния ΠΏΡƒΡ‚Π΅ΠΉ Π² систСмС присутствуСт ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Π° pg_config.

PG_CONFIG = pg_config
PGXS     := $(shell $(PG_CONFIG) --pgxs)
bindir   := $(shell $(PG_CONFIG) --bindir)
include $(PGXS)

Π€Π°ΠΉΠ»Ρ‹ C

Π’ Ρ„Π°ΠΉΠ»Π°Ρ… размСщаСтся исходный ΠΊΠΎΠ΄ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ объявили Π² sql Ρ„Π°ΠΉΠ»Π΅.

Π’ ΠΎΠ±Ρ‰Π΅ΠΌ случаС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ собранная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π°Π³Ρ€ΡƒΠ·ΠΈΠ»Π°ΡΡŒ ΠΊΠ°ΠΊ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ:

  • Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ макрос PG_MODULE_MAGIC;
  • для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ экспортируСмой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ макрос PG_FUNCTION_INFO_V1(my_function_name);
  • всС экспортируСмыС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΈΠΌΠ΅Ρ‚ΡŒ сигнатуру Datum my_function_name( FunctionCallInfo fcinfo );
  • ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π΄Π²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ - void _PG_init(void) ΠΈ void _PG_fini(void).

ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΠ΅ описаниС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΈ ΠΈΡ… состав ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ с исходным ΠΊΠΎΠ΄ΠΎΠΌ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ.

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ ΠΈΠ³Ρ€Ρ‹

Для сборки ядра ΠΈΠ³Ρ€Ρ‹ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ ΠΏΡ€ΠΎΠΏΠ°Ρ‚Ρ‡Π΅Π½Π½Ρ‹ΠΉ исходный ΠΊΠΎΠ΄, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ исправлСны Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ конструкции языка, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ мСшали ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΌΡƒ ΠΊΠΎΠ΄Ρƒ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΈ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ ΠΏΠΎΠ΄ соврСмСнными 64-Π±ΠΈΡ‚Π½Ρ‹ΠΌΠΈ систСмами. ΠžΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ исходный ΠΊΠΎΠ΄ ядра ΠΈΠ³Ρ€Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ Ρ‚ΡƒΡ‚.

Для запуска ΠΈΠ³Ρ€Ρ‹ Π½ΡƒΠΆΠ΅Π½ Ρ„Π°ΠΉΠ» doom.wad. Он содСрТит всС ΠΌΠ΅Π΄ΠΈΠ°Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ³Ρ€Ρ‹, Π½ΠΎ, ΠΊ соТалСнию, Π½Π΅ являСтся свободно распространяСмым Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ ядра ΠΈΠ³Ρ€Ρ‹. Π•Π³ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π²Π·ΡΡ‚ΡŒ ΠΈΠ· Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ ΠΈΠ³Ρ€Ρ‹ ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π»ΡŽΠ±Ρ‹ΠΌ Π΄Ρ€ΡƒΠ³ΠΈΠΌ Π»Π΅Π³Π°Π»ΡŒΠ½Ρ‹ΠΌ способом.

Для ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ ΠΈΠ³Ρ€Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° Π² Ρ„Π°ΠΉΠ»Π΅ doom.c. ΠŸΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ Π²Ρ‹Π·ΠΎΠ²Π΅ создаётся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ вызываСтся функция D_DoomMain, которая прСдставляСт собой основной Ρ†ΠΈΠΊΠ» ΠΈΠ³Ρ€Ρ‹.

Π’ процСссС Ρ€Π°Π±ΠΎΡ‚Ρ‹ Ρ†ΠΈΠΊΠ»Π° ΠΈΠ³Ρ€Ρ‹ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ Π²Π²ΠΎΠ΄ΠΎΠΌ-Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ ΠΈΠ³Ρ€Ρ‹:

  • I_InitGraphics;
  • I_ShutdownGraphics;
  • I_SetPalette;
  • I_StartTic;
  • I_ReadScreen;
  • I_InitNetwork.

ΠŸΡ€ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΌ запускС ΠΈΠ³Ρ€Ρ‹ эти Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ Π² Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€Π°Ρ… Π²Π²ΠΎΠ΄Π°-Π²Ρ‹Π²ΠΎΠ΄Π° ΠΈΠ³Ρ€Ρ‹. Но Π² нашСм Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠΈ Π΄Ρ€Π°ΠΉΠ²Π΅Ρ€Π° ΠΌΡ‹ Π½Π΅ ΠΊΠΎΠΌΠΏΠΈΠ»ΠΈΡ€ΡƒΠ΅ΠΌ, Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π½Π° взаимодСйствиС со структурами, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ доступны ΠΈΠ· ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ pg_doom_input ΠΈ pg_doom_screen.

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ†ΠΈΡ

ЗапускаСм сборку ΠΈ установку Π² систСму ΠΏΡ€ΠΈ ΠΏΠΎΠΌΠΎΡ‰ΠΈ Ρ‚ΠΈΠΏΠΎΠ²Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² make:

make -j$(nproc) && sudo make install

Запуск сСрвСра

Если Π² систСмС Π½Π΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½ PostgreSQL, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ экзСмпляр ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π΅Π³ΠΎ:

export PGDATA=/tmp/pg_doom_data
mkdir -p $PGDATA

initdb --no-clean --no-sync

cat >> $PGDATA/postgresql.conf <<-EOF
    log_filename             = 'server.log'
    log_min_messages         = 'warning'
    shared_preload_libraries = ''
    listen_addresses         = '0.0.0.0'
EOF

cat >> $PGDATA/pg_hba.conf <<-EOF
    host all    postgres 127.0.0.1/32 trust
    host doomdb slayer   0.0.0.0/0    trust
EOF

pg_ctl start &> /dev/null

Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ

Для запуска ΠΈΠ³Ρ€Ρ‹ создаём ΠΈ настраиваСм Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…:

CREATE DATABASE doomdb;
CREATE EXTENSION IF NOT EXISTS pg_doom;
CREATE ROLE slayer WITH LOGIN;
GRANT USAGE ON SCHEMA doom TO slayer;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA doom TO slayer;

Запуск ΠΈΠ³Ρ€Ρ‹

Для "ΠΊΠΎΠΌΡ„ΠΎΡ€Ρ‚Π½ΠΎΠΉ" ΠΈΠ³Ρ€Ρ‹ Π½Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ скрипт-ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΠ°. Он Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°Π½ΠΈΠΌΠ°Ρ‚ΡŒΡΡ Π²Π²ΠΎΠ΄ΠΎΠΌ-Π²Ρ‹Π²ΠΎΠ΄ΠΎΠΌ, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΌ ΠΊΠ°ΠΊ ΠΏΡ€ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ ΠΈΠ³Ρ€Π΅. Для этого Π½Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½Π°ΠΆΠ°Ρ‚Ρ‹Π΅ ΠΊΠ½ΠΎΠΏΠΊΠΈ ΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ Π½Π° экранС. ΠŸΠ΅Ρ€Π΅Π΄ запуском Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΈΡ‚ΡŒ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Π»:

stty -echo
clear
cols=$(expr $(tput cols  || 281) - 1)
rows=$(expr $(tput lines ||  92) - 2)

И Π΄Π°Π»Π΅Π΅ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Ρ†ΠΈΠΊΠ»:

{
    while true; do
        while read -n 1 -s -t 0.02 k; do
            echo "CALL doom.input('$k',10);";
        done;
        echo "SELECT '\\x1B[H';";
        echo "SELECT linetext FROM doom.screen($cols,$rows);";
        sleep 0.2;
    done;
} | psql -h 127.0.0.1 -U slayer -d doomdb -P pager=off -t -q | sed 's|\\x1B|\x1B|g'

Π’ Ρ†ΠΈΠΊΠ»Π΅ ΠΌΡ‹ динамичСски Ρ„ΠΎΡ€ΠΌΠΈΡ€ΡƒΠ΅ΠΌ тСкстовыС SQL ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΈ отправляСм ΠΈΡ… Π² stdin ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ psql, которая ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ…. Π•Ρ‘ Π²Ρ‹Π²ΠΎΠ΄ Π·Π°Ρ‚Π΅ΠΌ форматируСтся ΠΈ выводится Π½Π° экран. Π‘ΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ обновлСния ΠΈ input-lag сильно зависит ΠΎΡ‚ возмоТностСй ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π° ΠΈ ΠΈΠ³Ρ€ΠΎΠΊΠ°.


Objective

Run Doom on PostgreSQL.

Try it out

For convenience, the whole process is implemented as a Docker image, which you can try.

You only need to manually place the doom.wad file, which is copyright protected and not freely distributable.

git clone https://github.com/DreamNik/pg_doom
cd pg_doom
<manually place your doom.wad file in the pg_doom directory>
docker build --tag pg_doom --file docker/Dockerfile .
docker run --rm --interactive --tty pg_doom

screenshot

Controls - using the A, S, D, W, F, E keys.

Solution Architecture

The solution will consist of:

  • the "pg_doom" extension, which will work inside the DBMS;
  • a bash script, which will act as an input-output interface.

The extension will provide two new functions in the SQL language. The first will transmit the pressed keys; the second will get the "picture" for display. The script will, in turn, read the pressed buttons, passing them as an argument to the first function, and then call the second function and display its result.

Preparation

To write the extension, we will need:

  • a computer with Debian OS;
  • installed PostgreSQL with a development set;
  • a C language compiler and a set of GNU Make utilities.

The article uses Debian OS, but you can use any other Linux family OS with appropriate adaptation of some steps. Windows will also work, but the preparation steps are entirely different. So, we open the console and install the necessary packages:

export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y \
	git \
	build-essentials \
	postgresql

Creating the Extension

The source code for the PostgreSQL extension will consist of:

  • an extension metadata file - "pg_doom.control";
  • files with SQL code for initializing the extension in the database - "pg_doom.sql";
  • an extension build file - "Makefile";
  • source code files - "pg_doom.c" and others.

The article does not provide all the source code. You can view the full source code in the pg_doom repository.

pg_doom.control File

This file is used by PostgreSQL to define the composition of the extension and how and where to load it.

comment         = 'Provides ability to play the game.'
default_version = '1.0'
relocatable     = false
module_pathname = '$libdir/pg_doom'
schema          = doom

The interesting part here is the module_pathname - the path indicating the compiled binary module.

pg_doom--1.0.sql File

This file is executed when loading the extension into the database. If necessary, such files create tables, views, triggers, functions, and other structures required for the extension to work. We only need to provide two functions in the database schema - for input and output:

CREATE PROCEDURE doom.input(
    IN  chars      TEXT,
    IN  duration   INTEGER)
AS 'MODULE_PATHNAME', 'pg_doom_input' LANGUAGE C;

CREATE FUNCTION doom.screen(
    IN  width      INTEGER DEFAULT 320,
    IN  height     INTEGER DEFAULT 200,
    OUT lineNumber INTEGER,
    OUT lineText   TEXT)
RETURNS SETOF RECORD
AS 'MODULE_PATHNAME', 'pg_doom_screen' LANGUAGE C;

The key value MODULE_PATHNAME is used in the file as the module's name for the functions. This value is replaced with the actual address of the loaded module (library), as specified in the control file.

Makefile

The file is used for compiling and installing the extension. At the beginning of the file, the name and description of the extension are defined:

MODULE_big = pg_doom
EXTENSION  = pg_doom
PGFILEDESC = pg_doom

Next, the list of data files that will be installed with the extension is defined:

DATA = pg_doom--1.0.sql pg_doom.control

Then, we define the list of object files that need to be compiled. That is, we're defining not the list of source files, but the list of build artifacts. The library will be assembled from the listed object files.

OBJS = pg_doom.c ...

The compiler call and build scripts are installed in the system and can be included using the PGXS mechanism. The utility pg_config is present in the system for obtaining paths.

PG_CONFIG = pg_config
PGXS     := $(shell $(PG_CONFIG) --pgxs)
bindir   := $(shell $(PG_CONFIG) --bindir)
include $(PGXS)

C Files

In these files, the source code of the functions we declared in the SQL file is located.

Generally, in order for the compiled library to be loaded as an extension, you need to:

  • call the macro PG_MODULE_MAGIC;
  • for each exported function, call the macro PG_FUNCTION_INFO_V1(my_function_name);
  • all exported functions must have the signature Datum my_function_name( FunctionCallInfo fcinfo );
  • define two functions - void _PG_init(void) and void _PG_fini(void).

A detailed description of the functions and their composition can be found in the repository with the source code of the extension.

Game Integration

To build the game's core, a patched source code is required, in which some language constructs that interfered with the original code's compilation and execution on modern 64-bit systems have been fixed. The original source code of the game's core can be found here.

To run the game, you need the file doom.wad. It contains all the game's media data, but unfortunately, unlike the game's core, it is not freely distributed. You can take it from the directory of the original game or obtain it by any other legal means.

Game integration is implemented in the doom.c file. The first call creates a separate thread in which the function D_DoomMain is called, which represents the main loop of the game.

During the game loop's operation, functions are called that control the game's input-output:

  • I_InitGraphics;
  • I_ShutdownGraphics;
  • I_SetPalette;
  • I_StartTic;
  • I_ReadScreen;
  • I_InitNetwork.

In a typical game run, these functions are implemented in the game's I/O drivers. But in our extension, we don't compile the drivers, and the functions are defined to interact with the structures available from the declared functions pg_doom_input and pg_doom_screen.

Compilation

We initiate the build and installation into the system using standard make calls:

make -j$(nproc) && sudo make install

Starting the Server

If PostgreSQL is not running on your system, you can create a temporary instance and start it:

export PGDATA=/tmp/pg_doom_data
mkdir -p $PGDATA

initdb --no-clean --no-sync

cat >> $PGDATA/postgresql.conf <<-EOF
    log_filename             = 'server.log'
    log_min_messages         = 'warning'
    shared_preload_libraries = ''
    listen_addresses         = '0.0.0.0'
EOF

cat >> $PGDATA/pg_hba.conf <<-EOF
    host all    postgres 127.0.0.1/32 trust
    host doomdb slayer   0.0.0.0/0    trust
EOF

pg_ctl start &> /dev/null

Loading the Extension

To start the game, create and configure the database:

CREATE DATABASE doomdb;
CREATE EXTENSION IF NOT EXISTS pg_doom;
CREATE ROLE slayer WITH LOGIN;
GRANT USAGE ON SCHEMA doom TO slayer;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA doom TO slayer;

Starting the Game

For a "comfortable" game, we need a wrapper script. It should handle input-output, similar to a regular game. For this, we need to read the pressed buttons and display the picture on the screen. Before starting, prepare the terminal:

stty -echo
clear
cols=$(expr $(tput cols  || 281) - 1)
rows=$(expr $(tput lines ||  92) - 2)

And then run the loop:

{
    while true; do
        while read -n 1 -s -t 0.02 k; do
            echo "CALL doom.input('$k',10);";
        done;
        echo "SELECT '\\x1B[H';";
        echo "SELECT linetext FROM doom.screen($cols,$rows);";
        sleep 0.2;
    done;
} | psql -h 127.0.0.1 -U slayer -d doomdb -P pager=off -t -q | sed 's|\\x1B|\x1B|g'

In the loop, we dynamically form textual SQL commands and send them to stdin of the psql utility, which connects to the database. Its output is then formatted and displayed on the screen. The refresh rate and input lag depend heavily on the computer's and player's capabilities.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages