[decomp] clean up and make level-update-after-load work (#628)

* temp

* make level-update-after-load work

* add missing const
This commit is contained in:
water111 2021-06-26 13:03:31 -04:00 committed by GitHub
parent 490633d434
commit 1ffd42e090
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 482 additions and 120 deletions

View File

@ -1294,9 +1294,8 @@ bool TypeSystem::typecheck_and_throw(const TypeSpec& expected,
*/
bool TypeSystem::typecheck_base_types(const std::string& expected,
const std::string& actual) const {
// just to make sure it exists. (note - could there be a case when it just has to be forward
// declared, but not defined?)
lookup_type(expected);
// just to make sure it exists.
lookup_type_allow_partial_def(expected);
if (expected == actual || expected == lookup_type_allow_partial_def(actual)->get_name()) {
lookup_type_allow_partial_def(actual); // make sure it exists

View File

@ -577,6 +577,19 @@ bool ControlFlowGraph::is_goto_not_end_and_unreachable(CfgVtx* b0, CfgVtx* b1) {
return true; // match!
}
bool ControlFlowGraph::is_infinite_continue(CfgVtx* b0) {
if (!b0) {
return false;
}
// end branch always.
if (!b0->end_branch.has_branch || !b0->end_branch.branch_always || b0->end_branch.branch_likely) {
return false;
}
return true;
}
bool ControlFlowGraph::is_goto_end_and_unreachable(CfgVtx* b0, CfgVtx* b1) {
if (!b0 || !b1) {
return false;
@ -848,6 +861,98 @@ bool ControlFlowGraph::find_goto_end() {
return replaced;
}
int get_prev_count(CfgVtx* start, CfgVtx* to_find) {
int result = 0;
while (start && start != to_find) {
result++;
start = start->prev;
}
if (start == to_find) {
return result;
}
return -1;
}
bool ControlFlowGraph::find_infinite_continue() {
bool replaced = false;
for_each_top_level_vtx([&](CfgVtx* vtx) {
auto* b0 = vtx;
if (is_infinite_continue(b0)) {
int my_block = b0->get_first_block_id();
int dest_block = b0->succ_branch->get_first_block_id();
fmt::print("Considering {} as an infinite continue:\n", b0->to_string());
if (dest_block >= my_block) {
fmt::print(" Rejecting because destination block {} comes after me {}\n", dest_block,
my_block);
return true;
} else {
fmt::print(" Order OK {} -> {}\n", my_block, dest_block);
}
int prev_count = get_prev_count(b0, b0->succ_branch);
if (prev_count == -1) {
fmt::print(
" Rejecting because we can't find the destination in the current ungrouped sequence.");
return true;
} else {
fmt::print(" Sequencing OK: {} prev's\n", prev_count);
}
replaced = true;
auto* new_goto = alloc<Break>();
m_has_break = true;
new_goto->body = b0;
new_goto->unreachable_block = nullptr;
new_goto->dest_block_id = b0->succ_branch->get_first_block_id();
m_blocks.at(new_goto->dest_block_id)->needs_label = true;
// patch up thing -> goto branches
for (auto* new_pred : b0->pred) {
new_pred->replace_succ_and_check(b0, new_goto);
}
new_goto->pred = b0->pred;
assert(b0->succs().size() == 1 && b0->succs().front() == b0->succ_branch);
// patch up next and prev.
new_goto->next = b0->next;
if (new_goto->next) {
assert(new_goto->next->prev == b0);
new_goto->next->prev = new_goto;
}
new_goto->prev = b0->prev;
if (new_goto->prev) {
assert(new_goto->prev->next == b0);
new_goto->prev->next = new_goto;
}
// now we want to make it look like the goto will fall through to next.
if (new_goto->next) {
// now we will fall through
new_goto->succ_ft = b0->next;
assert(!new_goto->succ_ft->has_pred(new_goto));
new_goto->succ_ft->pred.push_back(new_goto);
assert(!new_goto->succ_branch);
}
// break goto preds.
b0->succ_branch->replace_preds_with_and_check({b0}, nullptr);
b0->parent_claim(new_goto);
return false;
}
// keep looking
return true;
});
return replaced;
}
bool ControlFlowGraph::find_goto_not_end() {
bool replaced = false;
@ -2132,6 +2237,7 @@ std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file,
cfg->flag_early_exit(func.basic_blocks);
bool changed = true;
bool complained_about_weird_gotos = false;
while (changed) {
changed = false;
// note - we should prioritize finding short-circuiting expressions.
@ -2164,7 +2270,14 @@ std::shared_ptr<ControlFlowGraph> build_cfg(const LinkedObjectFile& file,
if (!changed) {
changed = changed || cfg->find_cond_w_empty_else();
if (changed) {
}
if (!changed) {
changed = changed || cfg->find_infinite_continue();
if (changed && !complained_about_weird_gotos) {
complained_about_weird_gotos = true;
func.warnings.general_warning(
"Found some very strange gotos. Check result carefully, this is not well tested.");
}
}
}

View File

@ -110,7 +110,7 @@ class CfgVtx {
/*!
* Lazy function for getting all non-null succesors
*/
std::vector<CfgVtx*> succs() {
std::vector<CfgVtx*> succs() const {
std::vector<CfgVtx*> result;
if (succ_branch) {
result.push_back(succ_branch);
@ -320,6 +320,7 @@ class ControlFlowGraph {
bool find_cond_w_else(const CondWithElseLengthHack& hacks);
bool find_cond_w_empty_else();
bool find_cond_n_else();
bool find_infinite_continue();
// bool find_if_else_top_level();
bool find_seq_top_level(bool allow_self_loops);
@ -372,6 +373,7 @@ class ControlFlowGraph {
bool is_until_loop(CfgVtx* b1, CfgVtx* b2);
bool is_goto_end_and_unreachable(CfgVtx* b0, CfgVtx* b1);
bool is_goto_not_end_and_unreachable(CfgVtx* b0, CfgVtx* b1);
bool is_infinite_continue(CfgVtx* b0);
std::vector<BlockVtx*> m_blocks; // all block nodes, in order.
std::vector<CfgVtx*> m_node_pool; // all nodes allocated
EntryVtx* m_entry; // the entry vertex

View File

@ -193,6 +193,12 @@ void clean_up_break(FormPool& pool, BreakElement* ir) {
}
void clean_up_break_final(const Function& f, BreakElement* ir) {
EmptyElement* dead_empty = dynamic_cast<EmptyElement*>(ir->dead_code->try_as_single_element());
if (dead_empty) {
ir->dead_code = nullptr;
return;
}
SetVarElement* dead = dynamic_cast<SetVarElement*>(ir->dead_code->try_as_single_element());
if (!dead) {
dead = dynamic_cast<SetVarElement*>(ir->dead_code->elts().front());
@ -1464,6 +1470,14 @@ void insert_cfg_into_list(FormPool& pool,
}
}
Form* cfg_to_ir_allow_null(FormPool& pool, Function& f, const CfgVtx* vtx) {
if (vtx) {
return cfg_to_ir(pool, f, vtx);
} else {
return pool.alloc_single_element_form<EmptyElement>(nullptr);
}
}
Form* cfg_to_ir_helper(FormPool& pool, Function& f, const CfgVtx* vtx) {
if (dynamic_cast<const BlockVtx*>(vtx)) {
auto* bv = dynamic_cast<const BlockVtx*>(vtx);
@ -1627,15 +1641,14 @@ Form* cfg_to_ir_helper(FormPool& pool, Function& f, const CfgVtx* vtx) {
} else if (dynamic_cast<const Break*>(vtx)) {
auto* cvtx = dynamic_cast<const Break*>(vtx);
auto result = pool.alloc_single_element_form<BreakElement>(
nullptr, cfg_to_ir(pool, f, cvtx->body), cfg_to_ir(pool, f, cvtx->unreachable_block),
cvtx->dest_block_id);
nullptr, cfg_to_ir(pool, f, cvtx->body),
cfg_to_ir_allow_null(pool, f, cvtx->unreachable_block), cvtx->dest_block_id);
clean_up_break(pool, dynamic_cast<BreakElement*>(result->try_as_single_element()));
return result;
} else if (dynamic_cast<const EmptyVtx*>(vtx)) {
return pool.alloc_single_element_form<EmptyElement>(nullptr);
}
throw std::runtime_error("not yet implemented IR conversion.");
return nullptr;
}

View File

@ -1526,7 +1526,7 @@
(deftype vertical-planes-array (basic)
((length uint32 :offset-assert 4)
(data vertical-planes :dynamic :offset 16) ;; todo, why is this here?
(data vertical-planes :inline :dynamic :offset-assert 16)
)
:method-count-assert 9
:size-assert #x10
@ -4055,10 +4055,11 @@
;; - Types
(declare-type art-group basic)
(deftype load-dir (basic)
((unknown basic)
(string-array (array string))
(data-array (array basic)))
(data-array (array art-group)))
:flag-assert #xb00000010
(:methods
(new (symbol type int basic) _type_ 0)
@ -4067,6 +4068,7 @@
)
)
(deftype load-dir-art-group (load-dir)
()
:flag-assert #xb00000010
@ -4434,11 +4436,12 @@
:flag-assert #x900000074
)
(declare-type drawable basic)
(deftype login-state (basic)
((state int32 :offset-assert 4)
(pos uint32 :offset-assert 8)
(elts uint32 :offset-assert 12)
(elt uint32 16 :offset-assert 16)
(elt drawable 16 :offset-assert 16) ;; might be something more specific.
)
:method-count-assert 9
:size-assert #x50
@ -8666,7 +8669,7 @@
)
(deftype proxy-prototype-array-tie (basic)
((prototype-array-tie basic :offset-assert 4)
((prototype-array-tie prototype-array-tie :offset-assert 4)
(wind-vectors uint32 :offset-assert 8) ; likely a pointer
)
:method-count-assert 9
@ -11270,8 +11273,8 @@
(boxes box8s-array :offset-assert 148)
(unk-data-3 uint32 :offset-assert 152)
(ambients drawable-inline-array-ambient :offset-assert 156)
(unk-data-4 uint32 :offset-assert 160)
(unk-data-5 uint32 :offset-assert 164)
(unk-data-4 float :offset-assert 160)
(unk-data-5 float :offset-assert 164)
(adgifs adgif-shader-array :offset-assert 168)
(unk-data-6 pointer :offset-assert 172)
(unk-data-7 pointer :offset-assert 176)
@ -11810,7 +11813,7 @@
)
(deftype drawable-tree-instance-tie (drawable-tree)
((prototypes basic :offset 8)
((prototypes proxy-prototype-array-tie :offset 8)
)
:method-count-assert 18
:size-assert #x24
@ -12610,7 +12613,8 @@
;; - Functions
(define-extern entity-nav-login function) ;; only called in `level` in an asm function...tough, returns nothing
;; may be actor.
(define-extern entity-nav-login (function basic none)) ;; only called in `level` in an asm function...tough, returns nothing
;; - Symbols
@ -14494,7 +14498,7 @@
;; - Unknowns
;;(define-extern *subdivide-settings* object) ;; unknown type
(define-extern *subdivide-settings* subdivide-settings) ;; unknown type
;;(define-extern *tfrag-work* object) ;; unknown type
;;(define-extern *perf-stats* object) ;; unknown type
;;(define-extern *merc-global-stats* object) ;; unknown type
@ -16899,7 +16903,7 @@
(define-extern update-sound-banks function)
(define-extern load-vis-info function)
(define-extern on (function symbol process))
(define-extern level-update-after-load function)
(define-extern level-update-after-load (function level login-state none))
(define-extern add-bsp-drawable function)
(define-extern remap-level-name (function level-load-info object))
(define-extern bg (function symbol symbol))

View File

@ -280,9 +280,6 @@
"render-boundary-quad",
"draw-boundary-polygon",
// level BUG
"level-update-after-load",
// text BUG
"load-game-text-info",

View File

@ -591,5 +591,9 @@
"main": [
["L230", "_lambda_", true]
],
"geometry": [
["L125", "float", true]
]
}

View File

@ -705,5 +705,11 @@
"bg": [
[37, "a0", "symbol"]
],
"level-update-after-load": [
[[29, 55], "s2", "drawable-tree-tfrag"],
[[121, 146], "s1", "drawable-inline-array-tfrag"],
[[150, 151], "s1", "drawable-tree-instance-tie"]
]
}

View File

@ -590,6 +590,22 @@
"args": ["dst", "src", "plane-normal"]
},
"vector-reflect!": {
"args": ["dst", "src", "plane-normal"]
},
"vector-reflect-flat!": {
"args": ["dst", "src", "plane-normal"]
},
"vector-reflect-true-flat!": {
"args": ["dst", "src", "plane-normal"]
},
"vector-reflect-flat-above!": {
"args": ["dst", "src", "plane-normal"]
},
"deg-seek": {
"args": ["in", "target", "max-diff"],
"vars": {
@ -1847,31 +1863,35 @@
},
"entity-actor-lookup": {
"args":["lump", "name", "idx"]
"args": ["lump", "name", "idx"]
},
"(method 0 actor-link-info)" : {
"args":["allocation", "type-to-make", "proc"],
"vars": {"s5-0":"obj", "a0-1":"ent"}
"(method 0 actor-link-info)": {
"args": ["allocation", "type-to-make", "proc"],
"vars": { "s5-0": "obj", "a0-1": "ent" }
},
"(method 25 actor-link-info)" : {
"vars": {"s5-0":"actor", "gp-0":"count"}
"(method 25 actor-link-info)": {
"vars": { "s5-0": "actor", "gp-0": "count" }
},
"(method 9 actor-link-info)" : {
"(method 9 actor-link-info)": {
"args": ["obj", "matching-type"],
"vars": {"s3-0":"actor", "s5-0":"mask", "s4-0":"current-bit"}
"vars": { "s3-0": "actor", "s5-0": "mask", "s4-0": "current-bit" }
},
"(method 10 actor-link-info)" : {
"vars" : {"s5-0":"this-actor", "s4-0":"actor", "gp-0":"count"}
"(method 10 actor-link-info)": {
"vars": { "s5-0": "this-actor", "s4-0": "actor", "gp-0": "count" }
},
"alt-actor-list-subtask-incomplete-count": {
"vars":{"s4-0":"alt-actor-count", "gp-0":"incomplete-count", "s3-0":"alt-actor-idx"}
"vars": {
"s4-0": "alt-actor-count",
"gp-0": "incomplete-count",
"s3-0": "alt-actor-idx"
}
},
"check-irx-version": {
"vars": { "gp-0": ["cmd", "sound-rpc-get-irx-version"] }
},
@ -1906,12 +1926,19 @@
"vars": { "gp-0": ["cmd", "sound-rpc-set-ear-trans"] }
},
"sound-play-by-name": {
"args": [ "name", "id", "vol", "pitch", "bend", "group", "trans" ],
"vars": { "s5-0": ["cmd", "sound-rpc-play"], "s3-1": ["proc", "process-drawable"], "s4-0": "sound-trans" }
"args": ["name", "id", "vol", "pitch", "bend", "group", "trans"],
"vars": {
"s5-0": ["cmd", "sound-rpc-play"],
"s3-1": ["proc", "process-drawable"],
"s4-0": "sound-trans"
}
},
"sound-play-by-spec": {
"args": [ "spec", "id", "trans" ],
"vars": { "s5-0": ["cmd", "sound-rpc-play"], "s3-1": ["proc", "process-drawable"] }
"args": ["spec", "id", "trans"],
"vars": {
"s5-0": ["cmd", "sound-rpc-play"],
"s3-1": ["proc", "process-drawable"]
}
},
"sound-pause": {
"vars": { "v1-0": ["cmd", "sound-rpc-pause-sound"] }
@ -1957,87 +1984,116 @@
},
"(method 0 path-control)": {
"args":["allocation", "type-to-make", "proc", "name", "time"],
"vars": {"gp-0":["obj", "path-control"], "s3-1":"ent", "v1-7":"lookup-entity", "sv-16":"tag", "v1-9":"data"}
"args": ["allocation", "type-to-make", "proc", "name", "time"],
"vars": {
"gp-0": ["obj", "path-control"],
"s3-1": "ent",
"v1-7": "lookup-entity",
"sv-16": "tag",
"v1-9": "data"
}
},
"(method 0 curve-control)": {
"args":["allocation", "type-to-make", "proc", "name", "time"],
"vars": {"gp-0":"obj", "s3-1":"ent", "v1-3":"lookup-entity"}
"args": ["allocation", "type-to-make", "proc", "name", "time"],
"vars": { "gp-0": "obj", "s3-1": "ent", "v1-3": "lookup-entity" }
},
"nav-mesh-connect": {
"args":["proc", "trans", "nav-cont"],
"vars": {"s2-0":"ent", "v0-0":"lookup-entity", "s3-0":"entity-nav-mesh"}
"args": ["proc", "trans", "nav-cont"],
"vars": {
"s2-0": "ent",
"v0-0": "lookup-entity",
"s3-0": "entity-nav-mesh"
}
},
"(method 0 nav-control)": {
"args":["allocation", "type-to-make", "shape", "sphere-count", "nearest-y-threshold-default"],
"vars": {"s5-0":["obj", "nav-control"], "a0-3":"ent"}
"args": [
"allocation",
"type-to-make",
"shape",
"sphere-count",
"nearest-y-threshold-default"
],
"vars": { "s5-0": ["obj", "nav-control"], "a0-3": "ent" }
},
"add-debug-point": {
"vars": {
"a0-6":["a0-6", "(pointer uint64)"],
"a0-7":["a0-7", "dma-packet"],
"a3-0":["a3-0", "dma-packet"],
"a3-2":["a3-2", "gs-gif-tag"],
"a3-4":["a3-4", "vector4w-2"],
"a3-6":["a3-6", "vector4w-2"],
"a3-8":["a3-8", "vector4w-2"],
"a1-30":["a1-30", "vector4w-2"]
"a0-6": ["a0-6", "(pointer uint64)"],
"a0-7": ["a0-7", "dma-packet"],
"a3-0": ["a3-0", "dma-packet"],
"a3-2": ["a3-2", "gs-gif-tag"],
"a3-4": ["a3-4", "vector4w-2"],
"a3-6": ["a3-6", "vector4w-2"],
"a3-8": ["a3-8", "vector4w-2"],
"a1-30": ["a1-30", "vector4w-2"]
}
},
"internal-draw-debug-line": {
"vars": {
"s2-0":["s2-0", "rgba"],
"s5-0":["s5-0", "rgba"],
"a3-1":["a3-1", "dma-packet"],
"a3-3":["a3-3", "gs-gif-tag"],
"a1-43":["a1-43", "(inline-array vector4w-2)"],
"a0-31":["a0-31", "(pointer uint64)"],
"a0-32":["a0-32", "dma-packet"]
"s2-0": ["s2-0", "rgba"],
"s5-0": ["s5-0", "rgba"],
"a3-1": ["a3-1", "dma-packet"],
"a3-3": ["a3-3", "gs-gif-tag"],
"a1-43": ["a1-43", "(inline-array vector4w-2)"],
"a0-31": ["a0-31", "(pointer uint64)"],
"a0-32": ["a0-32", "dma-packet"]
}
},
"add-debug-flat-triangle": {
"vars": {
"a3-1":["a3-1", "dma-packet"],
"a3-3":["a3-3", "gs-gif-tag"],
"a3-5":["a3-5", "(inline-array vector4w-3)"],
"a0-9":["a0-9", "(pointer uint64)"],
"a0-10":["a0-10", "dma-packet"]
"a3-1": ["a3-1", "dma-packet"],
"a3-3": ["a3-3", "gs-gif-tag"],
"a3-5": ["a3-5", "(inline-array vector4w-3)"],
"a0-9": ["a0-9", "(pointer uint64)"],
"a0-10": ["a0-10", "dma-packet"]
}
},
"add-debug-line2d": {
"vars": {
"a2-3":["a2-3", "dma-packet"],
"a2-5":["a2-5", "gs-gif-tag"],
"a2-7":["a2-7", "(inline-array vector4w)"],
"a2-9":["a2-9", "(inline-array vector4w)"],
"a0-20":["a0-20", "(pointer uint64)"],
"v1-10":["v1-10", "dma-packet"]
"a2-3": ["a2-3", "dma-packet"],
"a2-5": ["a2-5", "gs-gif-tag"],
"a2-7": ["a2-7", "(inline-array vector4w)"],
"a2-9": ["a2-9", "(inline-array vector4w)"],
"a0-20": ["a0-20", "(pointer uint64)"],
"v1-10": ["v1-10", "dma-packet"]
}
},
"debug-percent-bar": {
"vars": {
"v1-5":["v1-5", "dma-packet"]
"v1-5": ["v1-5", "dma-packet"]
}
},
"debug-pad-display": {
"vars": {
"v1-12":["v1-12", "dma-packet"]
"v1-12": ["v1-12", "dma-packet"]
}
},
"internal-draw-debug-text-3d": {
"vars": {
"v1-11":["v1-11", "dma-packet"]
"v1-11": ["v1-11", "dma-packet"]
}
},
"add-debug-light": { "vars": { "s1-0":["s1-0", "rgba"]} },
"add-debug-light": { "vars": { "s1-0": ["s1-0", "rgba"] } },
"generic-init-buffers": {
"vars": {
"v1-8": ["packet", "dma-packet"]
}
},
"level-update-after-load": {
"args": ["loaded-level", "level-login-state"],
"vars": {
"s3-0":"level-drawable-trees",
"s5-0":"initial-timer",
"v1-4":"current-timer",
"v1-5":"elapsed-timer",
"s2-0":"current-login-pos",
"s2-1":"current-drawable",
"s1-0":"idx-in-drawable"
}
}
}

View File

@ -167,4 +167,5 @@
- The `deftype` form is more strict and will throw an error if the type definition is in any way incompatible with existing forward declarations of types.
- Added a `type-ref` form to insert a reference to a type into a static structure and optionally forward declare the number of methods
- The `method-of-type` form will now accept an expression returning a type instead of just a type name. In this case, it will only allow you to access method of `object`.
- Added a `defun-recursive` to make it easier to define recursive functions
- Added a `defun-recursive` to make it easier to define recursive functions
- Forward declared basics can be used in more places

View File

@ -191,9 +191,9 @@
;; NOTE - this is a strange pattern...this symbol isn't defined until a later file 'navigate'
;; But this seems to be setting the symbol to nothing if it's not found, but of course, our compiler freaks out
(define-extern entity-nav-login function)
(define-extern entity-nav-login (function basic none))
(if (zero? entity-nav-login)
(set! entity-nav-login nothing)
(set! entity-nav-login (the-as (function basic none) nothing))
)
;; definition of type actor-bank

View File

@ -5,6 +5,129 @@
;; name in dgo: geometry
;; dgos: GAME, ENGINE
(defun vector-flatten! ((dst vector) (src vector) (plane-normal vector))
"Get the projection of src onto a plane with the given normal
The normal should have magnitude 1.0."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf) ;; src
(vf2 :class vf) ;; normal
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> src quad))
(.lvf vf2 (&-> plane-normal quad))
(.mov.vf vf3 vf0 :mask #b1000)
(.outer.product.vf vf3 vf1 vf2) ;; has the right magnitude, but rotation is off by 90 degrees
(.outer.product.vf vf3 vf2 vf3) ;; rotate by 90 about normal of plane
(.svf (&-> dst quad) vf3)
dst
)
)
(defun vector-reflect! ((dst vector) (src vector) (plane-normal vector))
"Reflect a vector off of a plane."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
;; we want to split the vector into normal / tangent components.
;; let src = T + N, where T dot plane-normal = 0.
;; then the reflection is T - N = 2 * T - src.
;; we can compute T from vector-flatten!'s trick
(init-vf0-vector)
(.lvf vf1 (&-> src quad))
(.lvf vf2 (&-> plane-normal quad))
(.mov.vf vf3 vf0 :mask #b1000)
(.outer.product.vf vf3 vf1 vf2)
(.outer.product.vf vf3 vf2 vf3) ;; vf3 is the projection on the plane
(.add.vf acc vf3 vf3 :mask #b111) ;; double that part
(.sub.mul.w.vf vf3 vf1 vf0 acc :mask #b111) ;; and subtract the original
(.svf (&-> dst quad) vf3)
dst
)
)
(defun vector-reflect-flat! ((dst vector) (src vector) (plane-normal vector))
"This is a weird one. It doesn't care about the value of src dot normal
and it effectively replaces the component of src normal to the plane with
the plane's normal. I think this requires src/normal to both be unit vectors
in order to make sense.
NOTE: src should point from positive halfspace to negative otherwise it
doesn't work."
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> src quad))
(.lvf vf2 (&-> plane-normal quad))
(.mov.vf vf3 vf0 :mask #b1000)
(.outer.product.vf vf3 vf1 vf2)
(.outer.product.vf vf3 vf2 vf3) ;; part on the plane (requires normal to be unit)
(.add.vf vf3 vf3 vf2 :mask #b111) ;; add normal to that.
(.svf (&-> dst quad) vf3)
dst
)
)
(defun vector-reflect-true-flat! ((dst vector) (src vector) (plane-normal vector))
"Not really a reflect. Same as flatten"
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> src quad))
(.lvf vf2 (&-> plane-normal quad))
(.mov.vf vf3 vf0 :mask #b1000)
(.outer.product.vf vf3 vf1 vf2)
(.outer.product.vf vf3 vf2 vf3)
(.svf (&-> dst quad) vf3)
dst
)
)
(defun vector-reflect-flat-above! ((dst vector) (src vector) (plane-normal vector))
"A hacked up version of reflect, probably to make their collision system work.
It is a less aggressive version of reflect that also has a limit to the output
normal component"
(rlet ((acc :class vf)
(vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
)
(init-vf0-vector)
(.lvf vf1 (&-> src quad))
(.lvf vf2 (&-> plane-normal quad))
(.mov.vf vf3 vf0 :mask #b1000)
(.outer.product.vf vf3 vf1 vf2)
(.outer.product.vf vf3 vf2 vf3)
(.svf (&-> dst quad) vf3)
;; dst is now the normal part of src
(let ((f0-0 (vector-length dst)) ;; length of normal
(f1-1 (vector-dot dst plane-normal))) ;; ?? this is always zero.
(let* ((f1-2 f1-1)
;; f1-3 = .02 * length of normal. f1-2 is always zero here
(f1-3 (- (* 0.02 f0-0) f1-2))
)
;; scale down and limit the normal component
(vector+float*! dst dst plane-normal (fmin 16384.0 (* 16.0 f1-3)))
)
)
)
)
;; TODO vector-segment-distance-point!
;; TODO - temporary for lights.gc
(define-extern vector-deg-slerp (function vector vector vector float vector))
;; TODO - temporary for transformq.gc
@ -14,4 +137,4 @@
;; TODO
(define-extern vector-3pt-cross! (function vector vector vector vector vector))
(define-extern curve-evaluate! (function vector float int int vector int int))
(define-extern curve-evaluate! (function vector float int int vector int int))

View File

@ -105,7 +105,7 @@
)
(deftype proxy-prototype-array-tie (basic)
((prototype-array-tie basic :offset-assert 4)
((prototype-array-tie prototype-array-tie :offset-assert 4)
(wind-vectors uint32 :offset-assert 8)
)
:method-count-assert 9

View File

@ -48,7 +48,7 @@
)
(deftype drawable-tree-instance-tie (drawable-tree)
((prototypes basic :offset 8)
((prototypes proxy-prototype-array-tie :offset 8)
)
:method-count-assert 18
:size-assert #x24

View File

@ -42,8 +42,8 @@
(boxes box8s-array :offset-assert 148)
(unk-data-3 uint32 :offset-assert 152)
(ambients drawable-inline-array-ambient :offset-assert 156)
(unk-data-4 uint32 :offset-assert 160)
(unk-data-5 uint32 :offset-assert 164)
(unk-data-4 float :offset-assert 160)
(unk-data-5 float :offset-assert 164)
(adgifs adgif-shader-array :offset-assert 168)
(unk-data-6 pointer :offset-assert 172)
(unk-data-7 pointer :offset-assert 176)

View File

@ -72,11 +72,12 @@
:flag-assert #x900000074
)
(declare-type drawable basic)
(deftype login-state (basic)
((state int32 :offset-assert 4)
(pos uint32 :offset-assert 8)
(elts uint32 :offset-assert 12)
(elt uint32 16 :offset-assert 16)
(elt drawable 16 :offset-assert 16) ;; might be more specific
)
:method-count-assert 9
:size-assert #x50

View File

@ -5,13 +5,12 @@
;; name in dgo: loader-h
;; dgos: GAME, ENGINE
(define-extern art-group type)
;; This type didn't have an inspect method, so these field names are made up.
(declare-type art-group basic)
(deftype load-dir (basic)
((unknown basic)
(string-array (array string)) ;; these are the names
(data-array (array basic)) ;; this is the file data.
(data-array (array art-group)) ;; this is the file data.
)
:flag-assert #xb00000010
(:methods
@ -44,7 +43,7 @@
(set! (-> obj string-array length) 0)
;; create the data array
(set! (-> obj data-array)
(the-as (array basic)
(the-as (array art-group)
((method-of-type array new) allocation array basic length)
))
(set! (-> obj data-array length) 0)

View File

@ -11,11 +11,13 @@
;;;; float macros
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; at some point, this could be more optimized.
;; MIPS has an explicit abs.s instruction, but x86-64 doesn't.
;; modern clang on O3 does a comiss/branch and this is probably pretty close.
(defmacro fabs (x)
"Floating point absolute value"
;; in GOAL this was implemented by the compiler.
;; at some point, this could be more optimized.
;; MIPS has an explicit abs.s instruction, but x86-64 doesn't.
;; modern clang on O3 does a comiss/branch and this is probably pretty close.
`(if (< (the float ,x) 0)
(- (the float ,x))
(the float ,x))
@ -159,10 +161,12 @@
;;;; random vu hardware
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; added in OpenGOAL
;; in the PS2 there is a R register for generating random numbers
;; it is a "32-bit" register, but the upper bits are fixed so it always
;; represents a float in (1, 2).
;; we don't have this register on x86, so we add a special global: *_vu-reg-R_*
(define *_vu-reg-R_* 0)
;; TODO
(defun rand-vu-init ((seed float))
"Initialize the VU0 random generator"
;; (.ctc2.i R arg0)
@ -173,6 +177,7 @@
(the-as float *_vu-reg-R_*)
)
;; this is _almost_ sqrt(2) = 1.414
(rand-vu-init 1.418091058731079)
;; rand-vu

View File

@ -44,6 +44,7 @@
)
(defun matrix-copy! ((dst matrix) (src matrix))
"Copy src to dst"
(let ((v1-0 (-> src vector 0 quad))
(a2-0 (-> src vector 1 quad))
(a3-0 (-> src vector 2 quad))

View File

@ -5,11 +5,11 @@
;; name in dgo: transform-h
;; dgos: GAME, ENGINE
;; Transformation. w components of vectors should be 1.0
(deftype transform (structure)
((trans vector :inline :offset-assert 0)
(rot vector :inline :offset-assert 16)
(scale vector :inline :offset-assert 32)
((trans vector :inline :offset-assert 0) ;; translation
(rot vector :inline :offset-assert 16) ;; rotation (rotation vector)
(scale vector :inline :offset-assert 32) ;; scale (xyz components)
)
:method-count-assert 9
:size-assert #x30
@ -17,6 +17,7 @@
)
;; Like transform, but it's a basic.
(deftype trs (basic)
((trans vector :inline :offset-assert 16)
(rot vector :inline :offset-assert 32)

View File

@ -9,6 +9,8 @@
;; bit array
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the bit-array is a dynamically sized array that is bit addressable
(deftype bit-array (basic)
((length int32 :offset-assert 4)
(allocated-length int32 :offset-assert 8)
@ -103,6 +105,8 @@
;; vector types (integer)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; the GOAL vector types are structures, storing values in memory.
;; Vector of 4 unsigned bytes.
(deftype vector4ub (structure)
((data uint8 4 :offset-assert 0)
@ -363,6 +367,7 @@
:flag-assert #x900000010
)
;; ax + by + cz = d form
(deftype plane (vector)
((a float :offset 0)
(b float :offset 4)
@ -374,15 +379,15 @@
:flag-assert #x900000010
)
;; x, y, z are the origin, replaces w with r, the radius
(deftype sphere (vector)
((r float :offset 12)
((r float :offset 12 :score 10) ;; prefer over w
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype isphere (vec4s)
()
:method-count-assert 9
@ -452,7 +457,7 @@
(deftype vertical-planes-array (basic)
((length uint32 :offset-assert 4)
(data vertical-planes :dynamic :offset 16) ;; todo, why is this here?
(data vertical-planes :inline :dynamic :offset-assert 16) ;; likely inline based on alignment
)
:method-count-assert 9
:size-assert #x10
@ -485,7 +490,14 @@
:flag-assert #x90000000c
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Macros and inline functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro set-vector! (v xv yv zv wv)
"Set all fields in a vector"
(with-gensyms (vec)
`(let ((vec ,v))
(set! (-> vec x) ,xv)
@ -545,6 +557,7 @@
)
(defmacro print-vf (vf &key (name #f))
"Print out a vf register as a vector."
`(let ((temp (new 'stack 'vector)))
(.svf temp ,vf)
,(if name
@ -555,6 +568,7 @@
)
(defmacro print-vf-hex (vf)
"Print out a vf register as 4x 32-bit hexadecimal integers"
`(let ((temp (new 'stack 'vector4w)))
(.svf temp ,vf)
(format #t "~`vector4w`P~%" temp)

View File

@ -5,7 +5,10 @@
;; name in dgo: vu1-macros
;; dgos: GAME, ENGINE
;; this file has no code!
;; this file has no code, just macros for vector-unit stuff.
;; in OpenGOAL we're also using this for VU0 macros to help with VU0 operations that are not
;; directly implemented by the OpenGOAL compiler
(defmacro vu-clip (vfr cf)
"Returns the result of VCLIP.

View File

@ -18,12 +18,24 @@
:flag-assert #x900000004
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Common Units
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; in-game durations, distances, and rotations are stored in special formats.
;; these macros/constants convert from literals to the correct format.
;; for example, (meters 4.0) will give you a distance representing 4 in-game meters.
;; meters are stored as (usually) a float, scaled by 4096.
;; this gives you reasonable accuracy as an integer.
(defglobalconstant METER_LENGTH 4096.0)
(defmacro meters (x)
"Convert number to meters.
If the input is a constant float or integer, the result will be a
compile time constant float. Otherwise, it will not be constant."
;; we don't have enough constant propagation for the compiler to figure this out.
(cond
((float? x)
(* METER_LENGTH x)
@ -37,6 +49,10 @@
)
)
;; rotations are stored in 65,536ths of a full rotation.
;; like with meters, you get a reasonable accuracy as an integer.
;; additionally, it is a power-of-two, so wrapping rotations can be done
;; quickly by converting to an int, masking, and back to float
(defglobalconstant DEGREES_PER_ROT 65536.0)
(defmacro degrees (x)
@ -54,6 +70,10 @@
)
)
;; times are stored in 300ths of a second.
;; this divides evenly into frames at both 50 and 60 fps.
;; typically these are stored as integers as more precision is not useful.
;; an unsigned 32-bit integer can store about 150 days
(defglobalconstant TICKS_PER_SECOND 300) ;; 5 t/frame @ 60fps, 6 t/frame @ 50fps
(defmacro seconds (x)
@ -75,4 +95,4 @@
(defmacro vel-tick (vel)
"turn a velocity value into a per-tick value"
`(* (/ 1.0 ,TICKS_PER_SECOND) ,vel)
)
)

View File

@ -276,7 +276,7 @@
;; failed to figure out what this is:
(if (zero? entity-nav-login)
(set! entity-nav-login nothing)
(set! entity-nav-login (the-as (function basic none) nothing))
)
;; definition of type actor-bank

View File

@ -226,8 +226,8 @@
;; definition of type proxy-prototype-array-tie
(deftype proxy-prototype-array-tie (basic)
((prototype-array-tie basic :offset-assert 4)
(wind-vectors uint32 :offset-assert 8)
((prototype-array-tie prototype-array-tie :offset-assert 4)
(wind-vectors uint32 :offset-assert 8)
)
:method-count-assert 9
:size-assert #xc

View File

@ -86,7 +86,7 @@
;; definition of type drawable-tree-instance-tie
(deftype drawable-tree-instance-tie (drawable-tree)
((prototypes basic :offset 8)
((prototypes proxy-prototype-array-tie :offset 8)
)
:method-count-assert 18
:size-assert #x24

View File

@ -49,8 +49,8 @@
(boxes box8s-array :offset-assert 148)
(unk-data-3 uint32 :offset-assert 152)
(ambients drawable-inline-array-ambient :offset-assert 156)
(unk-data-4 uint32 :offset-assert 160)
(unk-data-5 uint32 :offset-assert 164)
(unk-data-4 float :offset-assert 160)
(unk-data-5 float :offset-assert 164)
(adgifs adgif-shader-array :offset-assert 168)
(unk-data-6 pointer :offset-assert 172)
(unk-data-7 pointer :offset-assert 176)

View File

@ -117,10 +117,10 @@
;; definition of type login-state
(deftype login-state (basic)
((state int32 :offset-assert 4)
(pos uint32 :offset-assert 8)
(elts uint32 :offset-assert 12)
(elt uint32 16 :offset-assert 16)
((state int32 :offset-assert 4)
(pos uint32 :offset-assert 8)
(elts uint32 :offset-assert 12)
(elt drawable 16 :offset-assert 16)
)
:method-count-assert 9
:size-assert #x50

View File

@ -3,9 +3,9 @@
;; definition of type load-dir
(deftype load-dir (basic)
((unknown basic :offset-assert 4)
(string-array (array string) :offset-assert 8)
(data-array (array basic) :offset-assert 12)
((unknown basic :offset-assert 4)
(string-array (array string) :offset-assert 8)
(data-array (array art-group) :offset-assert 12)
)
:method-count-assert 11
:size-assert #x10
@ -50,7 +50,7 @@
(set!
(-> obj data-array)
(the-as
(array basic)
(array art-group)
((method-of-type array new) allocation array basic length)
)
)

View File

@ -749,8 +749,8 @@
;; definition of type vertical-planes-array
(deftype vertical-planes-array (basic)
((length uint32 :offset-assert 4)
(data vertical-planes :dynamic :offset 16)
((length uint32 :offset-assert 4)
(data vertical-planes :inline :dynamic :offset-assert 16)
)
:method-count-assert 9
:size-assert #x10