Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - XmikeX

#1
Assembly / Re: 128 MLM Disassembly - with Comments
January 13, 2011, 11:08 AM
Quote from: Hydrophilic on January 12, 2011, 11:42 PM
I don't have C128 Internals (umm, I guess I could try Bombjack), but I do have C1571 Internals.  Their disassembly is always of dubious quality.  If you thought my comments of the code at $b687 were bad, take a look at theirs!
Haven't really looked at your disassembly yet, because the stuff is delivered in nanoprint (courtesy browser and forum) and I need to unlazy: copy/paste to offline editor, or whatever.

Quote from: Hydrophilic on January 12, 2011, 11:42 PM
Anyway, those Abacus books are a good start if you have no clue what's going on.
Indeed. Good start for many. =)

XmX
#2
That's wonderful stuff Hydro, although you might be a little late with some of this.  Some stuff looks very interesting though.  I'll have to check it out when more coherent.

Meanwhile, a few happenings and goings-on were already self-evident shortly after that sparse Supermon disassembly came along.**  -- The "mode table" nybble revelation (as documented previously) from that sparse "source", plus one/two insights from BDD, come to mind.

Forum-wise though, it did look like as if things might have gotten a bit uninteresting (pardon ze pun).  However, since at least Hydro seems active, might as well dump whatever I've got:

http://www.commodore128.org/index.php?topic=3709.0

There. Now Hydro or one of you other superhumans can take it to the next level.  Wink. Wink. =)
Undoc op support and single-step walkthrough please.

By the way:  I wonder how many of the forum-oldtimers (the ones that eat/breathe C-128 daily) knew about the relevant disassembly inside C-128 Internals by Abacus, but decided to keep mum about it?

Real Sneaky, Fellas.  Kudos on that one. =)

XmX

**The monitor relocation exercise, which I bet no one has downloaded yet, made evident some of those so-called "clever" stack tricks.  Didn't take long to realize out why things were jumping around to the WRONG locations after encountering RTS's with no clear JSR's behind them.
#3
Assembly / 128 MLM Disassembly - with Comments
January 12, 2011, 08:39 PM
Disassembly of C-128 ML Monitor with Comments
Code Comments/"re-sourcing" almost exclusively by Commodore 128 Internals - The Authoritative Insiders' Guide
         by Abacus Software / K. Gerits, J. Schieb, and F. Thrun

Section Comments from Mapping the 128 (of course)
         by Compute! Books / Otis R. Cowper


Compilation of this text and minor edits as follows, by XmikeX - 11 Jan 2011 (REVISION 01)
   - addition(s)
      Actual code listing(s) copied from VICE x128 v2.2xxxx, utilizing final NTSC 128DCR ROMset
      Instructions revealed by ROM but not listed in 'Internals'
         . fb02a  85 08    sta $08
         . fb662  f0 13    beq $b677
      Expanded Mnemonic Encoding Summary
      Some Table comments from a very-sparse disassembly of Supermon

   - correction(s)
      . fb0d4  bd fc b0 lda $b0fc,x   Monitor routine (Low) Address   -- original text: "Monitor routine (hi) addr."

   - grammar/legibility
      Expansion of some contractions, acronyms, and shorthand verbiage.

   - trickery using 24, 2C BIT as 'skip byte', 'skip word' 'instructions' noted in comments:
      . fb233  2c         Skip to $B236
      . fb7c8  24         Skip to $B7CA
      . fb87d  24         Skip to $B87F
      . fb9ae  24         Skip to $B9B0 (RTS)
      . fb9ae  24         Skip to $B9B0 (RTS)

Available here --> http://starbase.globalpc.net/~xmx/C128-MLM_Commented_Disassembly.txt
........or as a Notepad-Friendly .txt file attached to this forum post.

XmX

PS: Thanks to Fungus for confirming that 24 / 2C can be used as SKB/SKW
#4
Yet Another NMOS 6502 opcode list and block diagram, attached.

List arranged by opcodes, ascending, with binary expansion. Built from work by John West, Marko Mäkelä, Adam Vardy, John Selck.

Diagram from : http://homepage.mac.com/jorgechamorro/a2things/ , compacted a bit with .PNG

XmX
#5
Quote from: XmikeX on December 17, 2010, 09:00 PM
I had maybe three/four of these turn temporarily bad, as described in this thread earlier, due to a very simple problem : Gumming up of the On/Off Switch.

Temp Fix : disconnect power supply, toggle on/off switch rapidly 20-30 times, reconnect power supply - turn on c-128.

Perma Fixes : 1) clean the switch (disassemble switch, clean switch, reassemble switch) and/or 2) replace switch.


http://www.commodore128.org/index.php?topic=3604.msg18007#msg18007

XmX
#6
If anyone is interested in exploring the monitor-code in a more-interactive fashion within an emulated (or real) 128 environment, I've relocated Supermo^W the 128's ML Monitor into RAM.  I have it ranging from $2000- $2ffff with a few relocated tables in $2cxx-2exx.  A few bytes of BRK vector code, just before monitor is executed, is provided at $1FF0 if needed.  I've included an attachment, with monitor code and modded ROM files for VICE x128.  As described in the .README, these ROM files simply reassign some necessary vectors and the MONITOR command to the relocated locations.

XmX
#7
Quote from: BigDumbDinosaur on January 07, 2011, 01:51 AM
To find the mnemonic for any given opcode, use the opcode as a zero-based index into the tables.  Once the two encoded bytes have been retrieved, the same principle used with the C-128's monitor to convert the mnemonic to human-readable format can be used.

Why did I use this method?  All 256 opcodes are valid instructions with the W65C816S, making it impossible to use an opcode bit pattern based method of decoding/encoding, as was done in the C-128 monitor (which does date back in many ways to the old PET monitor).  Incidentally, a third table encodes the addressing mode and total instruction size for each opcode. ]

Outstanding stuff, BDD.
....and tables..tables everywhere.... inescapable reality.

