diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index a95758d44b..dd13277109 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -6287,7 +6287,6 @@ :flag-assert #x900000008 ) - ;; ---------------------- ;; File - capture ;; Source Path - engine/gfx/capture.gc diff --git a/goal_src/jak1/dgos/engine.gd b/goal_src/jak1/dgos/engine.gd index 976de2883a..bdcb904960 100644 --- a/goal_src/jak1/dgos/engine.gd +++ b/goal_src/jak1/dgos/engine.gd @@ -51,6 +51,7 @@ ("connect.o" "connect") ("text-h.o" "text-h") ("settings-h.o" "settings-h") + ("knuth-rand.o" "knuth-rand") ;; added ("capture.o" "capture") ("memory-usage-h.o" "memory-usage-h") ("texture.o" "texture") diff --git a/goal_src/jak1/dgos/game.gd b/goal_src/jak1/dgos/game.gd index 36f2ef82c0..15c245e5d8 100644 --- a/goal_src/jak1/dgos/game.gd +++ b/goal_src/jak1/dgos/game.gd @@ -47,6 +47,7 @@ ("connect.o" "connect") ("text-h.o" "text-h") ("settings-h.o" "settings-h") + ("knuth-rand.o" "knuth-rand") ;; added ("capture.o" "capture") ("memory-usage-h.o" "memory-usage-h") ("texture.o" "texture") diff --git a/goal_src/jak1/engine/game/settings-h.gc b/goal_src/jak1/engine/game/settings-h.gc index a6a8005ff1..3acdaf004f 100644 --- a/goal_src/jak1/engine/game/settings-h.gc +++ b/goal_src/jak1/engine/game/settings-h.gc @@ -233,3 +233,21 @@ ) (define-extern *setting-control* setting-control) + +(defun scf-time-to-uint64 () + (let ((date (new 'stack 'scf-time))) + (let ((temp (the uint64 0))) + (scf-get-time date) + + (logior! temp (-> date stat)) + (logior! temp (shl (-> date second) 8)) + (logior! temp (shl (-> date minute) 16)) + (logior! temp (shl (-> date hour) 24)) + (logior! temp (shl (-> date week) 32)) + (logior! temp (shl (-> date day) 40)) + (logior! temp (shl (-> date month) 48)) + (logior! temp (shl (-> date year) 56)) + temp + ) + ) +) diff --git a/goal_src/jak1/engine/math/knuth-rand.gc b/goal_src/jak1/engine/math/knuth-rand.gc new file mode 100644 index 0000000000..3447ac4035 --- /dev/null +++ b/goal_src/jak1/engine/math/knuth-rand.gc @@ -0,0 +1,71 @@ +;;-*-Lisp-*- +(in-package goal) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; mimicking Java's util.Random https://docs.oracle.com/javase/8/docs/api/java/util/Random.html +;;;; This is a linear congruential pseudorandom number generator, as defined by D. H. Lehmer +;;;; and described by Donald E. Knuth in The Art of Computer Programming, Volume 3: Seminumerical Algorithms, section 3.2.1. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(deftype knuth-rand-state (structure) + ((seed uint64)) + ) + +(define *knuth-rand-state* (new 'global 'knuth-rand-state)) + +(defun knuth-rand-init ((newSeed uint)) + (set! (-> *knuth-rand-state* seed) newSeed) +) +(knuth-rand-init (scf-time-to-uint64)) + +(defun knuth-rand-advance-seed () + ;; seed = (seed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1) + (set! (-> *knuth-rand-state* seed) (the uint64 (logand (+ (imul64 (-> *knuth-rand-state* seed) 25214903917) 11) (- (shl 1 48) 1)))) +) + +(defun knuth-rand-next ((bits int)) + (knuth-rand-advance-seed) + + ;; return (int)(seed >>> (48 - bits)) + (shr (-> *knuth-rand-state* seed) (- 48 bits)) +) + +(defun knuth-rand-nextInt () + (knuth-rand-advance-seed) + (-> *knuth-rand-state* seed) +) + +;; returns a pseudorandom int in the range [min, max) +(defun knuth-rand-nextIntRange ((min int) (max int)) + (let* ((bound (- max min)) + ;; int bits, val; + (bits (the uint64 0)) + (val (the uint64 0))) + + ;; if ((bound & -bound) == bound) // i.e., bound is a power of 2 + (if (= (logand bound (* -1 bound)) bound) + ;; return (int)((bound * (long)next(31)) >> 31); + (return (sar (* bound (knuth-rand-next 31)) 31)) + ) + + ;; do { + ;; bits = next(31); + ;; val = bits % bound; + ;; } while (bits - val + (bound-1) < 0); + ;; return val; + (while #t + (set! bits (knuth-rand-next 31)) + (set! val (mod bits bound)) + + (if (>= (+ bits (* -1 val) bound -1) 0) + (return (+ min val)) + ) + ) + ) + -1 +) + +;; returns a pseudorandom float in the range [0, 1) +(defun knuth-rand-nextFloat () + ;; return next(24) / ((float)(1 << 24)); + (/ (the float (knuth-rand-next 24)) (shl 1 24)) +) \ No newline at end of file diff --git a/goal_src/jak1/engine/math/math.gc b/goal_src/jak1/engine/math/math.gc index 0ab9ef0a25..48304b8112 100644 --- a/goal_src/jak1/engine/math/math.gc +++ b/goal_src/jak1/engine/math/math.gc @@ -315,5 +315,4 @@ (defmacro rand-float-gen (&key (gen *random-generator*)) "Generate a float from [0, 1)" `(+ -1.0 (the-as float (logior #x3f800000 (/ (rand-uint31-gen ,gen) 256)))) - ) - + ) \ No newline at end of file diff --git a/goal_src/jak1/game.gp b/goal_src/jak1/game.gp index 893e565cef..c89f76ab23 100644 --- a/goal_src/jak1/game.gp +++ b/goal_src/jak1/game.gp @@ -1696,6 +1696,7 @@ "engine/connect.gc" "ui/text-h.gc" "game/settings-h.gc" + "math/knuth-rand.gc" ;; added "util/capture.gc" "debug/memory-usage-h.gc" "gfx/texture/texture.gc"