From 784119188cdade17d58c667c5d577f3c99d4742b Mon Sep 17 00:00:00 2001 From: ManDude <7569514+ManDude@users.noreply.github.com> Date: Tue, 1 Jun 2021 21:07:45 +0100 Subject: [PATCH] [decomp] even more `res` (#529) * [decomp] even more `res` * [decompiler] make `logand` with pointers and constants return pointer * [decomp] more work * update offline tests * fix tests(?) * `*res-static-buf*` * fixes * fix reference * [opengoal] make `logand` work directly with pointers * [decomp] `inspect res-lump` * use the inline methods * don't use a math mode for pointers * [compiler] allow optionally setting disassembly output file * [x86 disasm] Keep casing consistent between instructions and offsets --- decompiler/IR2/AtomicOpTypeAnalysis.cpp | 8 + decompiler/IR2/FormExpressionAnalysis.cpp | 8 +- decompiler/config/all-types.gc | 20 +- decompiler/config/jak1_ntsc_black_label.jsonc | 2 +- .../config/jak1_ntsc_black_label/hacks.jsonc | 4 +- .../jak1_ntsc_black_label/label_types.jsonc | 3 +- .../jak1_ntsc_black_label/stack_vars.jsonc | 3 + .../jak1_ntsc_black_label/type_casts.jsonc | 4 + .../jak1_ntsc_black_label/var_names.jsonc | 49 +++- goal_src/engine/data/res-h.gc | 17 +- goal_src/engine/data/res.gc | 222 +++++++++++++++++- goal_src/engine/game/fact-h.gc | 2 + goal_src/goal-lib.gc | 20 +- .../compiler/compilation/CompilerControl.cpp | 19 +- goalc/compiler/compilation/Math.cpp | 13 +- goalc/debugger/disassemble.cpp | 4 +- .../reference/engine/load/load-dgo_REF.gc | 104 +++----- .../reference/engine/ps2/rpc-h_REF.gc | 5 +- .../reference/kernel/gkernel_REF.gc | 22 +- test/decompiler/test_gkernel_decomp.cpp | 19 +- 20 files changed, 390 insertions(+), 158 deletions(-) diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index fd5b2c6d6..c57ccecbf 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -503,6 +503,14 @@ TP_Type SimpleExpression::get_type_int2(const TypeState& input, } if (m_kind == Kind::AND) { + if (arg0_type.typespec().base_type() == "pointer" && tc(dts, TypeSpec("integer"), arg1_type)) { + // pointer logand integer = pointer + return TP_Type::make_from_ts(arg0_type.typespec()); + } else if (arg1_type.typespec().base_type() == "pointer" && + tc(dts, TypeSpec("integer"), arg0_type)) { + // integer logand pointer = pointer + return TP_Type::make_from_ts(arg1_type.typespec()); + } // base case for and. Just get an integer. return TP_Type::make_from_ts(TypeSpec("int")); } diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 1701239fa..805e0c554 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -1012,10 +1012,13 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env, update_from_stack_copy_first_int_2(env, kind, pool, stack, result, allow_side_effects); } else { // and, two forms + auto arg1_type = env.get_variable_type(m_expr.get_arg(1).var(), true); auto arg0_i = is_int_type(env, m_my_idx, m_expr.get_arg(0).var()); auto arg0_u = is_uint_type(env, m_my_idx, m_expr.get_arg(0).var()); auto arg1_i = is_int_type(env, m_my_idx, m_expr.get_arg(1).var()); auto arg1_u = is_uint_type(env, m_my_idx, m_expr.get_arg(1).var()); + auto arg0_n = arg0_i || arg0_u; + auto arg1_n = arg1_i || arg1_u; auto args = pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var()}, env, pool, stack, allow_side_effects); @@ -1065,8 +1068,11 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env, } } - if ((arg0_i && arg1_i) || (arg0_u && arg1_u)) { + if ((arg0_i && arg1_i) || (arg0_u && arg1_u) || + (arg0_n && arg1_type.base_type() == "pointer") || + (arg1_n && arg0_type.base_type() == "pointer")) { // types already good + // we also allow (logand intvar pointer) and (logand pointer intvar) auto new_form = pool.alloc_element(GenericOperator::make_fixed(kind), args.at(0), args.at(1)); result->push_back(new_form); diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 0d088fd15..5f2abc921 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -8564,18 +8564,18 @@ (:methods (new (symbol type int int) _type_ 0) (get-property-data (_type_ symbol symbol float pointer (pointer res-tag) pointer) pointer 9) - (dummy-10 (_type_ symbol symbol int symbol symbol pointer) int 10) - (dummy-11 (_type_ symbol symbol int int symbol pointer) int 11) - (dummy-12 (_type_ symbol symbol float float symbol pointer) float 12) + (get-property-struct (_type_ symbol symbol float structure (pointer res-tag) pointer) structure 10) + (get-property-value (_type_ symbol symbol float uint128 (pointer res-tag) pointer) uint128 11) + (get-property-value2 (_type_ symbol symbol float uint128 (pointer res-tag) pointer) uint128 12) (get-tag-index-data (_type_ int) pointer 13) (get-tag-data (_type_ res-tag) pointer 14) - (dummy-15 (_type_) none 15) - (dummy-16 (_type_ int int int int) none 16) - (dummy-17 (_type_ int int) res-lump 17) - (dummy-18 (_type_ int int) none 18) + (dummy-15 (_type_ res-tag) res-tag 15) + (sort! (_type_) _type_ 16) + (dummy-17 (_type_ res-tag pointer) res-lump 17) + (dummy-18 (_type_ res-tag res-tag) res-lump 18) (lookup-tag-idx (_type_ symbol symbol float) res-tag-pair 19) (make-property-data (_type_ float res-tag-pair pointer) pointer 20) - (dummy-21 (_type_ int int int int int) none 21) + (dummy-21 (_type_ pointer symbol symbol float) symbol 21) ) ) @@ -33646,8 +33646,8 @@ (define-extern part-group-pointer? function) (define-extern nav-mesh type) (define-extern collide-mesh type) -;;(define-extern sinteger object) ;; unknown type -;;(define-extern uinteger object) ;; unknown type +(define-extern sinteger type) +(define-extern uinteger type) ;;(define-extern id object) ;; unknown type ;;(define-extern aid object) ;; unknown type ;;(define-extern interp object) ;; unknown type diff --git a/decompiler/config/jak1_ntsc_black_label.jsonc b/decompiler/config/jak1_ntsc_black_label.jsonc index 057e97e5a..604c0122e 100644 --- a/decompiler/config/jak1_ntsc_black_label.jsonc +++ b/decompiler/config/jak1_ntsc_black_label.jsonc @@ -38,7 +38,7 @@ // these options are used rarely and should usually be left at false - // output a file type_defs.gc which is used the types part of all-types.gc + // output a file type_defs.gc which is used for the types part of all-types.gc "regenerate_all_types": false, // generate the symbol_map.json file. diff --git a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc index a701eb5cd..191a4d47d 100644 --- a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc @@ -16,7 +16,9 @@ // the second argument is the name of the first condition in the cond. Use print_cfg to find it out. // The third argument is the number of cases. If you set it too small it may fail to build the CFG. "cond_with_else_max_lengths":[ - ["(method 20 res-lump)", "b0", 2] + ["(method 20 res-lump)", "b0", 2], + ["(method 11 res-lump)", "b0", 1], + ["(method 12 res-lump)", "b0", 1] ], // if a cond with an else case is being used a value in a place where it looks wrong diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index 76d59250f..e0eb4ebe2 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -222,8 +222,6 @@ "pat-h": [["L1", "(inline-array pat-mode-info)", true, 4]], - "fact-h": [["L35", "_auto_", true]], - "sync-info": [ ["L78", "float", true], ["L84", "float", true], @@ -259,6 +257,7 @@ ], "fact-h": [ + ["L35", "_auto_", true], ["L36", "float", true], ["L37", "float", true], ["L38", "float", true], diff --git a/decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc b/decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc index a823f7ab2..a23c222f2 100644 --- a/decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc @@ -166,6 +166,9 @@ "draw-sprite2d-xy": [[16, "draw-context"]], "screen-gradient": [[16, "draw-context"]], + //"(method 18 res-lump)": [[16, "res-tag"]], + //"(method 21 res-lump)": [[16, "res-tag"], [32, "res-tag"]], + //"(method 0 fact-info)": [[16, "res-tag"]], "(method 10 oscillating-vector)": [[16, "vector"]], diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 22638191d..38d8f9eb0 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -387,6 +387,10 @@ [184, "t5", "(pointer uint64)"], [64, "t6", "(pointer uint64)"] ], + "(method 16 res-lump)": [ + [22, "t1", "(pointer uint64)"], + [29, "t2", "(pointer uint64)"] + ], // SHADOW-CPU-H "(method 10 shadow-control)": [[1, "v1", "int"]], diff --git a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc index 9bbd5304a..f1d66b6d1 100644 --- a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc @@ -1596,15 +1596,62 @@ "a2-13": "src-hi" } }, + "(method 3 res-lump)": { + "vars": { "s5-0": "i" } + }, "(method 9 res-lump)": { - "args": ["obj", "name", "mode", "time", "data-addr", "tag-addr", "buf-addr"], + "args": ["obj", "name", "mode", "time", "default", "tag-addr", "buf-addr"], "vars": { "s3-0": "tag-pair" } }, + "(method 10 res-lump)": { + "args": ["obj", "name", "mode", "time", "default", "tag-addr", "buf-addr"], + "vars": { "s3-0": "tag-pair", "v1-4": "tag" } + }, + "(method 11 res-lump)": { + "args": ["obj", "name", "mode", "time", "default", "tag-addr", "buf-addr"], + "vars": { + "a2-1": "tag-pair", + "s1-0": "tag", + "s0-0": "tag-type", + "gp-1": "data" + } + }, + "(method 12 res-lump)": { + "args": ["obj", "name", "mode", "time", "default", "tag-addr", "buf-addr"], + "vars": { + "a2-1": "tag-pair", + "s1-0": "tag", + "s0-0": "tag-type", + "gp-1": "data" + } + }, + "(method 16 res-lump)": { + "vars": { + "v1-0": "tags-sorted", + "a1-0": "i", + "a2-1": "tag-stop", + "a3-2": "tag1", + "t0-3": "tag2", + "t1-6": "tag-name1", + "t2-6": "tag-name2" + } + }, + "(method 15 res-lump)": { + "vars": { + "s5-0": ["tag-pair", "res-tag-pair"] + } + }, // FACT-H "(method 0 fact-info-target)": { "vars": { "gp-0": "obj" } }, + "(method 0 fact-info-enemy)": { + "vars": { + "gp-0": "obj", + "s5-0": "entity" + } + }, "(method 0 align-control)": { "vars": { "v0-0": ["obj", "align-control"] } diff --git a/goal_src/engine/data/res-h.gc b/goal_src/engine/data/res-h.gc index edd4df29d..8acfbe2f7 100644 --- a/goal_src/engine/data/res-h.gc +++ b/goal_src/engine/data/res-h.gc @@ -41,19 +41,20 @@ (:methods (new (symbol type int int) _type_ 0) (get-property-data (_type_ symbol symbol float pointer (pointer res-tag) pointer) pointer 9) - (dummy-10 (_type_ symbol symbol int symbol symbol pointer) int 10) - (dummy-11 (_type_ symbol symbol int int symbol pointer) int 11) - (dummy-12 (_type_ symbol symbol float float symbol pointer) float 12) + (get-property-struct (_type_ symbol symbol float structure (pointer res-tag) pointer) structure 10) + (get-property-value (_type_ symbol symbol float uint128 (pointer res-tag) pointer) uint128 11) + (get-property-value2 (_type_ symbol symbol float uint128 (pointer res-tag) pointer) uint128 12) (get-tag-index-data (_type_ int) pointer 13) (get-tag-data (_type_ res-tag) pointer 14) - (dummy-15 (_type_) none 15) - (dummy-16 (_type_ int int int int) none 16) - (dummy-17 (_type_ int int) res-lump 17) - (dummy-18 (_type_ int int) none 18) + (dummy-15 (_type_ res-tag) res-tag 15) + (sort! (_type_) _type_ 16) + (dummy-17 (_type_ res-tag pointer) res-lump 17) + (dummy-18 (_type_ res-tag res-tag) res-lump 18) (lookup-tag-idx (_type_ symbol symbol float) res-tag-pair 19) (make-property-data (_type_ float res-tag-pair pointer) pointer 20) - (dummy-21 (_type_ int int int int int) none 21) + (dummy-21 (_type_ pointer symbol symbol float) symbol 21) ) ) (define *res-key-string* (new 'global 'string 64 (the-as string #f))) ;; why 64? +(define-extern *res-static-buf* pointer) diff --git a/goal_src/engine/data/res.gc b/goal_src/engine/data/res.gc index 2192b2ea9..194929b7a 100644 --- a/goal_src/engine/data/res.gc +++ b/goal_src/engine/data/res.gc @@ -73,6 +73,7 @@ (defmethod get-tag-index-data res-lump ((obj res-lump) (n int)) "get the data address of the n'th tag." + (declare (inline)) (&+ (-> obj data-base) (-> obj tag n data-offset)) @@ -80,6 +81,7 @@ (defmethod get-tag-data res-lump ((obj res-lump) (tag res-tag)) "get the data address of the specified tag." + (declare (inline)) (&+ (-> obj data-base) (-> tag data-offset)) @@ -114,6 +116,31 @@ (-> obj data-size))) ) +(defmethod inspect res-lump ((obj res-lump)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Textra: ~A~%" (-> obj extra)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tdata-base: #x~X~%" (-> obj data-base)) + (format #t "~Tdata-top: #x~X~%" (-> obj data-top)) + (format #t "~Tdata-size: #x~X~%" (-> obj data-size)) + (format #t "~Ttag[~D]: @ #x~X~%" (-> obj allocated-length) (-> obj tag)) + (dotimes (i (-> obj length)) + (format #t "~T [~D] " i) + (print (-> (-> obj tag) i)) + (format #t " @ #x~X" (get-tag-index-data obj i)) + (cond + ((res-ref? (-> obj tag i)) + (format #t " = ~A~%" (deref basic (get-tag-index-data obj i))) + ) + (else + (format #t "~%") + ) + ) + ) + obj + ) + (defmethod lookup-tag-idx res-lump ((obj res-lump) (name-sym symbol) (mode symbol) (time float)) "Look up the index of the tag containing with the given name and timestamp. Correct lookups return a res-tag-pair, which contains one tag index in the lower 32 bits and one in the upper 32 bits. @@ -309,26 +336,26 @@ If tag-pair does not represent an exact point in the timeline, then the data is interpolated based on time with the result written into buf. buf must have enough space to copy all of the data. Otherwise, simply returns an address to the resource binary." - + (let* ((tag-lo (-> obj tag (-> tag-pair lo))) (tag-hi (-> obj tag (-> tag-pair hi))) (elt-count (-> tag-lo elt-count)) ) (cond ((res-ref? tag-lo) - (&+ (-> obj data-base) (-> tag-lo data-offset)) + (get-tag-data obj tag-lo) ) ((or (not buf) (= (-> tag-pair lo) (-> tag-pair hi)) (!= elt-count (-> tag-hi elt-count)) (!= (-> tag-lo elt-type) (-> tag-hi elt-type))) - (&+ (-> obj data-base) (-> tag-lo data-offset)) + (get-tag-data obj tag-lo) ) (else (let ((interp (/ (- time (-> tag-lo key-frame)) (- (-> tag-hi key-frame) (-> tag-lo key-frame)))) ;; DBZ - (src-lo (&+ (-> obj data-base) (-> tag-lo data-offset))) - (src-hi (&+ (-> obj data-base) (-> tag-hi data-offset))) + (src-lo (get-tag-data obj tag-lo)) + (src-hi (get-tag-data obj tag-hi)) ) (case (-> tag-lo elt-type symbol) (('float) @@ -380,7 +407,7 @@ buf ) (else - (&+ (-> obj data-base) (-> tag-lo data-offset)) + (get-tag-data obj tag-lo) ) ) ) @@ -389,10 +416,10 @@ ) ) -(defmethod get-property-data res-lump ((obj res-lump) (name symbol) (mode symbol) (time float) (data-addr pointer) (tag-addr (pointer res-tag)) (buf-addr pointer)) - "Returns an address to a given property's data at a specific time stamp. +(defmethod get-property-data res-lump ((obj res-lump) (name symbol) (mode symbol) (time float) (default pointer) (tag-addr (pointer res-tag)) (buf-addr pointer)) + "Returns an address to a given property's data at a specific time stamp, or default on error. name is the name of the property you want, mode is its lookup mode ('interp 'base 'exact), time is the timestamp. - data-addr is an address to the new data, or simply the old data if lookup failed. + default is the default result returned in the case of an error. tag-addr is an address to a res-tag. The current base tag is written to this. Ignored if tag-addr is #f buf-addr is an address to the data buffer used to write interpolated data to. It must have enough space! Only necessary for 'interp mode." @@ -402,13 +429,184 @@ (empty) ) (else - (set! data-addr (make-property-data obj time tag-pair buf-addr)) + (set! default (make-property-data obj time tag-pair buf-addr)) (if tag-addr (set! (-> tag-addr) (-> obj tag (-> tag-pair lo))) ) ) + ) ) - ) - data-addr + default ) +(defmethod get-property-struct res-lump ((obj res-lump) (name symbol) (mode symbol) (time float) (default structure) (tag-addr (pointer res-tag)) (buf-addr pointer)) + "Returns a given struct property's value at a specific time stamp, or default on error. + name is the name of the property you want, mode is its lookup mode ('interp 'base 'exact), time is the timestamp. + default is the default result returned in the case of an error. + tag-addr is an address to a res-tag. The current base tag is written to this. Ignored if tag-addr is #f + buf-addr is an address to the data buffer used to write interpolated data to. It must have enough space! Only necessary for 'interp mode." + + (let ((tag-pair (lookup-tag-idx obj name mode time))) + (cond + ((< (the-as int tag-pair) 0) + (empty) + ) + (else + (set! default (the-as structure (make-property-data obj time tag-pair buf-addr))) + (let ((tag (-> obj tag (-> tag-pair lo)))) + (if tag-addr + (set! (-> tag-addr 0) tag) + ) + (if (res-ref? tag) + (set! default (deref structure default)) + (empty) + ) + ) + ) + ) + ) + default + ) + +(defmethod get-property-value res-lump ((obj res-lump) (name symbol) (mode symbol) (time float) (default uint128) (tag-addr (pointer res-tag)) (buf-addr pointer)) + "Returns a given value property's value at a specific time stamp, or default on error. + name is the name of the property you want, mode is its lookup mode ('interp 'base 'exact), time is the timestamp. + default is the default result returned in the case of an error. + tag-addr is an address to a res-tag. The current base tag is written to this. Ignored if tag-addr is #f + buf-addr is an address to the data buffer used to write interpolated data to. It must have enough space! Only necessary for 'interp mode." + + (let ((tag-pair (lookup-tag-idx obj name mode time))) + (cond + ((< (the-as int tag-pair) 0) + (empty) + ) + (else + (let* ((tag (-> obj tag (-> tag-pair lo))) + (tag-type (-> tag elt-type)) + (data (make-property-data obj time tag-pair buf-addr)) + ) + (if tag-addr + (set! (-> tag-addr 0) tag) + ) + (cond + ((type-type? tag-type uinteger) + (case (-> tag elt-type size) + ((1) (set! default (the-as uint128 (deref uint8 data)))) + ((2) (set! default (the-as uint128 (deref uint16 data)))) + ((4) (set! default (the-as uint128 (deref uint32 data)))) + ((16) (set! default (the-as uint128 (deref uint128 data)))) + (else (set! default (the-as uint128 (deref uint64 data)))) + ) + ) + ((type-type? tag-type integer) + (case (-> tag elt-type size) + ((1) (set! default (the-as uint128 (deref int8 data)))) + ((2) (set! default (the-as uint128 (deref int16 data)))) + ((4) (set! default (the-as uint128 (deref int32 data)))) + ((16) (set! default (the-as uint128 (deref uint128 data)))) + (else (set! default (the-as uint128 (deref uint64 data)))) + ) + ) + ((type-type? tag-type float) + (set! default (the-as uint128 (deref float data))) + ) + (else + (empty) + ) + ) + ) + ) + ) + ) + default + ) + +(defmethod get-property-value2 res-lump ((obj res-lump) (name symbol) (mode symbol) (time float) (default uint128) (tag-addr (pointer res-tag)) (buf-addr pointer)) + "same as get-property-value but float type is checked first?" + + (let ((tag-pair (lookup-tag-idx obj name mode time))) + (cond + ((< (the-as int tag-pair) 0) + (empty) + ) + (else + (let* ((tag (-> obj tag (-> tag-pair lo))) + (tag-type (-> tag elt-type)) + (data (make-property-data obj time tag-pair buf-addr)) + ) + (if tag-addr + (set! (-> tag-addr 0) tag) + ) + (cond + ((type-type? tag-type float) + (set! default (the-as uint128 (deref float data))) + ) + ((type-type? tag-type uinteger) + (case (-> tag elt-type size) + ((1) (set! default (the-as uint128 (deref uint8 data)))) + ((2) (set! default (the-as uint128 (deref uint16 data)))) + ((4) (set! default (the-as uint128 (deref uint32 data)))) + ((16) (set! default (the-as uint128 (deref uint128 data)))) + (else (set! default (the-as uint128 (deref uint64 data)))) + ) + ) + ((type-type? tag-type integer) + (case (-> tag elt-type size) + ((1) (set! default (the-as uint128 (deref int8 data)))) + ((2) (set! default (the-as uint128 (deref int16 data)))) + ((4) (set! default (the-as uint128 (deref int32 data)))) + ((16) (set! default (the-as uint128 (deref uint128 data)))) + (else (set! default (the-as uint128 (deref uint64 data)))) + ) + ) + (else + (empty) + ) + ) + ) + ) + ) + ) + default + ) + +(defmethod sort! res-lump ((obj res-lump)) + "Sort all tags based on name, then key-frame." + + (let ((tags-sorted -1)) + (while (nonzero? tags-sorted) + (set! tags-sorted 0) + (let ((i 0) + (tag-stop (+ (-> obj length) -2)) + ) + (while (>= tag-stop i) + (let* ((tag1 (-> obj tag i)) + (tag2 (-> obj tag (1+ i))) + (tag-name1 (deref uint64 (-> (symbol->string (-> tag1 name)) data))) + (tag-name2 (deref uint64 (-> (symbol->string (-> tag2 name)) data))) + ) + (when (or (< tag-name2 tag-name1) + (and (= tag-name1 tag-name2) + (< (-> tag2 key-frame) (-> tag1 key-frame)))) + (1+! tags-sorted) + (set! (-> obj tag i) tag2) + (set! (-> obj tag (1+ i)) tag1) + ) + ) + (1+! i) + ) + ) + ) + ) + obj + ) + +;; method 15 res-lump +;; method 17 res-lump +;; method 18 res-lump +;; method 21 res-lump +;; mem-usage res-lump + + +(define *res-static-buf* (malloc 'global 128)) + diff --git a/goal_src/engine/game/fact-h.gc b/goal_src/engine/game/fact-h.gc index 474e0b09c..e456f396b 100644 --- a/goal_src/engine/game/fact-h.gc +++ b/goal_src/engine/game/fact-h.gc @@ -142,3 +142,5 @@ (defmethod dummy-11 fact-info ((obj fact-info)) 0.0 ) + + diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc index 46a2c46d7..37eb509fd 100644 --- a/goal_src/goal-lib.gc +++ b/goal_src/goal-lib.gc @@ -20,9 +20,9 @@ `(asm-file ,file :color :write) ) -(defmacro md (file) +(defmacro md (file &rest path) "Make Debug: make + print disassembly for a file" - `(asm-file ,file :color :write :disassemble) + `(asm-file ,file :color :write :disassemble ,@path) ) (defmacro ml (file) @@ -364,21 +364,21 @@ (cond ,@(apply (lambda (x) `( ;; each case is of format ((cond cond cond...) body) - ,@(let ((cond-list (first x)) ;; list of conds, OR just else + ,@(let ((conditions (first x)) ;; list of conditions, OR just else (body (rest x))) ;; the body (cond - ;; if the cond is just 'else' - ( (eq? cond-list 'else) + ;; if the condition is just 'else' + ( (eq? conditions 'else) `(else ,@body) ) - ;; if the list is made up of a single cond - ( (= (length cond-list) 1) - `((= sw ,(first cond-list)) ,@body) + ;; if the list is made up of a single condition + ( (= (length conditions) 1) + `((= sw ,(first conditions)) ,@body) ) - ;; otherwise it is made up of multiple conds, or them together! + ;; otherwise it is made up of multiple conditions, or them together! (#t - `((or ,@(apply (lambda (c) `(= sw ,c)) cond-list)) ,@body) + `((or ,@(apply (lambda (c) `(= sw ,c)) conditions)) ,@body) ) ) diff --git a/goalc/compiler/compilation/CompilerControl.cpp b/goalc/compiler/compilation/CompilerControl.cpp index b3ad803c7..57fe82712 100644 --- a/goalc/compiler/compilation/CompilerControl.cpp +++ b/goalc/compiler/compilation/CompilerControl.cpp @@ -81,6 +81,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re (void)env; int i = 0; std::string filename; + std::string disasm_filename = ""; bool load = false; bool color = false; bool write = false; @@ -91,7 +92,16 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re Timer total_timer; // parse arguments + bool last_was_disasm = false; for_each_in_list(rest, [&](const goos::Object& o) { + if (last_was_disasm) { + last_was_disasm = false; + if (o.type == goos::ObjectType::STRING) { + disasm_filename = as_string(o); + i++; + return; + } + } if (i == 0) { filename = as_string(o); } else { @@ -106,6 +116,7 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re no_code = true; } else if (setting == ":disassemble") { disassemble = true; + last_was_disasm = true; } else { throw_compiler_error(form, "The option {} was not recognized for asm-file.", setting); } @@ -146,7 +157,11 @@ Val* Compiler::compile_asm_file(const goos::Object& form, const goos::Object& re std::string disasm; if (disassemble) { codegen_and_disassemble_object_file(obj_file, &data, &disasm); - printf("%s\n", disasm.c_str()); + if (disasm_filename == "") { + printf("%s\n", disasm.c_str()); + } else { + file_util::write_text_file(disasm_filename, disasm); + } } else { data = codegen_object_file(obj_file); } @@ -541,4 +556,4 @@ Val* Compiler::compile_add_macro_to_autocomplete(const goos::Object& form, va_check(form, args, {goos::ObjectType::SYMBOL}, {}); m_symbol_info.add_macro(args.unnamed.at(0).as_symbol()->name, form); return get_none(); -} \ No newline at end of file +} diff --git a/goalc/compiler/compilation/Math.cpp b/goalc/compiler/compilation/Math.cpp index 7a6dbe494..50fb657f2 100644 --- a/goalc/compiler/compilation/Math.cpp +++ b/goalc/compiler/compilation/Math.cpp @@ -572,13 +572,18 @@ Val* Compiler::compile_logand(const goos::Object& form, const goos::Object& rest va_check(form, args, {{}, {}}, {}); auto first = compile_error_guard(args.unnamed.at(0), env)->to_gpr(env); auto second = compile_error_guard(args.unnamed.at(1), env)->to_gpr(env); - if (get_math_mode(first->type()) != MathMode::MATH_INT || - get_math_mode(second->type()) != MathMode::MATH_INT) { + auto math_1 = get_math_mode(first->type()); + auto math_2 = get_math_mode(second->type()); + if (!((math_1 == MathMode::MATH_INT && math_2 == MathMode::MATH_INT) || + (math_1 == MathMode::MATH_INT && m_ts.tc(TypeSpec("pointer"), second->type())) || + (m_ts.tc(TypeSpec("pointer"), first->type()) && math_2 == MathMode::MATH_INT))) { throw_compiler_error(form, "Cannot logand a {} by a {}.", first->type().print(), second->type().print()); } - auto result = env->make_gpr(first->type()); + // kind of a hack, but make (logand int pointer) return pointer. + auto result = + env->make_gpr(m_ts.tc(TypeSpec("pointer"), second->type()) ? second->type() : first->type()); env->emit(std::make_unique(result, first)); env->emit(std::make_unique(IntegerMathKind::AND_64, result, second)); return result; @@ -630,4 +635,4 @@ Val* Compiler::compile_lognot(const goos::Object& form, const goos::Object& rest env->emit(std::make_unique(result, first)); env->emit(std::make_unique(IntegerMathKind::NOT_64, result, nullptr)); return result; -} \ No newline at end of file +} diff --git a/goalc/debugger/disassemble.cpp b/goalc/debugger/disassemble.cpp index 777f53ee2..b3607a07f 100644 --- a/goalc/debugger/disassemble.cpp +++ b/goalc/debugger/disassemble.cpp @@ -121,7 +121,7 @@ std::string disassemble_x86_function(u8* data, std::string line; - line += fmt::format("{:c} [0x{:x}] ", prefix, base_addr); + line += fmt::format("{:c} [0x{:X}] ", prefix, base_addr); ZydisFormatterFormatInstruction(&formatter, &instr, print_buff, print_buff_size, base_addr); line += print_buff; @@ -147,4 +147,4 @@ std::string disassemble_x86_function(u8* data, } return result; -} \ No newline at end of file +} diff --git a/test/decompiler/reference/engine/load/load-dgo_REF.gc b/test/decompiler/reference/engine/load/load-dgo_REF.gc index fd6a8c95c..fb19ae143 100644 --- a/test/decompiler/reference/engine/load/load-dgo_REF.gc +++ b/test/decompiler/reference/engine/load/load-dgo_REF.gc @@ -320,77 +320,43 @@ ) ;; definition for function find-temp-buffer -;; INFO: Return type mismatch int vs pointer. (defun find-temp-buffer ((size int)) (let ((qwc (+ (/ size 16) 2))) - (the-as pointer (cond - ((< - (the-as uint qwc) - (the-as - uint - (dma-buffer-free - (-> - *display* - frames - (-> *display* on-screen) - frame - global-buf - ) - ) - ) - ) - (logand - -16 - (the-as - int - (&+ - (-> - *display* - frames - (-> *display* on-screen) - frame - global-buf - base - ) - 15 - ) - ) - ) - ) - ((< - (the-as uint qwc) - (the-as - uint - (dma-buffer-free - (-> - *display* - frames - (-> *display* on-screen) - frame - global-buf - ) - ) - ) - ) - (logand - -16 - (the-as - int - (&+ - (-> - *display* - frames - (-> *display* on-screen) - frame - global-buf - base - ) - 15 - ) - ) - ) - ) - ) + (cond + ((< + (the-as uint qwc) + (the-as + uint + (dma-buffer-free + (-> *display* frames (-> *display* on-screen) frame global-buf) + ) + ) + ) + (logand + -16 + (&+ + (-> *display* frames (-> *display* on-screen) frame global-buf base) + 15 + ) + ) + ) + ((< + (the-as uint qwc) + (the-as + uint + (dma-buffer-free + (-> *display* frames (-> *display* on-screen) frame global-buf) + ) + ) + ) + (logand + -16 + (&+ + (-> *display* frames (-> *display* on-screen) frame global-buf base) + 15 + ) + ) + ) ) ) ) diff --git a/test/decompiler/reference/engine/ps2/rpc-h_REF.gc b/test/decompiler/reference/engine/ps2/rpc-h_REF.gc index 708c1d15d..0a518cb95 100644 --- a/test/decompiler/reference/engine/ps2/rpc-h_REF.gc +++ b/test/decompiler/reference/engine/ps2/rpc-h_REF.gc @@ -48,10 +48,7 @@ (set! (-> v0-0 elt-count) arg1) (set! (-> v0-0 elt-used) (the-as uint 0)) (set! (-> v0-0 busy) #f) - (set! - (-> v0-0 base) - (the-as pointer (logand -64 (the-as int (&-> (-> v0-0 data) 63)))) - ) + (set! (-> v0-0 base) (logand -64 (&-> (-> v0-0 data) 63))) v0-0 ) ) diff --git a/test/decompiler/reference/kernel/gkernel_REF.gc b/test/decompiler/reference/kernel/gkernel_REF.gc index 46dfe9b7a..26c8bec96 100644 --- a/test/decompiler/reference/kernel/gkernel_REF.gc +++ b/test/decompiler/reference/kernel/gkernel_REF.gc @@ -146,7 +146,7 @@ ) ;; definition for method 0 of type cpu-thread -;; INFO: Return type mismatch object vs cpu-thread. +;; INFO: Return type mismatch pointer vs cpu-thread. (defmethod new cpu-thread @@ -164,26 +164,14 @@ (else (let ((v1-2 - (logand - -16 - (the-as int (&+ (-> arg0 heap-cur) 15)) - ) + (logand -16 (&+ (-> arg0 heap-cur) 15)) ) ) (set! (-> arg0 heap-cur) - (the-as - pointer - (+ - (+ - v1-2 - (the-as int (-> type-to-make size)) - ) - arg2 - ) - ) + (&+ (&+ v1-2 (-> type-to-make size)) arg2) ) - (the-as cpu-thread (+ v1-2 4)) + (the-as cpu-thread (&+ v1-2 4)) ) ) ) @@ -200,7 +188,7 @@ (set! (-> obj suspend-hook) (method-of-object obj thread-suspend)) (set! (-> obj resume-hook) (method-of-object obj thread-resume)) (set! (-> obj stack-size) arg2) - (the-as cpu-thread (the-as object obj)) + (the-as cpu-thread (the-as pointer obj)) ) ) diff --git a/test/decompiler/test_gkernel_decomp.cpp b/test/decompiler/test_gkernel_decomp.cpp index 3f2edcee7..355e34480 100644 --- a/test/decompiler/test_gkernel_decomp.cpp +++ b/test/decompiler/test_gkernel_decomp.cpp @@ -341,21 +341,12 @@ TEST_F(FormRegressionTest, ExprMethod0Thread) { " )\n" " (else\n" " (let\n" - " ((v1-2\n" - " (logand\n" - " -16\n" - " (the-as int (&+ (-> arg2 heap-cur) 15))\n" - " )\n" - " )\n" - " )\n" + " ((v1-2 (logand -16 (&+ (-> arg2 heap-cur) 15))))\n" " (set!\n" " (-> arg2 heap-cur)\n" - " (the-as\n" - " pointer\n" - " (+ (+ v1-2 (the-as int (-> arg1 size))) arg4)\n" - " )\n" + " (&+ (&+ v1-2 (-> arg1 size)) arg4)\n" " )\n" - " (the-as cpu-thread (+ v1-2 4))\n" + " (the-as cpu-thread (&+ v1-2 4))\n" " )\n" " )\n" " )\n" @@ -372,7 +363,7 @@ TEST_F(FormRegressionTest, ExprMethod0Thread) { " (set! (-> obj suspend-hook) (method-of-object obj thread-suspend))\n" " (set! (-> obj resume-hook) (method-of-object obj thread-resume))\n" " (set! (-> obj stack-size) arg4)\n" - " (the-as cpu-thread (the-as object obj))\n" + " (the-as cpu-thread (the-as pointer obj))\n" " )"; test_with_expr(func, type, expected, false, "cpu-thread", {}, "[[[13, 28], \"v0\", \"cpu-thread\"]]", @@ -2834,4 +2825,4 @@ TEST_F(FormRegressionTest, ExprMethod18DeadPoolHeap) { " (none)\n" " )"; test_with_expr(func, type, expected); -} \ No newline at end of file +}