XmX
#8
Quote from: XmikeX on January 06, 2011, 02:51 PM

I am hoping the process is relatively straightforward, once (if) understood.


If?  Did I write "if" ?

Hrmmm... scratch all that.  I believe I've come to the realization (i'm in denial) that what we're really looking at is Supermon.. sort of...  (hold on, i'm still in denial).

Ok Ok, I've been in denial since Day 1.  =)

~~~~20 seconds of google-ing here~~~~

Well Well ... here's $B6C3 again ...

                          ; supermon mode table... nybble organized
                          ; 0= err  4= implied  8= zer,x   c= zer,y
                          ; 1= imm  5= acc      9= abs,x   d= rel
                          ; 2= zer  6= (ind,x)  a= abs,y
                          ; 3= abs  7= (ind),y  b= (ind)

mode     dfb $40,$02,$45,$03
              dfb $d0,$08,$40,$09
              dfb $30,$22,$45,$33
              dfb $d0,$08,$40,$09
              dfb $40,$02,$45,$33
              dfb $d0,$08,$40,$09
              dfb $40,$02,$45,$b3
              dfb $d0,$08,$40,$09
              dfb $00,$22,$44,$33
              dfb $d0,$8c,$44,$00
              dfb $11,$22,$44,$33
              dfb $d0,$8c,$44,$9a
              dfb $10,$22,$44,$33
             dfb $d0,$08,$40,$09
             dfb $10,$22,$44,$33
             dfb $d0,$08,$40,$09
             dfb $62,$13,$78,$a9

Gotta love these C= oldtimers + CBM-influenced productions, eh?  =)
I hope 3-4 C= oldtimers here (i.e., anyone under 50 is a kid) have been laughing all along (or will claim to have been laughing, after they read this post).

Here's a sparsely commented source : http://www.ffd2.com/fridge/programs/supermon.s

There's probably tons more documentation on Supermon, of course.

XmX
#9
Hydrophilic wrote : "I guess I wasn't being clear.
  I'm not saying you couldn't have 256 opcodes, but there are only 4 unused mnemonics.
  So you could add 4 mnemonics, for example, ANC, DCP, ISB, LAX (or only 3 if the disassembler needs a ? ? ? entry).
  ISB and DCP have multiple addressing modes, and so does NOP.
  So you could add multiple opcodes with only 3 or 4 new mnemonics, but you couldn't add all the undoc'd opcodes...
  not even all the useful ones.. without expanding the mnemonic table."


Expanding the mnemonic table = Yes Yes, no arguments from me.

... but let's branch off for a moment...

Assuming the position of the mnemonic label is systematically linked to the generated opcode byte,
a bit of a curiosity follows... which may or may not be significant/useful.

B721   BRK 00  opcode byte
B722   PHP 08
B723   BPL 10
B724   CLC 18
B725   JSR 20  JSR $xxxx
B726   PLP 28
B727   BMI 30
B728   SEC 38
B729   RTI 40
B72A   PHA 48
B72B   BVC 50
B72C   CLI 58
B72D   RTS 60
B72E   PLA 68
B72F   BVS 70
B730   SEI 78
B731   ??x 80  <- is expected .. but inserting "ANC" (#$13) here and (#$C8) at $B731
                            or "LXA" (#$6E) / (#$44) .. or anything else, is parsed to an assembled opcode ..value 02  (!),
                            and.... during disassembly, "ANC" (or whatever you enter) displays opcode bytes 02 -and- FF  (!!!)

Hydrophilic wrote : "...the code that actually decodes the mnemonics doesn't seem to depend on a table limited to 64 entries."

That is a possible implication with respect to the presumably-decoded $B6C3, as I hinted at earlier.
""The expansion of the $B6C3 table (with SKIPS) was easily characterized as an 8x32 array (256).
This may suggest that the entire #$00-FF range of opcodes can be accounted for with some tweaks
to currrent monitor code and table expansion elsewhere.""
--

Hydrophilic wrote : " [...] It seems to me there must be a good reason the mnemonic table is 64 entries long."

Heh Heh.  At least we know there are less than 64 valid mnemonic labels (i should hope so!), and that the mnemonic
table can be arranged to mostly-track with that opcode matrix submitted earlier. =)
--

Hydrophilic earlier wrote : " So unless you want to add only 2 or 3 opcodes, it looks like it would require a major patch. "

Assuming we're just expanding tables and adding/changing a few lines of code, perhaps it won't be regarded as anything monumental. =)   I am hoping the process is relatively straightforward, once (if) understood.

XmX

EDIT: Picture added.
EDIT2: Formatting fixed.
#10
Quote from: Hydrophilic on January 05, 2011, 06:20 PM
I was looking at this last night.  I don't have an answer yet about the opcode table at $b6c3.
People familiar with 6502 instruction codes should notice the mnemonics go in ascending code order.  To my surprise, there are really ??? encoded strings.  Must be for the disassembler because you can't assemble them (I tried).

More important, perhaps, is there are only 4 unused entries.  So unless you want to add only 2 or 3 opcodes, it looks like it would require a major patch.  At least there's over 1kiB to work with...

The expansion of the $B6C3 table (with SKIPS) was easily characterized as an 8x32 array (256).  This may suggest that the entire #$00-FF range of opcodes can be accounted for with some tweaks to currrent monitor code and table expansion elsewhere.  In fact, I'd almost bet money that adding support for undoc ops, for example, would be a very mild task to whomever knows how the monitor really works.  Unfortunately, I haven't found any documentation to support these assertions.  Since this monitor appears to be descended from a line of earlier Commodore monitors, perhaps there exists some noteworthy documentation from some PET or other CBM enthusiast of long ago. (?)

.....and yes, first thing I did was to look at the mnemonic label tables.

The preformatted text below illustrates how I laid out the mnemonic label table(s) out, for my own perusal.

