Legacy code is a beast—especially when it is sufficiently large. I find it almost impossible to infer what the origin design/intent was. I found this article from Eric Raymond that is a pretty reasonable approach to diving into a new code base:
Essentially, his approach is (I have modified it a little here to make it apply better to legacy code at work, instead of just to open source projects)
Learn how to use the program.
Pick a small feature to change or add.
Search the code until you find the part you need to modify. (Do not try to read the entire program)
Make, test, debug, and document your change.
return to step 2
Raymond says, “As you go through this loop several times, you will gradually develop a more complete representation in your mind of the way the whole program fits together. At some point you will reach a threshold where you understand it all — or anyway enough of it for whatever your final purpose is.”