mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-27 16:31:14 +00:00
[Decompile] vector.gc (finally) (#394)
* support psubw * do half of vector * rest of vector * add test * format
This commit is contained in:
parent
53a70d8e43
commit
14028b90bc
@ -8,10 +8,9 @@ typedef OpenGOALAsm::InstructionModifiers MOD;
|
||||
|
||||
const std::map<InstructionKind, OpenGOALAsm::Function> MIPS_ASM_TO_OPEN_GOAL_FUNCS = {
|
||||
// ----- EE -------
|
||||
// TODO - these are waiting on proper 128-bit int support in OpenGOAL
|
||||
{InstructionKind::PSLLW, {".pw.sll", {}}},
|
||||
{InstructionKind::PSRAW, {".pw.sra", {}}},
|
||||
{InstructionKind::PSUBW, {"TODO.PSUBW", {}}},
|
||||
{InstructionKind::PSUBW, {".psubw", {}}},
|
||||
|
||||
{InstructionKind::PEXTUW, {".pextuw", {}}},
|
||||
{InstructionKind::PEXTLW, {".pextlw", {}}},
|
||||
|
@ -2694,7 +2694,7 @@
|
||||
(deftype dma-packet (structure)
|
||||
((dma dma-tag :offset-assert 0)
|
||||
(vif0 vif-tag :offset-assert 8)
|
||||
(vif1 vif-tag :offset-assert 12) ;; doesn't have to be a vif tag.
|
||||
(vif1 vif-tag :offset-assert 12)
|
||||
(quad uint128 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
@ -3672,7 +3672,7 @@
|
||||
(define-extern vector-v+! (function vector vector vector vector))
|
||||
(define-extern vector-v*float+! (function vector vector vector float vector))
|
||||
(define-extern vector-v++! (function vector vector vector))
|
||||
(define-extern vector-v*float! (function vector float float vector))
|
||||
(define-extern vector-v*float! (function vector vector float vector))
|
||||
(define-extern vector-v*float++! (function vector vector float vector))
|
||||
(define-extern vector-to-ups! (function vector vector vector))
|
||||
(define-extern vector-from-ups! (function vector vector vector))
|
||||
@ -3703,16 +3703,16 @@
|
||||
(define-extern vector-degi (function vector vector vector))
|
||||
(define-extern vector-degf (function vector vector vector))
|
||||
(define-extern vector-degmod (function vector vector vector))
|
||||
(define-extern vector-deg-diff (function vector vector vector vector))
|
||||
(define-extern vector-deg-diff (function vector vector vector none))
|
||||
(define-extern vector-deg-lerp-clamp! (function vector vector vector float vector)) ;; todo
|
||||
(define-extern vector3s-copy! (function vector vector vector))
|
||||
(define-extern vector3s+! (function vector vector vector vector))
|
||||
(define-extern vector3s*float! (function vector vector float vector))
|
||||
(define-extern vector3s-! (function vector vector vector vector))
|
||||
(define-extern spheres-overlap? (function vector vector symbol))
|
||||
(define-extern spheres-overlap? (function sphere sphere symbol))
|
||||
(define-extern sphere<-vector! (function sphere vector sphere))
|
||||
(define-extern sphere<-vector+r! (function sphere vector float sphere))
|
||||
(define-extern rand-vu-sphere-point! (function vector sphere vector)) ;; todo
|
||||
(define-extern rand-vu-sphere-point! (function vector float vector)) ;; todo
|
||||
|
||||
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -164,6 +164,9 @@
|
||||
"vif1-handler", // F: weird asm for interrupt handler
|
||||
"vif1-handler-debug",
|
||||
|
||||
// vector
|
||||
"vector=", // asm branching
|
||||
|
||||
// texture
|
||||
"adgif-shader<-texture-with-update!", // F: asm branching
|
||||
"(method 9 texture-page-dir)",
|
||||
|
@ -800,6 +800,88 @@
|
||||
"vars": { "gp-0": "obj" }
|
||||
},
|
||||
|
||||
"vector-seek-2d-xz-smooth!": {
|
||||
"args": ["vec", "target", "max-step", "alpha"],
|
||||
"vars": {
|
||||
"f0-1": "x-diff",
|
||||
"f2-1": "z-diff",
|
||||
"f1-5": "x-step",
|
||||
"f0-3": "z-step",
|
||||
"f2-4": "step-len"
|
||||
}
|
||||
},
|
||||
|
||||
"vector-seek-2d-yz-smooth!": {
|
||||
"args": ["vec", "target", "max-step", "alpha"],
|
||||
"vars": {
|
||||
"f0-1": "y-diff",
|
||||
"f2-1": "z-diff",
|
||||
"f1-5": "y-step",
|
||||
"f0-3": "z-step",
|
||||
"f2-4": "step-len",
|
||||
"f2-6": "step-scale"
|
||||
}
|
||||
},
|
||||
|
||||
"vector-seek-3d-smooth!": {
|
||||
"args": ["vec", "target", "max-step", "alpha"],
|
||||
"vars": {
|
||||
"f0-1": "x-diff",
|
||||
"f1-2": "y-diff",
|
||||
"f3-1": "z-diff",
|
||||
"f2-6": "x-step",
|
||||
"f1-3": "y-step",
|
||||
"f0-4": "z-step",
|
||||
"f3-5": "step-len",
|
||||
"f3-7": "step-scale"
|
||||
}
|
||||
},
|
||||
|
||||
"seek-with-smooth": {
|
||||
"args": ["value", "target", "max-step", "alpha", "deadband"],
|
||||
"vars": { "f0-1": "diff", "f0-2": "step", "f1-4": "min-step" }
|
||||
},
|
||||
|
||||
"vector-v+!": {
|
||||
"args": ["result", "position", "velocity"]
|
||||
},
|
||||
|
||||
"vector-v*float+!": {
|
||||
"args": ["result", "position", "velocity", "velocity-scale"]
|
||||
},
|
||||
|
||||
"vector-v++!": {
|
||||
"args": ["position", "velocity"]
|
||||
},
|
||||
|
||||
"vector-v*float!": {
|
||||
"args": ["delta-p", "velocity", "scale"]
|
||||
},
|
||||
|
||||
"vector-v*float++!": {
|
||||
"args": ["position", "velocity", "scale"]
|
||||
},
|
||||
|
||||
"vector-lerp!": {
|
||||
"args": ["out", "a", "b", "alpha"]
|
||||
},
|
||||
|
||||
"vector-lerp-clamp!": {
|
||||
"args": ["out", "a", "b", "alpha"]
|
||||
},
|
||||
|
||||
"vector4-lerp!": {
|
||||
"args": ["out", "a", "b", "alpha"]
|
||||
},
|
||||
|
||||
"vector4-lerp-clamp!": {
|
||||
"args": ["out", "a", "b", "alpha"]
|
||||
},
|
||||
|
||||
"vector-deg-lerp-clamp!": {
|
||||
"args": ["out", "min-val", "max-val", "in"]
|
||||
},
|
||||
|
||||
"(method 9 display)": {
|
||||
"args": ["obj", "delta-seconds"],
|
||||
"vars": { "gp-0": "obj", "s5-0": "delta" }
|
||||
|
@ -140,3 +140,5 @@
|
||||
- `defenum` now creates real types. Boxed arrays of enums and bitfields correctly have runtime type of the parent integer.
|
||||
- Added a `:copy-entries <typename>` to copy entries from a previous bitfield.
|
||||
- Adding a duplicate entry to an enum now generates a compiler error.
|
||||
- Added `.psubw` assembly form
|
||||
- Changed `.ftoi` to `VCVTTPS2DQ` to make the rounding behavior match the PS2 (truncate).
|
@ -6,7 +6,7 @@
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(defun vector-cross! ((arg0 vector) (arg1 vector) (arg2 vector))
|
||||
"Compute the cross product."
|
||||
"Compute the cross product. The w component is set to junk."
|
||||
(rlet ((acc :class vf)
|
||||
(vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -320,9 +320,13 @@
|
||||
(.lvf vf2 (&-> arg1 quad))
|
||||
(.sub.vf vf1 vf2 vf1)
|
||||
(.abs.vf vf1 vf1)
|
||||
;; put abs.x in acc.w
|
||||
(.mul.x.vf acc vf0 vf1 :mask #b1000)
|
||||
;; add abs.y
|
||||
(.add.mul.y.vf acc vf0 vf1 acc :mask #b1000)
|
||||
;; add abs.z
|
||||
(.add.mul.z.vf vf3 vf0 vf1 acc :mask #b1000)
|
||||
;; set acc.x = acc.w
|
||||
(.add.w.vf vf3 vf0 vf3 :mask #b1)
|
||||
(.mov v0-0 vf3)
|
||||
v0-0
|
||||
@ -354,27 +358,69 @@
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-seek-2d-xz-smooth! ((arg0 vector) (arg1 vector) (arg2 float) (arg3 float))
|
||||
(let ((f0-1 (- (-> arg1 data 0) (-> arg0 data 0)))
|
||||
(f2-1 (- (-> arg1 data 2) (-> arg0 data 2)))
|
||||
(defun vector-seek-2d-xz-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
|
||||
"Smoothly seek vec's x and z components toward target.
|
||||
The step always points toward the target and has length (dist * alpha)
|
||||
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
|
||||
Doesn't touch y or w."
|
||||
;; how much we have to go to get to the target
|
||||
(let ((x-diff (- (-> target data 0) (-> vec data 0)))
|
||||
(z-diff (- (-> target data 2) (-> vec data 2)))
|
||||
)
|
||||
(if (or (!= f0-1 0.0) (!= f2-1 0.0))
|
||||
(let* ((f1-5 (* f0-1 arg3))
|
||||
(f0-3 (* f2-1 arg3))
|
||||
(f2-4 (sqrtf (+ (* f1-5 f1-5) (* f0-3 f0-3))))
|
||||
;; do we have to move?
|
||||
(if (or (!= x-diff 0.0) (!= z-diff 0.0))
|
||||
;; if so, scale by alpha,
|
||||
(let* ((x-step (* x-diff alpha))
|
||||
(z-step (* z-diff alpha))
|
||||
;; and get the length of this step
|
||||
(step-len (sqrtf (+ (* x-step x-step) (* z-step z-step))))
|
||||
)
|
||||
(cond
|
||||
((>= arg2 f2-4)
|
||||
(set! (-> arg0 data 0) (+ (-> arg0 data 0) f1-5))
|
||||
(let ((f0-4 (+ (-> arg0 data 2) f0-3)))
|
||||
(set! (-> arg0 data 2) f0-4)
|
||||
((>= max-step step-len)
|
||||
;; step is within max-step, just do it.
|
||||
(+! (-> vec data 0) x-step)
|
||||
(+! (-> vec data 2) z-step)
|
||||
)
|
||||
(else
|
||||
;; not in range.
|
||||
(let ((f2-6 (/ max-step step-len)))
|
||||
(+! (-> vec data 0) (* f2-6 x-step))
|
||||
(+! (-> vec data 2) (* f2-6 z-step))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
vec
|
||||
)
|
||||
|
||||
|
||||
(defun vector-seek-2d-yz-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
|
||||
"Smoothly seek vec's y and z components toward target.
|
||||
The step always points toward the target and has length (dist * alpha)
|
||||
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
|
||||
Doesn't touch x or w."
|
||||
(let ((y-diff (- (-> target data 1) (-> vec data 1)))
|
||||
(z-diff (- (-> target data 2) (-> vec data 2)))
|
||||
)
|
||||
(if (or (!= y-diff 0.0) (!= z-diff 0.0))
|
||||
(let* ((y-step (* y-diff alpha))
|
||||
(z-step (* z-diff alpha))
|
||||
(step-len (sqrtf (+ (* y-step y-step) (* z-step z-step))))
|
||||
)
|
||||
(cond
|
||||
((>= max-step step-len)
|
||||
(set! (-> vec data 1) (+ (-> vec data 1) y-step))
|
||||
(let ((f0-4 (+ (-> vec data 2) z-step)))
|
||||
(set! (-> vec data 2) f0-4)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(let ((f2-6 (/ arg2 f2-4)))
|
||||
(set! (-> arg0 data 0) (+ (-> arg0 data 0) (* f2-6 f1-5)))
|
||||
(let ((f0-6 (+ (-> arg0 data 2) (* f2-6 f0-3))))
|
||||
(set! (-> arg0 data 2) f0-6)
|
||||
(let ((step-scale (/ max-step step-len)))
|
||||
(set! (-> vec data 1) (+ (-> vec data 1) (* step-scale y-step)))
|
||||
(let ((f0-6 (+ (-> vec data 2) (* step-scale z-step))))
|
||||
(set! (-> vec data 2) f0-6)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -382,30 +428,38 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
vec
|
||||
)
|
||||
|
||||
(defun vector-seek-2d-yz-smooth! ((arg0 vector) (arg1 vector) (arg2 float) (arg3 float))
|
||||
(let ((f0-1 (- (-> arg1 data 1) (-> arg0 data 1)))
|
||||
(f2-1 (- (-> arg1 data 2) (-> arg0 data 2)))
|
||||
(defun vector-seek-3d-smooth! ((vec vector) (target vector) (max-step float) (alpha float))
|
||||
"Smoothly seek vec's x, y, and z components toward target.
|
||||
The step always points toward the target and has length (dist * alpha)
|
||||
If the step is longer than max-step, the step is projected onto a circle of radius max-step.
|
||||
Doesn't touch w."
|
||||
(let ((x-diff (- (-> target data 0) (-> vec data 0)))
|
||||
(y-diff (- (-> target data 1) (-> vec data 1)))
|
||||
(z-diff (- (-> target data 2) (-> vec data 2)))
|
||||
)
|
||||
(if (or (!= f0-1 0.0) (!= f2-1 0.0))
|
||||
(let* ((f1-5 (* f0-1 arg3))
|
||||
(f0-3 (* f2-1 arg3))
|
||||
(f2-4 (sqrtf (+ (* f1-5 f1-5) (* f0-3 f0-3))))
|
||||
(if (or (!= x-diff 0.0) (!= y-diff 0.0) (!= z-diff 0.0))
|
||||
(let* ((x-step (* x-diff alpha))
|
||||
(y-step (* y-diff alpha))
|
||||
(z-step (* z-diff alpha))
|
||||
(step-len (sqrtf (+ (+ (* x-step x-step) (* y-step y-step)) (* z-step z-step))))
|
||||
)
|
||||
(cond
|
||||
((>= arg2 f2-4)
|
||||
(set! (-> arg0 data 1) (+ (-> arg0 data 1) f1-5))
|
||||
(let ((f0-4 (+ (-> arg0 data 2) f0-3)))
|
||||
(set! (-> arg0 data 2) f0-4)
|
||||
((>= max-step step-len)
|
||||
(set! (-> vec data 0) (+ (-> vec data 0) x-step))
|
||||
(set! (-> vec data 1) (+ (-> vec data 1) y-step))
|
||||
(let ((f0-5 (+ (-> vec data 2) z-step)))
|
||||
(set! (-> vec data 2) f0-5)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(let ((f2-6 (/ arg2 f2-4)))
|
||||
(set! (-> arg0 data 1) (+ (-> arg0 data 1) (* f2-6 f1-5)))
|
||||
(let ((f0-6 (+ (-> arg0 data 2) (* f2-6 f0-3))))
|
||||
(set! (-> arg0 data 2) f0-6)
|
||||
(let ((step-scale (/ max-step step-len)))
|
||||
(set! (-> vec data 0) (+ (-> vec data 0) (* step-scale x-step)))
|
||||
(set! (-> vec data 1) (+ (-> vec data 1) (* step-scale y-step)))
|
||||
(let ((f0-7 (+ (-> vec data 2) (* step-scale z-step))))
|
||||
(set! (-> vec data 2) f0-7)
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -413,66 +467,35 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
vec
|
||||
)
|
||||
|
||||
(defun vector-seek-3d-smooth! ((arg0 vector) (arg1 vector) (arg2 float) (arg3 float))
|
||||
(let ((f0-1 (- (-> arg1 data 0) (-> arg0 data 0)))
|
||||
(f1-2 (- (-> arg1 data 1) (-> arg0 data 1)))
|
||||
(f3-1 (- (-> arg1 data 2) (-> arg0 data 2)))
|
||||
)
|
||||
(if (or (!= f0-1 0.0) (!= f1-2 0.0) (!= f3-1 0.0))
|
||||
(let* ((f2-6 (* f0-1 arg3))
|
||||
(f1-3 (* f1-2 arg3))
|
||||
(f0-4 (* f3-1 arg3))
|
||||
(f3-5 (sqrtf (+ (+ (* f2-6 f2-6) (* f1-3 f1-3)) (* f0-4 f0-4))))
|
||||
)
|
||||
(defun seek-with-smooth ((value float) (target float) (max-step float) (alpha float) (deadband float))
|
||||
"Move value closer to target.
|
||||
If we are within deadband, just go straight to target.
|
||||
If not, try to go alpha*err. If that is a larger step than max-step, limit to max-step"
|
||||
(let ((diff (- target value)))
|
||||
(if (>= deadband (fabs diff))
|
||||
target
|
||||
(let ((step (* diff alpha)))
|
||||
(let ((min-step (- max-step)))
|
||||
(cond
|
||||
((>= arg2 f3-5)
|
||||
(set! (-> arg0 data 0) (+ (-> arg0 data 0) f2-6))
|
||||
(set! (-> arg0 data 1) (+ (-> arg0 data 1) f1-3))
|
||||
(let ((f0-5 (+ (-> arg0 data 2) f0-4)))
|
||||
(set! (-> arg0 data 2) f0-5)
|
||||
((< step min-step)
|
||||
(set! step min-step)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(let ((f3-7 (/ arg2 f3-5)))
|
||||
(set! (-> arg0 data 0) (+ (-> arg0 data 0) (* f3-7 f2-6)))
|
||||
(set! (-> arg0 data 1) (+ (-> arg0 data 1) (* f3-7 f1-3)))
|
||||
(let ((f0-7 (+ (-> arg0 data 2) (* f3-7 f0-4))))
|
||||
(set! (-> arg0 data 2) f0-7)
|
||||
((< max-step step)
|
||||
(set! step max-step)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun seek-with-smooth ((arg0 float) (arg1 float) (arg2 float) (arg3 float) (arg4 float))
|
||||
(let ((f0-1 (- arg1 arg0)))
|
||||
(if (>= arg4 (fabs f0-1))
|
||||
arg1
|
||||
(let ((f0-2 (* f0-1 arg3)))
|
||||
(let ((f1-4 (- arg2)))
|
||||
(cond
|
||||
((< f0-2 f1-4)
|
||||
(set! f0-2 f1-4)
|
||||
)
|
||||
((< arg2 f0-2)
|
||||
(set! f0-2 arg2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(+ f0-2 arg0)
|
||||
(+ step value)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-identity! ((arg0 vector))
|
||||
"Set arg0 to 1, 1, 1, 1"
|
||||
(set! (-> arg0 data 0) 1.0)
|
||||
(set! (-> arg0 data 1) 1.0)
|
||||
(set! (-> arg0 data 2) 1.0)
|
||||
@ -481,20 +504,23 @@
|
||||
)
|
||||
|
||||
(defun vector-seconds ((arg0 vector) (arg1 vector))
|
||||
(set! (-> arg0 data 0) (* 300.0 (-> arg1 data 0)))
|
||||
(set! (-> arg0 data 1) (* 300.0 (-> arg1 data 1)))
|
||||
(set! (-> arg0 data 2) (* 300.0 (-> arg1 data 2)))
|
||||
"Convert from actual seconds to the seconds unit."
|
||||
(set! (-> arg0 data 0) (seconds (-> arg1 data 0)))
|
||||
(set! (-> arg0 data 1) (seconds (-> arg1 data 1)))
|
||||
(set! (-> arg0 data 2) (seconds (-> arg1 data 2)))
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun vector-seconds! ((arg0 vector))
|
||||
(set! (-> arg0 data 0) (* 300.0 (-> arg0 data 0)))
|
||||
(set! (-> arg0 data 1) (* 300.0 (-> arg0 data 1)))
|
||||
(set! (-> arg0 data 2) (* 300.0 (-> arg0 data 2)))
|
||||
"Convert from actual seconds to seconds, in place"
|
||||
(set! (-> arg0 data 0) (seconds (-> arg0 data 0)))
|
||||
(set! (-> arg0 data 1) (seconds (-> arg0 data 1)))
|
||||
(set! (-> arg0 data 2) (seconds (-> arg0 data 2)))
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun vector-v! ((arg0 vector))
|
||||
"Convert a velocity to a displacement per frame. The velocity should be in X/actual_second"
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -517,32 +543,37 @@
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-v+! ((arg0 vector) (arg1 vector) (arg2 vector))
|
||||
(vector+float*! arg0 arg1 arg2 (-> *display* seconds-per-frame))
|
||||
arg0
|
||||
(defun vector-v+! ((result vector) (position vector) (velocity vector))
|
||||
"Euler forward step, using the current display time settings"
|
||||
(vector+float*! result position velocity (-> *display* seconds-per-frame))
|
||||
result
|
||||
)
|
||||
|
||||
(defun vector-v*float+! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(vector+float*! arg0 arg1 arg2 (* arg3 (-> *display* seconds-per-frame)))
|
||||
arg0
|
||||
|
||||
(defun vector-v*float+! ((result vector) (position vector) (velocity vector) (velocity-scale float))
|
||||
"Euler forward step, scaling velocity by velocity-scale"
|
||||
(vector+float*! result position velocity (* velocity-scale (-> *display* seconds-per-frame)))
|
||||
result
|
||||
)
|
||||
|
||||
(defun vector-v++! ((arg0 vector) (arg1 vector))
|
||||
(vector+float*! arg0 arg0 arg1 (-> *display* seconds-per-frame))
|
||||
arg0
|
||||
(defun vector-v++! ((position vector) (velocity vector))
|
||||
"Update position in place, using display's current timing"
|
||||
(vector+float*! position position velocity (-> *display* seconds-per-frame))
|
||||
position
|
||||
)
|
||||
|
||||
(defun vector-v*float! ((arg0 vector) (arg1 float) (arg2 float))
|
||||
(defun vector-v*float! ((delta-p vector) (velocity vector) (scale float))
|
||||
"Go from velocity to delta-p per frame, scaling by scale"
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
)
|
||||
(.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0))
|
||||
(let ((v0-0 arg0))
|
||||
(let ((v1-0 arg1)
|
||||
(f0-1 (* arg2 (-> *display* seconds-per-frame)))
|
||||
(let ((v0-0 delta-p))
|
||||
(let ((v1-0 velocity)
|
||||
(f0-1 (* scale (-> *display* seconds-per-frame)))
|
||||
)
|
||||
(.lvf vf1 v1-0)
|
||||
(.lvf vf1 (&-> v1-0 quad))
|
||||
(let ((v1-1 f0-1))
|
||||
(.mov vf2 v1-1)
|
||||
)
|
||||
@ -555,12 +586,15 @@
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-v*float++! ((arg0 vector) (arg1 vector) (arg2 float))
|
||||
(vector+float*! arg0 arg0 arg1 (* arg2 (-> *display* seconds-per-frame)))
|
||||
arg0
|
||||
(defun vector-v*float++! ((position vector) (velocity vector) (scale float))
|
||||
"update position with given velocity, scaled by scale."
|
||||
(vector+float*! position position velocity (* scale (-> *display* seconds-per-frame)))
|
||||
position
|
||||
)
|
||||
|
||||
|
||||
(defun vector-to-ups! ((arg0 vector) (arg1 vector))
|
||||
"Go from units per frame to units per second?"
|
||||
(local-vars (at-0 int))
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
@ -580,6 +614,7 @@
|
||||
)
|
||||
|
||||
(defun vector-from-ups! ((arg0 vector) (arg1 vector))
|
||||
"Go from units per second to units per frame?"
|
||||
(local-vars (at-0 int))
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
@ -599,6 +634,7 @@
|
||||
)
|
||||
|
||||
(defun vector-length ((arg0 vector))
|
||||
"Get the length of the xyz part."
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
@ -623,6 +659,7 @@
|
||||
)
|
||||
|
||||
(defun vector-length-squared ((arg0 vector))
|
||||
"Get the squared length of the xyz part."
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((acc :class vf)
|
||||
(vf0 :class vf)
|
||||
@ -642,22 +679,22 @@
|
||||
)
|
||||
|
||||
(defun vector-xz-length-squared ((arg0 vector))
|
||||
(+
|
||||
(* (-> arg0 data 0) (-> arg0 data 0))
|
||||
"Get the length of the xz part, squared."
|
||||
(+ (* (-> arg0 data 0) (-> arg0 data 0))
|
||||
(* (-> arg0 data 2) (-> arg0 data 2))
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-xz-length ((arg0 vector))
|
||||
(sqrtf
|
||||
(+
|
||||
(* (-> arg0 data 0) (-> arg0 data 0))
|
||||
"Get the length of the xz part, squared"
|
||||
(sqrtf (+ (* (-> arg0 data 0) (-> arg0 data 0))
|
||||
(* (-> arg0 data 2) (-> arg0 data 2))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-vector-distance ((arg0 vector) (arg1 vector))
|
||||
"Subtract the xyz parts and get the norm"
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
@ -686,6 +723,7 @@
|
||||
)
|
||||
|
||||
(defun vector-vector-distance-squared ((arg0 vector) (arg1 vector))
|
||||
"Squared norm of the difference of the xyz parts"
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -703,6 +741,7 @@
|
||||
)
|
||||
|
||||
(defun vector-vector-xz-distance ((arg0 vector) (arg1 vector))
|
||||
"Distance on the xz plane"
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
@ -730,6 +769,7 @@
|
||||
)
|
||||
|
||||
(defun vector-vector-xz-distance-squared ((arg0 vector) (arg1 vector))
|
||||
"Squared distance on the xz plane"
|
||||
(local-vars (v0-0 float))
|
||||
(rlet ((vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -746,6 +786,7 @@
|
||||
)
|
||||
|
||||
(defun vector-normalize! ((arg0 vector) (arg1 float))
|
||||
"Modify arg0 in place to have length arg1 for its xyz components. The w part is not changed."
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
(vf0 :class vf)
|
||||
@ -774,6 +815,8 @@
|
||||
)
|
||||
|
||||
(defun vector-normalize-ret-len! ((arg0 vector) (arg1 float))
|
||||
"Modify arg0 in place to have length arg1 for its xyz components.
|
||||
The w part isn't changed and the _original_ length is returned."
|
||||
(local-vars (v1-1 float))
|
||||
(rlet ((acc :class vf)
|
||||
(Q :class vf)
|
||||
@ -807,6 +850,9 @@
|
||||
)
|
||||
|
||||
(defun vector-normalize-copy! ((arg0 vector) (arg1 vector) (arg2 float))
|
||||
"Normalize, but not in place.
|
||||
This implementation is very good compared to the vector-normalize! one.
|
||||
The w component is set to 1."
|
||||
(let ((f0-0 (vector-length arg1)))
|
||||
(if (= f0-0 0.0)
|
||||
(set! (-> arg0 quad) (-> arg1 quad))
|
||||
@ -824,13 +870,12 @@
|
||||
)
|
||||
|
||||
(defun vector-xz-normalize! ((arg0 vector) (arg1 float))
|
||||
"Normalize, xz components only"
|
||||
(let ((f0-0 (vector-xz-length arg0)))
|
||||
(if (!= f0-0 0.0)
|
||||
(let ((v1-1 (/ arg1 f0-0)))
|
||||
(set! (-> arg0 data 0) (* (-> arg0 data 0) v1-1))
|
||||
(let ((f0-5 (* (-> arg0 data 2) v1-1)))
|
||||
(set! (-> arg0 data 2) f0-5)
|
||||
)
|
||||
(set! (-> arg0 data 2) (* (-> arg0 data 2) v1-1))
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -838,15 +883,16 @@
|
||||
)
|
||||
|
||||
(defun vector-length-max! ((arg0 vector) (arg1 float))
|
||||
"Make vector at most arg1 length (xyz only).
|
||||
If it is larger, project onto sphere.
|
||||
Doesn't touch w"
|
||||
(let ((f0-0 (vector-length arg0)))
|
||||
(when (not (or (= f0-0 0.0) (< f0-0 arg1)))
|
||||
(set! f0-0 (/ f0-0 arg1))
|
||||
(when (!= f0-0 0.0)
|
||||
(set! (-> arg0 data 0) (/ (-> arg0 data 0) f0-0))
|
||||
(set! (-> arg0 data 1) (/ (-> arg0 data 1) f0-0))
|
||||
(let ((f0-1 (/ (-> arg0 data 2) f0-0)))
|
||||
(set! (-> arg0 data 2) f0-1)
|
||||
)
|
||||
(set! (-> arg0 data 2) (/ (-> arg0 data 2) f0-0))
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -854,6 +900,9 @@
|
||||
)
|
||||
|
||||
(defun vector-xz-length-max! ((arg0 vector) (arg1 float))
|
||||
"Make vector at most arg1 length (xz only).
|
||||
It it is larger, project onto circle.
|
||||
Doesn't touch w or y"
|
||||
(let ((f0-0 (vector-xz-length arg0)))
|
||||
(when (not (or (= f0-0 0.0) (< f0-0 arg1)))
|
||||
(set! f0-0 (/ f0-0 arg1))
|
||||
@ -869,6 +918,7 @@
|
||||
)
|
||||
|
||||
(defun vector-rotate-around-y! ((arg0 vector) (arg1 vector) (arg2 float))
|
||||
"Rotate a vector around the y axis"
|
||||
(let ((f26-0 (-> arg1 data 2))
|
||||
(f30-0 (-> arg1 data 0))
|
||||
(f28-0 (cos arg2))
|
||||
@ -882,13 +932,14 @@
|
||||
)
|
||||
|
||||
(defun rotate-y<-vector+vector ((arg0 vector) (arg1 vector))
|
||||
(atan
|
||||
(- (-> arg1 data 0) (-> arg0 data 0))
|
||||
"Get the y rotation between vectors. These should have the same length."
|
||||
(atan (- (-> arg1 data 0) (-> arg0 data 0))
|
||||
(- (-> arg1 data 2) (-> arg0 data 2))
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-cvt.w.s! ((arg0 vector) (arg1 vector))
|
||||
"Convert float to int32. Truncate."
|
||||
(rlet ((vf1 :class vf))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.ftoi.vf vf1 vf1)
|
||||
@ -898,6 +949,7 @@
|
||||
)
|
||||
|
||||
(defun vector-cvt.s.w! ((arg0 vector) (arg1 vector))
|
||||
"Convert float to int32."
|
||||
(rlet ((vf1 :class vf))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.itof.vf vf1 vf1)
|
||||
@ -907,6 +959,8 @@
|
||||
)
|
||||
|
||||
(defun rot-zxy-from-vector! ((arg0 vector) (arg1 vector))
|
||||
"I think this gives you a vector of euler angles to rotate some unit vector
|
||||
to arg1."
|
||||
(let* ((f28-0 (-> arg1 data 2))
|
||||
(f30-0 (-> arg1 data 0))
|
||||
(f0-0 (atan f30-0 f28-0))
|
||||
@ -924,6 +978,8 @@
|
||||
)
|
||||
|
||||
(defun rot-zyx-from-vector! ((arg0 vector) (arg1 vector))
|
||||
"I think this gives you a vector of euler angles to rotate some unit vector
|
||||
to arg1."
|
||||
(let* ((f28-0 (-> arg1 data 2))
|
||||
(f30-0 (- (-> arg1 data 1)))
|
||||
(f0-1 (atan f30-0 f28-0))
|
||||
@ -940,8 +996,9 @@
|
||||
arg0
|
||||
)
|
||||
|
||||
;; definition for function vector-lerp!
|
||||
(defun vector-lerp! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(defun vector-lerp! ((out vector) (a vector) (b vector) (alpha float))
|
||||
"Linearly interpolate between two vectors. Alpha isn't clampled.
|
||||
w will be set to 1."
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -949,23 +1006,21 @@
|
||||
(vf4 :class vf)
|
||||
)
|
||||
(.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.lvf vf2 (&-> arg2 quad))
|
||||
(.mov vf4 arg3)
|
||||
(.lvf vf1 (&-> a quad))
|
||||
(.lvf vf2 (&-> b quad))
|
||||
(.mov vf4 alpha)
|
||||
(.add.x.vf vf3 vf0 vf0 :mask #b1000)
|
||||
(.sub.vf vf2 vf2 vf1)
|
||||
(.mul.x.vf vf2 vf2 vf4)
|
||||
(.add.vf vf3 vf1 vf2 :mask #b111)
|
||||
(.svf (&-> arg0 quad) vf3)
|
||||
arg0
|
||||
(.svf (&-> out quad) vf3)
|
||||
out
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function vector-lerp-clamp!
|
||||
;; Used lq/sq
|
||||
(defun
|
||||
vector-lerp-clamp!
|
||||
((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(defun vector-lerp-clamp! ((out vector) (a vector) (b vector) (alpha float))
|
||||
"Linearly interpolate between two vectors, clamping alpha to 0, 1
|
||||
w will be set to 1."
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
@ -974,17 +1029,17 @@
|
||||
)
|
||||
(.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0))
|
||||
(cond
|
||||
((>= 0.0 arg3)
|
||||
(set! (-> arg0 quad) (-> arg1 quad))
|
||||
((>= 0.0 alpha)
|
||||
(set! (-> out quad) (-> a quad))
|
||||
)
|
||||
((>= arg3 1.0)
|
||||
(set! (-> arg0 quad) (-> arg2 quad))
|
||||
((>= alpha 1.0)
|
||||
(set! (-> out quad) (-> b quad))
|
||||
)
|
||||
(else
|
||||
(let ((v1-2 arg0))
|
||||
(let ((f0-2 arg3))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.lvf vf2 (&-> arg2 quad))
|
||||
(let ((v1-2 out))
|
||||
(let ((f0-2 alpha))
|
||||
(.lvf vf1 (&-> a quad))
|
||||
(.lvf vf2 (&-> b quad))
|
||||
(let ((a1-1 f0-2))
|
||||
(.mov vf4 a1-1)
|
||||
)
|
||||
@ -997,50 +1052,47 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
out
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function vector4-lerp!
|
||||
(defun vector4-lerp! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(defun vector4-lerp! ((out vector) (a vector) (b vector) (alpha float))
|
||||
"Interpolate all 4 elements of a vector. Alpha is not clamped"
|
||||
(rlet ((vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
(vf3 :class vf)
|
||||
(vf4 :class vf)
|
||||
)
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.lvf vf2 (&-> arg2 quad))
|
||||
(.mov vf4 arg3)
|
||||
(.lvf vf1 (&-> a quad))
|
||||
(.lvf vf2 (&-> b quad))
|
||||
(.mov vf4 alpha)
|
||||
(.sub.vf vf2 vf2 vf1)
|
||||
(.mul.x.vf vf2 vf2 vf4)
|
||||
(.add.vf vf3 vf1 vf2)
|
||||
(.svf (&-> arg0 quad) vf3)
|
||||
arg0
|
||||
(.svf (&-> out quad) vf3)
|
||||
out
|
||||
)
|
||||
)
|
||||
|
||||
;; definition for function vector4-lerp-clamp!
|
||||
;; Used lq/sq
|
||||
(defun
|
||||
vector4-lerp-clamp!
|
||||
((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(defun vector4-lerp-clamp! ((out vector) (a vector) (b vector) (alpha float))
|
||||
"Interpolate all 4 elements of a vector. Alpha is clamped to [0, 1]"
|
||||
(rlet ((vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
(vf3 :class vf)
|
||||
(vf4 :class vf)
|
||||
)
|
||||
(cond
|
||||
((>= 0.0 arg3)
|
||||
(set! (-> arg0 quad) (-> arg1 quad))
|
||||
((>= 0.0 alpha)
|
||||
(set! (-> out quad) (-> a quad))
|
||||
)
|
||||
((>= arg3 1.0)
|
||||
(set! (-> arg0 quad) (-> arg2 quad))
|
||||
((>= alpha 1.0)
|
||||
(set! (-> out quad) (-> b quad))
|
||||
)
|
||||
(else
|
||||
(let ((v1-2 arg0))
|
||||
(let ((f0-2 arg3))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.lvf vf2 (&-> arg2 quad))
|
||||
(let ((v1-2 out))
|
||||
(let ((f0-2 alpha))
|
||||
(.lvf vf1 (&-> a quad))
|
||||
(.lvf vf2 (&-> b quad))
|
||||
(let ((a1-1 f0-2))
|
||||
(.mov vf4 a1-1)
|
||||
)
|
||||
@ -1052,12 +1104,16 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
arg0
|
||||
out
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-degi ((arg0 vector) (arg1 vector))
|
||||
(local-vars (v1-0 float) (v1-1 uint128))
|
||||
"Convert a vector (in _rotations_) to degrees units, stored in an int.
|
||||
Truncates to the nearest _rotation_.
|
||||
Neither the input or output is a commonly used form.
|
||||
Unsurprisingly, this strange function is never used."
|
||||
(local-vars (v1-0 uint128) (v1-1 uint128))
|
||||
(rlet ((vf1 :class vf))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.ftoi.vf vf1 vf1)
|
||||
@ -1069,6 +1125,9 @@
|
||||
)
|
||||
|
||||
(defun vector-degf ((arg0 vector) (arg1 vector))
|
||||
"Convert a vector (in integer degree units) to floating point rotations.
|
||||
Truncates to the nearest _rotation_.
|
||||
Like the previous function, this is stupid and unused"
|
||||
(local-vars (v1-1 uint128))
|
||||
(rlet ((vf1 :class vf))
|
||||
(let ((v1-0 (-> arg1 quad)))
|
||||
@ -1082,7 +1141,9 @@
|
||||
)
|
||||
|
||||
(defun vector-degmod ((arg0 vector) (arg1 vector))
|
||||
(local-vars (v1-0 float) (v1-1 uint128) (v1-2 uint128))
|
||||
"This one is actually right. Wraps degrees units (in floats, like they should be)
|
||||
to +/- half a rotation."
|
||||
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
||||
(rlet ((vf1 :class vf))
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.ftoi.vf vf1 vf1)
|
||||
@ -1096,40 +1157,75 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; todo: vector-deg-diff
|
||||
|
||||
(defun vector-deg-lerp-clamp! ((arg0 vector) (arg1 vector) (arg2 vector) (arg3 float))
|
||||
(defun vector-deg-diff ((arg0 vector) (arg1 vector) (arg2 vector))
|
||||
"Wrapped difference, degrees units. Will have the usual 16-bit accuracy issue"
|
||||
(local-vars
|
||||
(v0-0 float)
|
||||
(v1-0 uint128)
|
||||
(v1-1 uint128)
|
||||
(v1-2 uint128)
|
||||
(v1-3 uint128)
|
||||
(a1-1 uint128)
|
||||
(a1-2 uint128)
|
||||
)
|
||||
(rlet ((vf1 :class vf)
|
||||
(vf2 :class vf)
|
||||
)
|
||||
(.lvf vf1 (&-> arg1 quad))
|
||||
(.lvf vf2 (&-> arg2 quad))
|
||||
(.ftoi.vf vf1 vf1)
|
||||
(.ftoi.vf vf2 vf2)
|
||||
(.mov a1-1 vf1)
|
||||
(.mov v1-0 vf2)
|
||||
(.pw.sll a1-2 a1-1 16)
|
||||
(.pw.sll v1-1 v1-0 16)
|
||||
(.psubw v1-2 a1-2 v1-1)
|
||||
(.pw.sra v1-3 v1-2 16)
|
||||
(.mov vf1 v1-3)
|
||||
(.itof.vf vf1 vf1)
|
||||
(.svf (&-> arg0 quad) vf1)
|
||||
(.mov v0-0 vf1)
|
||||
(none)
|
||||
)
|
||||
)
|
||||
|
||||
(defun vector-deg-lerp-clamp! ((out vector) (min-val vector) (max-val vector) (in float))
|
||||
"Apply deg-lerp-clamp to the xyz components of a vector. Sets w = 1."
|
||||
(cond
|
||||
((>= 0.0 arg3)
|
||||
(let ((v1-0 arg0))
|
||||
(set! (-> v1-0 quad) (-> arg1 quad))
|
||||
((>= 0.0 in)
|
||||
;; there is actually something weird here where it is not possible
|
||||
;; this was written like you would expect. Perhaps this is from a macro?
|
||||
(let ((v1-0 out))
|
||||
(set! (-> v1-0 quad) (-> min-val quad))
|
||||
)
|
||||
)
|
||||
((>= arg3 1.0)
|
||||
(let ((v1-1 arg0))
|
||||
(set! (-> v1-1 quad) (-> arg2 quad))
|
||||
((>= in 1.0)
|
||||
(let ((v1-1 out))
|
||||
(set! (-> v1-1 quad) (-> max-val quad))
|
||||
)
|
||||
)
|
||||
(else
|
||||
(set!
|
||||
(-> arg0 data 0)
|
||||
(deg-lerp-clamp (-> arg1 data 0) (-> arg2 data 0) arg3)
|
||||
(set! (-> out data 0)
|
||||
(deg-lerp-clamp (-> min-val data 0) (-> max-val data 0) in)
|
||||
)
|
||||
(set!
|
||||
(-> arg0 data 1)
|
||||
(deg-lerp-clamp (-> arg1 data 1) (-> arg2 data 1) arg3)
|
||||
(set! (-> out data 1)
|
||||
(deg-lerp-clamp (-> min-val data 1) (-> max-val data 1) in)
|
||||
)
|
||||
(set!
|
||||
(-> arg0 data 2)
|
||||
(deg-lerp-clamp (-> arg1 data 2) (-> arg2 data 2) arg3)
|
||||
(set! (-> out data 2)
|
||||
(deg-lerp-clamp (-> min-val data 2) (-> max-val data 2) in)
|
||||
)
|
||||
(let ((f0-11 1.0))
|
||||
(set! (-> arg0 data 3) f0-11)
|
||||
(set! (-> out data 3) 1.0)
|
||||
)
|
||||
)
|
||||
out
|
||||
)
|
||||
arg0
|
||||
)
|
||||
|
||||
|
||||
;; The weird docstrings for the next 4 functions were left behind in the game.
|
||||
;; We suspect they accidentally put something before the docstring, turning it
|
||||
;; into a string constant. GOAL doesn't eliminate dead code and
|
||||
;; loads into registers greedily, so it decompiles into a variable assignment.
|
||||
|
||||
(defun vector3s-copy! ((arg0 vector) (arg1 vector))
|
||||
(let ((v1-0 "Copy a vector3s"))
|
||||
@ -1167,7 +1263,8 @@
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun spheres-overlap? ((arg0 vector) (arg1 vector))
|
||||
(defun spheres-overlap? ((arg0 sphere) (arg1 sphere))
|
||||
"Do the spheres overlap?"
|
||||
(local-vars (v1-0 float) (a0-1 float))
|
||||
(rlet ((vf0 :class vf)
|
||||
(vf1 :class vf)
|
||||
@ -1192,6 +1289,7 @@
|
||||
)
|
||||
|
||||
(defun sphere<-vector! ((arg0 sphere) (arg1 vector))
|
||||
"Set the position of the sphere to arg1. Does not change the radius"
|
||||
(let ((f0-0 (-> arg0 data 3)))
|
||||
(set! (-> arg0 quad) (-> arg1 quad))
|
||||
(set! (-> arg0 data 3) f0-0)
|
||||
@ -1200,17 +1298,20 @@
|
||||
)
|
||||
|
||||
(defun sphere<-vector+r! ((arg0 sphere) (arg1 vector) (arg2 float))
|
||||
"Set the position of the sphere from arg1 and the radius from arg2"
|
||||
(set! (-> arg0 quad) (-> arg1 quad))
|
||||
(set! (-> arg0 data 3) arg2)
|
||||
arg0
|
||||
)
|
||||
|
||||
(defun rand-vu-sphere-point! ((arg0 vector) (arg1 sphere))
|
||||
(defun rand-vu-sphere-point! ((arg0 vector) (arg1 float))
|
||||
"Get a random point on the sphere at the origin with radius arg1.
|
||||
The point is on the surface of the sphere."
|
||||
(let ((s4-0 arg0))
|
||||
(set! (-> s4-0 data 0) (rand-vu-float-range -1.0 1.0))
|
||||
(set! (-> s4-0 data 1) (rand-vu-float-range -1.0 1.0))
|
||||
(set! (-> s4-0 data 2) (rand-vu-float-range -1.0 1.0))
|
||||
(set! (-> s4-0 data 3) 1.0)
|
||||
)
|
||||
(vector-normalize! arg0 (rand-vu-float-range 0.0 (the-as float arg1)))
|
||||
(vector-normalize! arg0 (rand-vu-float-range 0.0 arg1))
|
||||
)
|
||||
|
@ -53,3 +53,18 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro seconds (x)
|
||||
"Convert number to seconds unit."
|
||||
(cond
|
||||
((float? x)
|
||||
(* 300.0 x)
|
||||
)
|
||||
((integer? x)
|
||||
(* 300 x)
|
||||
)
|
||||
(#t
|
||||
`(* 300.0 ,x)
|
||||
)
|
||||
)
|
||||
)
|
@ -429,6 +429,7 @@ class Compiler {
|
||||
Val* compile_asm_pcpyld(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_asm_pceqw(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_asm_ppach(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_asm_psubw(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_asm_xorp(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
||||
// Atoms
|
||||
|
@ -1471,6 +1471,9 @@ std::string IR_Int128Math3Asm::print() {
|
||||
case Kind::PCEQW:
|
||||
function = ".pceqw";
|
||||
break;
|
||||
case Kind::PSUBW:
|
||||
function = ".psubw";
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
@ -1514,6 +1517,10 @@ void IR_Int128Math3Asm::do_codegen(emitter::ObjectGenerator* gen,
|
||||
case Kind::PCEQW:
|
||||
gen->add_instr(IGen::pceqw(dst, src1, src2), irec);
|
||||
break;
|
||||
case Kind::PSUBW:
|
||||
// psubW on mips is psubD on x86...
|
||||
gen->add_instr(IGen::vpsubd(dst, src1, src2), irec);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
@ -548,7 +548,8 @@ class IR_VFMath3Asm : public IR_Asm {
|
||||
|
||||
class IR_Int128Math3Asm : public IR_Asm {
|
||||
public:
|
||||
enum class Kind { PEXTLW, PEXTUW, PCPYUD, PCPYLD, PCEQW };
|
||||
// these are MIPS names, not x86 names.
|
||||
enum class Kind { PEXTLW, PEXTUW, PCPYUD, PCPYLD, PCEQW, PSUBW };
|
||||
IR_Int128Math3Asm(bool use_color,
|
||||
const RegVal* dst,
|
||||
const RegVal* src1,
|
||||
|
@ -627,6 +627,10 @@ Val* Compiler::compile_asm_pceqw(const goos::Object& form, const goos::Object& r
|
||||
return compile_asm_int128_math3(form, rest, IR_Int128Math3Asm::Kind::PCEQW, env);
|
||||
}
|
||||
|
||||
Val* Compiler::compile_asm_psubw(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
return compile_asm_int128_math3(form, rest, IR_Int128Math3Asm::Kind::PSUBW, env);
|
||||
}
|
||||
|
||||
Val* Compiler::compile_asm_ppach(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
va_check(form, args, {{}, {}, {}}, {});
|
||||
|
@ -102,6 +102,7 @@ const std::unordered_map<
|
||||
{".pcpyud", &Compiler::compile_asm_pcpyud},
|
||||
{".pceqw", &Compiler::compile_asm_pceqw},
|
||||
{".ppach", &Compiler::compile_asm_ppach},
|
||||
{".psubw", &Compiler::compile_asm_psubw},
|
||||
|
||||
// BLOCK FORMS
|
||||
{"top-level", &Compiler::compile_top_level},
|
||||
|
@ -2391,9 +2391,10 @@ class IGen {
|
||||
static Instruction ftoi_vf(Register dst, Register src) {
|
||||
assert(dst.is_xmm());
|
||||
assert(src.is_xmm());
|
||||
Instruction instr(0x5b); // VCVTDQ2PS
|
||||
// VEX.128.F3.0F.WIG 5B /r VCVTTPS2DQ xmm1, xmm2/m128
|
||||
Instruction instr(0x5b); // VCVTTPS2DQ
|
||||
instr.set_vex_modrm_and_rex(dst.hw_id(), src.hw_id(), VEX3::LeadingBytes::P_0F, 0, false,
|
||||
VexPrefix::P_66);
|
||||
VexPrefix::P_F3);
|
||||
return instr;
|
||||
}
|
||||
|
||||
@ -2494,6 +2495,18 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction vpsubd(Register dst, Register src0, Register src1) {
|
||||
assert(dst.is_xmm());
|
||||
assert(src0.is_xmm());
|
||||
assert(src1.is_xmm());
|
||||
// VEX.128.66.0F.WIG FA /r VPSUBD xmm1, xmm2, xmm3/m128
|
||||
// reg, vec, r/m
|
||||
Instruction instr(0xfa);
|
||||
instr.set_vex_modrm_and_rex(dst.hw_id(), src1.hw_id(), VEX3::LeadingBytes::P_0F, src0.hw_id(),
|
||||
false, VexPrefix::P_66);
|
||||
return instr;
|
||||
}
|
||||
|
||||
static Instruction vpsrldq(Register dst, Register src, u8 imm) {
|
||||
assert(dst.is_xmm());
|
||||
assert(src.is_xmm());
|
||||
|
@ -286,5 +286,9 @@
|
||||
;; display-h
|
||||
(declare-type display basic)
|
||||
(define-extern set-display (function display int int int int int display))
|
||||
|
||||
(define-extern *display* display)
|
||||
|
||||
|
||||
;; vector
|
||||
;; only because trig isn't in the reference yet.
|
||||
(define-extern deg-lerp-clamp (function float float float float))
|
||||
|
1278
test/decompiler/reference/vector_REF.gc
Normal file
1278
test/decompiler/reference/vector_REF.gc
Normal file
File diff suppressed because it is too large
Load Diff
@ -51,4 +51,24 @@
|
||||
(print128 s3q) (format #t "~%")
|
||||
)
|
||||
)
|
||||
|
||||
(let ((s1 (new 'stack 'array 'uint32 4))
|
||||
(s2 (new 'stack 'array 'uint32 4)))
|
||||
(set! (-> s1 0) #x300)
|
||||
(set! (-> s1 1) #x3)
|
||||
(set! (-> s1 2) #x100)
|
||||
(set! (-> s1 3) #x100000)
|
||||
(set! (-> s2 0) #x1)
|
||||
(set! (-> s2 1) #x5)
|
||||
(set! (-> s2 2) #x2)
|
||||
(set! (-> s2 3) #x70000)
|
||||
|
||||
(let ((s1q (-> (the (pointer uint128) s1)))
|
||||
(s2q (-> (the (pointer uint128) s2)))
|
||||
(s3q (the uint128 0)))
|
||||
(.psubw s3q s1q s2q)
|
||||
(print128 s3q) (format #t "~%")
|
||||
;; #x00090000000000fefffffffe000002ff
|
||||
)
|
||||
)
|
||||
)
|
138
test/goalc/source_templates/with_game/test-vector.gc
Normal file
138
test/goalc/source_templates/with_game/test-vector.gc
Normal file
@ -0,0 +1,138 @@
|
||||
(defmacro stack-vec-xyzw (x y z w)
|
||||
`(let ((vec (new 'stack 'vector)))
|
||||
(set! (-> vec x) ,x)
|
||||
(set! (-> vec y) ,y)
|
||||
(set! (-> vec z) ,z)
|
||||
(set! (-> vec w) ,w)
|
||||
vec
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro print-vec (x)
|
||||
`(begin
|
||||
(format #t "[~F] [~F] [~F] [~F]~%" (-> ,x x) (-> ,x y) (-> ,x z) (-> ,x w))
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro print-veci (x)
|
||||
`(begin
|
||||
(let ((veci (the (pointer int32) ,x)))
|
||||
(format #t "~d ~d ~d ~d~%" (-> veci 0) (-> veci 1) (-> veci 2) (-> veci 3))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro print-vec-deg-i (x)
|
||||
`(begin
|
||||
(let ((veci (the (pointer int32) ,x)))
|
||||
(format #t "~r ~r ~r ~r~%"
|
||||
(the float (-> veci 0))
|
||||
(the float (-> veci 1))
|
||||
(the float (-> veci 2))
|
||||
(the float (-> veci 3)))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro print-vec-deg-f (x)
|
||||
`(format #t "~r ~r ~r ~r~%"
|
||||
(-> ,x x)
|
||||
(-> ,x y)
|
||||
(-> ,x z)
|
||||
(-> ,x w)
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro set-veci! (vec x y z w)
|
||||
`(begin
|
||||
(let ((veci (the (pointer int32) ,vec)))
|
||||
(set! (-> veci 0) ,x)
|
||||
(set! (-> veci 1) ,y)
|
||||
(set! (-> veci 2) ,z)
|
||||
(set! (-> veci 3) ,w)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defmacro set-vecd! (vec x y z w)
|
||||
`(begin
|
||||
(set! (-> ,vec x) (degrees ,x))
|
||||
(set! (-> ,vec y) (degrees ,y))
|
||||
(set! (-> ,vec z) (degrees ,z))
|
||||
(set! (-> ,vec w) (degrees ,w))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
(let ((v1 (stack-vec-xyzw 1. 2. 3. 4.))
|
||||
(v2 (stack-vec-xyzw 5. 6. 7. 8.))
|
||||
(v4 (new 'stack 'vector))
|
||||
(v3 (new 'stack 'vector)))
|
||||
;; part 1
|
||||
;; w gets set to junk by vector-cross!
|
||||
(vector-cross! v3 v1 v2) (set! (-> v3 w) 0.0) (print-vec v3)
|
||||
(vector+float! v3 v1 2.0) (print-vec v3)
|
||||
(vector*! v3 v1 v2) (print-vec v3)
|
||||
(vector+*! v3 v1 v2 2.0) (print-vec v3)
|
||||
(vector-*! v3 v1 v2 2.0) (print-vec v3)
|
||||
(vector/! v3 v1 v2) (print-vec v3)
|
||||
(vector-float*! v3 v1 -2.0) (print-vec v3)
|
||||
(vector-average! v3 v1 v2) (print-vec v3)
|
||||
(vector+float*! v3 v1 v2 2.0) (print-vec v3)
|
||||
(vector--float*! v3 v1 v2 2.0) (print-vec v3)
|
||||
(vector-float/! v3 v1 -2.0) (print-vec v3)
|
||||
(vector-negate! v3 v1) (print-vec v3)
|
||||
|
||||
|
||||
;; part 2
|
||||
(format #t "part 2~%")
|
||||
(vector-negate-in-place! v1) (print-vec v1)
|
||||
(vector-negate-in-place! v1)
|
||||
|
||||
(format #t "~A ~A ~A ~A~%"
|
||||
(vector= v1 v2) ;; no
|
||||
(vector= v1 v1) ;; yes
|
||||
(vector= v1 (stack-vec-xyzw 1. 2. 3. 5.)) ;; yes
|
||||
(vector= v1 (stack-vec-xyzw 1. 2. 3.1 4.)) ;; no
|
||||
)
|
||||
|
||||
(format #t "~f~%" (vector-delta (stack-vec-xyzw 1.0 -2.0 3.0 -4.0)
|
||||
(stack-vec-xyzw 2.0 -3.0 1.0 -20.0)))
|
||||
|
||||
;; part 3
|
||||
(format #t "part 3~%")
|
||||
(vector-copy! v3 v1)
|
||||
(vector-seek! v3 v2 0.5)
|
||||
(print-vec v3)
|
||||
(vector-seek! v3 v2 100.0)
|
||||
(print-vec v3)
|
||||
|
||||
;; 2,3,6 -> 7 pythagorean quadruple (is that even a thing)
|
||||
(format #t "~f~%" (vector-length (stack-vec-xyzw 2.0 3.0 6.0 99.99)))
|
||||
(format #t "~f~%" (vector-length-squared (stack-vec-xyzw 2.0 3.0 6.0 99.99)))
|
||||
(format #t "~f~%" (vector-vector-distance
|
||||
(stack-vec-xyzw 4.0 5.0 7.0 1.0)
|
||||
(stack-vec-xyzw 6.0 2.0 1.0 99.99)))
|
||||
(print-vec (vector-normalize!
|
||||
(stack-vec-xyzw 1.0 1.5 3. 10.0)
|
||||
49.0))
|
||||
|
||||
(format #t "~f~%" (vector-normalize-ret-len!
|
||||
(stack-vec-xyzw 1.0 1.5 3. 10.0)
|
||||
49.0))
|
||||
|
||||
(vector-cvt.w.s! v3 (stack-vec-xyzw -1.9 2.9 -3.1 4.1))
|
||||
(print-veci v3)
|
||||
(vector-cvt.s.w! v3 v3)
|
||||
(print-vec v3)
|
||||
|
||||
(vector-degi v3 (stack-vec-xyzw (/ 10.0 360.0) (/ 721.0 360.0) (/ 370.0 360.0) (/ -187.0 360.0)))
|
||||
(print-vec-deg-i v3)
|
||||
|
||||
(set-vecd! v3 25 45 -25 (+ -360 -25))
|
||||
(set-vecd! v4 45 25 (+ 360 -45) -45)
|
||||
|
||||
(vector-deg-diff v3 v3 v4)
|
||||
(print-vec-deg-f v3)
|
||||
|
||||
)
|
@ -488,6 +488,39 @@ TEST_F(WithGameTests, Trig) {
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
TEST_F(WithGameTests, Vector) {
|
||||
runner.run_static_test(env, testCategory, "test-vector.gc",
|
||||
{"[ -4.0000] [ 8.0000] [ -4.0000] [ 0.0000]\n"
|
||||
"[ 3.0000] [ 4.0000] [ 5.0000] [ 1.0000]\n"
|
||||
"[ 5.0000] [ 12.0000] [ 21.0000] [ 1.0000]\n"
|
||||
"[ 11.0000] [ 14.0000] [ 17.0000] [ 1.0000]\n"
|
||||
"[ -9.0000] [ -10.0000] [ -11.0000] [ 1.0000]\n"
|
||||
"[ 0.2000] [ 0.3333] [ 0.4285] [ 1.0000]\n"
|
||||
"[ -2.0000] [ -4.0000] [ -6.0000] [ 1.0000]\n"
|
||||
"[ 3.0000] [ 4.0000] [ 5.0000] [ 1.0000]\n"
|
||||
"[ 11.0000] [ 14.0000] [ 17.0000] [ 1.0000]\n"
|
||||
"[ -9.0000] [ -10.0000] [ -11.0000] [ 1.0000]\n"
|
||||
"[ -0.5000] [ -1.0000] [ -1.5000] [ 1.0000]\n"
|
||||
"[ -1.0000] [ -2.0000] [ -3.0000] [ 1.0000]\n"
|
||||
"part 2\n"
|
||||
"[ -1.0000] [ -2.0000] [ -3.0000] [ 4.0000]\n"
|
||||
"#f #t #t #f\n"
|
||||
"4.0000\n"
|
||||
"part 3\n"
|
||||
"[ 1.5000] [ 2.5000] [ 3.5000] [ 1.0000]\n"
|
||||
"[ 5.0000] [ 6.0000] [ 7.0000] [ 1.0000]\n"
|
||||
"7.0000\n"
|
||||
"49.0000\n"
|
||||
"7.0000\n"
|
||||
"[ 14.0000] [ 21.0000] [ 42.0000] [ 10.0000]\n"
|
||||
"3.5000\n"
|
||||
"-1 2 -3 4\n"
|
||||
"[ -1.0000] [ 2.0000] [ -3.0000] [ 4.0000]\n"
|
||||
"0.0000 720.0000 360.0000 0.0000\n"
|
||||
"-20.0006 20.0006 20.0006 20.0006\n"
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
TEST_F(WithGameTests, InlinedPackedBasics) {
|
||||
runner.run_static_test(env, testCategory, "inlined-packed-basics.gc",
|
||||
{"rec stride: 48\n"
|
||||
@ -607,6 +640,7 @@ TEST_F(WithGameTests, Pextlw) {
|
||||
"#x1f1e1d1c1b1a19180f0e0d0c0b0a0908\n"
|
||||
"#x0d0c0908050401001d1c191815141110\n"
|
||||
"#xffffffff00000000ffffffff00000000\n"
|
||||
"#x00090000000000fefffffffe000002ff\n"
|
||||
"0\n"});
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ const std::unordered_set<std::string> g_object_files_to_decompile = {
|
||||
"trigonometry-h", /* transformq-h */ "matrix", "transform", "quaternion",
|
||||
"euler", /* geometry, trigonometry, */
|
||||
"gsound-h", "timer-h", "timer", "vif-h", "dma-h", "video-h", "vu1-user-h", "dma", "dma-buffer",
|
||||
"dma-bucket", "dma-disasm", "pad", "gs", "display-h",
|
||||
"dma-bucket", "dma-disasm", "pad", "gs", "display-h", "vector",
|
||||
/* gap */
|
||||
"bounding-box",
|
||||
/* gap */
|
||||
@ -32,7 +32,7 @@ const std::vector<std::string> g_object_files_to_check_against_reference = {
|
||||
/* transformq-h, */
|
||||
"matrix", "transform", "quaternion", "euler", /* geometry, trigonometry */
|
||||
"gsound-h", "timer-h", /* timer, */ "vif-h", "dma-h", "video-h", "vu1-user-h", "dma",
|
||||
"dma-buffer", "dma-bucket", "dma-disasm", "pad", "gs", "display-h",
|
||||
"dma-buffer", "dma-bucket", "dma-disasm", "pad", "gs", "display-h", "vector",
|
||||
/* gap */ "bounding-box",
|
||||
/* gap */
|
||||
"sync-info-h", "sync-info"};
|
||||
@ -71,6 +71,7 @@ const std::unordered_set<std::string> expected_skip_in_decompiler = {
|
||||
"dma-sync-with-count", "dma-send-no-scratch", "dma-sync-fast",
|
||||
// dma
|
||||
"symlink2", "symlink3", "dma-sync-hang", // handwritten asm
|
||||
"vector=", // asm branching
|
||||
// sync-info
|
||||
"(method 15 sync-info)", // needs *res-static-buf*
|
||||
"(method 15 sync-info-eased)", // needs *res-static-buf*
|
||||
@ -126,6 +127,10 @@ const std::unordered_set<std::string> skip_in_compiling = {
|
||||
// display-h
|
||||
"put-draw-env",
|
||||
|
||||
// vector
|
||||
// bad decisions on float vs int128
|
||||
"vector-degf", "vector-degmod", "vector-deg-diff", "vector-degi",
|
||||
|
||||
// sync-info
|
||||
"(method 15 sync-info)", // needs display stuff first
|
||||
"(method 15 sync-info-eased)", // needs display stuff first
|
||||
|
@ -340,7 +340,7 @@ TEST(EmitterAVX, FTOI) {
|
||||
tester.emit(IGen::ftoi_vf(XMM0 + 3, XMM0 + 14));
|
||||
tester.emit(IGen::ftoi_vf(XMM0 + 13, XMM0 + 4));
|
||||
tester.emit(IGen::ftoi_vf(XMM0 + 13, XMM0 + 14));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "C5F95BDCC4C1795BDEC5795BECC441795BEE");
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "C5FA5BDCC4C17A5BDEC57A5BECC4417A5BEE");
|
||||
}
|
||||
|
||||
TEST(EmitterAVX, VPSRAD) {
|
||||
@ -488,7 +488,7 @@ TEST(EmitterAVX, VPSHUFHW) {
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "C5FA70DC03C4C17A70DE04C57A70EC05C4417A70EE06");
|
||||
}
|
||||
|
||||
TEST(EmitrerAVX, movq_to_gpr_from_xmm) {
|
||||
TEST(EmitterAVX, movq_to_gpr_from_xmm) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(1024);
|
||||
tester.emit(IGen::movq_gpr64_xmm64(RSP, XMM0 + 3));
|
||||
@ -498,7 +498,7 @@ TEST(EmitrerAVX, movq_to_gpr_from_xmm) {
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "66480F7EDC664C0F7EEC66490F7EDC664D0F7EEC");
|
||||
}
|
||||
|
||||
TEST(EmitrerAVX, movq_to_xmm_from_gpr) {
|
||||
TEST(EmitterAVX, movq_to_xmm_from_gpr) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(1024);
|
||||
tester.emit(IGen::movq_xmm64_gpr64(XMM0 + 3, RSP));
|
||||
@ -507,3 +507,18 @@ TEST(EmitrerAVX, movq_to_xmm_from_gpr) {
|
||||
tester.emit(IGen::movq_xmm64_gpr64(XMM0 + 13, R12));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true), "66480F6EDC664C0F6EEC66490F6EDC664D0F6EEC");
|
||||
}
|
||||
|
||||
TEST(EmitterAVX, VPSUBD) {
|
||||
CodeTester tester;
|
||||
tester.init_code_buffer(1024);
|
||||
tester.emit(IGen::vpsubd(XMM0 + 3, XMM0 + 3, XMM0 + 3));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 3, XMM0 + 3, XMM0 + 13));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 3, XMM0 + 13, XMM0 + 3));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 3, XMM0 + 13, XMM0 + 13));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 13, XMM0 + 3, XMM0 + 3));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 13, XMM0 + 3, XMM0 + 13));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 13, XMM0 + 13, XMM0 + 3));
|
||||
tester.emit(IGen::vpsubd(XMM0 + 13, XMM0 + 13, XMM0 + 13));
|
||||
EXPECT_EQ(tester.dump_to_hex_string(true),
|
||||
"C5E1FADBC4C161FADDC591FADBC4C111FADDC561FAEBC44161FAEDC511FAEBC44111FAED");
|
||||
}
|
Loading…
Reference in New Issue
Block a user