From 7e73843ac5873833c707687cd0ada0a3034e600c Mon Sep 17 00:00:00 2001 From: pryazha Date: Thu, 11 Sep 2025 19:25:30 +0500 Subject: add new files --- arena.c | 38 +++++++ arena.h | 17 ++++ build.sh | 31 ++++++ example/utf8.txt | 204 ++++++++++++++++++++++++++++++++++++++ linux.c | 70 +++++++++++++ macros.h | 50 ++++++++++ prbm.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ prbm.h | 112 +++++++++++++++++++++ prbs.c | 132 +++++++++++++++++++++++++ prbs.h | 45 +++++++++ prbwin.c | 77 +++++++++++++++ sys.h | 14 +++ types.h | 19 ++++ 13 files changed, 1106 insertions(+) create mode 100644 arena.c create mode 100644 arena.h create mode 100755 build.sh create mode 100644 example/utf8.txt create mode 100644 linux.c create mode 100644 macros.h create mode 100644 prbm.c create mode 100644 prbm.h create mode 100644 prbs.c create mode 100644 prbs.h create mode 100644 prbwin.c create mode 100644 sys.h create mode 100644 types.h diff --git a/arena.c b/arena.c new file mode 100644 index 0000000..03a1c1c --- /dev/null +++ b/arena.c @@ -0,0 +1,38 @@ +#include "arena.h" +#include "macros.h" +#include "sys.h" + +struct arena alloc_arena(u64 capacity) +{ + /* TODO(pryazha): Find reasonable maximum capacity through testing */ + assert(capacity <= (u64)gigabytes(16)); + if (!capacity) + capacity = kilobytes(4); + void *memory = sys_alloc(capacity); + assert(memory); + return (struct arena){memory, capacity, 0}; +} + +void release_arena(struct arena *arena) +{ + assert(arena); + sys_free(arena->memory, arena->capacity); + arena->memory = 0; + arena->capacity = 0; + arena->used = 0; +} + +void *push_arena(struct arena *arena, u64 size) +{ + assert(arena); + assert(arena->used + size <= arena->capacity); + void *memory = arena->memory + arena->used; + arena->used += size; + return memory; +} + +void pop_arena(struct arena *arena, u64 size) +{ + assert(arena); + arena->used -= min(size, arena->used); +} diff --git a/arena.h b/arena.h new file mode 100644 index 0000000..38e3483 --- /dev/null +++ b/arena.h @@ -0,0 +1,17 @@ +#ifndef arena_h +#define arena_h + +#include "types.h" + +struct arena { + void *memory; + u64 capacity; + u64 used; +}; + +struct arena alloc_arena(u64 capacity); +void release_arena(struct arena *a); +void *push_arena(struct arena *arena, u64 size); +void pop_arena(struct arena *arena, u64 size); + +#endif diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..53ad6cb --- /dev/null +++ b/build.sh @@ -0,0 +1,31 @@ +#!/bin/sh +start=`pwd` +dir=`dirname "$0"` +if [ "$1" = 'clean' ] ; then + set -x + cd $dir + rm -f *.o + cd "$start" + exit +fi +cc='tcc' +debug='-g' +release='-O2' +cflags="-c -std=c99" +if [ "$1" = "debug" ] ; then + cflags="$debug $cflags" +else + cflags="$release $cflags" +fi +set -x +cd $dir +$cc $cflags prbm.c +$cc $cflags arena.c +$cc $cflags prbs.c +$cc $cflags linux.c +ar rcs libprb.a\ + prbm.o \ + arena.o \ + prbs.o \ + linux.o +cd "$start" diff --git a/example/utf8.txt b/example/utf8.txt new file mode 100644 index 0000000..3af7875 --- /dev/null +++ b/example/utf8.txt @@ -0,0 +1,204 @@ +// Original by Markus Kuhn, adapted for HTML by Martin D + +UTF-8 encoded sample plain-text file +‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +Markus Kuhn [ˈmaʳkʊs kuːn] mkuhn@acm.org — 1999-08-20 + + +The ASCII compatible UTF-8 encoding of ISO 10646 and Unicode +plain-text files is defined in RFC 2279 and in ISO 10646-1 Annex R. + + +Using Unicode/UTF-8, you can write in emails and source code things such as + +Mathematics and Sciences: + + ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), + + ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B), + + 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm + +Linguistics and dictionaries: + + ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn + Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ] + +APL: + + ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈ + +Nicer typography in plain text files: + + ╔══════════════════════════════════════════╗ + ║ ║ + ║ • ‘single’ and “double” quotes ║ + ║ ║ + ║ • Curly apostrophes: “We’ve been here” ║ + ║ ║ + ║ • Latin-1 apostrophe and accents: '´` ║ + ║ ║ + ║ • ‚deutsche‘ „Anführungszeichen“ ║ + ║ ║ + ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║ + ║ ║ + ║ • ASCII safety test: 1lI|, 0OD, 8B ║ + ║ ╭─────────╮ ║ + ║ • the euro symbol: │ 14.95 € │ ║ + ║ ╰─────────╯ ║ + ╚══════════════════════════════════════════╝ + +Greek (in Polytonic): + + The Greek anthem: + + Σὲ γνωρίζω ἀπὸ τὴν κόψη + τοῦ σπαθιοῦ τὴν τρομερή, + σὲ γνωρίζω ἀπὸ τὴν ὄψη + ποὺ μὲ βία μετράει τὴ γῆ. + + ᾿Απ᾿ τὰ κόκκαλα βγαλμένη + τῶν ῾Ελλήνων τὰ ἱερά + καὶ σὰν πρῶτα ἀνδρειωμένη + χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά! + + From a speech of Demosthenes in the 4th century BC: + + Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι, + ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς + λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ + τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿ + εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ + πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν + οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι, + οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν + ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον + τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι + γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν + προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους + σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ + τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ + τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς + τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον. + + Δημοσθένους, Γ´ ᾿Ολυνθιακὸς + +Georgian: + + From a Unicode conference invitation: + + გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო + კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს, + ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს + ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი, + ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება + ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში, + ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში. + +Russian: + + From a Unicode conference invitation: + + Зарегистрируйтесь сейчас на Десятую Международную Конференцию по + Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии. + Конференция соберет широкий круг экспертов по вопросам глобального + Интернета и Unicode, локализации и интернационализации, воплощению и + применению Unicode в различных операционных системах и программных + приложениях, шрифтах, верстке и многоязычных компьютерных системах. + +Thai (UCS Level 2): + + Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese + classic 'San Gua'): + + [----------------------------|------------------------] + ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่ + สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา + ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา + โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ + เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ + ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ + พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้ + ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ + + (The above is a two-column text. If combining characters are handled + correctly, the lines of the second column should be aligned with the + | character above.) + +Ethiopian: + + Proverbs in the Amharic language: + + ሰማይ አይታረስ ንጉሥ አይከሰስ። + ብላ ካለኝ እንደአባቴ በቆመጠኝ። + ጌጥ ያለቤቱ ቁምጥና ነው። + ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው። + የአፍ ወለምታ በቅቤ አይታሽም። + አይጥ በበላ ዳዋ ተመታ። + ሲተረጉሙ ይደረግሙ። + ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል። + ድር ቢያብር አንበሳ ያስር። + ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም። + እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም። + የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ። + ሥራ ከመፍታት ልጄን ላፋታት። + ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል። + የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ። + ተንጋሎ ቢተፉ ተመልሶ ባፉ። + ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው። + እግርህን በፍራሽህ ልክ ዘርጋ። + +Runes: + + ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ + + (Old English, which transcribed into Latin reads 'He cwaeth that he + bude thaem lande northweardum with tha Westsae.' and means 'He said + that he lived in the northern land near the Western Sea.') + +Braille: + + ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌ + + ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞ + ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎ + ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂ + ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙ + ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑ + ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲ + + ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ + + ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹ + ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞ + ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕ + ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹ + ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎ + ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎ + ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳ + ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞ + ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ + + (The first couple of paragraphs of "A Christmas Carol" by Dickens) + +Compact font selection example text: + + ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789 + abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ + –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд + ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა + +Greetings in various languages: + + Hello world, Καλημέρα κόσμε, コンニチハ + +Box drawing alignment tests: █ + ▉ + ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳ + ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳ + ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳ + ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳ + ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎ + ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏ + ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█ diff --git a/linux.c b/linux.c new file mode 100644 index 0000000..ff20e92 --- /dev/null +++ b/linux.c @@ -0,0 +1,70 @@ +#include "sys.h" +#include "macros.h" +#include +#include +#include +#include +#include + +void *sys_alloc(u64 length) +{ + assert(length); + i32 prot = PROT_READ | PROT_WRITE; + i32 flags = MAP_PRIVATE|MAP_ANONYMOUS; + void *result = mmap(0, length, prot, flags, -1, 0); + return result; +} + +void sys_free(void *memory, u64 length) +{ + assert(memory); + assert(length); + munmap(memory, length); +} + +void die(const char *format, ...) +{ + va_list args; + va_start(args, format); + fprintf(stderr, "error: "); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + va_end(args); + _exit(1); +} + +void info(const char *format, ...) +{ + va_list args; + va_start(args, format); + vprintf(format, args); + putchar('\n'); + va_end(args); +} + +char *read_entire_file(struct arena *arena, u64 *len, const char *filename) +{ + FILE *file = fopen(filename, "rb"); + if (!file) + return 0; + if (fseek(file, 0, SEEK_END) == -1) + goto error; + i64 n = ftell(file); + if (n <= 0) + goto error; + if (len) + *len = n; + if (fseek(file, 0, SEEK_SET) == -1) + goto error; + char *buffer = push_arena(arena, n + 1); + if (!fread(buffer, 1, n, file)) { + pop_arena(arena, n + 1); + goto error; + } + fclose(file); + buffer[n] = 0; + return buffer; +error: + fclose(file); + return 0; +} diff --git a/macros.h b/macros.h new file mode 100644 index 0000000..eb514b5 --- /dev/null +++ b/macros.h @@ -0,0 +1,50 @@ +#ifndef macros_h +#define macros_h + +#undef assert +#define assert(expr) if (!(expr)) { *(int *)0 = 0; } + +#define array_count(array) (sizeof(array)/sizeof(*(array))) + +#undef offsetof +#define offsetof(type, element) ((u64)(&(((type *)0)->element))) + +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +#define clamp(a, x, b) \ + (((x) < (a)) ? (a) : \ + (((x) > (b)) ? (b) : (x))) + +#define swap(type, a, b) { type tmp = (a); (a) = (b); (b) = tmp; } + +#define kilobytes(n) n*1024 +#define megabytes(n) kilobytes(n)*1024 +#define gigabytes(n) megabytes(n)*1024 + +/* NOTE(pryazha): Singly linked list */ +#define sllpush(first, last, node) \ + ((first) == 0 ? \ + ((first) = (last) = (node), (node)->next = 0) : \ + ((last)->next = (node), (last) = (node), (node)->next = 0)) +#define sllpop(first, last) \ + ((first) == (last) ? \ + ((first) = (last) = 0) : \ + ((first) = (first)->next)) + +/* NOTE(pryazha): Doubly linked list */ +#define dllpush(first, last, node, next, prev) \ + ((first) == 0 ? \ + ((first) = (last) = (node), (node)->next = (node)->prev = 0) : \ + ((node)->prev = (last), (last)->next = (node), (last) = (node), (node)->next = 0)) +#define dllpushback(first, last, node) dllpush(first, last, node, next, prev) +#define dllpushfront(first, last, node) dllpush(last, first, node, prev, next) + +#define dllremove(first, last, node) \ + ((first) == (node) ? \ + ((first) == (last) ? (first) = (last) = 0 : \ + ((first) = (first)->next, (first)->prev = 0)) : \ + ((last) == (node) ? ((last) = (last)->prev, (last)->next = 0) : \ + ((node)->next->prev = (node)->prev, (node)->prev->next = (node)->next))) + +#endif diff --git a/prbm.c b/prbm.c new file mode 100644 index 0000000..ae1ac97 --- /dev/null +++ b/prbm.c @@ -0,0 +1,297 @@ +#include "prbm.h" +#include + +struct v2 fillv2(f32 a) +{ + return (struct v2){a, a}; +} + +struct v2 invv2(struct v2 a) +{ + return (struct v2){-a.x, -a.y}; +} + +struct v2 addv2(struct v2 a, struct v2 b) +{ + return (struct v2){a.x + b.x, a.y + b.y}; +} + +struct v2 subv2(struct v2 a, struct v2 b) +{ + return (struct v2){a.x - b.x, a.y - b.y}; +} + +struct v2 scalev2(struct v2 a, f32 s) +{ + return (struct v2){a.x * s, a.y * s}; +} + +struct v2 scalevv2(struct v2 a, struct v2 s) +{ + return (struct v2){a.x * s.x, a.y * s.y}; +} + +f32 dotv2(struct v2 a, struct v2 b) +{ + return (a.x * b.x + a.y * b.y); +} + +f32 len2v2(struct v2 a) +{ + return dotv2(a, a); +} + +f32 lenv2(struct v2 a) +{ + return sqrtf(len2v2(a)); +} + +struct v2 normv2(struct v2 a) +{ + f32 len = lenv2(a); + if (len) { + return v2_zero; + } + f32 ilen = 1.0f / len; + return (struct v2){a.x * len, a.y * len}; +} + +struct v3 fillv3(f32 a) +{ + return (struct v3){a, a, a}; +} + +struct v3 invv3(struct v3 a) +{ + return (struct v3){-a.x, -a.y, -a.z}; +} + +struct v3 addv3(struct v3 a, struct v3 b) +{ + return (struct v3){a.x + b.x, a.y + b.y, a.z + b.z}; +} + +struct v3 subv3(struct v3 a, struct v3 b) +{ + return (struct v3){a.x - b.x, a.y - b.y, a.z - b.z}; +} + +struct v3 scalev3(struct v3 a, f32 s) +{ + return (struct v3){a.x * s, a.y * s, a.z * s}; +} + +struct v3 scalevv3(struct v3 a, struct v3 s) +{ + return (struct v3){a.x * s.x, a.y * s.y, a.z * s.z}; +} + +f32 dotv3(struct v3 a, struct v3 b) +{ + return (a.x * b.x + a.y * b.y + a.z * b.z); +} + +struct v3 crossv3(struct v3 l, struct v3 r) +{ + return (struct v3){ + (l.y * r.z - r.y * l.z), + (r.x * l.z - l.x * r.z), + (l.x * r.y - r.x * l.y) + }; +} + +f32 len2v3(struct v3 a) +{ + return dotv3(a, a); +} + +f32 lenv3(struct v3 a) +{ + return sqrtf(len2v3(a)); +} + +struct v3 normv3(struct v3 a) +{ + f32 len = lenv3(a); + if (!len) + return v3_zero; + f32 ilen = 1.0f / len; + return (struct v3){a.x * len, a.y * len, a.z * len}; +} + +struct v4 fillv4(f32 a) +{ + return (struct v4){a, a, a, a}; +} + +struct v4 invv4(struct v4 a) +{ + return (struct v4){-a.x, -a.y, -a.z, -a.w}; +} + +struct v4 addv4(struct v4 a, struct v4 b) +{ + return (struct v4){a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w}; +} + +struct v4 subv4(struct v4 a, struct v4 b) +{ + return (struct v4){a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w}; +} + +struct v4 scalev4(struct v4 a, f32 s) +{ + return (struct v4){a.x * s, a.y * s, a.z * s, a.w * s}; +} + +struct v4 scalevv4(struct v4 a, struct v4 s) +{ + return (struct v4){a.x * s.x, a.y * s.y, a.z * s.z, a.w * s.w}; +} + +f32 dotv4(struct v4 a, struct v4 b) +{ + return (a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w); +} + +f32 len2v4(struct v4 a) +{ + return dotv4(a, a); +} + +f32 lenv4(struct v4 a) +{ + return sqrtf(len2v4(a)); +} + +struct v4 normv4(struct v4 a) +{ + f32 len = lenv4(a); + if (!len) + return v4_zero; + f32 ilen = 1.0f / len; + return (struct v4){a.x * ilen, a.y * ilen, a.z * ilen, a.w * ilen}; +} + +struct mat transpmat(struct mat m) +{ + struct mat r = m; + r.c0.y = m.c1.x; + r.c0.z = m.c2.x; + r.c0.w = m.c3.x; + r.c1.z = m.c2.y; + r.c1.w = m.c3.y; + r.c2.w = m.c3.z; + return r; +} + +struct mat mulmat(struct mat left, struct mat right) +{ + f32 l00 = left.c0.x, l01 = left.c0.y, l02 = left.c0.z, l03 = left.c0.w; + f32 l10 = left.c1.x, l11 = left.c1.y, l12 = left.c1.z, l13 = left.c1.w; + f32 l20 = left.c2.x, l21 = left.c2.y, l22 = left.c2.z, l23 = left.c2.w; + f32 l30 = left.c3.x, l31 = left.c3.y, l32 = left.c3.z, l33 = left.c3.w; + f32 r00 = right.c0.x, r01 = right.c0.y, r02 = right.c0.z, r03 = right.c0.w; + f32 r10 = right.c1.x, r11 = right.c1.y, r12 = right.c1.z, r13 = right.c1.w; + f32 r20 = right.c2.x, r21 = right.c2.y, r22 = right.c2.z, r23 = right.c2.w; + f32 r30 = right.c3.x, r31 = right.c3.y, r32 = right.c3.z, r33 = right.c3.w; + return (struct mat){ + { + l00*r00 + l10*r01 + l20*r02 + l30*r03, + l01*r00 + l11*r01 + l21*r02 + l31*r03, + l02*r00 + l12*r01 + l22*r02 + l32*r03, + l03*r00 + l13*r01 + l23*r02 + l33*r03 + }, + { + l00*r10 + l10*r11 + l20*r12 + l30*r13, + l01*r10 + l11*r11 + l21*r12 + l31*r13, + l02*r10 + l12*r11 + l22*r12 + l32*r13, + l03*r10 + l13*r11 + l23*r12 + l33*r13 + }, + { + l00*r20 + l10*r21 + l20*r22 + l30*r23, + l01*r20 + l11*r21 + l21*r22 + l31*r23, + l02*r20 + l12*r21 + l22*r22 + l32*r23, + l03*r20 + l13*r21 + l23*r22 + l33*r23 + }, + { + l00*r30 + l10*r31 + l20*r32 + l30*r33, + l01*r30 + l11*r31 + l21*r32 + l31*r33, + l02*r30 + l12*r31 + l22*r32 + l32*r33, + l03*r30 + l13*r31 + l23*r32 + l33*r33 + } + }; +} + +struct mat make_translate(struct v3 v) +{ + return (struct mat){ + {1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f}, + {v.x, v.y, v.z, 1.0f} + }; +} + +struct mat make_scale(struct v3 v) +{ + return (struct mat){ + {v.x, 0.0f, 0.0f, 0.0f}, + {0.0f, v.y, 0.0f, 0.0f}, + {0.0f, 0.0f, v.z, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f} + }; +} + +struct mat make_rotate(struct v3 x, struct v3 y, struct v3 z) +{ + return (struct mat){ + {x.x, x.y, x.z, 0.0f}, + {y.x, y.y, y.z, 0.0f}, + {z.x, z.y, z.z, 0.0f}, + {0.0f, 0.0f, 0.0f, 1.0f} + }; +} + +struct mat translate_mat(struct mat m, struct v3 v) +{ + return mulmat(make_translate(v), m); +} + +struct mat scale_mat(struct mat m, struct v3 v) +{ + return mulmat(make_scale(v), m); +} + +struct mat rotate_mat(struct mat m, struct v3 angles) +{ + f32 angle = deg2rad(angles.x); + f32 cx = cosf(angle); + f32 sx = sinf(angle); + angle = deg2rad(angles.y); + f32 cy = cosf(angle); + f32 sy = sinf(angle); + angle = deg2rad(angles.z); + f32 cz = cosf(angle); + f32 sz = sinf(angle); + struct v3 x = { cy*cz, sx*sy*cz + cx*sz, -cx*sy*cz + sx*sz}; + struct v3 y = {-cy*sz, -sx*sy*sz + cx*cz, cx*sy*sz + sx*cz}; + struct v3 z = { sy, -sx*cy, cx*cy}; + return mulmat(make_rotate(x, y, z), m); +} + +struct v4 mulmatv4(struct mat m, struct v4 v) +{ + return (struct v4){ + m.c0.x*v.x + m.c1.x*v.y + m.c2.x*v.z + m.c3.x*v.w, + m.c0.y*v.x + m.c1.y*v.y + m.c2.y*v.z + m.c3.y*v.w, + m.c0.z*v.x + m.c1.z*v.y + m.c2.z*v.z + m.c3.z*v.w, + m.c0.w*v.x + m.c1.w*v.y + m.c2.w*v.z + m.c3.w*v.w + }; +} + +i32 in_rect(struct v2 pos, struct rect rect) +{ + return (pos.x > rect.start.x) && (pos.x < rect.end.x) && + (pos.y > rect.start.y) && (pos.y < rect.end.y); +} diff --git a/prbm.h b/prbm.h new file mode 100644 index 0000000..f3932dd --- /dev/null +++ b/prbm.h @@ -0,0 +1,112 @@ +#ifndef prbm_h +#define prbm_h + +#include "types.h" + +struct v2 { + f32 x; + f32 y; +}; + +struct v3 { + f32 x; + f32 y; + f32 z; +}; + +struct v4 { + f32 x; + f32 y; + f32 z; + f32 w; +}; + +// column-major +struct mat { + struct v4 c0; + struct v4 c1; + struct v4 c2; + struct v4 c3; +}; + +struct rect { + struct v2 start; + struct v2 end; +}; + +#define v2_zero (struct v2){ 0.0f, 0.0f} +#define v2_one (struct v2){ 1.0f, 1.0f} +#define v2_right (struct v2){ 1.0f, 0.0f} +#define v2_up (struct v2){ 0.0f, 1.0f} +#define v2_left (struct v2){-1.0f, 0.0f} +#define v2_down (struct v2){ 0.0f, -1.0f} + +#define v3_zero (struct v3){ 0.0f, 0.0f, 0.0f} +#define v3_one (struct v3){ 1.0f, 1.0f, 1.0f} +#define v3_right (struct v3){ 1.0f, 0.0f, 0.0f} +#define v3_up (struct v3){ 0.0f, 1.0f, 0.0f} +#define v3_left (struct v3){-1.0f, 0.0f, 0.0f} +#define v3_down (struct v3){ 0.0f, -1.0f, 0.0f} +#define v3_forward (struct v3){ 0.0f, 0.0f, 1.0f} +#define v3_backward (struct v3){ 0.0f, 0.0f, -1.0f} + +#define v4_zero (struct v4){0.0f, 0.0f, 0.0f, 0.0f} +#define v4_one (struct v4){1.0f, 1.0f, 1.0f, 1.0f} + +#define mat_identity (struct mat){ \ + {1.0f, 0.0f, 0.0f, 0.0f}, \ + {0.0f, 1.0f, 0.0f, 0.0f}, \ + {0.0f, 0.0f, 1.0f, 0.0f}, \ + {0.0f, 0.0f, 0.0f, 1.0f}} + +#define f32pi 3.14159265359f + +#define deg2rad(angle) (f32pi/180.0f*(angle)) + +struct v2 fillv2(f32 a); +struct v2 invv2(struct v2 a); +struct v2 addv2(struct v2 a, struct v2 b); +struct v2 subv2(struct v2 a, struct v2 b); +struct v2 scalev2(struct v2 a, f32 s); +struct v2 scalevv2(struct v2 a, struct v2 s); +f32 dotv2(struct v2 a, struct v2 b); +f32 len2v2(struct v2 a); +f32 lenv2(struct v2 a); +struct v2 normv2(struct v2 a); + +struct v3 fillv3(f32 a); +struct v3 invv3(struct v3 a); +struct v3 addv3(struct v3 a, struct v3 b); +struct v3 subv3(struct v3 a, struct v3 b); +struct v3 scalev3(struct v3 a, f32 s); +struct v3 scalevv3(struct v3 a, struct v3 s); +f32 dotv3(struct v3 a, struct v3 b); +struct v3 crossv3(struct v3 l, struct v3 r); +f32 len2v3(struct v3 a); +f32 lenv3(struct v3 a); +struct v3 normv3(struct v3 a); + +struct v4 fillv4(f32 a); +struct v4 invv4(struct v4 a); +struct v4 addv4(struct v4 a, struct v4 b); +struct v4 subv4(struct v4 a, struct v4 b); +struct v4 scalev4(struct v4 a, f32 s); +struct v4 scalevv4(struct v4 a, struct v4 s); +f32 dotv4(struct v4 a, struct v4 b); +f32 len2v4(struct v4 a); +f32 lenv4(struct v4 a); +struct v4 normv4(struct v4 a); + +struct mat transpmat(struct mat m); +struct mat mulmat(struct mat left, struct mat right); +struct mat make_translate(struct v3 v); +struct mat make_scale(struct v3 v); +struct mat make_rotate(struct v3 x, struct v3 y, struct v3 z); +struct mat translate_mat(struct mat m, struct v3 v); +struct mat scale_mat(struct mat m, struct v3 v); +struct mat rotate_mat(struct mat m, struct v3 angles); +struct v4 mulmatv4(struct mat m, struct v4 v); + +i32 in_rect(struct v2 pos, struct rect rect); + +#endif diff --git a/prbs.c b/prbs.c new file mode 100644 index 0000000..818a110 --- /dev/null +++ b/prbs.c @@ -0,0 +1,132 @@ +#include "prbs.h" +#include "macros.h" +#include +#include + +i32 cstrings_equal(const char *s1, const char *s2) +{ + assert(s1 && s2); + while (*s1++ == *s2++) + if (!*s1) + return 1; + return 0; +} + +char *string_to_cstring(struct arena *arena, struct string str) +{ + u64 len = str.len + 1; + char *cstr = push_arena(arena, len); + memmove(cstr, str.ptr, len); + cstr[str.len] = 0; + return cstr; +} + +i32 strings_equal(struct string str1, struct string str2) +{ + if (str1.len != str2.len) + return 0; + for (u64 i = 0; i < str1.len; ++i) + if (str1.ptr[i] != str2.ptr[i]) + return 0; + return 1; +} + +u8 *find_char(struct string str, i32 c) +{ + for (u64 i = 0; i < str.len; ++i) + if (str.ptr[i] == c) + return str.ptr + i; + return 0; +} + +u8 *find_last_char(struct string str, i32 c) +{ + for (u64 i = str.len - 1; i > 0; --i) + if (str.ptr[i] == c) + return str.ptr + i; + return 0; +} + +struct string string_from_range(u8 *start, u8 *end) +{ + assert(start); + assert(end); + assert(start < end); + return (struct string){start, end - start}; +} + +struct string get_dirname(struct string str) +{ + assert(str.len); + u8 *slash = find_last_char(str, '/'); + if (!slash) + return str; + return string_from_range(str.ptr, slash); +} + +struct string push_fstringv(struct arena *arena, const char *format, va_list args) +{ + char tmp[kilobytes(4) + 1]; + i32 len = vsnprintf(tmp, kilobytes(4), format, args); + struct string str = {0}; + if (len < 0) + return str; + u8 *ptr = push_arena(arena, len); + memmove(ptr, tmp, len); + return (struct string){ptr, len}; +} + +struct string push_fstring(struct arena *arena, const char *format, ...) +{ + va_list args; + va_start(args, format); + struct string str = push_fstringv(arena, format, args); + va_end(args); + return str; +} + +void print_string(struct string str) +{ + assert(str.ptr && str.len); + printf("%.*s", str.len, str.ptr); +} + +void push_string_to_list(struct arena *arena, struct string_list *list, i32 front, struct string str) +{ + struct string_node *node = push_arena(arena, sizeof(struct string_node)); + node->str = str; + if (front) + dllpushfront(list->first, list->last, node); + else + dllpushback(list->first, list->last, node); + list->len += str.len; + list->cnt++; +} + +void push_fstring_to_list(struct arena *arena, struct string_list *list, i32 front, const char *format, ...) +{ + va_list args; + va_start(args, format); + struct string str = push_fstringv(arena, format, args); + va_end(args); + push_string_to_list(arena, list, front, str); +} + +struct string join_string_list(struct arena *arena, struct string_list *list) +{ + assert(arena); + assert(list); + struct string str = {arena->memory + arena->used, 0}; + for (struct string_node *node = list->first; node; node = node->next) { + u8 *ptr = push_arena(arena, node->str.len); + memmove(ptr, node->str.ptr, node->str.len); + str.len += node->str.len; + } + return str; +} + +void print_string_list(struct string_list *list) +{ + for (struct string_node *node = list->first; node; node = node->next) + print_string(node->str); +} diff --git a/prbs.h b/prbs.h new file mode 100644 index 0000000..4547d7c --- /dev/null +++ b/prbs.h @@ -0,0 +1,45 @@ +#ifndef prbs_h +#define prbs_h + +#include "types.h" +#include "arena.h" +#include + +i32 cstrings_equal(const char *s1, const char *s2); + +struct string { + u8 *ptr; + u64 len; +}; + +struct string_node { + struct string str; + struct string_node *next; + struct string_node *prev; +}; + +struct string_list { + i32 cnt; + u64 len; + struct string_node *first; + struct string_node *last; +}; + +#define string_from_cliteral(str) (sturct string){(u8 *)(str), sizeof(str) - 1} +#define expand_string(str) (i32)((str).len), ((str).ptr) + +char *string_to_cstring(struct arena *arena, struct string str); +i32 strings_equal(struct string str1, struct string str2); +u8 *find_char(struct string str, i32 c); +u8 *find_last_char(struct string str, i32 c); +struct string string_from_range(u8 *start, u8 *end); +struct string get_dirname(struct string str); +struct string push_fstringv(struct arena *arena, const char *format, va_list args); +struct string push_fstring(struct arena *arena, const char *format, ...); +void print_string(struct string str); +void push_string_to_list(struct arena *arena, struct string_list *list, i32 front, struct string str); +void push_fstring_to_list(struct arena *arena, struct string_list *list, i32 front, const char *format, ...); +struct string join_string_list(struct arena *arena, struct string_list *list); +void print_string_list(struct string_list *list); + +#endif diff --git a/prbwin.c b/prbwin.c new file mode 100644 index 0000000..81ad626 --- /dev/null +++ b/prbwin.c @@ -0,0 +1,77 @@ +#include "sys.h" + +void *sys_alloc(u64 length) +{ + assert(length); + void *result = VirtualAlloc(0, length, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); + return result; +} + +void sys_free(void *memory, u64 length) +{ + assert(memory); + assert(length); + assert(VirtualFree(memory, 0, MEM_RELEASE)); +} + +void die(const char *error_string, ...) +{ + va_list args; + va_start(args, error_string); + printf("error: "); + vprintf(error_string, args); + printf("\n"); + va_end(args); + exit(1); +} + +void info(const char *format, ...) +{ + va_list args; + va_start(args, format); + vprintf(format, args); + putchar('\n'); + va_end(args); +} + +char *read_entire_file(struct arena *arena, u64 *len, const char *filename) +{ + HANDLE file = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, + 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (file == INVALID_HANDLE_VALUE) + return 0; + LARGE_INTEGER lisize; + if (!GetFileSizeEx(file, &lisize)) + goto error; + *len = lisize.QuadPart; + if (!*len) + goto error; + char *buffer = push_arena(arena, *len + 1); + DWORD bytes_read; + if (!ReadFile(file, *buffer, size, &bytes_read, 0)) { + pop_arena(arena, *len + 1); + goto error; + } + CloseHandle(file); + buffer[*len] = 0; + return buffer; +error: + CloseHandle(file); + return 0; +} + +char *get_exe_path(arena_t *arena) +{ + char path[max_path_len] = {0}; + u32 len = GetModuleFileName(0, path, max_path_len); + if (!len) + return 0; + char *dir = strrchr(path, '\\'); + if (!dir) + return path; + len = dir - path; + dir = push_arena(arena, len + 1); + memmove(dir, path, len); + dir[len] = 0; + return dir; +} diff --git a/sys.h b/sys.h new file mode 100644 index 0000000..81d9f0c --- /dev/null +++ b/sys.h @@ -0,0 +1,14 @@ +#ifndef sys_h +#define sys_h + +#include "types.h" +#include "arena.h" + +#define max_path_len 1024 +void *sys_alloc(u64 length); +void sys_free(void *memory, u64 length); +void die(const char *format, ...); +void info(const char *format, ...); +char *read_entire_file(struct arena *arena, u64 *len, const char *filename); + +#endif diff --git a/types.h b/types.h new file mode 100644 index 0000000..8297917 --- /dev/null +++ b/types.h @@ -0,0 +1,19 @@ +#ifndef types_h +#define types_h + +#include + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef float f32; +typedef double f64; + +#endif -- cgit v1.2.3-70-g09d2