diff --git a/common.py b/common.py index a0942ee0..7702845f 100644 --- a/common.py +++ b/common.py @@ -409,8 +409,22 @@ JSYSTEM_BASE = [ "-sym on", # might also be on for base flags? "-O4,s" # in mkdd some libraries use O4,p, might be the case here too ] +JSYSTEM_JGADGET_BASE = [ + "-lang=c++", + "-inline on", + "-fp fmadd", + #"-fp_contract on", + #"-pool off", # this is wrong + "-Cpp_exceptions off", + "-RTTI on", + "-char signed", + "-enum int", + # "-sym on", # might also be on for base flags? + "-O4,s" # in mkdd some libraries use O4,p, might be the case here too +] JSYSTEM_CFLAGS = ' '.join(JSYSTEM_BASE + LOCAL_CFLAGS) +JSYSTEM_JGADGET_CFLAGS = ' '.join(JSYSTEM_JGADGET_BASE + LOCAL_CFLAGS) DOL_CFLAGS = ' '.join(BASE_DOL_CFLAGS + LOCAL_CFLAGS) DOL_BOOT_CFLAGS = ' '.join(BOOT_CFLAGS + LOCAL_CFLAGS) DOL_DVDERR_CFLAGS = ' '.join(DVDERR_CFLAGS + LOCAL_CFLAGS) diff --git a/config/dol_slices.yml b/config/dol_slices.yml index c36022c8..119c166f 100644 --- a/config/dol_slices.yml +++ b/config/dol_slices.yml @@ -230,6 +230,8 @@ JSystem/JSupport/JSUInputStream.cpp: # .text: [0x8006e3e4, 0x8006e604] # .data: [0x800dedb8, 0x800dee60] # .sdata: [0x80218068, 0x80218088] +JSystem/JGadget/linklist.cpp: + .text: [0x8006e604, 0x8006e800] JSystem/JUtility/JUTGamePad.cpp: .text: [0x80070274, 0x800713b0] .ctors: [0x800a97ac, 0x800a97b0] diff --git a/configure.py b/configure.py index 94f2df41..4b4830fb 100644 --- a/configure.py +++ b/configure.py @@ -618,6 +618,9 @@ class CSource(Source): if path.startswith("src/dolphin/"): self.cflags = c.SDK_FLAGS self.cc = c.OCC + elif path.startswith("src/JSystem/JGadget/"): + self.cflags = c.JSYSTEM_JGADGET_CFLAGS + self.cc = c.CC elif path.startswith("src/JSystem/"): self.cflags = c.JSYSTEM_CFLAGS self.cc = c.CC diff --git a/include/JSystem/JGadget/define.h b/include/JSystem/JGadget/define.h new file mode 100644 index 00000000..883ed4e7 --- /dev/null +++ b/include/JSystem/JGadget/define.h @@ -0,0 +1,51 @@ +#ifndef DEFINE_H +#define DEFINE_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +class JGadget_outMessage { +public: + typedef void (*MessageFunc)(const char*, int, const char*); + + static void warning(const char*, int, const char*); + + JGadget_outMessage(MessageFunc fn, const char* file, int line); + ~JGadget_outMessage(); + + JGadget_outMessage& operator<<(const char* str); + +private: + MessageFunc mMsgFunc; + char mBuffer[256]; + char* mWrite_p; + char* mFile; + int mLine; +}; + +#ifdef DEBUG + +#define JGADGET_ASSERTWARN(cond) \ + ((cond) || ((JGadget_outMessage(JGadget_outMessage::warning, __FILE__, __LINE__) << (#cond)), false)) + +#define JGADGET_EXITWARN(cond) \ + if (!(cond)) { JGadget_outMessage(JGadget_outMessage::warning, __FILE__, __LINE__) << (#cond), false; return false; } + +#else + +#define JGADGET_ASSERTWARN(cond) \ + ((cond) || (false)) + +#define JGADGET_EXITWARN(cond) \ + if (!(cond)) { false; return false; } + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/JSystem/JGadget/linklist.h b/include/JSystem/JGadget/linklist.h new file mode 100644 index 00000000..aed8e8a3 --- /dev/null +++ b/include/JSystem/JGadget/linklist.h @@ -0,0 +1,285 @@ +#ifndef JGADGET_LINK_H +#define JGADGET_LINK_H + +#include "types.h" + +#include "JSystem/JUtility/JUTAssertion.h" +#include "JSystem/JGadget/define.h" + +namespace JGadget { + +namespace { + +template +class TPRIsEqual_pointer_ { +public: + TPRIsEqual_pointer_(const T* p) { this->p_ = p; } + + bool operator()(const T& rSrc) const { + return &rSrc == this->p_; + } + +private: + const T* p_; +}; + +} + +class TLinkListNode { +public: + TLinkListNode() { + this->pNext_ = nullptr; + this->pPrev_ = nullptr; + } + + ~TLinkListNode() { + // Seemingly not present in earlier versions of JSystem + /* + #line 77 + JUT_ASSERT(pNext_==NULL); + JUT_ASSERT(pPrev_==NULL); + */ + } + + TLinkListNode* getNext() const { + return this->pNext_; + } + + TLinkListNode* getPrev() const { + return this->pPrev_; + } + + void clear_() { + this->pNext_ = nullptr; + this->pPrev_ = nullptr; + } + + TLinkListNode* pNext_; + TLinkListNode* pPrev_; +}; + +class TNodeLinkList { +public: + TNodeLinkList() : oNode_() { Initialize_(); } + ~TNodeLinkList(); + + class iterator { + public: + iterator() { this->p_ = nullptr; } + iterator(TLinkListNode* node) { this->p_ = node; } + + iterator& operator++() { + this->p_ = this->p_->getNext(); + return *this; + } + + iterator& operator--() { + this->p_ = this->p_->getPrev(); + return *this; + } + + TLinkListNode& operator*() const { + JUT_ASSERT(p_!=0); + return *this->p_; + } + + TLinkListNode* operator->() const { return this->p_; } + + TLinkListNode* p_; + }; + + class const_iterator { + public: + const_iterator(const TLinkListNode* node) { this->p_ = node; } + const_iterator(iterator it) { this->p_ = it.p_; } + + const const_iterator& operator++() { + this->p_ = this->p_->getNext(); + return *this; + } + + const const_iterator& operator--() { + this->p_ = this->p_->getPrev(); + return *this; + } + + const TLinkListNode* operator->() const { return this->p_; } + + const TLinkListNode* p_; + }; + + bool Confirm() const; + bool Confirm_iterator(const_iterator it) const; + iterator Erase(TLinkListNode* node); + iterator Find(const TLinkListNode* node); + iterator Insert(iterator it, TLinkListNode* node); + void Remove(TLinkListNode* node); + template void Remove_if(Predicate predicate, TNodeLinkList& tList) { + iterator it = this->begin(); + + while(!Iterator_isEnd_(it)) { + if (predicate(*it)) { + iterator itPrev = it; + ++it; + tList.splice(tList.end(), *this, itPrev); + } + else { + ++it; + } + } + } + + s32 size() const { return this->size_; } + bool empty() const { return this->size() == 0; } + void clear() { this->erase(this->begin(), this->end()); } + iterator erase(iterator itStart, iterator itEnd); + iterator erase(iterator it); + template void remove_if(Predicate predicate) { + TNodeLinkList list; + + this->Remove_if(predicate, list); + } + void splice(iterator it, TNodeLinkList& rSrc, iterator itBegin, iterator itEnd); + void splice(iterator it, TNodeLinkList& rSrc); + void splice(iterator it, TNodeLinkList& rSrc, iterator otherIt); + iterator pop_back() { return this->erase(--this->end()); } + iterator pop_font() { return this->erase(++this->begin()); } + + iterator begin() { return this->oNode_.getNext(); } + const_iterator begin() const { return this->oNode_.getNext(); } + + iterator end() { return &this->oNode_; } + const_iterator end() const { return &this->oNode_; } + +private: + void Initialize_() { + this->size_ = 0; + this->oNode_.pNext_ = &this->oNode_; + this->oNode_.pPrev_ = &this->oNode_; + } + + bool Iterator_isEnd_(const_iterator it) const { return it.p_ == &this->oNode_; } + + s32 size_; + TLinkListNode oNode_; +}; + +inline bool operator==(TNodeLinkList::iterator lhs, TNodeLinkList::iterator rhs) { return lhs.p_ == rhs.p_; } +inline bool operator!=(TNodeLinkList::iterator lhs, TNodeLinkList::iterator rhs) { return !(lhs == rhs); } + +inline bool operator==(TNodeLinkList::const_iterator lhs, TNodeLinkList::const_iterator rhs) { return lhs.p_ == rhs.p_; } +inline bool operator!=(TNodeLinkList::const_iterator lhs, TNodeLinkList::const_iterator rhs) { return !(lhs == rhs); } + +/* TODO: TLinkList has not been matched and should be verified */ + +template +class TLinkList : public TNodeLinkList { + class iterator { + public: + iterator(TNodeLinkList::iterator it) : mIt(it) { } + + bool operator==(iterator other) { return (mIt == other.mIt); } + bool operator!=(iterator other) { return !(*this == other); } + iterator& operator++() { + ++mIt; + return *this; + } + iterator& operator--() { + --mIt; + return *this; + } + + T* operator->() const { return TLinkList::Element_toValue(mIt.operator->()); } + T& operator*() const { + T* p = this->operator->(); + #line 541 + JUT_ASSERT(p!=0); + return *p; + } + + private: + TNodeLinkList::iterator mIt; + }; + + class const_iterator { + public: + const_iterator(TNodeLinkList::const_iterator it) : mIt(it) { } + + bool operator==(const_iterator other) { return (mIt == other.mIt); } + bool operator!=(const_iterator other) { return !(*this == other); } + const_iterator& operator++() { + ++mIt; + return *this; + } + const_iterator& operator--() { + --mIt; + return *this; + } + + const T* operator->() const { return TLinkList::Element_toValue(mIt.operator->()); } + const T& operator*() const { + T* p = this->operator->(); + #line 586 + JUT_ASSERT(p!=0); + return *p; + } + + private: + TNodeLinkList::const_iterator mIt; + }; + + iterator Find(const T* p) { return TNodeLinkList::Find(TLinkList::Element_toNode(p)); } + iterator Erase( T* p) { return TNodeLinkList::Erase(Element_toNode(p)); } + iterator Insert(iterator it, T* p) { return TNodeLinkList::Insert(it, Element_toNode(p)); } + void Remove(T* p) { TNodeLinkList::Remove(TLinkList::Element_toNode(p)); } + void Push_front(T* p) { Insert(begin(), p); } + void Push_back(T* p) { Insert(end(), p); } + + T& front() { + #line 642 + JUT_ASSERT(!empty()); + return *begin(); + } + + T& back() { + #line 652 + JUT_ASSERT(!empty()); + iterator itEnd = end(); + --itEnd; + return *itEnd; + } + + iterator begin() { return TNodeLinkList::begin(); } + const_iterator begin() const { return TNodeLinkList::begin(); } + + iterator end() { return TNodeLinkList::end(); } + const_iterator end() const { return TNodeLinkList::end(); } + + static TLinkListNode* Element_toNode(T* p) { + #line 753 + JUT_ASSERT(p!=0); + return (TLinkListNode*)((char*)p + O); + } + + static const TLinkListNode* Element_toNode(const T* p) { + #line 758 + JUT_ASSERT(p!=0); + return (const TLinkListNode*)((const char*)p + O); + } + + static T* Element_toValue(TLinkListNode* p) { + #line 763 + JUT_ASSERT(p!=0); + return (T*)((char*)p - O); + } + + static const T* Element_toValue(const TLinkListNode* p) { + #line 768 + JUT_ASSERT(p!=0); + return (const T*)((const char*)p - O); + } +}; + +} + +#endif diff --git a/include/JSystem/JUtility/JUTAssertion.h b/include/JSystem/JUtility/JUTAssertion.h index b273397f..a96af3f3 100644 --- a/include/JSystem/JUtility/JUTAssertion.h +++ b/include/JSystem/JUtility/JUTAssertion.h @@ -52,11 +52,7 @@ namespace JUTAssertion #else #define JUT_ASSERT(COND) \ - if ((COND) == false) \ - { \ - JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, __LINE__, #COND); \ - OSHalt("Halt"); \ - } + ((COND)) ? (void)0 : (JUTAssertion::showAssert(JUTAssertion::getSDevice(), __FILE__, __LINE__, #COND), OSHalt("Halt")); #define JUT_ASSERT_F(COND, ...) \ if ((COND) == false) \ diff --git a/include/MSL_CPP/algorithm.h b/include/MSL_CPP/algorithm.h new file mode 100644 index 00000000..2856cb97 --- /dev/null +++ b/include/MSL_CPP/algorithm.h @@ -0,0 +1,19 @@ +#ifndef ALGORITHM_H +#define ALGORITHM_H + +#include "types.h" + +namespace std { + +template +inline +InputIterator +find_if(InputIterator first, InputIterator last, Predicate pred) { + while (first != last && !pred(*first)) + ++first; + return first; +} + +} // namespace std + +#endif diff --git a/include/MSL_CPP/iterator.h b/include/MSL_CPP/iterator.h new file mode 100644 index 00000000..88998d2d --- /dev/null +++ b/include/MSL_CPP/iterator.h @@ -0,0 +1,32 @@ +#ifndef ITERATOR_H +#define ITERATOR_H + +#include "types.h" + +namespace std { + +/* TODO: these should be properly implemented */ + +struct input_iterator_tag {}; + +template +inline +s32 +__distance(InputIterator first, InputIterator last, input_iterator_tag) { + s32 result = 0; + for (; first != last; ++first) + ++result; + return result; +} + +template +inline +s32 +distance(InputIterator first, InputIterator last) { + input_iterator_tag tag; + return __distance(first, last, tag); +} + +} // namespace std + +#endif diff --git a/src/JSystem/JGadget/linklist.cpp b/src/JSystem/JGadget/linklist.cpp new file mode 100644 index 00000000..9232b684 --- /dev/null +++ b/src/JSystem/JGadget/linklist.cpp @@ -0,0 +1,193 @@ +#include "JSystem/JGadget/linklist.h" + +#include "MSL_CPP/algorithm.h" +#include "MSL_CPP/iterator.h" + +namespace JGadget { + +TNodeLinkList::~TNodeLinkList() { + #ifdef DEBUG + Confirm(); + clear(); + #endif + JGADGET_ASSERTWARN(empty()); + //this->oNode_.clear_(); +} + +TNodeLinkList::iterator TNodeLinkList::erase(iterator it, iterator itEnd) { + TLinkListNode* cur = it.p_; + TLinkListNode* end = itEnd.p_; + TLinkListNode* next; + + for (; cur != end; cur = next) { + next = cur->pNext_; + this->Erase(cur); + } + + return itEnd; +} + +TNodeLinkList::iterator TNodeLinkList::erase(TNodeLinkList::iterator it) { + #line 102 + JUT_ASSERT(it.p_!=&oNode_); + + iterator itNext = it; + ++itNext; + + return this->erase(it, itNext); +} + +void TNodeLinkList::splice(TNodeLinkList::iterator it, TNodeLinkList& rSrc, TNodeLinkList::iterator itBegin, TNodeLinkList::iterator itEnd) { + s32 dist = 0; + + if (this == &rSrc) { + if (itBegin == itEnd) { + return; + } + } + else { + dist = std::distance(itBegin, itEnd); + + if (dist == 0) { + return; + } + } + + TLinkListNode* node_it = it.p_; + TLinkListNode* node_beg = itBegin.p_; + TLinkListNode* node_end = itEnd.p_; + + TLinkListNode* end_prev = node_end->pPrev_; + TLinkListNode* beg_prev = node_beg->pPrev_; + + beg_prev->pNext_ = node_end; + node_end->pPrev_ = beg_prev; + rSrc.size_ -= dist; + + TLinkListNode* it_prev = node_it->pPrev_; + + it_prev->pNext_ = node_beg; + node_beg->pPrev_ = it_prev; + end_prev->pNext_ = node_it; + node_it->pPrev_ = end_prev; + + this->size_ += dist; +} + +void TNodeLinkList::splice(TNodeLinkList::iterator it, TNodeLinkList& rSrc, TNodeLinkList::iterator itSrc) { + iterator itSrcNext = itSrc; + ++itSrcNext; + + if ((it == itSrc) || (it == itSrcNext)) { + return; + } + else { + TLinkListNode* const node = &*itSrc; + + rSrc.Erase(node); + this->Insert(it, node); + } +} + +void TNodeLinkList::splice(iterator it, TNodeLinkList& rSrc) { + #line 146 + JUT_ASSERT(this!=&rSrc); + this->splice(it, rSrc, rSrc.begin(), rSrc.end()); + JUT_ASSERT(rSrc.empty()); +} + +TNodeLinkList::iterator TNodeLinkList::Find(const TLinkListNode* node) { + return std::find_if(this->begin(), this->end(), TPRIsEqual_pointer_(node)); +} + +#undef NULL +#define NULL 0 + +TNodeLinkList::iterator TNodeLinkList::Insert(iterator it, TLinkListNode* p) { + #line 300 + JUT_ASSERT(p!=0); + TLinkListNode* pIt = it.p_; + JUT_ASSERT(pIt!=0); + + TLinkListNode* pItPrev = pIt->pPrev_; + JUT_ASSERT(pItPrev!=0); + + JGADGET_ASSERTWARN(p->pNext_==NULL); + JGADGET_ASSERTWARN(p->pPrev_==NULL); + + p->pNext_ = pIt; + p->pPrev_ = pItPrev; + pIt->pPrev_ = p; + pItPrev->pNext_ = p; + this->size_++; + + return p; +} + +#undef NULL +#define NULL (void*)0; + +TNodeLinkList::iterator TNodeLinkList::Erase(TLinkListNode* p) { + #line 325 + JUT_ASSERT(!empty()); + JUT_ASSERT(p!=0); + JUT_ASSERT(p!=&oNode_); + TLinkListNode* pNext = p->pNext_; + TLinkListNode* pPrev = p->pPrev_; + JUT_ASSERT(pNext!=0); + pNext->pPrev_ = pPrev; + JUT_ASSERT(pPrev!=0); + pPrev->pNext_ = pNext; + this->size_--; + //p->clear_(); + return pNext; +} + +void TNodeLinkList::Remove(TLinkListNode* node) { + this->remove_if(TPRIsEqual_pointer_(node)); +} + +bool TNodeLinkList::Confirm() const { + u32 u = 0; + const_iterator itEnd = this->end(); + + #line 357 + JGADGET_EXITWARN(itEnd.p_==&oNode_); + const_iterator it = this->begin(); + JGADGET_EXITWARN(it.p_==oNode_.pNext_); // #line 359 + + for (; it != itEnd; ++it, ++u) { + JGADGET_EXITWARN(upNext_->pPrev_==pIt); + JGADGET_EXITWARN(pIt->pPrev_->pNext_==pIt); // #line 366 + } + + #line 368 + JGADGET_EXITWARN(it.p_==&oNode_); + JGADGET_EXITWARN(u==size()); + return true; +} + +bool TNodeLinkList::Confirm_iterator(const_iterator it) const { + const_iterator itBegin = begin(); + const_iterator itEnd = end(); + + while (itBegin != itEnd) { + if (itBegin == it) { + return true; + } + + ++itBegin; + } + + #line 383 + JGADGET_EXITWARN(it==itEnd); + + return true; +} + +} // namespace JGadget +