I posted this on the coursera discussion area but I'm not sure how visible that is.
There should be enough information to explain (and reproduce) the issue over at https://github.com/purple-pixie/nand2tetrisbug/ but in short, while inside the body of Sys.init, the Sys class seems confused about where its static variables reside, and just addresses them as RAM[16+static_variable_index] i.e. its first static variable will be written/read from RAM, its second from RAM.
While in other functions of Sys (or at least custom ones, I didn't test inside of other API-required functions) it is able to correctly address its own region of the static segment, and not clobber the statics belonging to other classes.
Edit: After a bit of thinking about it, it seems reasonably intuitive that the root cause is how the VM "calls" Sys.init in the first place - however it's doing that doesn't specify that the currently-executed class is Sys, which in turn means it doesn't know where to look for statics.
Somewhat amusingly, it was my inability to make the breakpoints work in just the way I wanted that let me find what was going on - I decided to move the static assignments out of init and into a separate function called by init, so I could set a breakpoing on currentFunction, and as soon as I did that the problem magically disappeared.
One issue I have with the VMEmulator is that it really shouldn't have any hint of the underlying implementation. The VM language specification is completely independent of how it is implemented on a particular hardware platform, so the emulator should adhere to this notion and create separate static memory pools for each class. The same is true for any other aspect of the emulator. Ideally, someone should be able to write and run VM programs and have everything they see in the VMEmulator make complete sense without any awareness of any underlying architecture.
The VMEmulator really should have two modes of operation. In the first is it truly virtual. In this mode, for instance, an attempt to write to a location in the Temp memory segment that is outside its bounds should produce an error. It should NOT overwrite data in the static segment since there is nothing in the VM language spec to indicate that these memory segments have any relation to each other, let alone that they happen to be adjacent in physical memory.
The other mode of operation would be real mode, in which it faithfully executes VM commands as if they are implemented using the reference VM Translator implementation and running on the Hack hardware. This would entail, for instance, NOT checking that the THIS and THAT pointers are pointing to the Heap or Screen screen, since such checks are not part of the actual VM implementation specification.
There are some issues with this approach, however. One is that the VM language spec has no concept of the memory mapped I/O, but I think this can be dealt with. Another is ROM constraints. In virtual mode, there would be no limit on the size of the VM program (which is the case for the current VMEmulator), but it real mode there would be. The issue is that the actual constraint depends on the implementation of the VM Translator, and thus the student would be unable to know if a particular VM program will fit into ROM using THEIR VM Translator, only the reference implementation.