As you can see from the opcode matrix i've mated to the mnemonic label table, those four zero'ed out entries are zero'ed out for good reason perhaps. =)  I believe (but not 100% sure) the entries would otherwise be assembled as "NOPs" with "different" "addressing modes".  In other words, if you add mnemonic encode bytes for <some bytes other than 00> into these blanked entries, you'll probably achieve successful assembly of these other flavors of NOP with their associated opcodes assembled into ram.  I've not tried this myself (yet) so I can't say for sure (yet). =)

The tables sit at $B721 and $B761, of course.  The B721 (BC01) and B761 (BD01) stuff is merely (original location) (relocated location in my test rom file).

XmX
--
                                                       6510 (opcodes) Instructions by Addressing Modes
                                                        Offsets   Positive                  Negative
             BRK  PHP  BPL  CLC  JSR  PLP  BMI  SEC         00      20      40      60      80      a0      c0      e0
B721 (BC01): 1c   8a   1c   23   5d   8b   1b   a1     +00  BRK     JSR                                           Implied and/or Immediate
B761 (BD01): d8   62   5a   48   26   62   94   88     +08  PHP     PLP                                           for these groups of instructions:
                                                       +10  BPL     BMI                                            B721 (BC01) - B740 (BC20)
                                                       +18  CLC     SEC                                            B761 (BD01) - B780 (BD20)
             RTI  PHA  BVC  CLI  RTS  PLA  BVS  SEI
B729 (BC09): 9d   8a   1d   23   9d   8b   1d   a1     +00                  RTI     RTS
B769 (BD09): 54   44   c8   54   68   44   e8   94     +08                  PHA     PLA
                                                       +10                  BVC     BVS
                                                       +18                  CLI     SEI
             ***  DEY  BCC  TYA  LDY  TAY  BCS  CLV
B731 (BC11): 00   29   19   ae   69   a8   19   23     +00                                  ??*     LDY
B771 (BD11): 00   b4   08   84   74   b4   28   6e     +08                                  DEY     TAY
                                                       +10                                  BCC     BCS
                                                       +18                                  TYA     CLV
             CPY  INY  BNE  CLD  CPX  INX  BEQ  SED
B739 (BC19): 24   53   1b   23   24   53   19   a1     +00                                                  CPY     CPX
B779 (BD19): 74   f4   cc   4a   72   f2   a4   8a     +08                                                  INY     INX
                                                       +10                                                  BNE     BEQ
                                                       +18                                                  CLD     SED

                                                        Offsets   Positive                  Negative
                                                            00      20      40      60      80      a0      c0      e0
             ***  BIT  JMP  JMP  STY  LDY  CPY  CPX    +04  ??*     BIT     ??*     ??*     STY     LDY     CPY     CPX     Zeropage
B741 (BC21): 00   1a   5b   5b   a5   69   24   24   ; +0c  ??*     BIT     JMP     JMP()   STY     LDY     CPY     CPX     Absolute
B781 (BD21): 00   aa   a2   a2   74   74   74   72     +14  ??*     ??*     ??*     ??*     STY     LDY     ??*     ??*     Zeropage,x
                                                       +1c  ??*     ??*     ??*     ??*     SHY*    LDY     ??*     ??*     Absolute,x

                                                        Offsets   Positive                  Negative
             TXA  TXS  TAX  TSX  DEX  ***  NOP  ***                                         80      a0      c0      e0   
B749 (BC29): ae   ae   a8   ad   29   00   7c   00   ; +0a                                  TXA     TAX     DEX     NOP     Accu/implied 
B789 (BD29): 44   68   b2   32   b2   00   22   00     +1a                                  TXS     TSX     ??*     ??*     Implied

                                                        Offsets   Positive                  Negative
             ASL  ROL  LSR  ROR  STX  LDX  DEC  INC         00      20      40      60      80      a0      c0      e0
B751 (BC31): 15   9c   6d   9c   a5   69   29   53   ; +06  ASL     ROL     LSR     ROR     STX     LDX     DEC     INC     Zeropage
B791 (BD31): 1a   1a   26   26   72   72   88   c8     +0e  ASL     ROL     LSR     ROR     STX     LDX     DEC     INC     Absolute
                                                       +0a  ASL     ROL     LSR     ROR     TXA     TAX     DEX     NOP     Accu/impl
                                                       +0e  ASL     ROL     LSR     ROR     STX     LDX     DEC     INC     Absolute
                                                       +16  ASL     ROL     LSR     ROR     STX^^   LDX^^   DEC     INC     Zeropage,x
                                                       +1e  ASL     ROL     LSR     ROR     SHX^^   LDX^^   DEC     INC     Absolute,x
                                                                                               ^^indexed using Y instead of X


#11
Quote from: XmikeX on January 04, 2011, 06:23 PM

...mnemonic encoding itself is easy to understand due to proper documentation


To elaborate on this, Mapping the 128 does indeed describe this encoding well, as follows:

:::::::::
46086 $B406 ASSMBLE -- Handles A (assemble) command or its equivalent (.).
Checks for values following the A or period (.) and signals an error if none is found.
The period is accepted as a synonym for A to simplify the assembly process by allowing you to edit the lines displayed by the D (disassemble) command. Since the D command automatically provides the period before each line, you may not have realized that it is treated as a separate command, but you can substitute it freely for A.

If only an address is found following the command, the routine simply returns to the main loop [$B08B].
Next, the routine searches for the first group of three nonspace characters.
Any values on the input line with fewer than three characters are ignored; this explains why the two-digit hexadecimal byte values displayed in front of the three-character mnemonic by the disassemble routine are ignored when the instruction is edited. It also explains why changes to the two-digit byte values are ignored by this routine.

The three-character pattern is then packed into a two-byte value. This packing scheme is a holdover from the RAM-resident monitors of earlier Commodore computers. It's really unnecessary in the 128, which has room to spare in this block of memory, but Commodore's programmers probably found it easier to reuse the existing code.

All 8502 ML mnemonics consist of combinations of the alphabetic characters A-Z. Since there are only 26 different valid characters, any single character can be represented by a five-bit value (which can hold 0-31), and three five-bit values can fit nicely into two eight-bit bytes.

