[Decompile] DMA and similar (#275)

* add some dma

* clean up

* add progress script and make codacy happy
This commit is contained in:
water111 2021-02-21 11:02:28 -05:00 committed by GitHub
parent ea1a4ef1bb
commit 4b1b7e9507
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2126 additions and 180 deletions

View file

@ -484,6 +484,12 @@ Object Interpreter::eval_symbol(const Object& sym, const std::shared_ptr<Environ
return result; return result;
} }
bool Interpreter::eval_symbol(const Object& sym,
const std::shared_ptr<EnvironmentObject>& env,
Object* result) {
return try_symbol_lookup(sym, env, result);
}
/*! /*!
* Evaluate a pair, either as special form, builtin form, macro application, or lambda application. * Evaluate a pair, either as special form, builtin form, macro application, or lambda application.
*/ */

View file

@ -23,6 +23,9 @@ class Interpreter {
Object intern(const std::string& name); Object intern(const std::string& name);
void disable_printfs(); void disable_printfs();
Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env); Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env);
bool eval_symbol(const Object& sym,
const std::shared_ptr<EnvironmentObject>& env,
Object* result);
Arguments get_args(const Object& form, const Object& rest, const ArgumentSpec& spec); Arguments get_args(const Object& form, const Object& rest, const ArgumentSpec& spec);
void set_args_in_env(const Object& form, void set_args_in_env(const Object& form,
const Arguments& args, const Arguments& args,

View file

@ -40,6 +40,7 @@
#include "Object.h" #include "Object.h"
#include "common/util/FileUtil.h" #include "common/util/FileUtil.h"
#include "third-party/fmt/core.h"
namespace goos { namespace goos {
@ -90,6 +91,18 @@ std::string fixed_to_string(FloatType x) {
return {buff}; return {buff};
} }
/*!
* Special case to print an integer
*/
template <>
std::string fixed_to_string(IntType x) {
if (x > 10000) {
return fmt::format("#x{:x}", x);
} else {
return fmt::format("{}", x);
}
}
/*! /*!
* Special case to print a character and escape the weird ones. * Special case to print a character and escape the weird ones.
*/ */

View file

@ -104,6 +104,12 @@ std::string fixed_to_string<FloatType>(FloatType);
template <> template <>
std::string fixed_to_string<char>(char); std::string fixed_to_string<char>(char);
/*!
* Special case to print integer
*/
template <>
std::string fixed_to_string<IntType>(IntType);
/*! /*!
* Common implementation for a fixed object * Common implementation for a fixed object
*/ */

View file

@ -779,9 +779,10 @@ void TypeSystem::add_builtin_types() {
// VU FUNCTION // VU FUNCTION
// don't inherit // don't inherit
add_field_to_type(vu_function_type, "length", make_typespec("int32")); // todo integer type add_field_to_type(vu_function_type, "length", make_typespec("int32")); // todo integer type
add_field_to_type(vu_function_type, "origin", make_typespec("pointer")); // todo sign extend? add_field_to_type(vu_function_type, "origin", make_typespec("int32")); // todo sign extend?
add_field_to_type(vu_function_type, "qlength", make_typespec("int32")); // todo integer type add_field_to_type(vu_function_type, "qlength", make_typespec("int32")); // todo integer type
add_field_to_type(vu_function_type, "data", make_typespec("uint8"), false, true);
// link block // link block
builtin_structure_inherit(link_block_type); builtin_structure_inherit(link_block_type);

View file

@ -128,7 +128,7 @@ goos::Object SimpleAtom::to_form(const std::vector<DecompilerLabel>& labels, con
case Kind::VARIABLE: case Kind::VARIABLE:
return m_variable.to_form(env); return m_variable.to_form(env);
case Kind::INTEGER_CONSTANT: case Kind::INTEGER_CONSTANT:
return pretty_print::to_symbol(std::to_string(m_int)); return goos::Object::make_integer(m_int);
case Kind::SYMBOL_PTR: case Kind::SYMBOL_PTR:
return pretty_print::to_symbol(fmt::format("'{}", m_string)); return pretty_print::to_symbol(fmt::format("'{}", m_string));
case Kind::SYMBOL_VAL: case Kind::SYMBOL_VAL:

View file

@ -1335,13 +1335,6 @@ void FunctionCallElement::update_from_stack(const Env& env,
// throw std::runtime_error("Failed to match new method: " + // throw std::runtime_error("Failed to match new method: " +
// temp_form->to_string(env)); // temp_form->to_string(env));
} }
} else {
auto ti = env.dts->ts.lookup_type(type_1);
auto is_basic = dynamic_cast<BasicType*>(ti);
if (!is_basic) {
throw std::runtime_error(
fmt::format("Method call detected, not yet implemented {} {}\n", name, type_1));
}
} }
} }
} }
@ -1815,6 +1808,15 @@ FormElement* ConditionElement::make_generic(const Env&,
casted); casted);
} }
case IR2_Condition::Kind::GREATER_THAN_ZERO_UNSIGNED: {
auto casted = make_cast(source_forms, types, TypeSpec("uint"), pool);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(0));
casted.push_back(zero);
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GT),
casted);
}
case IR2_Condition::Kind::GREATER_THAN_ZERO_SIGNED: { case IR2_Condition::Kind::GREATER_THAN_ZERO_SIGNED: {
auto casted = make_cast(source_forms, types, TypeSpec("int"), pool); auto casted = make_cast(source_forms, types, TypeSpec("int"), pool);
auto zero = pool.alloc_single_element_form<SimpleAtomElement>( auto zero = pool.alloc_single_element_form<SimpleAtomElement>(
@ -1984,7 +1986,8 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool&, FormStack& stack)
auto as_special = dynamic_cast<const SpecialOp*>(m_op); auto as_special = dynamic_cast<const SpecialOp*>(m_op);
if (as_special) { if (as_special) {
if (as_special->kind() == SpecialOp::Kind::NOP || if (as_special->kind() == SpecialOp::Kind::NOP ||
as_special->kind() == SpecialOp::Kind::BREAK) { as_special->kind() == SpecialOp::Kind::BREAK ||
as_special->kind() == SpecialOp::Kind::CRASH) {
stack.push_form_element(this, true); stack.push_form_element(this, true);
return; return;
} }

View file

@ -60,6 +60,9 @@
(define-extern file-stream-length (function file-stream int)) (define-extern file-stream-length (function file-stream int))
(define-extern file-stream-read (function file-stream pointer int int)) (define-extern file-stream-read (function file-stream pointer int int))
(define-extern dma-sync (function pointer int int int))
(define-extern flush-cache (function int none))
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; GCOMMON ;;;;;;;;;;;;;;;;;;; ;;;; GCOMMON ;;;;;;;;;;;;;;;;;;;
@ -1567,14 +1570,20 @@
;;(define-extern sound-id object) ;; unknown type ;;(define-extern sound-id object) ;; unknown type
(deftype sound-id (uint32) (deftype sound-id (uint32)
() ()
(:methods
(dummy-9 () none 9)
)
:flag-assert #xa00000004
) )
(deftype sound-bank-id (uint32) (deftype sound-bank-id (uint32)
() ()
:flag-assert #x900000004
) )
(deftype sound-name (uint128) (deftype sound-name (uint128)
() ()
:flag-assert #x900000010
) )
;;(define-extern sound-play-parms object) ;; unknown type ;;(define-extern sound-play-parms object) ;; unknown type
;;(define-extern sound-rpc-load-bank object) ;; unknown type ;;(define-extern sound-rpc-load-bank object) ;; unknown type
@ -2022,33 +2031,51 @@
(define-extern stopwatch-elapsed-ticks (function stopwatch uint)) (define-extern stopwatch-elapsed-ticks (function stopwatch uint))
(define-extern stopwatch-elapsed-seconds (function stopwatch float)) (define-extern stopwatch-elapsed-seconds (function stopwatch float))
;;;;;;;;;;;;; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;; vif-h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; ;;;; VIF-H ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
; ;; vif-h ; ;; vif-h
(deftype vif-stat (uint32) (deftype vif-stat (uint32)
() ((vps uint8 :offset 0 :size 2)
(vew uint8 :offset 2 :size 1)
(mrk uint8 :offset 6 :size 1)
(vss uint8 :offset 8 :size 1)
(vfs uint8 :offset 9 :size 1)
(vis uint8 :offset 10 :size 1)
(int uint8 :offset 11 :size 1)
(er0 uint8 :offset 12 :size 1)
(er1 uint8 :offset 13 :size 1)
(fqc uint8 :offset 24 :size 4)
)
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4
:flag-assert #x900000004 :flag-assert #x900000004
;; likely a bitfield type
) )
(deftype vif-fbrst (uint32) (deftype vif-fbrst (uint32)
() ((rst uint8 :offset 0 :size 1)
(fbk uint8 :offset 1 :size 1)
(stp uint8 :offset 2 :size 1)
(stc uint8 :offset 3 :size 1)
)
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4
:flag-assert #x900000004 :flag-assert #x900000004
;; likely a bitfield type
) )
(deftype vif-err (uint32) (deftype vif-err (uint32)
() ((mii uint8 :offset 0 :size 1)
(me0 uint8 :offset 1 :size 1) ;; PS2 hardware bug, must set this to 1 for correct operation.
(me1 uint8 :offset 2 :size 1)
)
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4
:flag-assert #x900000004 :flag-assert #x900000004
;; likely a bitfield type
) )
;; vif-h ;; vif-h
@ -2081,13 +2108,31 @@
:size-assert #x174 :size-assert #x174
:flag-assert #x900000174 :flag-assert #x900000174
) )
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; DMA-H ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
(deftype dma-sqwc (uint32)
()
:flag-assert #x900000004
)
; ;; dma-h ; ;; dma-h
(deftype dma-chcr (uint32) (deftype dma-chcr (uint32)
() ((dir uint8 :offset 0 :size 1) ;; 1 - from memory
(mod uint8 :offset 2 :size 2) ;; normal, chain, interleave
(asp uint8 :offset 4 :size 2) ;; none, 1, 2
(tte uint8 :offset 6 :size 1) ;; transfer tag (sc only)
(tie uint8 :offset 7 :size 1) ;; tag interrupt
(str uint8 :offset 8 :size 1) ;; start!
(tag uint16 :offset 16)
)
:method-count-assert 9 :method-count-assert 9
:size-assert #x4 :size-assert #x4
:flag-assert #x900000004 :flag-assert #x900000004
;; likely a bitfield type
) )
(deftype dma-ctrl (uint32) (deftype dma-ctrl (uint32)
@ -2099,7 +2144,7 @@
) )
(deftype dma-bank (structure) (deftype dma-bank (structure)
((chcr uint32 :offset 0) ((chcr dma-chcr :offset 0)
(madr uint32 :offset 16) (madr uint32 :offset 16)
(qwc uint32 :offset 32) (qwc uint32 :offset 32)
) )
@ -2134,10 +2179,10 @@
) )
(deftype dma-bank-control (structure) (deftype dma-bank-control (structure)
((ctrl uint32 :offset 0) ((ctrl dma-ctrl :offset 0)
(stat uint32 :offset 16) (stat uint32 :offset 16)
(pcr uint32 :offset 32) (pcr uint32 :offset 32)
(sqwc uint32 :offset 48) (sqwc dma-sqwc :offset 48)
(rbsr uint32 :offset 64) (rbsr uint32 :offset 64)
(rbor uint32 :offset 80) (rbor uint32 :offset 80)
(stadr uint32 :offset 96) (stadr uint32 :offset 96)
@ -2162,33 +2207,74 @@
; ;; dma-h ; ;; dma-h
(deftype dma-tag (uint64) (deftype dma-tag (uint64)
() ((qwc uint16 :offset 0) ;; quadword count
(pce uint8 :offset 26 :size 2) ;; priority (source mode)
(id uint8 :offset 28 :size 3) ;; ID (what the tag means)
(irq uint8 :offset 31 :size 1) ;; interrupt at the end?
(addr uint32 :offset 32 :size 31) ;; address (31 bits)
(spr uint8 :offset 63 :size 1) ;; spr or not flag.
)
:method-count-assert 9 :method-count-assert 9
:size-assert #x8 :size-assert #x8
:flag-assert #x900000008 :flag-assert #x900000008
;; likely a bitfield type
) )
; ;; dma-h ; ;; dma-h
(deftype dma-bucket (structure) (deftype dma-bucket (structure)
((tag uint64 :offset-assert 0) ((tag dma-tag :offset-assert 0) ;; the DMA tag to transfer the bucket's data
(last uint32 :offset-assert 8) (last (pointer uint64) :offset-assert 8) ;; the last tag of this bucket.
(dummy uint32 :offset-assert 12) (dummy uint32 :offset-assert 12) ;; empty space.
(next uint32 :offset 4) (next uint32 :offset 4) ;; this overlaps with the addr bit-field of the dma-tag
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x10 :size-assert #x10
:flag-assert #x900000010 :flag-assert #x900000010
) )
; ;; dma-h
; (deftype vif-tag (uint32) ;; dma-h
; ()
; :method-count-assert 9 (deftype vif-tag (uint32)
; :size-assert #x4 ((imm uint16 :offset 0 :size 16)
; :flag-assert #x900000004 (num uint8 :offset 16 :size 8)
; ;; likely a bitfield type (cmd uint8 :offset 24 :size 8)
; ) (irq uint8 :offset 31 :size 1) ;;?
(msk uint8 :offset 15 :size 1)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(deftype dma-enable (uint32)
()
:flag-assert #x900000004
)
(deftype vu-stat (uint64)
()
:flag-assert #x900000008
)
(deftype vif-mask (uint32)
()
:flag-assert #x900000004
)
(deftype vif-stcycl-imm (uint16)
()
:flag-assert #x900000002
)
(deftype vif-unpack-imm (uint16)
()
:flag-assert #x900000002
)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; VIDEO-H ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
; ;; video-h ; ;; video-h
(deftype video-parms (structure) (deftype video-parms (structure)
@ -2214,6 +2300,12 @@
:flag-assert #x900000048 :flag-assert #x900000048
) )
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; VU1-USER-H ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;; vu1-user-h ;; vu1-user-h
(deftype dma-foreground-sink (basic) (deftype dma-foreground-sink (basic)
((bucket int32 :offset-assert 4) ((bucket int32 :offset-assert 4)
@ -2244,25 +2336,118 @@
:flag-assert #x900000014 :flag-assert #x900000014
) )
(deftype dma-foreground-sink (basic)
((bucket int32 :offset-assert 4) ;; not sure if this is a bucket index or pointer?
(foreground-texture-page int8 :offset-assert 8) ;; ?
(foreground-texture-level int8 :offset-assert 9) ;; ?
(foreground-output-bucket int8 :offset-assert 10) ;; ?
)
:method-count-assert 9
:size-assert #xb
:flag-assert #x90000000b
)
(deftype dma-foreground-sink-group (basic) (deftype dma-foreground-sink-group (basic)
((sink basic 3 :offset-assert 4) ((sink dma-foreground-sink 3 :offset-assert 4)
(merc-sink basic :offset 4) (merc-sink dma-foreground-sink :offset 4)
(generic-sink basic :offset 8) (generic-sink generic-dma-foreground-sink :offset 8)
(level basic :offset 16) (level basic :offset-assert 16)
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x14 :size-assert #x14
:flag-assert #x900000014 :flag-assert #x900000014
) )
;;;;;;;;;;;;;;;
;; dma-buffer ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; DMA ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
(define-extern reset-path (function none))
(define-extern reset-graph (function int int int int none))
(define-extern dma-sync-crash (function dma-bank none))
(define-extern dma-send (function dma-bank uint uint none))
(define-extern dma-send-chain (function dma-bank-source uint none))
(define-extern dma-send-chain-no-tte (function dma-bank-source uint none))
(define-extern dma-send-chain-no-flush (function dma-bank-source uint none))
(define-extern dma-send-to-spr (function uint uint uint symbol none))
(define-extern dma-send-to-spr-no-flush (function uint uint uint symbol none))
(define-extern dma-send-from-spr (function uint uint uint symbol none))
(define-extern dma-send-from-spr-no-flush (function uint uint uint symbol none))
(define-extern dma-initialize (function none))
(define-extern clear-vu0-mem (function none))
(define-extern clear-vu1-mem (function none))
(define-extern dump-vu1-mem (function none))
(define-extern dump-vu1-range (function uint uint symbol))
(define-extern reset-vif1-path (function none))
(define-extern ultimate-memcpy (function pointer pointer uint none))
;
;;(define-extern vif-stat object) ;; unknown type
;;(define-extern vif-fbrst object) ;; unknown type
;;(define-extern vif-err object) ;; unknown type
;;(define-extern vif-bank object) ;; unknown type
(define-extern dma-count-until-done (function dma-bank (pointer int32) int))
;;(define-extern vif-tag object) ;; unknown type
(define-extern dma-send-no-scratch (function dma-bank uint32 uint32 none))
;;(define-extern dma-tag object) ;; unknown type
;;(define-extern dma-chcr object) ;; unknown type
;;(define-extern dma-bank-spr object) ;; unknown type
;;(define-extern dma-bucket object) ;; unknown type
(define-extern dma-sync-with-count (function dma-bank (pointer int32) int))
;;(define-extern vu-code-block object) ;; unknown type
(define-extern dma-sync-fast (function dma-bank none))
;;(define-extern vif-mask object) ;; unknown type
;;(define-extern dma-bank-control object) ;; unknown type
;;(define-extern vif-unpack-imm object) ;; unknown type
;;(define-extern dma-ctrl object) ;; unknown type
;;(define-extern dma-enable object) ;; unknown type
;;(define-extern vu-stat object) ;; unknown type
;;(define-extern dma-bank-source object) ;; unknown type
;;(define-extern dma-bank-vif object) ;; unknown type
;;(define-extern dma-sqwc object) ;; unknown type
;;(define-extern vif-stcycl-imm object) ;; unknown type
;;(define-extern dma-bank object) ;; unknown type
;;(define-extern flush-cache object) ;; unknown type
;;(define-extern *video-parms* object) ;; unknown type
;;(define-extern video-parms object) ;; unknown type
;;(define-extern generic-bucket-state object) ;; unknown type
;;(define-extern *vu1-enable-user-menu* object) ;; unknown type
(define-extern dma-foreground-sink type)
(define-extern dma-foreground-sink-group type)
;;(define-extern *vu1-enable-user* object) ;; unknown type
(define-extern generic-dma-foreground-sink type)
(define-extern symlink3 (function none))
(define-extern dma-sync-hang (function dma-bank none))
(define-extern symlink2 (function none))
(define-extern dma-send (function dma-bank uint uint none))
(define-extern *video-reset-parm* int)
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; DMA-BUFFER ;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
(deftype dma-packet (structure) (deftype dma-packet (structure)
((dma uint64 :offset-assert 0) ((dma dma-tag :offset-assert 0)
(vif0 uint32 :offset-assert 8) (vif0 vif-tag :offset-assert 8)
(vif1 uint32 :offset-assert 12) (vif1 vif-tag :offset-assert 12) ;; doesn't have to be a vif tag.
(quad uint128 :offset 0) (quad uint128 :offset 0)
) )
:method-count-assert 9 :method-count-assert 9
@ -2289,32 +2474,64 @@
(deftype dma-buffer (basic) (deftype dma-buffer (basic)
((allocated-length int32 :offset-assert 4) ((allocated-length int32 :offset-assert 4)
(base uint32 :offset-assert 8) (base pointer :offset-assert 8)
(end uint32 :offset-assert 12) (end uint32 :offset-assert 12)
(data uint64 1 :offset-assert 16) ;; hmmm, seems wrong (data uint64 1 :offset-assert 16) ;; weird, I guess this aligns the data?
(data-buffer uint8 :dynamic :offset 16)
)
(:methods
(new (symbol type int) _type_ 0)
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x18 :size-assert #x18
:flag-assert #x900000018 :flag-assert #x900000018
) )
;;(define-extern reset-path object) ;; unknown type
;;(define-extern reset-graph object) ;; unknown type
;;(define-extern dma-sync object) ;; unknown type
;;(define-extern dma-packet-array object) ;; unknown type
(define-extern dma-buffer-inplace-new (function dma-buffer int dma-buffer))
(define-extern dma-buffer-length (function dma-buffer uint))
(define-extern dma-buffer-free (function dma-buffer int))
;;(define-extern dma-gif-packet object) ;; unknown type
(define-extern dma-buffer-add-vu-function (function dma-buffer vu-function int symbol))
;;(define-extern dma-packet object) ;; unknown type
;;(define-extern dma-buffer object) ;; unknown type
(define-extern dma-buffer-send-chain (function dma-bank-source dma-buffer none))
(define-extern dma-buffer-send (function dma-bank dma-buffer none))
(define-extern dma-bucket-insert-tag (function dma-bucket int dma-bucket (pointer uint64) dma-bucket))
(define-extern dma-buffer-add-buckets (function dma-buffer int none))
(define-extern dma-buffer-patch-buckets (function dma-bucket int int))
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;; dma-disasm ;; dma-disasm
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
(deftype vif-disasm-element (structure) (deftype vif-disasm-element (structure)
((mask uint32 :offset-assert 0) ((mask uint32 :offset-assert 0)
(tag uint32 :offset-assert 4) (tag uint32 :offset-assert 4)
(val uint32 :offset-assert 8) (val uint32 :offset-assert 8)
(print uint32 :offset-assert 12) (print uint32 :offset-assert 12)
(string1 basic :offset-assert 16) (string1 string :offset-assert 16)
(string2 basic :offset-assert 20) (string2 string :offset-assert 20)
) )
:method-count-assert 9 :method-count-assert 9
:size-assert #x18 :size-assert #x18
:flag-assert #x900000018 :flag-assert #x900000018
) )
(define-extern *vif-disasm-table* (array vif-disasm-element)) ;; unknown type
(define-extern disasm-vif-tag function)
(define-extern disasm-dma-tag function)
(define-extern disasm-vif-details (function symbol (pointer uint8) int int int))
(define-extern vif-disasm-element type)
;;(define-extern *dma-disasm* object) ;; unknown type
(define-extern disasm-dma-list function)
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;; pad ;; pad
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
@ -31921,84 +32138,9 @@
(define-extern vector-circle-tangent-new function) (define-extern vector-circle-tangent-new function)
;
;;(define-extern vif-stat object) ;; unknown type
;;(define-extern vif-fbrst object) ;; unknown type
;;(define-extern vif-err object) ;; unknown type
;;(define-extern vif-bank object) ;; unknown type
(define-extern dma-count-until-done function)
;;(define-extern vif-tag object) ;; unknown type
(define-extern dma-send-no-scratch function)
;;(define-extern dma-tag object) ;; unknown type
;;(define-extern dma-chcr object) ;; unknown type
;;(define-extern dma-bank-spr object) ;; unknown type
;;(define-extern dma-bucket object) ;; unknown type
(define-extern dma-sync-with-count function)
;;(define-extern vu-code-block object) ;; unknown type
(define-extern dma-sync-fast function)
;;(define-extern vif-mask object) ;; unknown type
;;(define-extern dma-bank-control object) ;; unknown type
;;(define-extern vif-unpack-imm object) ;; unknown type
;;(define-extern dma-ctrl object) ;; unknown type
;;(define-extern dma-enable object) ;; unknown type
;;(define-extern vu-stat object) ;; unknown type
;;(define-extern dma-bank-source object) ;; unknown type
;;(define-extern dma-bank-vif object) ;; unknown type
;;(define-extern dma-sqwc object) ;; unknown type
;;(define-extern vif-stcycl-imm object) ;; unknown type
;;(define-extern dma-bank object) ;; unknown type
;;(define-extern flush-cache object) ;; unknown type
;;(define-extern *video-parms* object) ;; unknown type
;;(define-extern video-parms object) ;; unknown type
;;(define-extern generic-bucket-state object) ;; unknown type
;;(define-extern *vu1-enable-user-menu* object) ;; unknown type
(define-extern dma-foreground-sink type)
(define-extern dma-foreground-sink-group type)
;;(define-extern *vu1-enable-user* object) ;; unknown type
(define-extern generic-dma-foreground-sink type)
(define-extern reset-vif1-path function)
(define-extern dump-vu1-range function)
(define-extern symlink3 function)
(define-extern dma-sync-crash function)
(define-extern clear-vu0-mem function)
(define-extern dump-vu1-mem function)
(define-extern dma-send-from-spr function)
(define-extern dma-send-to-spr function)
(define-extern dma-sync-hang function)
(define-extern symlink2 function)
(define-extern ultimate-memcpy function)
(define-extern dma-send-to-spr-no-flush function)
(define-extern dma-initialize function)
(define-extern dma-send function)
(define-extern dma-send-chain-no-flush function)
(define-extern clear-vu1-mem function)
(define-extern dma-send-from-spr-no-flush function)
;;(define-extern *video-reset-parm* object) ;; unknown type
(define-extern dma-send-chain function)
(define-extern dma-send-chain-no-tte function)
;;(define-extern reset-path object) ;; unknown type
;;(define-extern reset-graph object) ;; unknown type
;;(define-extern dma-sync object) ;; unknown type
;;(define-extern dma-packet-array object) ;; unknown type
(define-extern dma-buffer-inplace-new function)
(define-extern dma-buffer-length function)
;;(define-extern dma-gif-packet object) ;; unknown type
(define-extern dma-buffer-free function)
(define-extern dma-buffer-add-vu-function function)
;;(define-extern dma-packet object) ;; unknown type
;;(define-extern dma-buffer object) ;; unknown type
(define-extern dma-buffer-send-chain function)
(define-extern dma-buffer-send function)
(define-extern dma-bucket-insert-tag function)
(define-extern dma-buffer-add-buckets function)
(define-extern dma-buffer-patch-buckets function)
;;(define-extern *vif-disasm-table* object) ;; unknown type
(define-extern disasm-vif-tag function)
(define-extern disasm-dma-tag function)
(define-extern disasm-vif-details function)
(define-extern vif-disasm-element type)
;;(define-extern *dma-disasm* object) ;; unknown type
(define-extern disasm-dma-list function)
;;(define-extern error object) ;; unknown type ;;(define-extern error object) ;; unknown type
;;(define-extern details object) ;; unknown type ;;(define-extern details object) ;; unknown type
(define-extern cpad-set-buzz! function) (define-extern cpad-set-buzz! function)

View file

@ -32,7 +32,7 @@
], ],
"(method 2 handle)":[ "(method 2 handle)":[
[10, ["a2", "(pointer process)"]], [10, ["a2", "(pointer process)"]],
[11, ["a3", "process"]], [11, ["a3", "process"]],
[12, ["v1", "int"]], [12, ["v1", "int"]],
[16, ["gp", "int"]] [16, ["gp", "int"]]
@ -77,8 +77,8 @@
"(method 14 dead-pool)":[ "(method 14 dead-pool)":[
// bug in game! // bug in game!
[24, ["v1", "(pointer process-tree)"]], [24, ["v1", "(pointer process-tree)"]],
[30, ["s4", "(pointer process-tree)"]] [30, ["s4", "(pointer process-tree)"]]
], ],
"throw":[ "throw":[
@ -108,16 +108,76 @@
], ],
"string-cat-to-last-char":[ "string-cat-to-last-char":[
[3, ["s5", "(pointer uint8)"]], [3, ["s5", "(pointer uint8)"]],
[4, ["s5", "string"]] [4, ["s5", "string"]]
], ],
"string-strip-trailing-whitespace!":[ "string-strip-trailing-whitespace!":[
[15, ["v1", "(pointer uint8)"]] [15, ["v1", "(pointer uint8)"]]
], ],
"(anon-function 15 hud)":[ "(anon-function 15 hud)":[
[0, ["s6", "hud"]] [0, ["s6", "hud"]]
] ],
"dma-send-to-spr":[
[5, ["s5", "dma-bank-spr"]]],
"dma-send-to-spr-no-flush":[
[5, ["s5", "dma-bank-spr"]]],
"dma-send-from-spr":[
[5, ["s5", "dma-bank-spr"]]],
"dma-send-from-spr-no-flush":[
[5, ["s5", "dma-bank-spr"]]],
"dma-initialize":[
[1, ["v1", "vif-bank"]],
[6, ["a0", "vif-bank"]],
[8, ["v1", "vif-bank"]],
[13, ["a0", "vif-bank"]]],
"clear-vu0-mem":[
[1, ["v1", "(pointer uint32)"]]
],
"clear-vu1-mem":[
[1, ["v1", "(pointer uint32)"]]
],
"dump-vu1-mem":[
[1, ["gp", "(pointer uint32)"]]],
"dump-vu1-range":[
[3, ["s4", "(pointer uint32)"]]],
"ultimate-memcpy":[
[5, ["s3", "dma-bank-spr"],["s4", "dma-bank-spr"]]
],
"dma-buffer-add-vu-function":[
[13, ["v1", "uint"]],
[23, ["t2", "(pointer uint32)"]]
],
"dma-buffer-add-buckets":[
[1, ["v0", "dma-bucket"]],
[5, ["v1", "uint"]],
[6, ["t0", "uint"]],
[9, ["v1", "dma-bucket"]],
[11, ["v1", "uint"]],
[12, ["v1", "dma-bucket"]]
],
"dma-buffer-patch-buckets":[
[7, ["a0", "uint"]],
[11, ["a0", "dma-bucket"]],
[14, ["a0", "uint"]],
[15, ["a0", "dma-bucket"]]
],
"dma-bucket-insert-tag":[
[1, ["a0", "uint"]],
[2, ["v1", "dma-bucket"]]
]
} }

View file

@ -380,6 +380,54 @@
}, },
"ease-in-out":{ "ease-in-out":{
"args":["total", "progress"] "args":["total", "progress"]
},
"dma-send-to-spr":{
"args":["sadr", "madr", "qwc", "sync"]
},
"dma-send-to-spr-no-flush":{
"args":["sadr", "madr", "qwc", "sync"]
},
"dma-send-from-spr":{
"args":["madr", "sadr", "qwc", "sync"]
},
"dma-send-from-spr-no-flush":{
"args":["madr", "sadr", "qwc", "sync"]
},
"dump-vu1-range":{
"args":["start", "total-count"]
},
"ultimate-memcpy":{
"args":["dst", "src", "size-bytes"],
"vars":{"s2-0":"qwc-remaining",
"s1-0":"qwc-transferred-now",
"s4-0":"spr-to-bank",
"s3-0":"spr-from-bank"}
},
"dma-buffer-add-vu-function":{
"args":["dma-buf", "vu-func"],
"vars":{"t1-1":"dma-buf-2", "v1-0":"func-ptr", "a3-0":"qlen", "a1-1":"origin", "t0-1":"qwc-now",
"t2-0":"buf-ptr"}
},
"dma-buffer-add-buckets":{
"args":["dma-buf", "count"],
"vars":{"a2-0":"i", "v1-0":"current-bucket"}
},
"dma-buffer-patch-buckets":{
"args":["bucket", "count"],
"vars":{"v1-1":"i"}
},
"dma-bucket-insert-tag":{
"args":["base", "idx", "tag-start", "tag-end"]
},
"disasm-vif-details":{
"args":["stream", "data", "kind", "count"],
"vars":{"s4-0":"count2", "s3-0":"data-ptr", "s2-0":"i"}
} }
} }

View file

@ -68,20 +68,48 @@
## `trigonometry-h`: **Done** ## `trigonometry-h`: **Done**
- Empty - Empty
## `transformq-h`: ## `transformq-h`: waiting on stack stuff
- Needs stack stuff - Needs stack stuff
## `bounding-box`: ## `bounding-box`: asm
## `matrix`: ## `matrix`: asm
## `transform`: ## `transform`: asm
## `quaternion`: ## `quaternion`: asm
## `euler`: ## `euler`: asm
## `geometry`: ## `geometry`: asm
## `trigonometry`: **Done** ## `trigonometry`: **Done**
- `sincos!` and `sincos-rad!` have a bug where cosine is slightly off - `sincos!` and `sincos-rad!` have a bug where cosine is slightly off
## `gsound-h`: **Done**
## `timer-h`: **Done**
- `timer-init` removed for PC port.
## `timer`: Decompiled, probably needs porting
- Has functions for accessing PS2 timers, needs to be ported to PC. All the logic for stopwatches etc is decopmiled, just the timer reads/writes need to be modified.
## `vif-h`: **Done**
## `dma-h`: **Done**
- DMA sync disabled by default.
## `video-h`: **Done**
## `vu1-user-h`: **Done**
## `dma`: **Done**
- `dma-initialize` disabled on PC.
- Plan is to modify things at a higher level than this for the PC graphics system, most of these functions are non-functional on the PC.
- `ultimate-memcpy` may need to be modified, or we can just swap out code to use the non-`ultimate` version of `memcpy`.
## `dma-buffer`: **Done**
- The sends won't work on PC, but it should let you build the buffer...
## `dma-bucket`: **Done**
- Could clean up some bitfield access, should probably add some features to the compiler to help here.

View file

@ -36,6 +36,8 @@ set(RUNTIME_SOURCE
system/Deci2Server.cpp system/Deci2Server.cpp
sce/libcdvd_ee.cpp sce/libcdvd_ee.cpp
sce/libscf.cpp sce/libscf.cpp
sce/libdma.cpp
sce/libgraph.cpp
sce/deci2.cpp sce/deci2.cpp
sce/sif_ee.cpp sce/sif_ee.cpp
sce/iop.cpp sce/iop.cpp

View file

@ -878,7 +878,7 @@ uint64_t link_resume() {
*/ */
void* ultimate_memcpy(void* dst, void* src, uint32_t size) { void* ultimate_memcpy(void* dst, void* src, uint32_t size) {
// only possible if alignment is good. // only possible if alignment is good.
if (!(u64(dst) & 0xf) && !(u64(src) & 0xf) && !(u64(size) & 0xf)) { if (!(u64(dst) & 0xf) && !(u64(src) & 0xf) && !(u64(size) & 0xf) && size > 0xfff) {
if (!gfunc_774.offset) { if (!gfunc_774.offset) {
// GOAL function is unknown, lets see if its loaded: // GOAL function is unknown, lets see if its loaded:
auto sym = find_symbol_from_c("ultimate-memcpy"); auto sym = find_symbol_from_c("ultimate-memcpy");
@ -887,7 +887,7 @@ void* ultimate_memcpy(void* dst, void* src, uint32_t size) {
} }
gfunc_774.offset = sym->value; gfunc_774.offset = sym->value;
} }
printf("calling goal um\n"); printf("calling goal ultimate-memcpy!\n");
return Ptr<u8>(call_goal(gfunc_774, make_u8_ptr(dst).offset, make_u8_ptr(src).offset, size, return Ptr<u8>(call_goal(gfunc_774, make_u8_ptr(dst).offset, make_u8_ptr(src).offset, size,
s7.offset, g_ee_main_mem)) s7.offset, g_ee_main_mem))
.c(); .c();

View file

@ -24,6 +24,8 @@
#include "game/sce/sif_ee.h" #include "game/sce/sif_ee.h"
#include "game/sce/libcdvd_ee.h" #include "game/sce/libcdvd_ee.h"
#include "game/sce/stubs.h" #include "game/sce/stubs.h"
#include "game/sce/libdma.h"
#include "game/sce/libgraph.h"
#include "common/symbols.h" #include "common/symbols.h"
#include "common/log/log.h" #include "common/log/log.h"
using namespace ee; using namespace ee;

View file

@ -12,9 +12,9 @@
void setup_logging(bool verbose) { void setup_logging(bool verbose) {
lg::set_file(file_util::get_file_path({"log/game.txt"})); lg::set_file(file_util::get_file_path({"log/game.txt"}));
if (verbose) { if (verbose) {
lg::set_file_level(lg::level::info); lg::set_file_level(lg::level::debug);
lg::set_stdout_level(lg::level::info); lg::set_stdout_level(lg::level::debug);
lg::set_flush_level(lg::level::info); lg::set_flush_level(lg::level::debug);
} else { } else {
lg::set_file_level(lg::level::warn); lg::set_file_level(lg::level::warn);
lg::set_stdout_level(lg::level::warn); lg::set_stdout_level(lg::level::warn);

8
game/sce/libdma.cpp Normal file
View file

@ -0,0 +1,8 @@
#include "libdma.h"
namespace ee {
int sceDmaSync(sceDmaChan*, s32, s32) {
// successful transfer finish, without timeout = 0
return 0;
}
} // namespace ee

9
game/sce/libdma.h Normal file
View file

@ -0,0 +1,9 @@
#pragma once
#include "common/common_types.h"
namespace ee {
struct sceDmaChan {};
int sceDmaSync(sceDmaChan* chan, s32 mode, s32 timeout);
} // namespace ee

9
game/sce/libgraph.cpp Normal file
View file

@ -0,0 +1,9 @@
#include "libgraph.h"
#include "common/log/log.h"
namespace ee {
void sceGsResetPath() {}
void sceGsResetGraph(int mode, int inter, int omode, int ffmode) {
lg::warn("sceGsResetGraph: mode {} inter {} omode {} fmode {}\n", mode, inter, omode, ffmode);
}
} // namespace ee

6
game/sce/libgraph.h Normal file
View file

@ -0,0 +1,6 @@
#pragma once
namespace ee {
void sceGsResetPath();
void sceGsResetGraph(int mode, int inter, int omode, int ffmode);
} // namespace ee

View file

@ -19,18 +19,10 @@ void sceGsSyncPath() {
assert(false); assert(false);
} }
void sceGsResetPath() {
assert(false);
}
void sceGsResetGraph() { void sceGsResetGraph() {
assert(false); assert(false);
} }
void sceDmaSync() {
assert(false);
}
void sceGsPutIMR() { void sceGsPutIMR() {
assert(false); assert(false);
} }

View file

@ -10,9 +10,6 @@
namespace ee { namespace ee {
void sceGsSyncV(); void sceGsSyncV();
void sceGsSyncPath(); void sceGsSyncPath();
void sceGsResetPath();
void sceGsResetGraph();
void sceDmaSync();
void sceGsPutIMR(); void sceGsPutIMR();
void sceGsGetIMR(); void sceGsGetIMR();
void sceGsExecStoreImage(); void sceGsExecStoreImage();

View file

@ -5,3 +5,79 @@
;; name in dgo: dma-bucket ;; name in dgo: dma-bucket
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; A dma-bucket is a 16 byte thing that lives in the dma-buffer.
;; buckets live consecutively in the dma-buffer, and can mark the start of a DMA chain
;; location anywhere.
;; The typical process is:
;; - empty buckets are allocated with add-buckets
;; - tags are put somewhere and added to the appropriate bucket with insert-tag, updating last as needed.
;; - buckets are patched to link to each other with dma-buffer-add-buckets.
;; the idea here is that you can build the buckets in whatever order you want, but the buckets
;; will be DMAd in the bucket allocation order.
;; Each bucket contains:
;; a tag, (64-bits), to point to the chain of the bucket
;; last, a pointer to the last tag of this bucket, so the bucket can be patched to point to the next.
(defun dma-buffer-add-buckets ((dma-buf dma-buffer) (count int))
"Add count buckets to the dma buffer. Each bucket is initialized empty."
(local-vars (current-bucket dma-bucket) (i int))
;; grab the first free memory
(set! current-bucket (the dma-bucket (-> dma-buf base)))
(set! i 0)
(while (< i count)
;; also sets next, which points to the memory after this bucket
(set! (-> current-bucket tag)
(the dma-tag (logior
#x20000000
(the-as int (shr (shl (+ (the-as uint current-bucket) 16) 33) 1))
)
)
)
;; nothing in the bucket chain, so our last tag is the bucket tag.
(set! (-> current-bucket last) (the (pointer uint64) current-bucket))
;; advance to next bucket
(set! current-bucket (&+ current-bucket 16))
(set! i (+ i 1))
)
;; update base ptr.
(set! (-> dma-buf base) (the pointer current-bucket))
(none)
)
(defun dma-buffer-patch-buckets ((bucket dma-bucket) (count int))
"Patch last pointers in a sequence of buckets.
Call this after you have added everything to buckets."
(local-vars (i int))
(when (nonzero? bucket)
(set! i 0)
(while (< i count)
;; make last tag of this bucket point to the next bucket.
(set! (-> bucket last 0)
(logior (logand (-> bucket last 0) #x80000000ffffffff)
(shr (shl (+ (the-as uint bucket) 16) 33) 1)
)
)
;; clear last, and move on to the next bucket.
(set! (-> bucket last) (the (pointer uint64) 0))
(set! bucket (&+ bucket 16))
(set! i (+ i 1))
)
)
(the-as int bucket)
)
(defun dma-bucket-insert-tag ((base dma-bucket) (idx int) (tag-start dma-bucket) (tag-end (pointer uint64)))
"Splice in a tag."
(local-vars (bucket dma-bucket))
;; seek to bucket we want to splice before.
(set! bucket (&+ base (shl idx 4)))
;; append to last tag (kind of a hack here with the types)
(set! (-> (the dma-bucket (-> bucket last)) next) (the uint tag-start))
;; make prev = end of tag so we can add more.
(set! (-> bucket last) tag-end)
tag-start
)

View file

@ -5,3 +5,209 @@
;; name in dgo: dma-buffer ;; name in dgo: dma-buffer
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; DMA buffers are used per frame to store DMA data.
;; The dma-buffer manages the memory and dma-bucket organizes the stuff within.
;; The DMA system reads dma-tags. A common trick is to set the dma in tte mode, which transfers
;; the upper 64-bits of the 128-bit "packet" to the VIF, and you can put your vifcode there:
;; Ex:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 32-bit vifcode ;; 32-bit vifcode ;; 64-bit dma-tag ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; in this case, the vifcodes will be sent to the vif, if
;; the dma transfer has tte set.
;; note that the second vifcode can also hold other stuff depending on the mode.
;; first quadword of a DMA with vif packet
(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.
(quad uint128 :offset 0)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;; seems to be unused?
(deftype dma-packet-array (inline-array-class)
()
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(set! (-> dma-packet-array heap-base) 16)
;; For doing a dma -> vif -> gif (path 2) transfer.
(deftype dma-gif-packet (structure)
((dma-vif dma-packet :inline :offset-assert 0)
(gif uint64 2 :offset-assert 16) ;; guess
(quad uint128 2 :offset 0)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
;; dma-buffer holds per-frame data for dma.
;; the allocated-length is in bytes.
;; the base points to the first unused memory in the buffer
;; it is a dynamically sized type.
(deftype dma-buffer (basic)
((allocated-length int32 :offset-assert 4)
(base pointer :offset-assert 8)
(end uint32 :offset-assert 12)
(data uint64 1 :offset-assert 16) ;; weird, I guess this aligns the data?
(data-buffer uint8 :dynamic :offset 16)
)
(:methods
(new (symbol type int) _type_ 0)
)
:method-count-assert 9
:size-assert #x18
:flag-assert #x900000018
)
(defmethod new dma-buffer ((allocation symbol) (type-to-make type) (size int))
"Allocate a new dma-buffer with size bytes of space"
(local-vars (v0-0 dma-buffer))
;; we really get size + 4 bytes I think...
(set! v0-0
(object-new allocation type-to-make
(+ (+ size -4) (the-as int (-> type-to-make size)))
)
)
(set! (-> v0-0 base) (-> v0-0 data))
(set! (-> v0-0 allocated-length) size)
v0-0
)
(defun dma-buffer-inplace-new ((obj dma-buffer) (size int))
"Initialize a DMA buffer in place. Doesn't set the type of the memory"
(set! (-> obj base) (-> obj data))
(set! (-> obj allocated-length) size)
obj
)
(defmethod length dma-buffer ((obj dma-buffer))
"Get the size of the buffer"
(-> obj allocated-length)
)
(defmethod asize-of dma-buffer ((obj dma-buffer))
"Get the size in memory of the object"
(+ (+ (-> obj allocated-length) -4) (the-as int (-> dma-buffer size)))
)
(defun dma-buffer-length ((arg0 dma-buffer))
"Get length used in quadwords, rounded down"
(shr (+ (&- (-> arg0 base) (-> arg0 data)) 15) 4)
)
(defun dma-buffer-free ((arg0 dma-buffer))
"Get the number of free quadwords, rounded down."
(the-as int
(shr (+ (&- (-> arg0 end) (-> arg0 base)) 15) 4)
)
)
(defun dma-buffer-add-vu-function ((dma-buf dma-buffer) (vu-func vu-function) (arg2 int))
"Add DMA chain instructions to load the given VU function to VU program memory.
The destination address in VU memory is specified inside of the vu-function.
if arg2 = 0, then use FLUSHE, otherwise use FLUSHA, I think the runs _before_ the program upload.
Should run with TTE."
(local-vars
(func-ptr uint)
(origin int)
(qlen int)
(qwc-now int)
(dma-buf-2 dma-buffer)
(buf-ptr pointer)
)
;; our strategy is to upload the program in chunks, as we can only upload 127 or 128 quadwords at a time.
;; it is not clear why they did 127 quadword chunks, it seems like 128 would have worked too.
;; the actual data to upload.
(set! func-ptr (the uint (&-> vu-func data 4)))
;; how long it is
(set! qlen (-> vu-func qlength))
;; where to upload to. In 64-bit units because the PS2 is annoying.
(set! origin (-> vu-func origin))
;; while we still have stuff to transfer...
(while (> qlen 0)
;; get up to 127 quadwords. maybe they thought they lost one for the dmatag + 2 vif tags?
(set! qwc-now (min 127 qlen))
(set! dma-buf-2 dma-buf)
;; grab a pointer to the next free memory
(set! buf-ptr (-> dma-buf-2 base))
;; We will add the following tags
;; | 32-bit MPG VIFCode | 32-bit FLUSHX VIFCode | 64-bit DMATag |
;; DMA Tag will the REF - indicating to transfer some other data (the program), then advance to
;; the next quadword in this buffer for the next steps.
;; FLUSHX makes sure the VU isn't running while we upload a program.
;; MPG tells VIF to upload the program to the VU.
;; put in a DMA Tag, REF
(set! (-> (the-as (pointer int64) buf-ptr))
(logior (logior #x30000000 ;; tag id = ref
(shr (shl qwc-now 48) 48)) ;; qwc = qwc-now
(the-as int (shr (shl (the-as uint func-ptr) 33) 1)) ;; addr = func-ptr
)
)
;; VIFCODE - FLUSHE or FLUSHA, wait for previous program to finish?
(set! (-> (the-as (pointer int32) buf-ptr) 2)
(shr (shl (if (zero? arg2) 16 19) 57) 33)
)
;; MPG - Transfers the microgram!
;; sets num to 0, which means 256x 64 bit units, or 128 quadwords.
;; I think this transfers one quadword too many, but it's okay.
(set! (-> (the-as (pointer int32) buf-ptr) 3)
(logior (logior #x4a000000 (shr (shl origin 48) 48))
(shr (shl (shl qwc-now 1) 56) 40)
)
)
;; advance buffer pointer to next quadword.
(set! (-> dma-buf-2 base) (&-> (the (pointer uint32) buf-ptr) 4))
;; advance data pointer
(set! func-ptr (+ func-ptr (the-as uint (shl qwc-now 4))))
;; count down transfered quads
(set! qlen (- qlen qwc-now))
;; source pointer advances by doublewords...
(set! origin (+ origin (shl qwc-now 1)))
)
'#f
)
(defun dma-buffer-send ((chan dma-bank) (buf dma-buffer))
"Send the DMA buffer! DOES NOT TRANSFER TAG."
(when (< (-> buf allocated-length)
(&- (-> buf base) (-> buf data))
)
;; oops. we overflowed the DMA buffer. die.
(segfault)
)
(dma-send
chan
(the-as uint (-> buf data))
(the-as uint (dma-buffer-length buf))
)
)
(defun dma-buffer-send-chain ((chan dma-bank-source) (buf dma-buffer))
"Send the DMA buffer! Sends the tags"
(when (< (-> buf allocated-length)
(&- (-> buf base) (-> buf data))
)
;; oops. we overflowed the DMA buffer. die.
(segfault)
)
(dma-send-chain
chan
(the-as uint (-> buf data))
)
)

View file

@ -5,3 +5,17 @@
;; name in dgo: dma-disasm ;; name in dgo: dma-disasm
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
(deftype vif-disasm-element (structure)
((mask uint32 :offset-assert 0)
(tag uint32 :offset-assert 4)
(val uint32 :offset-assert 8)
(print uint32 :offset-assert 12)
(string1 string :offset-assert 16)
(string2 string :offset-assert 20)
)
:method-count-assert 9
:size-assert #x18
:flag-assert #x900000018
)

View file

@ -5,3 +5,304 @@
;; name in dgo: dma-h ;; name in dgo: dma-h
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; Constants/type for the PS2 DMA System.
;; There are a number of DMA channels.
;; The PS2 supports several types of DMA, including simple chunk transfer and more complicated
;; "chain" transfers, where the hardware can follow a linked data-structure.
;; In OpenGOAL, "DMA" will be instant. By default, DMA syncs will be disabled by this flag.
(defglobalconstant INSTANT_DMA #t)
;; count returned by dma-sync-with-count
;; when instant dma is enabled.
(defglobalconstant INSTANT_DMA_COUNT 123)
;; DMA Channel Control Register. This starts the DMA and can be checked to see if it done.
(deftype dma-chcr (uint32)
((dir uint8 :offset 0 :size 1) ;; 1 - from memory
(mod uint8 :offset 2 :size 2) ;; normal, chain, interleave
(asp uint8 :offset 4 :size 2) ;; none, 1, 2
(tte uint8 :offset 6 :size 1) ;; transfer tag (sc only)
(tie uint8 :offset 7 :size 1) ;; tag interrupt
(str uint8 :offset 8 :size 1) ;; start!
(tag uint16 :offset 16)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(defmethod inspect dma-chcr ((obj dma-chcr))
(format #t "~Tdir: ~D~%" (-> obj dir))
(format #t "~Tmod: ~D~%" (-> obj mod))
(format #t "~Tasp: ~D~%" (-> obj asp))
(format #t "~Ttte: ~D~%" (-> obj tte))
(format #t "~Ttie: ~D~%" (-> obj tie))
(format #t "~Tstr: ~D~%" (-> obj str))
(format #t "~Ttag: #x~X~%" (-> obj tag))
obj
)
;; Most basic DMA register layout
(deftype dma-bank (structure)
((chcr dma-chcr :offset 0) ;; control register
(madr uint32 :offset 16) ;; memory address
(qwc uint32 :offset 32) ;; quadword count
)
:method-count-assert 9
:size-assert #x24
:flag-assert #x900000024
)
;; DMA register layout for channels supporting source-chain
(deftype dma-bank-source (dma-bank)
((tadr uint32 :offset 48) ;; tag address
)
:method-count-assert 9
:size-assert #x34
:flag-assert #x900000034
)
;; The DMA source chain supports a two-entry "call stack" of tags.
;; The tag addresses are stored here.
(deftype dma-bank-vif (dma-bank-source)
((as0 uint32 :offset 64) ;; pushed tag register
(as1 uint32 :offset 80) ;; pushed tag register
)
:method-count-assert 9
:size-assert #x54
:flag-assert #x900000054
)
;; The toSPR and fromSPR DMA channels require a second address in the scratchpad.
;; This is an offset from the start of SPR.
(deftype dma-bank-spr (dma-bank-source)
((sadr uint32 :offset 128) ;; spad address.
)
:method-count-assert 9
:size-assert #x84
:flag-assert #x900000084
)
(defconstant VIF0_DMA_BANK (the dma-bank-vif #x10008000))
(defconstant VIF1_DMA_BANK (the dma-bank-vif #x10009000))
;; gif, ipuFrom, ipTop, sif0, sif1, sif2 believed unused.
(defconstant SPR_FROM_BANK (the dma-bank-spr #x1000d000))
(defconstant SPR_TO_BANK (the dma-bank-spr #x1000d400))
;; D_CTRL, master DMA control register, shraed for all channels.
(deftype dma-ctrl (uint32)
()
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; D_ENABLEW, D_ENABLER?
(deftype dma-enable (uint32)
()
:flag-assert #x900000004
)
;; D_SQWC
(deftype dma-sqwc (uint32)
()
:flag-assert #x900000004
)
;; Shared DMA control registers.
(deftype dma-bank-control (structure)
((ctrl dma-ctrl :offset 0)
(stat uint32 :offset 16)
(pcr uint32 :offset 32)
(sqwc dma-sqwc :offset 48)
(rbsr uint32 :offset 64)
(rbor uint32 :offset 80)
(stadr uint32 :offset 96)
(enabler uint32 :offset 5408)
(enablew uint32 :offset 5520)
)
:method-count-assert 9
:size-assert #x1594
:flag-assert #x900001594
)
(defconstant DMA_CONTROL_BANK (the dma-bank-control #x1000e000))
;; Seems to be unused. The vu-function type is used instead.
(deftype vu-code-block (basic)
((name basic :offset-assert 4)
(code uint32 :offset-assert 8)
(size int32 :offset-assert 12)
(dest-address uint32 :offset-assert 16)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)
;; ?? not sure what this is.
(deftype vu-stat (uint64)
()
:flag-assert #x900000008
)
;; In source chain mode, the DMA controller reads "DMAtag"s to determine addresses
;; sizes, and the next thing to transfer.
;; A tag is 8 bytes.
(deftype dma-tag (uint64)
((qwc uint16 :offset 0) ;; quadword count
(pce uint8 :offset 26 :size 2) ;; priority (source mode)
(id uint8 :offset 28 :size 3) ;; ID (what the tag means)
(irq uint8 :offset 31 :size 1) ;; interrupt at the end?
(addr uint32 :offset 32 :size 31) ;; address (31 bits)
(spr uint8 :offset 63 :size 1) ;; spr or not flag.
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
;; A DMA bucket is a way of organizing data within a dma buffer.
;; The buckets themselves live inside in the dma buffer.
;; the addr field of their tag should point to the next bucket.
;; This is not a PS2 hardware thing
(deftype dma-bucket (structure)
((tag dma-tag :offset-assert 0) ;; the DMA tag to transfer the bucket's data
(last (pointer uint64) :offset-assert 8) ;; the last tag of this bucket.
(dummy uint32 :offset-assert 12) ;; empty space.
(next uint32 :offset 4) ;; this overlaps with the addr bit-field of the dma-tag
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
;; ??
(deftype vif-mask (uint32)
()
:flag-assert #x900000004
)
;; ??
(deftype vif-stcycl-imm (uint16)
()
:flag-assert #x900000002
)
;; ??
(deftype vif-unpack-imm (uint16)
()
:flag-assert #x900000002
)
;; The VIF also has tags to control it.
;; Different VIF commands (called VIFCode) have different tag layouts.
(deftype vif-tag (uint32)
((imm uint16 :offset 0 :size 16)
(num uint8 :offset 16 :size 8)
(cmd uint8 :offset 24 :size 8)
(irq uint8 :offset 31 :size 1) ;;?
(msk uint8 :offset 15 :size 1)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(defmethod inspect vif-tag ((obj vif-tag))
(format #t "~Timm: #x~X~%" (-> obj imm))
(format #t "~Tnum: ~D~%" (-> obj num))
(format #t "~Tcmd: ~D~%" (-> obj cmd))
(format #t "~Tirq: ~D~%" (-> obj irq))
(format #t "~Tmsk: ~D~%" (-> obj msk))
obj
)
;; NOTE: these functions are never called
;; so they are not really modified for x86-64
;; they were inline assembly originally
(defun dma-sync-fast ((bank dma-bank))
"Wait for chcr str to go to 0, indicating DMA
is complete."
(declare (inline))
(#cond
(INSTANT_DMA
;; nothing to do.
0
)
(#t
(while (nonzero? (-> bank chcr str))
;; they had a precise number of nops here.
;; it turns out that spamming the DMA registers is not a good idea
;; because it uses the main bus that the DMA is possibly also trying to use.
(nop!)
)
)
)
(none)
)
(defun dma-send-no-scratch ((bank dma-bank)
(madr uint32)
(qwc uint32))
"Begin a DMA transfer, directly to the bank.
Makes sure any ongoing transfer on the channel is done
Flushes the cache. Sets dir to 0, so I don't expect
this to be used for VIF1 transfers.
Madr should not be a scratchpad address."
((inline dma-sync-fast) bank)
(flush-cache 0)
;; (.sync.l)
(set! (-> bank madr) madr)
(set! (-> bank qwc) qwc)
;; (.sync.l)
;; this seems wrong, the set everything to 0,
;; including dir, which is the to-memory direction
(set! (-> bank chcr)
(new 'static 'dma-chcr :str 1)
)
(none)
)
(defun dma-sync-with-count ((bank dma-bank)
(count (pointer int32)))
"Wait for DMA to finish, incrementing count.
This doesn't seem like a very accurate way
to find out how long it takes..."
(#cond
(INSTANT_DMA
(set! (-> count) INSTANT_DMA_COUNT)
0
)
(#t
(when (nonzero? (-> bank chcr str))
(let ((x (-> count)))
(while (nonzero? (-> bank chcr str))
(+! x 1)
(set! (-> count) x)
)
)
)
0
)
)
)
(defun dma-count-until-done ((bank dma-bank)
(count (pointer int32)))
"Like the previous one, kinda"
(#cond
(INSTANT_DMA
(set! (-> count) INSTANT_DMA_COUNT)
0
)
(#t
(while (nonzero? (-> bank chcr str))
(set! (-> count) (+ 1 (-> count)))
)
)
)
)

View file

@ -5,3 +5,418 @@
;; name in dgo: dma ;; name in dgo: dma
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; DMA send and sync functions:
;; These functions transfer existing DMA chains and buffers.
;; In general, there are two types:
;; - plain transfer of a buffer (like, src, dst, size)
;; - chain, a data structure the PS2 DMA hardware can traverse, just give it a starting address.
;; The plan for OpenGOAL is to patch things higher up, likely in renderers or buffers.
;; So we would replace a (dma-send-chain ...) in a render with
;; (generic-dma-pc-port ...) that will pass the data along to the PC renderer.
;; these functions are just here for completeness and won't work properly on PC.
;; DMA sync functions will succeed and return instantly, so it's safe to leave those in.
(defconstant SPR_FROM_BANK (the dma-bank-spr #x100D000))
(defconstant SPR_TO_BANK (the dma-bank-spr #x1000D400))
(defun dma-sync-hang ((bank dma-bank))
"Hang here until the dma transfer is completed.
This is worse than the dma-sync-fast because it ends
up spamming the DMA bank register more often, and reduces
the speed of the DMA transfer."
(#cond
(INSTANT_DMA
0)
(#t
(while (nonzero? (-> bank chcr str))
(nop!)
)
)
)
(none)
)
(defun dma-sync-crash ((arg0 dma-bank))
"Try to sync DMA for a bit, then crash if we can't"
(local-vars (count int))
(#when INSTANT_DMA
(return 0)
)
(set! count 5000000)
;; checking str
(while (nonzero? (logand (the-as int (-> arg0 chcr)) 256))
(if (zero? count)
(segfault)
(set! count (+ count -1))
)
)
(none)
)
(defun dma-send ((arg0 dma-bank) (madr uint) (qwc uint))
"Send DMA! madr can be a scratchpad address.
Like dma-send-no-scratch, this sets chcr to zero, which may be undesirable."
(dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0)
;;(.sync.l)
(set! (-> arg0 madr)
(logior (logand #xfffffff (the-as int madr)) ;; lower 28 bits are untouched
;; if we are transferring to the scratchpad (at 70000000)
;; we should set bit 31 in madr, per the manual.
(if (= (logand #x70000000 (the-as int madr)) #x70000000)
(shl 32768 16) ;; set bit 31
0)
)
)
(set! (-> arg0 qwc) qwc)
;(.sync.l)
;; set str!
(set! (-> arg0 chcr) (new 'static 'dma-chcr :str 1))
;(.sync.l)
(none)
)
(defun dma-send-chain ((arg0 dma-bank-source) (tadr uint))
"Send DMA! tadr should be a tag address, possibly in spad ram."
(dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0)
;(.sync.l)
(set! (-> arg0 qwc) 0)
;; adjust address
(set! (-> arg0 tadr)
(logior (logand 268435455 (the-as int tadr))
(if (= (logand 1879048192 (the-as int tadr)) 1879048192)
(shl 32768 16)
0)
)
)
;(.sync.l)
;;(set! (-> arg0 chcr) 325)
(set! (-> arg0 chcr)
(new 'static 'dma-chcr
:dir 1 ;; from memory
:mod 1 ;; source chain
:tte 1 ;; send tags
:str 1) ;; go!
)
;(.sync.l)
(none)
)
(defun dma-send-chain-no-tte ((arg0 dma-bank-source) (arg1 uint))
"Send DMA chain! TTE bit is not set, don't transfer tags."
(dma-sync (the-as pointer arg0) 0 0)
(flush-cache 0)
;;(.sync.l)
(set! (-> arg0 qwc) 0)
(set!
(-> arg0 tadr)
(logior
(logand 268435455 (the-as int arg1))
(the-as
uint
(if (= (logand 1879048192 (the-as int arg1)) 1879048192) (shl 32768 16) 0)
)
)
)
;;(.sync.l)
(set! (-> arg0 chcr)
(new 'static 'dma-chcr
:dir 1 ;; from memory
:mod 1 ;; source chain
:tte 0 ;; no tags
:str 1) ;; go!
)
;;(.sync.l)
(none)
)
(defun dma-send-chain-no-flush ((arg0 dma-bank-source) (arg1 uint))
"Send DMA chain! But don't flush the cache, so be careful here. TTE enable."
(local-vars (v0-1 int))
(dma-sync (the-as pointer arg0) 0 0)
(.sync.l)
(set! (-> arg0 qwc) 0)
(set!
(-> arg0 tadr)
(logior
(logand 268435455 (the-as int arg1))
(the-as
uint
(if (= (logand 1879048192 (the-as int arg1)) 1879048192) (shl 32768 16) 0)
)
)
)
;;(.sync.l)
;;(set! (-> arg0 chcr) 325)
(set! (-> arg0 chcr)
(new 'static 'dma-chcr
:dir 1
:mod 1
:tte 1
:str 1)
)
;;(.sync.l)
(set! v0-1 0)
(none)
)
(defun dma-send-to-spr ((sadr uint) (madr uint) (qwc uint) (sync symbol))
"Transfer data to spr"
(local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_TO_BANK)
(dma-sync (the-as pointer s5-0) 0 0)
(flush-cache 0)
(.sync.l)
(set! (-> s5-0 madr) (logand #xFFFFFFF (the-as int madr)))
(set! (-> s5-0 sadr) (logand #xFFFFFFF (the-as int sadr)))
(set! (-> s5-0 qwc) qwc)
;;(.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
(if sync
(dma-sync (the-as pointer s5-0) 0 0))
(none)
)
(defun dma-send-to-spr-no-flush ((sadr uint) (madr uint) (qwc uint) (sync symbol))
"Transfer to spr. Doesn't flush the cache first, so be careful."
(local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_TO_BANK)
(dma-sync (the-as pointer s5-0) 0 0)
;;(.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr)))
(set! (-> s5-0 qwc) qwc)
;;(.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0))
(none)
)
(defun dma-send-from-spr ((madr uint) (sadr uint) (qwc uint) (sync symbol))
"Transfer from spr."
(local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_FROM_BANK)
(dma-sync (the-as pointer s5-0) 0 0)
(flush-cache 0)
;;(.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr)))
(set! (-> s5-0 qwc) qwc)
;;(.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0))
(none)
)
(defun dma-send-from-spr-no-flush ((madr uint) (sadr uint) (qwc uint) (sync symbol))
"Transfer from spr, don't flush the cache."
(local-vars (s5-0 dma-bank-spr))
(set! s5-0 SPR_FROM_BANK)
(dma-sync (the-as pointer s5-0) 0 0)
;;(.sync.l)
(set! (-> s5-0 madr) (logand 268435455 (the-as int madr)))
(set! (-> s5-0 sadr) (logand 268435455 (the-as int sadr)))
(set! (-> s5-0 qwc) qwc)
;;(.sync.l)
(set! (-> s5-0 chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
(if sync (dma-sync (the-as pointer s5-0) 0 0))
(none)
)
(defun dma-initialize ()
"Due to a bug in the PS2 hardware, you must always disable the DMAtag mismatch
error. This is done here."
(#when PC_PORT
(format 0 "[dma.gc] skipping dma-initialize for PC port~%")
(return 0)
)
(set! (-> VIF0_BANK err)
(logior (logand (-> VIF0_BANK err) (the-as uint -3)) 2)
)
(set! (-> (the vif-bank #x10003c00) err)
(logior (logand (-> VIF1_BANK err) (the-as uint -3)) 2)
)
(none)
)
(defun clear-vu0-mem ()
"Clear the data memory of VU0, filling it with abadbeef
This uses the slow memory mapping of VU0's data memory at 0x11004000"
(local-vars
(v1-0 (pointer uint32))
(a0-0 int)
)
(set! v1-0 (the (pointer uint32) #x11004000))
(set! a0-0 0)
(while (< a0-0 1024)
(set! (-> v1-0 a0-0) #xabadbeef)
(set! a0-0 (+ a0-0 1))
)
(none)
)
(defun clear-vu1-mem ()
"Clear the data memory of VU1, filling it with abadbeef
This uses the slow memory mapping of VU0's data memory at 0x11004000"
(local-vars
(v1-0 (pointer uint32))
(a0-0 int)
)
(set! v1-0 (the (pointer uint32) #x1100c000))
(set! a0-0 0)
(while (< a0-0 4096)
(set! (-> v1-0 a0-0) #xabadbeef)
(set! a0-0 (+ a0-0 1))
)
(none)
)
(defun dump-vu1-mem ()
"Print VU1 memory to runtime stdout."
(local-vars (s5-0 int) (gp-0 (pointer uint32)))
(set! gp-0 (the (pointer uint32) #x1100c000))
(set! s5-0 0)
(while (< s5-0 1024) ;; 1k quadwords
(format 0 "~4,'0X: ~8,'0X ~8,'0X ~8,'0X ~8,'0X"
s5-0
(-> gp-0 (shl s5-0 2))
(-> gp-0 (+ (shl s5-0 2) 1))
(-> gp-0 (+ (shl s5-0 2) 2))
(-> gp-0 (+ (shl s5-0 2) 3))
)
(format 0 " ~F ~F ~F ~F ~%"
(-> gp-0 (shl s5-0 2))
(-> gp-0 (+ (shl s5-0 2) 1))
(-> gp-0 (+ (shl s5-0 2) 2))
(-> gp-0 (+ (shl s5-0 2) 3))
)
(set! s5-0 (+ s5-0 1))
)
(none)
)
(defun dump-vu1-range ((start uint) (total-count uint))
"Print part of VU1 memory to runtime stdout."
(local-vars (s3-0 int) (s2-0 int) (s4-0 (pointer uint32)))
(set! s4-0 (the (pointer uint32) #x1100c000))
(set! s3-0 0)
(while (< s3-0 (the-as int total-count))
(set! s2-0 (+ s3-0 (the-as int start)))
(format 0 "~4,'0X: ~8x ~8x ~8x ~8x"
s2-0
(-> s4-0 (shl s2-0 2))
(-> s4-0 (+ (shl s2-0 2) 1))
(-> s4-0 (+ (shl s2-0 2) 2))
(-> s4-0 (+ (shl s2-0 2) 3))
)
(format 0 " ~F ~F ~F ~F ~%"
(-> s4-0 (shl s2-0 2))
(-> s4-0 (+ (shl s2-0 2) 1))
(-> s4-0 (+ (shl s2-0 2) 2))
(-> s4-0 (+ (shl s2-0 2) 3))
)
(set! s3-0 (+ s3-0 1))
)
'#f
)
;; if we send junk DMA data due to an engine bug, the PS2 will eventually time out the transfer.
;; in this case, the main loop will attempt to reset everything to hopefully recover.
;; this value is the PAL/NTSC constant for the Sony reset functions.
;; if we switch PAL/NTSC during runtime, we should update this.
(define *video-reset-parm* 2)
(defun reset-vif1-path ()
"When things go wrong, totally reset vif1."
;; inspect the banks
(#unless PC_PORT
((method-of-type dma-bank-vif inspect) VIF1_DMA_BANK)
((method-of-type vif-bank inspect) VIF1_BANK)
)
;; sceGsResetPath
(reset-path)
;; sceGsResetGraph
(reset-graph 1 1 *video-reset-parm* 1)
(format 0 "gkernel: vif1 path reset!~%")
(none)
)
(defun ultimate-memcpy ((dst pointer) (src pointer) (size-bytes uint))
"Fast memcpy using the scratchpad. Will blow away everything in scratch.
Rounds to nearest quadword for size, dst and source should be aligned 16-bytes."
(local-vars
(qwc-transferred-now uint)
(qwc-remaining uint)
(spr-from-bank dma-bank-spr)
(spr-to-bank dma-bank-spr)
)
(set! spr-to-bank (the dma-bank-spr #x1000d400))
(set! spr-from-bank (the dma-bank-spr #x1000d000))
(set! qwc-remaining (shr size-bytes 4))
(flush-cache 0)
(dma-sync (the-as pointer spr-to-bank) 0 0)
(dma-sync (the-as pointer spr-from-bank) 0 0)
(while (> qwc-remaining 0)
;; figure out how much to transfer, limited by 1024 quadword size of spad.
(set! qwc-transferred-now qwc-remaining)
(when (< (the-as uint 1024) qwc-transferred-now)
(set! qwc-transferred-now (the uint 1024))
)
(set! qwc-remaining (- qwc-remaining (the-as uint qwc-transferred-now)))
;;(.sync.l)
;; set up dma
(set! (-> spr-to-bank madr) (the uint src))
(set! (-> spr-to-bank sadr) 0)
(set! (-> spr-to-bank qwc) qwc-transferred-now)
;;(.sync.l)
;; start dma
(set! (-> spr-to-bank chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
;; sync
(dma-sync (the-as pointer spr-to-bank) 0 0)
;; advance source pointer.
(set! src (&+ src (the-as uint (shl qwc-transferred-now 4))))
;; setup transfer back
(set! (-> spr-from-bank madr) (the uint dst))
(set! (-> spr-from-bank sadr) 0)
(set! (-> spr-from-bank qwc) qwc-transferred-now)
;; transfer!
;;(.sync.l)
(set! (-> spr-from-bank chcr) (new 'static 'dma-chcr :str 1))
;;(.sync.l)
;; sync!
(dma-sync (the-as pointer spr-from-bank) 0 0)
;; advance dst.
(set! dst (&+ dst (the-as uint (shl qwc-transferred-now 4))))
)
(none)
)
(defun symlink2 ()
"symlink2 is a handwritten assembly version of the v2 linking routine.
it is not ported because the OpenGOAL linker has its own implementation already."
(segfault)
(none)
)
(defun symlink3 ()
"symlink3 is a handwritten assembly version of the v3 linking routine.
OpenGOAL uses a different format for v3, customized for x86-64, so this is not
needed. The C++ implementation is plenty fast enough"
(segfault)
(none)
)
;; configuration required to work around hardware bug.
;; doesn't do anything important
(dma-initialize)

View file

@ -5,3 +5,45 @@
;; name in dgo: video-h ;; name in dgo: video-h
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
(deftype video-parms (structure)
((set-video-mode basic :offset-assert 0)
(reset-video-mode basic :offset-assert 4)
(screen-sy int32 :offset-assert 8)
(screen-hy int32 :offset-assert 12)
(screen-miny int32 :offset-assert 16)
(screen-maxy int32 :offset-assert 20)
(screen-masky int32 :offset-assert 24)
(display-dx int32 :offset-assert 28)
(display-dy int32 :offset-assert 32)
(screen-pages-high int32 :offset-assert 36)
(_pad int64)
(relative-x-scale float :offset-assert 48)
(relative-y-scale float :offset-assert 52)
(_pad2 int64)
(relative-x-scale-reciprical float :offset-assert 64)
(relative-y-scale-reciprical float :offset-assert 68)
)
:method-count-assert 9
:size-assert #x48
:flag-assert #x900000048
)
(define *video-parms*
(new 'static 'video-parms
:set-video-mode #f
:reset-video-mode #f
:screen-sy 224
:screen-hy 112
:screen-miny 1824
:screen-maxy 2272
:screen-masky #xdf
:display-dx 0
:display-dy 8
:screen-pages-high 7
:relative-x-scale 1.0
:relative-y-scale 1.0
:relative-x-scale-reciprical 1.0
:relative-y-scale-reciprical 0.0 ;; ??
)
)

View file

@ -5,3 +5,56 @@
;; name in dgo: vu1-user-h ;; name in dgo: vu1-user-h
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; VU1 renderers are enabled/disabled with a bitmask.
;; I believe this is renderers which can be enabled/disabled in the debug menu?
(define *vu1-enable-user-menu*
#x1FFFF8)
;; by default, all off.
;; the menu renderers get copied to this on each frame
(define *vu1-enable-user* 0)
;; a dma "sink" is somewhere where a renderer can put stuff.
(deftype dma-foreground-sink (basic)
((bucket int32 :offset-assert 4) ;; not sure if this is a bucket index or pointer?
(foreground-texture-page int8 :offset-assert 8) ;; ?
(foreground-texture-level int8 :offset-assert 9) ;; ?
(foreground-output-bucket int8 :offset-assert 10) ;; ?
)
:method-count-assert 9
:size-assert #xb
:flag-assert #x90000000b
)
;; additional info for the generic renderer
(deftype generic-bucket-state (structure)
((gifbuf-adr uint32 :offset-assert 0)
(inbuf-adr uint32 :offset-assert 4)
)
:pack-me
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
;; sink for the generic renderer, a normal sink + extra data.
(deftype generic-dma-foreground-sink (dma-foreground-sink)
((state generic-bucket-state :inline :offset-assert 12)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)
;; group of sinks used for the foreground renderers.
(deftype dma-foreground-sink-group (basic)
((sink dma-foreground-sink 3 :offset-assert 4)
(merc-sink dma-foreground-sink :offset 4)
(generic-sink generic-dma-foreground-sink :offset 8)
(level basic :offset-assert 16)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)

View file

@ -76,7 +76,9 @@
) )
;; segfaults OpenGOAL as it does not support ps2 EE timers ;; segfaults OpenGOAL as it does not support ps2 EE timers
; (timer-init (the-as timer-bank EE_TIMER1) (the-as timer-mode #x82)) (#unless PC_PORT
(timer-init (the-as timer-bank EE_TIMER1) (the-as timer-mode #x82))
)
(deftype profile-frame (structure) (deftype profile-frame (structure)

View file

@ -5,3 +5,96 @@
;; name in dgo: vif-h ;; name in dgo: vif-h
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; Types related to VIF: the PS2's Vector Interface.
;; Each of VU0 and VU1 has a VIF which is used to sent/receive data.
;; The VIFs are controller by registers and fed data using DMA
;;VIF0_STAT or VIF1_STAT bitfields
(deftype vif-stat (uint32)
((vps uint8 :offset 0 :size 2)
(vew uint8 :offset 2 :size 1)
(mrk uint8 :offset 6 :size 1)
(vss uint8 :offset 8 :size 1)
(vfs uint8 :offset 9 :size 1)
(vis uint8 :offset 10 :size 1)
(int uint8 :offset 11 :size 1)
(er0 uint8 :offset 12 :size 1)
(er1 uint8 :offset 13 :size 1)
(fqc uint8 :offset 24 :size 4)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(defmethod inspect vif-stat ((obj vif-stat))
(format #t "~Tvps: ~D" (-> obj vps))
(format #t "~Tvew: ~D" (-> obj vew))
(format #t "~Tmrk: ~D" (-> obj mrk))
(format #t "~Tvss: ~D" (-> obj vss))
(format #t "~Tvfs: ~D" (-> obj vfs))
(format #t "~Tvis: ~D" (-> obj vis))
(format #t "~Tint: ~D" (-> obj int))
(format #t "~Ter0: ~D" (-> obj er0))
(format #t "~Ter1: ~D" (-> obj er1))
(format #t "~Tfqc: ~D" (-> obj fqc))
obj)
;; VIF "reset" register.
(deftype vif-fbrst (uint32)
((rst uint8 :offset 0 :size 1)
(fbk uint8 :offset 1 :size 1)
(stp uint8 :offset 2 :size 1)
(stc uint8 :offset 3 :size 1)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Error mask register
(deftype vif-err (uint32)
((mii uint8 :offset 0 :size 1)
(me0 uint8 :offset 1 :size 1) ;; PS2 hardware bug, must set this to 1 for correct operation.
(me1 uint8 :offset 2 :size 1)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; Common layout of hardware registers shared between the two VIFs
(deftype vif-bank (structure)
((stat uint32 :offset-assert 0)
(fbrst uint32 :offset 16)
(err uint32 :offset 32)
(mark uint32 :offset 48)
(cycle uint32 :offset 64)
(mode uint32 :offset 80)
(num uint32 :offset 96)
(mask uint32 :offset 112)
(code uint32 :offset 128)
(itops uint32 :offset 144)
(base uint32 :offset 160)
(offset uint32 :offset 176)
(tops uint32 :offset 192)
(itop uint32 :offset 208)
(top uint32 :offset 224)
(r0 uint32 :offset 256)
(r1 uint32 :offset 272)
(r2 uint32 :offset 288)
(r3 uint32 :offset 304)
(c0 uint32 :offset 320)
(c1 uint32 :offset 336)
(c2 uint32 :offset 352)
(c3 uint32 :offset 368)
)
:method-count-assert 9
:size-assert #x174
:flag-assert #x900000174
)
;; PS2 VIF map. There are no VIFs in OpenGOAL.
(defconstant VIF0_BANK (the vif-bank #x10003800))
(defconstant VIF1_BANK (the vif-bank #x10003c00))

View file

@ -5,3 +5,352 @@
;; name in dgo: gsound-h ;; name in dgo: gsound-h
;; dgos: GAME, ENGINE ;; dgos: GAME, ENGINE
;; Type definitions for sound.
;; The actual sound code is all on the IOP, and the EE can send RPCs to control.
;; There is also some sort of per-frame status update, that is not included here.
(deftype sound-id (uint32)
()
(:methods
(dummy-9 () none 9)
)
:flag-assert #xa00000004
)
(deftype sound-bank-id (uint32)
()
:flag-assert #x900000004
)
;; Sound names were sometimes packed into a uint128
(deftype sound-name (uint128)
()
:flag-assert #x900000010
)
;; like should match the sound type in OVERLORD
;; This is shared between all sound RPCs.
(deftype sound-rpc-cmd (structure)
((rsvd1 uint16 :offset-assert 0)
(command uint16 :offset-assert 2)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(deftype sound-play-parms (structure)
((mask uint16 :offset-assert 0)
(pitch-mod int16 :offset-assert 2)
(bend int16 :offset-assert 4)
(fo-min int16 :offset-assert 6)
(fo-max int16 :offset-assert 8)
(fo-curve int8 :offset-assert 10)
(priority int8 :offset-assert 11)
(volume int32 :offset-assert 12)
(trans float 3 :offset-assert 16) ;; guess on type here
(group uint8 :offset-assert 28)
)
:pack-me
:method-count-assert 9
:size-assert #x1d
:flag-assert #x90000001d
)
(deftype sound-rpc-bank-cmd (sound-rpc-cmd)
((bank-name uint128 :offset-assert 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype sound-rpc-sound-cmd (sound-rpc-cmd)
((id uint32 :offset-assert 4)
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(deftype sound-rpc-group-cmd (sound-rpc-cmd)
((group uint8 :offset-assert 4)
)
:method-count-assert 9
:size-assert #x5
:flag-assert #x900000005
)
(deftype sound-rpc-load-bank (sound-rpc-bank-cmd)
()
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype sound-rpc-load-music (sound-rpc-bank-cmd)
()
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype sound-rpc-unload-bank (sound-rpc-bank-cmd)
()
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype sound-rpc-play (sound-rpc-sound-cmd)
((name uint128 :offset-assert 16)
(parms sound-play-parms :inline :offset-assert 32)
)
:method-count-assert 9
:size-assert #x3d
:flag-assert #x90000003d
)
(deftype sound-rpc-pause-sound (sound-rpc-sound-cmd)
()
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(deftype sound-rpc-stop-sound (sound-rpc-sound-cmd)
()
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(deftype sound-rpc-continue-sound (sound-rpc-sound-cmd)
()
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(deftype sound-rpc-set-param (sound-rpc-sound-cmd)
((parms sound-play-parms :inline :offset-assert 8)
(auto-time int32 :offset-assert 40)
(auto-from int32 :offset-assert 44)
)
:method-count-assert 9
:size-assert #x30
:flag-assert #x900000030
)
(deftype sound-rpc-set-master-volume (sound-rpc-group-cmd)
((volume int32 :offset-assert 8)
)
:method-count-assert 9
:size-assert #xc
:flag-assert #x90000000c
)
(deftype sound-rpc-pause-group (sound-rpc-group-cmd)
()
:method-count-assert 9
:size-assert #x5
:flag-assert #x900000005
)
(deftype sound-rpc-stop-group (sound-rpc-group-cmd)
()
:method-count-assert 9
:size-assert #x5
:flag-assert #x900000005
)
(deftype sound-rpc-continue-group (sound-rpc-group-cmd)
()
:method-count-assert 9
:size-assert #x5
:flag-assert #x900000005
)
(deftype sound-rpc-get-irx-version (sound-rpc-cmd)
((major uint32 :offset-assert 4)
(minor uint32 :offset-assert 8)
(ee-addr uint32 :offset-assert 12)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype sound-rpc-set-language (sound-rpc-cmd)
((lang uint32 :offset-assert 4)
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
(deftype sound-rpc-set-falloff-curve (sound-rpc-cmd)
((curve int32 :offset-assert 4)
(falloff int32 :offset-assert 8)
(ease int32 :offset-assert 12)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
)
(deftype sound-rpc-set-sound-falloff (sound-rpc-cmd)
((name uint128 :offset-assert 16)
(curve int32 :offset-assert 32)
(min int32 :offset-assert 36)
(max int32 :offset-assert 40)
)
:method-count-assert 9
:size-assert #x2c
:flag-assert #x90000002c
)
(deftype sound-rpc-reload-info (sound-rpc-cmd)
()
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(deftype sound-rpc-set-reverb (sound-rpc-cmd)
((core uint8 :offset-assert 4)
(reverb int32 :offset-assert 8)
(left uint32 :offset-assert 12)
(right uint32 :offset-assert 16)
)
:method-count-assert 9
:size-assert #x14
:flag-assert #x900000014
)
(deftype sound-rpc-set-ear-trans (sound-rpc-cmd)
((ear-trans float 3 :offset-assert 4) ;; guess on float, may be fixed point
(cam-trans float 3 :offset-assert 16)
(cam-angle int32 :offset-assert 28)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
)
(deftype sound-rpc-set-flava (sound-rpc-cmd)
((flava uint8 :offset-assert 4)
)
:method-count-assert 9
:size-assert #x5
:flag-assert #x900000005
)
(deftype sound-rpc-shutdown (sound-rpc-cmd)
()
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(deftype sound-rpc-list-sounds (sound-rpc-cmd)
()
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(deftype sound-rpc-unload-music (sound-rpc-cmd)
()
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; union of all the possible sound commands.
(deftype sound-rpc-union (structure)
((data uint32 20 :offset-assert 0)
(load-bank sound-rpc-load-bank :offset 0)
(unload-bank sound-rpc-unload-bank :offset 0)
(play sound-rpc-play :offset 0)
(pause-sound sound-rpc-pause-sound :offset 0)
(stop-sound sound-rpc-stop-sound :offset 0)
(continue-sound sound-rpc-continue-sound :offset 0)
(set-param sound-rpc-set-param :offset 0)
(set-master-volume sound-rpc-set-master-volume :offset 0)
(pause-group sound-rpc-pause-group :offset 0)
(stop-group sound-rpc-stop-group :offset 0)
(continue-group sound-rpc-continue-group :offset 0)
(get-irx-version sound-rpc-get-irx-version :offset 0)
(set-falloff-curve sound-rpc-set-falloff-curve :offset 0)
(set-sound-falloff sound-rpc-set-sound-falloff :offset 0)
(reload-info sound-rpc-reload-info :offset 0)
(set-language sound-rpc-set-language :offset 0)
(set-reverb sound-rpc-set-reverb :offset 0)
(set-ear-trans sound-rpc-set-ear-trans :offset 0)
(set-flava sound-rpc-set-flava :offset 0)
(shutdown sound-rpc-shutdown :offset 0)
(list-sounds sound-rpc-list-sounds :offset 0)
(unload-music sound-rpc-unload-music :offset 0)
)
:method-count-assert 9
:size-assert #x50
:flag-assert #x900000050
)
(deftype sound-spec (basic)
((mask uint16 :offset-assert 4)
(num float :offset-assert 8)
(group uint8 :offset-assert 12)
(sound-name-char uint8 16 :offset 16)
(sound-name uint128 :offset 16)
(trans float 4 :offset-assert 32) ;; guess
(volume int32 :offset-assert 48)
(pitch-mod int32 :offset-assert 52)
(bend int32 :offset-assert 56)
(fo-min int16 :offset-assert 60)
(fo-max int16 :offset-assert 62)
(fo-curve int8 :offset-assert 64)
(priority int8 :offset-assert 65)
(auto-time int32 :offset-assert 68)
(auto-from int32 :offset-assert 72)
)
:method-count-assert 9
:size-assert #x4c
:flag-assert #x90000004c
)
(define *current-sound-id* (the sound-id 65536))
(deftype ambient-sound (basic)
((spec basic :offset-assert 4)
(playing-id uint32 :offset-assert 8)
(trans vector :inline :offset-assert 16)
(name uint128 :offset-assert 32)
(play-time uint64 :offset-assert 48)
(time-base uint64 :offset-assert 56)
(time-random uint64 :offset-assert 64)
(volume int32 :offset-assert 72)
(pitch int32 :offset-assert 76)
(falloff-near int32 :offset-assert 80)
(falloff-far int32 :offset-assert 84)
(falloff-mode int32 :offset-assert 88)
(params uint32 :offset-assert 92)
(param-count int32 :offset-assert 96)
(entity basic :offset-assert 100)
(sound-count int32 :offset-assert 104)
)
:method-count-assert 14
:size-assert #x6c
:flag-assert #xe0000006c
(:methods
(dummy-9 () none 9)
(dummy-10 () none 10)
(dummy-11 () none 11)
(dummy-12 () none 12)
(dummy-13 () none 13)
)
)
(define *sound-bank-1* #f)
(define *sound-bank-2* #f)

View file

@ -114,13 +114,14 @@
;; put-display-env ;; put-display-env
;; syncv ;; syncv
;; sync-path ;; sync-path
;; reset-path (define-extern reset-path (function none))
;; rest-graph (define-extern reset-graph (function int int int int none))
;; dma-sync ;; dma-sync
(define-extern dma-sync (function pointer int int int))
;; gs-put-imr ;; gs-put-imr
;; gs-get-imr ;; gs-get-imr
;; gs-store-image ;; gs-store-image
;; flush-cache (define-extern flush-cache (function int none))
;; cpad-open ;; cpad-open
;; cpad-get-data ;; cpad-get-data
;; install-handler ;; install-handler

View file

@ -20,6 +20,8 @@
(defconstant RELOC_METHOD_ID 7) ;; or login? (defconstant RELOC_METHOD_ID 7) ;; or login?
(defconstant MEM_USAGE_METHOD_ID 8) (defconstant MEM_USAGE_METHOD_ID 8)
(defglobalconstant PC_PORT #t)
;; distance from a symbol pointer to a (pointer string) ;; distance from a symbol pointer to a (pointer string)
;; this relies on the memory layout of the symbol table ;; this relies on the memory layout of the symbol table
;; this must match SYM_INFO_OFFSET in goal_constants.h + offset of the str field in struct SymUpper. ;; this must match SYM_INFO_OFFSET in goal_constants.h + offset of the str field in struct SymUpper.

View file

@ -9,13 +9,9 @@ using namespace goos;
bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest) { bool Compiler::try_getting_macro_from_goos(const goos::Object& macro_name, goos::Object* dest) {
Object macro_obj; Object macro_obj;
bool got_macro = false; bool got_macro = false;
try { if (m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env(), &macro_obj) &&
macro_obj = m_goos.eval_symbol(macro_name, m_goos.goal_env.as_env()); macro_obj.is_macro()) {
if (macro_obj.is_macro()) { got_macro = true;
got_macro = true;
}
} catch (std::runtime_error& e) {
got_macro = false;
} }
if (got_macro) { if (got_macro) {

View file

@ -779,7 +779,8 @@ Val* Compiler::compile_static_new(const goos::Object& form,
} }
throw_compiler_error(form, throw_compiler_error(form,
"Cannot do a static new of a {} because it is not a bitfield or structure."); "Cannot do a static new of a {} because it is not a bitfield or structure.",
type.print());
return get_none(); return get_none();
} }

View file

@ -0,0 +1,59 @@
import os
import glob
import argparse
### Script to track decompilation progress.
### Example usage: python3 scripts/decomp_progress.py ~/jak-project/goal_src
def get_goal_files(root_dir):
"""Get all GOAL source files under root_dir"""
return [goal_file for file in os.walk(root_dir) for goal_file in glob.glob(os.path.join(file[0], '*.gc'))]
def lines_in_file(file_path):
with open(file_path) as f:
lines = 0
for _ in f:
lines += 1
return lines
def print_table(stats):
total_lines = 0
print("| {: <24} | {: <6} |".format("file name", "lines"))
print("-------------------------------------")
for x in stats:
print(" {: <24} | {: >6} |".format(x[0], x[1]))
total_lines += x[1]
print("-------------------------------------")
print("| {: <24} | {: >6} |".format("TOTAL", total_lines))
print("-------------------------------------")
estimated_lines = 500000
print("Progress: {}/{} lines ({:.2f}%)".format(total_lines, estimated_lines, 100. * total_lines / estimated_lines))
def main():
parser = argparse.ArgumentParser()
parser.add_argument(dest='goal_src', help='the goal_src folder')
args = parser.parse_args()
all_files = get_goal_files(args.goal_src)
file_stats = []
excluded_files = {"all_files.gc", "goal-lib.gc"}
for fn in all_files:
short_name = os.path.basename(fn)
line_count = lines_in_file(fn)
if line_count == 7 or short_name in excluded_files:
# the template has 7 lines, just skip it.
continue
file_stats.append((short_name, line_count))
file_stats.sort(key=lambda x: x[1])
print_table(file_stats)
if __name__ == "__main__":
main()

View file

@ -465,13 +465,13 @@ TEST(DecompilerAtomicOpBuilder, LHU) {
} }
TEST(DecompilerAtomicOpBuilder, LUI) { TEST(DecompilerAtomicOpBuilder, LUI) {
test_case(assembly_from_list({"lui a3, 2"}), {"(set! a3 131072)"}, {{"a3"}}, {{}}, {{}}); test_case(assembly_from_list({"lui a3, 2"}), {"(set! a3 #x20000)"}, {{"a3"}}, {{}}, {{}});
} }
TEST(DecompilerAtomicOpBuilder, LUI_ORI) { TEST(DecompilerAtomicOpBuilder, LUI_ORI) {
test_case(assembly_from_list({"L100:", "lui a0, 2", "ori a1, a0, 3"}), {"(set! a1 131075)"}, test_case(assembly_from_list({"L100:", "lui a0, 2", "ori a1, a0, 3"}), {"(set! a1 #x20003)"},
{{"a1"}}, {{}}, {{"a0"}}); {{"a1"}}, {{}}, {{"a0"}});
test_case(assembly_from_list({"L100:", "lui a0, 2", "ori a0, a0, 3"}), {"(set! a0 131075)"}, test_case(assembly_from_list({"L100:", "lui a0, 2", "ori a0, a0, 3"}), {"(set! a0 #x20003)"},
{{"a0"}}, {{}}, {{}}); {{"a0"}}, {{}}, {{}});
test_case(assembly_from_list({"L100:", "lui a0, L100", "ori a1, a0, L100"}), {"(set! a1 L100)"}, test_case(assembly_from_list({"L100:", "lui a0, L100", "ori a1, a0, L100"}), {"(set! a1 L100)"},
{{"a1"}}, {{}}, {{"a0"}}); {{"a1"}}, {{}}, {{"a0"}});

View file

@ -871,7 +871,8 @@ TEST(GoosLib, Desfun) {
TEST(GoosLib, Factorial) { TEST(GoosLib, Factorial) {
Interpreter i; Interpreter i;
EXPECT_EQ(e(i, "(factorial 10)"), "3628800"); // now large numbers are printed as hex.
EXPECT_EQ(e(i, "(factorial 10)"), "#x375f00");
} }
TEST(GoosLib, ApplySimple) { TEST(GoosLib, ApplySimple) {