diff options
-rw-r--r-- | arena.c | 38 | ||||
-rw-r--r-- | arena.h | 17 | ||||
-rwxr-xr-x | build.sh | 31 | ||||
-rw-r--r-- | example/utf8.txt | 204 | ||||
-rw-r--r-- | linux.c | 70 | ||||
-rw-r--r-- | macros.h | 50 | ||||
-rw-r--r-- | prbm.c | 297 | ||||
-rw-r--r-- | prbm.h | 112 | ||||
-rw-r--r-- | prbs.c | 132 | ||||
-rw-r--r-- | prbs.h | 45 | ||||
-rw-r--r-- | prbwin.c | 77 | ||||
-rw-r--r-- | sys.h | 14 | ||||
-rw-r--r-- | types.h | 19 |
13 files changed, 1106 insertions, 0 deletions
@@ -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); +} @@ -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: █ + ▉ + ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳ + ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳ + ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳ + ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳ + ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎ + ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏ + ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█ @@ -0,0 +1,70 @@ +#include "sys.h" +#include "macros.h" +#include <sys/mman.h> +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + +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 @@ -0,0 +1,297 @@ +#include "prbm.h" +#include <math.h> + +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); +} @@ -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 @@ -0,0 +1,132 @@ +#include "prbs.h" +#include "macros.h" +#include <string.h> +#include <stdio.h> + +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); +} @@ -0,0 +1,45 @@ +#ifndef prbs_h +#define prbs_h + +#include "types.h" +#include "arena.h" +#include <stdarg.h> + +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; +} @@ -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 @@ -0,0 +1,19 @@ +#ifndef types_h +#define types_h + +#include <stdint.h> + +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 |