As an example of how this packing works, suppose the pattern found is LDA-corresponding to hex bytes $4C $44 $41.
First, the value 63/$3F is subtracted from each byte, yielding $OD $05 $02. The binary equivalents are %00001101 %00000101 %00000010. The rightmost five bits of each value are shifted rightward into two bytes. The resulting packed mnemonic in these locations is %01101001 %01000100, or $69 $44.
:::::::::


This is my visually-oriented take on the above description:
::::
LDA --> #$4c #$44 #$41 --> 01001100  01000100  01000001 
       -#$3F #$3F #$3F   - 00111111  00111111  00111111 
       =#$0d #$05 #$02   = 00001101  00000101  00000010 
                              ^^^^^     ^^^^^     ^^^^^ --> 01101  00101  00010
                                                        --> 011010010100010
                                                        --> 01101001.0100010 +0
                                                        ==  01101001 01000100
                                                            (#$69)   (#$44)
#$69 = first byte  -> goes into table at $B721
#$44 = second byte -> goes into table at $B761

::::

ANC is a popular mnemonic label for an undocumented instruction with typical opcode 0B in immediate mode.

ANC --> #$41 #$4e #$43 --> 01000001  01001110  01000011
       -#$3F #$3F #$3F   - 00111111  00111111  00111111
       =#$02 #$0F #$04   = 00000010  00001111  00000100
                              ^^^^^     ^^^^^     ^^^^^ --> 00010  01111  00100
                                                        --> 000100111100100
                                                        --> 00010011.1100100 +0
                                                        ==  00010011 11001000
                                                            (#$13)   (#$C8)
#$13 = first byte  -> goes into table at $B721
#$C8 = second byte -> goes into table at $B761

You can test the encoding scheme by substituting the ANC mnemonic for some other mnemonic in the mnemonic table.
Substituting ANC for BRK is the simplest choice since BRK is at the start of the table.
Writing #$13 to $B721 and #$C8 in $B761 in ROM, or "basichi" file in VICE's C128 dir, changes BRK mnemonic label to ANC.
This won't introduce an actual ANC opcode (0B is one of them) into the monitor, but all references to opcode 00 BRK
will now show up as 00 ANC.
::::

XmX
#12
The other day, I noticed how VICE has become a liberating vehicle insofar as any taboos with ROMcode were concerned.  Just then it dawned on me that, for years, I've been dying to do some extensions for the 128's ML monitor within the ROM itself.  So, off I went, and located the monitor inside the basichi file in the VICE's C128 dir.... and behold, the legends were true, there really are 1100 bytes free in the ML Monitor ROM section.  (At this point, it is time to play with this thing.)

......but how to play with it?

Well that's an ongoing battle.  Some aspects are easy, other aspects are mysterious.

For example, while mnemonic encoding itself is easy to understand due to proper documentation, other spots seem to be poorly documented.  Just how are opcode bytes linked to that nefarious so-called OPCDTBL at $B6C3 (ala Mapping the 128) ??  Sounds like a challenge, and maybe we can have some fun with it (fun? this is fun?).
--

--Let's make OPCDTBL the focus of our efforts in this forum post.--

Looking at the raw OPCDTBL table data in memory or looping through the table with vicemon yielded little clues.  Where's the documentation?  The documentation is the assembler and calcmn routines in ROM?  That's not documentation, that's torture. =)

Alas, I jumped to the documentation, I mean disassembly, of these two key routines: "Monitor command: A (Assemble) $B406" and "$B659 CALCMN".   This is somewhat confusing and only yields a few clues for now, but this leads me to want to know how these two routines and that table work together on an opcode per opcode basis.

....about  halfway into it, I realized that the mathematics dancing around the OPCDTBL table could be nothing more than a decompression of sorts.  This encouraged me to believe that the REAL proper table (that did not have to fit in the confines of a PET.. thank you legacy code) could be realized out of this.

ASSUMING OUR DECODING IS CORRECT : The preformatted text further down illustrates the actual table and decoded table, and how it was done.
--
46787 $B6C3 OPCDTBL -- Opcode decoding table.  ( C128 ML MONITOR )
The values in this table are used by the mnemonic and mode calculation routine [$B659]
to determine the packed mnemonic table offset for the specified opcode value.

Address reference table in ROM   - 8x8 array +4
B6C3 (BE00): 40 02 45 03 d0 08 40 09
B6CB (BE08): 30 22 45 33 d0 08 40 09 
B6D3 (BE10): 40 02 45 33 d0 08 40 09 
B6DB (BE18): 40 02 45 b3 d0 08 40 09 
B6E3 (BE20): 00 22 44 33 d0 8c 44 00
B6EB (BE28): 11 22 44 33 d0 8c 44 9a
B6F3 (BE30): 10 22 44 33 d0 08 40 09
B6FB (BE38): 10 22 44 33 d0 08 40 09
B703 (BE40): 62 13 78 a9

Calculated table from address reference table - #$00-BF bytes   - 8x24 array

             40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
             30 62 30 22 62 22 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
             40 62 40 02 62 02 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
             40 62 40 02 62 02 45 13 45 b3 13 b3 d0 78 d0 08 78 08 40 a9 40 09 a9 09
             00 62 00 22 62 22 44 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 00 a9 00 11
             62 11 22 62 22 44 13 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 9a a9 9a 10
             62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09 10
             62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09 10

Calculated table from address reference table + SKIPs (see below) - #$00-FF bytes   - 8x32 array

             40 62 40 xx 02 62 02 xx 45 13 45 xx 03 13 03 xx d0 78 d0 xx 08 78 08 xx 40 a9 40 xx 09 a9 09 xx
             30 62 30 xx 22 62 22 xx 45 13 45 xx 33 13 33 xx d0 78 d0 xx 08 78 08 xx 40 a9 40 xx 09 a9 09 xx
             40 62 40 xx 02 62 02 xx 45 13 45 xx 33 13 33 xx d0 78 d0 xx 08 78 08 xx 40 a9 40 xx 09 a9 09 xx
             40 62 40 xx 02 62 02 xx 45 13 45 xx b3 13 b3 xx d0 78 d0 xx 08 78 08 xx 40 a9 40 xx 09 a9 09 xx
             00 62 00 xx 22 62 22 xx 44 44 33 xx 13 33 d0 xx 78 d0 8c xx 78 8c 44 xx a9 44 00 xx a9 00 11 xx
             62 11 22 xx 62 22 44 xx 13 44 33 xx 13 33 d0 xx 78 d0 8c xx 78 8c 44 xx a9 44 9a xx a9 9a 10 xx
             62 10 22 xx 62 22 44 xx 13 44 33 xx 13 33 d0 xx 78 d0 08 xx 78 08 40 xx a9 40 09 xx a9 09 10 xx
             62 10 22 xx 62 22 44 xx 13 44 33 xx 13 33 d0 xx 78 d0 08 xx 78 08 40 xx a9 40 09 xx a9 09 10 xx

This listing below illustrates modifications/additions to the ML Monitor Rom code used to decode the table.

The process works as follows : First, you must have the ML Monitor Rom section patched with the code below.
                                                     --  VICE makes this easy : relevant file in VICE is "basichi" in C128 dir.
                                                 Do a hard reset on your 128, or power-up from purely-OFF state.
                                                 Immediately go into ML Monitor after power-up.
                                                 Type A F3000 INC $3000,X
                                                     -- (doesn't have to be F3000 or $3000 specifically, just need to assemble INC $xxxx,X (FE opcide) into ram.)
                                                 Return to monitor command prompt WITHOUT assembling or disassembling anything else.
                                                 Memory (use M 1400 14FF) from $1400 to 14FF will now have the uncompressed table,
                                                      except for the last byte which is wrong (possible bug in code).
                                                      This last byte should be replaced by a "10" (manually checked).
                                                      We don't have a valid FF opcode that the monitor's assembler will (currently) accept,
                                                      so this is as far as we can fly with it.
                                                 If you are running this under VICE, you can copy the data from x128's ram (if you're using the VIC screen),
                                                      to your favorite text editor.

Relevant Routine starts at $B659
46681 $B659 CALCMN -- Calculates mnemonic and addressing mode.

. fb66a  4c 80 be jmp $be80   ; replace lda $b6c3,x with this, in order to jump to the routine below.
                              ; the code below starts at $be80, part of the ROM freespace (1100 bytes free)
[...]
; to the best of my knowledge, a proper human-readable table-decode for $B6C3 is not available in the literature.
; .. in other words, the proper uncompressed? (aka real) table data, is not available in any text,
; so instead of asking endless questions about it (we must spare our dear C= friends' patience),
; we're just going to have to try to generate it ourselves with the following code:

. fbe80  bd 00 be lda $b6c3,x ; duplicate the instruction which used to sit at $b66a
. fbe83  8d 00 13 sta $1300   ; we need to save all pre-existing variables first, so stash A to $1300 mem
. fbe86  8e 01 13 stx $1301   ; stash X to $1301 mem
. fbe89  8c 02 13 sty $1302   ; stash Y to $1302 mem
. fbe8c  ba       tsx         ; transfer stack pointer to X
. fbe8d  8e 03 13 stx $1303   ; stash X (our stack pointer) to $1303 mem
. fbe90  08       php         ; push processor status to top of the stack
. fbe91  68       pla         ; pull the processor status from stack and into A
. fbe92  8d 04 13 sta $1304   ; stash A (our processor status) into $1304 mem
. fbe95  ae 10 13 ldx $1310   ; load X from $1310 (this will set the pointer X.
                              ; we're assuming our patch routine here is running only
                              ; after hard reset where $1310 is "00", so that our
                              ; pointer will work as intended.)
. fbe98  ad 00 13 lda $1300   ; load A (our first A which we saved to $1300.
                              ; it is generated from lda $b6c3,x which is indexing
                              ; off the original "compressed" address reference table)
. fbe9b  9d 00 14 sta $1400,x ; stash this A to $1400+index byte denoted by X
. fbe9e  ee 10 13 inc $1310   ; increment $1310 (we're using $1310 as our pointer for X)
. fbea1  ad 04 13 lda $1304   ; ok..time to return all variables as they once were and
                              ; pass control back to the monitor, load A (our processor status) from $1304
. fbea4  48       pha         ; push A (processor status) to top of stack
. fbea5  28       plp         ; pull processor status from top of stack back to its normal spot
. fbea6  ae 03 13 ldx $1303   ; load X (our stack pointer) from $1303
. fbea9  9a       txs         ; transfer X (our stack pointer) back to its normal spot
. fbeaa  ac 02 13 ldy $1302   ; load original Y from $1302
. fbead  ae 01 13 ldx $1301   ; load original X from $1301
. fbeb0  ad 00 13 lda $1300   ; load original A from $1300
. fbeb3  4c 6d b6 jmp $b66d   ; jump back to instruction immediately after .fb66a lda $b6c3,x

Very good, we have our calculated table.  It's #$BF bytes long and is easily visualized as a 8x24 array (192 values) vs. the original table at #$44 bytes in length and visualized as an 8x8(+4) array (68 values).  We also know from the documentation, I mean disassembly, that the two opcode-generating routines ("Monitor command: A (Assemble) $B406" and "$B659 CALCMN") loop with this table (and sometimes SKIP the table).  On each loop they pull the presumed opcode byte from storage (then apparently check it against the mnemonic table?), increment it with the Accumulator, and put it back in storage until they've reached the proper opcode byte necessary to be assembled.  For example, to assemble PHP (opcode #$08) the loop goes round and round always adding +1 to the opcode byte in storage until #$08 is achieved.

A bit of a warning at this point:  We just noted that the monitor routines sometimes SKIP the table at $B6C3 while looping through to the desired opcode byte.  Our calculated table may therefore be incomplete.  The SKIPs seem to occur as follows:

08                     PHP           (40 62 40 <SKIP> 02 62 02 <SKIP> 45)
10                     BPL $xxxx (40 62 40 <SKIP> 02 62 02 <SKIP> 45 13 45 <SKIP> 03 13 03 <SKIP> d0)
18                     CLC           (40 62 40 <SKIP> 02 62 02 <SKIP> 45 13 45 <SKIP> 03 13 03 <SKIP> d0 78 d0 <SKIP> 08 78 08 <SKIP> 40)

Ramblings regarding this SKIP stuff: If we add the number of table reads with SKIPs we get a total of opcode byte + #$01.  It seems as if the main assembly routines loop (opcode-value+1) times when generating the actual opcode value.  Adding the SKIPs to the 8x24 array yields a 8x32 array (with SKIPs denoted by xx, as illustrated previously).  It may be that these SKIPs represent fill bytes for a full 00-FF table.  Fortunately, this is a work in progress and we can probably apply more monitor patches, or drudge through vicemon, etc., to find out. =)

Hopefully, we're progressing on the "want to know how these two routines and that table work together on an opcode per opcode basis" stuff.

Unfortunately, we're not there yet but our new calc'ed table sheds a glimmer.  The new table is generated by our patch routine by inputting INC $xxxx,X + "10".  However, you can use the patch routine to test out any valid instruction and generate partial table data.  In other words, you can see how far the table-data extends for the instruction/opcode you input, until the main monitor routine loops back to console input.  Please note : Our patch routine duplicates the last byte generated.  This may or may not be a bug, so the final byte may or may not be disregarded.  =)

A few examples are illustrated below (without SKIPs):

Opcode value - Mnemonic  (Table extension)
00                     BRK           (40)
01                     ORA           (40 62)
                         ($zp,X)
08                     PHP           (40 62 40 02 62 02 45)
10                     BPL $xxxx (40 62 40 02 62 02 45 13 45 03 13 03 d0)
18                     CLC           (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40)
20                     JSR $xxxx  (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                           30)
24                     BIT $zp      (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            30 62 30 22)
28                     PLP            (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            30 62 30 22 62 22 45)
[...]

FD                     SBC           (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                         $xxxx,x       30 62 30 22 62 22 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            40 62 40 02 62 02 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            40 62 40 02 62 02 45 13 45 b3 13 b3 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            00 62 00 22 62 22 44 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 00 a9 00 11
                                            62 11 22 62 22 44 13 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 9a a9 9a 10
                                            62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09 10
                                            62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9)

FE                     INC            (40 62 40 02 62 02 45 13 45 03 13 03 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                         $xxxx,x       30 62 30 22 62 22 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            40 62 40 02 62 02 45 13 45 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            40 62 40 02 62 02 45 13 45 b3 13 b3 d0 78 d0 08 78 08 40 a9 40 09 a9 09
                                            00 62 00 22 62 22 44 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 00 a9 00 11
                                            62 11 22 62 22 44 13 44 33 13 33 d0 78 d0 8c 78 8c 44 a9 44 9a a9 9a 10
                                            62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09 10
                                            62 10 22 62 22 44 13 44 33 13 33 d0 78 d0 08 78 08 40 a9 40 09 a9 09)
---

XmX
#13
Community Projects / Re: Media Player 128
January 01, 2011, 01:32 PM
I'm wondering if there's some place in your code for undocumented ops, especially in your timing sensitive portions.

For example, looking at some of your sources I noticed stuff like this:

jIRQ2r3.src
   lda myVicY+1   ;[4] get y_scroll and stuff
   and #7      ;[2] mask y_scroll
   clc      ;[2]
   adc #constC   ;[2]
   adc vHeight   ;[4] rasters in video

With respect to the AND / CLC sequence above, would it be desirable/useful to save 2 cycles with "ANC" instead?
If not, then how about elsewhere?  How about with other "illegals" like LAX, SAX, which seem to work solid on 128s (IIRC)? ...

This page seems to describe ANC nicely : http://codebase64.org/doku.php?id=base:some_words_about_the_anc_opcode

65816 accelerator compatibility? who cares!?  =)

XmX

PS: This was amusing for me as well .. http://codebase64.org/doku.php?id=base:decrease_x_register_by_more_than_1
#14
Rebuttal..

#2 - nintendo dishes out concept games all the time, and even sony is known to have few odd concept games every now and then

#3 - I wonder what those FMV sequences of latest generation of Command & Conquer games were all about...

#4 - blatant copying can and will happen. check out Singstar-wannabe 'Lips' on x360... or...
        (or maybe every FPS made since Doom.. perhaps..)

#5 - publishers have, are, and shall continue to work in the most 'interesting' places.

#7 - games on cartridges never disappeared. they've followed nintendo all the way, as pointed out already.

#8 - given the right title, there is still the possibility to rise to fame with game music.
        (pay attention to wipeout series (through ps1/ps2/psp/ps3), it's been a regular superstar-generator)

#9 - MoCap came to replace digitized graphics. it's effectively the same, however, only for different era.

#11 - plenty of unattractive characters out there - this one comes to mind right off the bat (since it's still fresh in memory): http://www.thegamecritique.com/wp-content/uploads/2010/02/Brutal-Legend-3.jpg  Also, stuff like left 4 dead 1 and 2 have a decidedly average bunch of main characters, which makes them believable.

#12 - almost every soccer/hockey game you can rig to overhead view mode through menu buttons

#13 - Archer MacLean would most certainly disagree at this point. he can and will bring out games starring "inanimate objects" (or substances/liquids).

#15 - if you never see it coming, it counts as completely random.   no, this insanity never really went away.
         (e.g., Killing Floor loves to spawn a fleshpound or scrake 2 feet from you... just as soon as you turn around and look the other direction for a moment ... basically instant death)

#16 - simple enough idea with low enough production costs and moderately sized development studio, we will all walk away as millionaires.  PopCap games, I am looking at you.

#18 - Bioshock, Left4Dead, Call of Duty games (among others) make a big point about their Loader screens.

XmX

Side Note : one-man dev teams · probably now more than ever for iphone, as suggested in this thread.
it seems as if iphone these days has more titles than all computers+consoles combined from 1980s onwards.  gee, that was fast.
#15
For reference, Zer0-X is using a Zeroplus Logic Cube LAP-C 16032 that has been modded to 322000 model by changing the internal SRAM chip and soldering in another bus transceiver and other required components.

Pic below:

http://starbase.globalpc.net/~xmx/zrx_zeroplus.jpg (temp link)

XmX
#16
This next recording from Zer0-X, attached below, is synced to z80phi.

http://starbase.globalpc.net/~xmx/C128_Z80_boot.gif  (temporary link)

XmX
#17
Herdware / C-128 Z80 phi - visualized with analyzer.
December 27, 2010, 09:41 AM
Zer0-X from Finland (kiitos!) was kind enough to test the 4 MHz clock on z80's pin 6 with his analyzer.
He generated the .gif attached to this post.

XmX


EDIT : okok.. i'm hearing from non-registered users that they can't see the attachment.
           Here's a link to the file: http://starbase.globalpc.net/~xmx/z80phi.gif  (temporary, may expire)
#18
Herdware / Re: Z80
December 27, 2010, 05:33 AM
Tangentially related to the thread here, an interesting Z80/C128 thread on usenet : http://groups.google.com/group/comp.sys.cbm/browse_thread/thread/60e46cab6bb731f5/bec3d794a00567fa?hl=en&

- end summary here : http://groups.google.com/group/comp.sys.cbm/browse_thread/thread/712680742367b2fc/f7c66d120e620e?hl=en&q=#00f7c66d120e620e

At the moment, I can find no further record of the OP's progress beyond 2004.
Unfortunately, the OP (Sven Paepke) seems to have died in a diving accident in 2007.

XmX
#19
In case anyone else is wondering, ZP fill as hydrophilic mentioned (STA $zp,x) can work as follows:

.. for illustrative purposes on the 40x25 screen .. remember, VIC-IIe screen memory typical range is $0400-07FF ..

Paste into the ML monitor:
.f3000 ldy #$04         <--- set Y to the number of 256-byte pages you want to fill
.f3002 ldx #$02         <--- set X to #$02 to avoid $00/01 in sta $00,x below
.
.For sanity's sake, we're avoiding the CPU's built-in I/O ports at $00/01.  They are always visible while 8502 is active and therefore all references to/from $00/01 in Zero Page or Relocated Zero Page will affect these I/O ports.
.
.f3004 lda #$04         <--- we need to set up a start page for ZP relocation, so we load A with #$04 and ..
.f3006 sta $d507       <--- relocate zero page to start at $0400 here.
.f3009 lda #$00         <--- load A with our fill-byte, which is #$00, representing"@"
.f300b sta $00,x        <--- start at $02 ($00+02) and work up to $FF .. avoid $00/01
.f300d inx                   <--- increment X so that we can work up to $FF in the same page
.f300e bne $300b      <---  this checks if X=0, since X will overflow to #$00, and then we can leave the loop
.f3010 inc $3005        <--- increment the memory location holding #$04 above, so that we can score a new page to fill (#$04 becomes #$05.. page pointer sets to $0500..etc)
.f3013 dey                 <--- decrement Y from above.. Y keeps track of how many pages we want to fill.
.f3014 bne $3002      <--- this checks if Y=0, once Y hits #$00, we can leave this loop
.f3016 lda #$00         <--- we're done with our loops, so we load A with #$00
.f3018 sta $d507       <--- and stash A here to set zero page to its normal spot
.
Are we done?  not yet...
.
Since we've just safely relocated zero page to its usual spot, we can fill in these missing $00/01 areas very simply :
.
.f301b sta $0400       <--- to fill in $00/01 stuff that we avoided earlier, we apply these sta's as patches
.f301e sta $0401             **these sta's reuse the #$00 byte we loaded recently into A because #$00 is
.f3021 sta $0500                 our original fill-byte in any case.  Whatever fill-byte you use must be loaded into A
.f3024 sta $0501                 before applying these sta's here.
.f3027 sta $0600
.f302a sta $0601
.f302d sta $0700
.f3030 sta $0701
.f3033 rts                   <--- return from subroutine

j f3000        to execute within monitor
--

Benefits with ZP relocation and STA $zp,X vs. STACK relocation and PHA, as noted by hydrophilic:
    - we can have IRQs happen while we are messing with ZP
    - we can do sequential or random access at 4 cycles per byte
--

Unfortunately, MMU STACK relocation and PHA is still a very appealing 3 cycles per byte.

Fortunately, STA $zp happens to be 3 cycles, IIRC.... so we can trade memory for speed.
For example, we can set up a "table" of unrolled STA $zp bytes, instead of STA $zp,X.  We can then jump to this "table" wherever and whenever needed.

...jump here at start of "table" or anywhere within the "table"
...With respect to sta $zp, your "table" can be organized beforehand to suit your needs.  It's not necessary to have sta $02..03..04.. as i've laid it out.
sta $02      <-- 3 cycles per sta $zp
sta $03   
sta $04
sta $05
[...]
sta $fc
sta $fd
sta $fe
sta $ff
...jump back to wherever, or return to whatever called the "table"

We now have the benefit of 3 cycles per byte and no cycles lost to loop-activity.  Setting up a "table" for PHA works as well, but the speed gains for PHA will only come from being outside a loop since each PHA remains at 3 cycles.

The slight disadvantages to "tables" is that "table" action must be set-up beforehand, and they do eat up some memory.

XmX

PS: No one pointed out that ugly ADC business (and other trifles) in my original post.  It's been a while since I've messed with this stuff, and I momentarily forgot about some things .... like INC $xxxx. =)

PPS: Thanks to iAN_CooG for reminding me of certain properties of ADC (CLC, ADC).
#20
Quote from: airship on October 05, 2010, 09:55 AM
These were used by Xerox in a research lab. Each board has two 6522 VIAs and logic chips to use each 6522 as two parallel ports. That makes each board a quad parallel interface.
This brings back memories of ye olde Interfacing Blue Book ..

.. Dual User ports (sort of) with CIA, on page 60, here : http://www.bombjack.org/commodore/books/pdf/Commodore_64_Interfacing_Blue_Book.zip

http://www.bombjack.org/commodore/   (Thanks again, DLH and DLH's contributors!)

XmX
#21
With respect to diagnosing C128s, is it safe (and meaningful/useful) to test voltages here -> VIC IIe pins/lines 26,27,28 on power-up?  Specifically, I would presume testing these pins/lines would let me know if Z80 is good/bad and if Z80bios rom relocation has/has not occurred.

My rationale (hopefully correct) is as follows:
--
Early in the c128 boot sequence the following appears:
"0041:       ED 51             OUT (C),D                write #$FF (11111111) to $D02F."

and this appears just before the C128 is forced into 1MHz mode, oddly enough,
as noted here --> http://www.commodore128.org/index.php?topic=3670.msg18033#msg18033

According to Mapping the 128 and others, $D02F is the Extended Keyboard Scan-Line Control Register (XSCAN). Setting XSCAN bits 0-2 to 1 slams the output lines (K0, K1, K2) to a high (+5v) state.

According to this - http://www.zimmers.net/anonftp/pub/cbm/schematics/computers/c128/310378-2-right.gif , K0-K2 correspond to pins 26-28 on the VIC IIe.
--

XmX
#22
A few questions ....

1) Why no Memory Mapped $Dxxx I/O for Z80 ?  Please note the following examples.

Example 1 - Store any 8-bit value into $FF00    ACCEPTABLE, FUNCTIONAL

  ld a,#$xx         (LDA #$xx)   Acceptable
  ld ($ff00),a         (STA $ff00)   .. $FF00 is visible in all configurations, we can use ld ($ff00),a

Example 2 - Store any 8-bit value into $DXXX    UNACCEPTABLE, NON-FUNCTIONAL

  ld a,#$xx         (LDA #$xx)   $d000-dfff is the block of addresses where I/O sits.
  ld ($dxxx),a         (STA $dxxx)   simple store here falls through to RAM sharing the same addresses as I/O.

Example 3 - Store any 8-bit value into $DXXX    ACCEPTABLE, FUNCTIONAL with OUT instruction.

  ld a,#$xx         (LDA #$xx)   Load 8-bit value into Accumulator (a)
  ld bc,$dxxx               Load $dxxx into registers b and c
  out (c),a               Put value in (a) into I/O ($dxxx) not RAM ($dxxx)

Example 4 - Changing 40 column (VIC-II) Background Color to Black

  Z80 using OUT
      ld a,0
      ld bc,$d021
      out (c),a         .....3 instructions to finish this task

8502
      LDA #$00
      STA $d021      .....2 instructions to finish this task

BASIC
      POKE 53281,0

Access to $FF00 is load/store.  Why did CBM go "by the book" with $Dxxx?  Why no MMIO there with simple load/stores?  I would have preferred MMIO while reserving IN/OUT for accessing the ram "under" the I/O block.
--

2) As per the literature, the Z80 rom is physically located at the $Dxxx I/O block and Z80 sees this rom at $0000--.  How is this done?  Does this "relocation" play a role with respect to the IN/OUT requirement for I/O access?
--

3) The z80 bios rom startup, as follows:

