Supermon64 sources
Supermon64 sources
I've been teaching myself 6502 assembly over the last month or so, starting with Jim Butterfield's book, Machine Language for the Commodore 64 (available here: https://archive.org/details/Machine_Lan ... ed_Edition). After reading the book I wanted to find some code for a "real" application to study and Supermon64, which I had just used to complete the book seemed like a natural place to start. I could have disassembled it but without labels it would be even harder to understand especially for a beginner. I tracked down the original Supermon64 sources, which wasn't as easy as you might think. I've posted them here: https://github.com/jblang/supermon64. (I saw the code on the fridge, but that's been modified from the original, and it appears to be for an older version.) The story of how I tracked down the original is in the README.
I made the minimal number of changes necessary to get it to assemble using 64tass, reindented it, and for the past few days, I've been working my way through the code trying to understand it. As I go, I'm writing comments since the original source was almost completely uncommented. I thought I'd post it here in case anyone finds it interesting: https://github.com/jblang/supermon64/bl ... rmon64.asm. I'm not done yet (maybe about 50%)... I'll keep updating it as I go. Next I'll tackle the assembler and disassembler which is probably the most interesting part of the code.
I made the minimal number of changes necessary to get it to assemble using 64tass, reindented it, and for the past few days, I've been working my way through the code trying to understand it. As I go, I'm writing comments since the original source was almost completely uncommented. I thought I'd post it here in case anyone finds it interesting: https://github.com/jblang/supermon64/bl ... rmon64.asm. I'm not done yet (maybe about 50%)... I'll keep updating it as I go. Next I'll tackle the assembler and disassembler which is probably the most interesting part of the code.
Last edited by jblang on Wed Jan 18, 2017 3:10 pm, edited 1 time in total.
Re: Supermon64 sources
Thanks for republishing, and welcome! The annotation project sounds like an interesting one, and a public good.
Re: Supermon64 sources
Great work! I love seeing projects like this.
Plus, I didn't have that book in my collection so I quickly added it. I'm a huge fan of Jim Butterfield's work.
Plus, I didn't have that book in my collection so I quickly added it. I'm a huge fan of Jim Butterfield's work.
Cat; the other white meat.
Re: Supermon64 sources
Thanks for the encouragement. I've gotten a bit further and run into a few puzzlers...
I can't figure out the purpose of these two lines: https://github.com/jblang/supermon64/bl ... #L485-L486
As far as I can tell that branch will *never* be taken. Am I missing something, or is that just something he left in by mistake?
Another question: why use a loop here? https://github.com/jblang/supermon64/bl ... #L346-L350
By my calculation, using the loop takes 10 bytes and 29 cycles while just duplicating the LDA/STA would take 10 bytes and 14 cycles.
Maybe I'm putting Jim Butterfield on a pedestal and he just made mistakes, but I wanted to make sure I wasn't missing anything, especially when he resorted to tricks like this to shave off a few bytes in other places: https://github.com/jblang/supermon64/bl ... #L871-L873.
I can't figure out the purpose of these two lines: https://github.com/jblang/supermon64/bl ... #L485-L486
As far as I can tell that branch will *never* be taken. Am I missing something, or is that just something he left in by mistake?
Another question: why use a loop here? https://github.com/jblang/supermon64/bl ... #L346-L350
By my calculation, using the loop takes 10 bytes and 29 cycles while just duplicating the LDA/STA would take 10 bytes and 14 cycles.
Maybe I'm putting Jim Butterfield on a pedestal and he just made mistakes, but I wanted to make sure I wasn't missing anything, especially when he resorted to tricks like this to shave off a few bytes in other places: https://github.com/jblang/supermon64/bl ... #L871-L873.
Re: Supermon64 sources
Quote:
As far as I can tell that branch will *never* be taken. Am I missing something, or is that just something he left in by mistake?
Code: Select all
LDA SAVY ; ?? not sure what these two lines are for...
BEQ LERROR ; ?? afaict SAVY will never be 0, so why check?As for the loop, perhaps at one point it might have been copying more, or might have had the potential to need to copy more.
Pretty much everyone makes mistakes - it's more a question of whether they've all been found and fixed by time someone else sees the code. Until every last byte has been squeezed, even evidence that some byte-squeezing has been done doesn't mean that all the dead code has gone. Working on something as large as this, you need a lot of context in your head. Some parts will be more familiar than others, even if you wrote it yourself. So, you'll squeeze something which is close to hand, or close to mind - you won't carefully review every line, because there's no need.
This kind of archaeology is fascinating! You may be aware that we found odd bits of nonsense layout in the 6502 when looking over visual6502 - even a chip which had to be squeezed is not clear of oddities, because the work stops when it's good enough, and small enough.
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Supermon64 sources
BigEd wrote:
It looks like this location you've called SAVY...a remnant, which isn't even quite in the right place any more.
Quote:
Pretty much everyone makes mistakes - it's more a question of whether they've all been found and fixed by time someone else sees the code.
With as much programming as Jim Butterfield did over the years there is bound to be something somewhere that isn't 100 percent copacetic. That being the case merely points out that he was mortal like the rest of us.
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Supermon64 sources
Thanks for confirming my suspicions. FWIW, I didn't name it SAVY--the labels in the source are Jim's original labels. He reuses that as well as other things (especially TMP0) all over the place. That's probably the thing that has made me scratch my head longer than anything else. I guess because the original source was assembled *on* a C64, he had to economize on label names too, an not just code. With a modern cross-assembler, you'd probably just make multiple labels pointing to the same location in memory so the intent is clearer.
I've been tempted to clean up some things like the reused labels and the little oddities I found before, but I've got a strict comments-only rule for this project because I want to preserve the historical context. No modification of the actual code beyond what was absolutely necessary to get it to assemble using 64tass. For the record, the only changes I made are a few directives that 64tass didn't support: ".ASC" to ".TEXT", and "*=*+X" to ".FILL X". I also added the basic header for convenience while I'm working with the code, but I'll probably remove that once I'm done.
As a fun project once I'm done commenting, I may--on a different file--try modifying it to take advantage of some more modern assembler features and at the same time get rid of some of the more "WTF?" moments that I found in the code.
I've been tempted to clean up some things like the reused labels and the little oddities I found before, but I've got a strict comments-only rule for this project because I want to preserve the historical context. No modification of the actual code beyond what was absolutely necessary to get it to assemble using 64tass. For the record, the only changes I made are a few directives that 64tass didn't support: ".ASC" to ".TEXT", and "*=*+X" to ".FILL X". I also added the basic header for convenience while I'm working with the code, but I'll probably remove that once I'm done.
As a fun project once I'm done commenting, I may--on a different file--try modifying it to take advantage of some more modern assembler features and at the same time get rid of some of the more "WTF?" moments that I found in the code.
Re: Supermon64 sources
Ah, original sources, I hadn't quite got that. So, indeed, developing in a very constrained way.
Re: Supermon64 sources
I've gotten probably about 60% through the assembler code at this point. It definitely took a bit longer to understand. Upon discovering the packed 2 byte mnemonics...
First thought: WTF is going on here?
Second thought: Hey that's pretty clever!
Third thought: This sure adds a lot of complexity, I wonder how much space it really saves?
My calculation: saves 56 bytes in the mnemonic table (one for each legal instruction). But the code to pack the mnemonics in the assembler is 23 bytes and the code to unpack and display them in the disassembler is 38 bytes, for a total cost of 61 bytes, so it doesn't seem like it really saves any space at all.
I decided then to look at a few other monitors including the C128 monitor and the Apple II mini-assembler and it seems like they all do it. A case of premature optimization maybe? Or am I mistaken?
First thought: WTF is going on here?
Second thought: Hey that's pretty clever!
Third thought: This sure adds a lot of complexity, I wonder how much space it really saves?
My calculation: saves 56 bytes in the mnemonic table (one for each legal instruction). But the code to pack the mnemonics in the assembler is 23 bytes and the code to unpack and display them in the disassembler is 38 bytes, for a total cost of 61 bytes, so it doesn't seem like it really saves any space at all.
I decided then to look at a few other monitors including the C128 monitor and the Apple II mini-assembler and it seems like they all do it. A case of premature optimization maybe? Or am I mistaken?
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Supermon64 sources
jblang wrote:
Upon discovering the packed 2 byte mnemonics...But the code to pack the mnemonics in the assembler is 23 bytes and the code to unpack and display them in the disassembler is 38 bytes, for a total cost of 61 bytes, so it doesn't seem like it really saves any space at all.
I decided then to look at a few other monitors including the C128 monitor and the Apple II mini-assembler and it seems like they all do it. A case of premature optimization maybe? Or am I mistaken?
I decided then to look at a few other monitors including the C128 monitor and the Apple II mini-assembler and it seems like they all do it. A case of premature optimization maybe? Or am I mistaken?
It's all a matter of performance. In the case of the 6502, determining if an entered mnemonic is legitimate is reduced to a two byte comparison vs. three for use of unencoded mnemonics. In the case of the 65C816 operating 16 bits at a time, checking a mnemonic is reduced to a one word comparison, vs. a three byte comparison. Adding insult to injury in the case of the '816, the encoded mnemonic table can be stored in byte-ascending order, allowing the use of a binary search algorithm, since each two-byte encoded mnemonic can be read in a single operation.
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Supermon64 sources
Thanks for the explanation. I was thinking about it only in terms of saving bytes and not the number of cycles it would take to do the comparison. I was thinking that packing and unpacking the opcodes was a lot of work but I guess that loop does a lot fewer iterations than the loop to compare the mnemonics so it's a good tradeoff.
After looking more at the Apple Mini-Assembler, I've come to the conclusion that Supermon 64's assembler is at least partially derived from it. The labels are different, but the code for the INSTXX subroutine in Supermon 64 is identical to the INSDS2 subroutine on page 78 of the Apple II Redbook.
After looking more at the Apple Mini-Assembler, I've come to the conclusion that Supermon 64's assembler is at least partially derived from it. The labels are different, but the code for the INSTXX subroutine in Supermon 64 is identical to the INSDS2 subroutine on page 78 of the Apple II Redbook.
- BigDumbDinosaur
- Posts: 9428
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Supermon64 sources
jblang wrote:
After looking more at the Apple Mini-Assembler, I've come to the conclusion that Supermon 64's assembler is at least partially derived from it. The labels are different, but the code for the INSTXX subroutine in Supermon 64 is identical to the INSDS2 subroutine on page 78 of the Apple II Redbook.
The very first M/L monitor for the 6502 came from MOS Technology (I encountered that version in the latter part of 1976 when I was learning the 6502 assembly language) and it wouldn't surprise me at all if the Apple monitor was a derivative of the MOS Technology one. The original Supermon is c. 1978, around the time the Commodore PET went into widespread distribution. The first generation PET had a rudimentary monitor with very limited capabilities compared to Supermon. I'm sure Jim Butterfield would had full access to the MOS Technology monitor source code, seeing as how by then MOS Technology had been acquired by Commodore.
x86? We ain't got no x86. We don't NEED no stinking x86!
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Supermon64 sources
BigDumbDinosaur wrote:
... The very first M/L monitor for the 6502 came from MOS Technology (I encountered that version in the latter part of 1976 when I was learning the 6502 assembly language) and it wouldn't surprise me at all if the Apple monitor was a derivative of the MOS Technology one ...
Mike B.
Re: Supermon64 sources
Whoa... didn't mean to start a fight! 
Anyway, regardless of who came first it's clear they share a common heritage. In general, it looks like the origins of many of the early 6502 monitors were pretty incestuous and nobody really bothered much with attribution.
Update: I've finished commenting the majority of the assembler and committed those comments but I'm still not quite finished.
Anyway, regardless of who came first it's clear they share a common heritage. In general, it looks like the origins of many of the early 6502 monitors were pretty incestuous and nobody really bothered much with attribution.
Update: I've finished commenting the majority of the assembler and committed those comments but I'm still not quite finished.
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Supermon64 sources
Nah, BDD and I both have pretty thick skin, and like to butt heads in a good-natured way from time to time. I have a lot of respect for him, for his experience and generous disposition ... and his ability to survive giant deadly meteor impacts.
http://www.sciencemag.org/news/2016/03/ ... -dinosaurs
Mike B.
http://www.sciencemag.org/news/2016/03/ ... -dinosaurs
Mike B.