ADDR   Bytes on disk   Z80 code     PSEUDO-6502 Equivalent and Comments
   ----   ---------------------------------------------------------------------------------
  0000:       3E 3E             LD A,$3E          LDA #$3E
  0002:       32 00 FF         LD ($FF00),A   STA $FF00   nothing new here
  0005:       C3 3B 00        JP $003B         JMP $003B   jump to $003B
[..........]
  003B:       01 2F D0        LD BC,$D02F    ye olde XSCAN (extended keyboard)
  003E:       11 FC FF        LD DE,$FFFC     LDX #$FF  and  LDY #$FC
  0041:       ED 51             OUT (C),D         STX $D02F       write #$FF (11111111), set output lines high.. why? maybe we'll find out later in the rom...
  0043:       03                  INC BC             now BC=d030 -- ye olde CLKRATE
  0044:       ED 59             OUT (C),E         STY $D030    write $FC (11111100), bit0 to (1 MHz-Mode), bit1 (test-bit, interlace) to 0.


Without even thinking about "Why the #$FF to $D02F?", why does #$FF-> $D02F happen --before-- the system is forced to 1 MHz?  ...$D02F is at VIC IIe, so why fiddle with this register before making sure VIC is "safe" @ 1 MHz?
--

4) and finally....

Z80 using OUT
      ld a,0
      ld bc,$d021
      out (c),a

Why does it seem as if every bit of Z80 documentation characterizes the OUT instruction as if it only holds the lower byte (c) instead of the proper/full two-byte address (bc) ?!   I would expect source code to read as follows: OUT (bc),a for two byte address, and OUT (c),a for one byte address.
--

XmX
#23
Nederlands / Genoeg Engels! Spreek Nederlands!
December 19, 2010, 10:26 AM
Welkom nederlandse CBM-ers op dit forum.

XmX
#24
Suomi / Pois Englanti, Pois PakkoRuotsi !
December 19, 2010, 10:09 AM
Toivotan täten Suomalaiset Commodore-käyttäjät tervetulleeksi tälle foorumille.

XmX
#25
This is an odd "feature", and interesting enough for a necrobump (sorry) back to active status.

If anyone has any other MMU anomalies to report, please do and please follow-up on them!  (I'm still waiting for someone from that 1997 USENET thread to elucidate the MMU "feature" which supposedly activates Z80 & 8502 simultaneously.)  (!!)  =)

XmX