User Tools

Site Tools


magazines:discovery1

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

magazines:discovery1 [2015-04-17 04:35] (current)
Line 1: Line 1:
 +<​code> ​
 + 
 +                             ////////​
 +          //              ////////
 +         // ​            ////////​
 +        //       /// ​ /////// ​ /////                         
 +    /////  //  //    /////// ​           /////   // ​    // ​ ///  /////  //   //
 +  //  //  // /////// ​ /////// ​ /////  //    //  //    //  /  / //      //  //
 + // ​ //  //     // ​    /////// ​       //    //   // //   //// ​ //      // // 
 + //// ​  // ​  /// ​        //////// ​     /////      //    /      //       //
 +                          //////// ​                    /// ​          //
 +                                        /////////////////////////////​
 + 
 +                 The Journal of the Commodore Enthusiast
 + 
 + 
 +                      I s s u e  1  :  May 17, 1996
 + 
 + 
 +                             P R E A M B L E
  
 +
 +We greet you to the first issue of disC=overy, the Journal of the Commodore
 +Enthusiast. ​ Our inspiration for launching this work derives from you, the
 +ones who still hold our beloved 8 bit machines in high regard and respect.
 +In honor of your committment to these classic platforms we have pledged
 +ourselves to assemble this entire journal on modest C64 and C128 systems.
 +It is our sincerest hope that you will find our efforts to be of interest
 +and special joy.  We thank you from the bottom of our hearts and look forward
 +to forging a solid productive relationship with all of you.
 +
 +  - Mike Gordillo, Steven Judd, Ernest Stokes, and the authors of disC=overy.
 +
 +
 +                A R T I C L E S    O F    O P E R A T I O N
 +
 +
 +Article 1 : Mission Statement
 + 
 +Our intent is to present useful information in order to enhance and preserve
 +the knowledge base of the Commodore 8-bit domain, including, but not limited
 +to, the Commodore 64 and Commodore 128 home computers. ​ To this end, we shall
 +require that every article contain what in our discretion should be a viable
 +Commodore 8-bit hardware and/or software point of relevance. ​ Likewise, each 
 +issue should include material that can both potentially enlighten the most
 +saavy of users as well as the layman. ​ We intend to complement and assist all
 +others engaged in similar endeavours. ​ We believe it is of paramount concern
 +to stave off entropy as long as possible.
 + 
 + 
 +Article 2 : disC=overy Staff
 + 
 +The current staff of disC=overy, the Journal of the Commodore Enthusiast,
 +is as follows:
 + 
 +        Editor-in-Chief ​ : Mike Gordillo ​ (s0621126@dominic.barry.edu)
 +        Associate Editor : Steven Judd    (judd@merle.acns.nwu.edu)
 +        Webmaster ​       : Ernest Stokes ​ (drray@eskimo.com)
 + 
 +We invite any and all interested parties to join us as authors, panelists,
 +and staff members.
 + 
 + 
 +Article 3 : General Procedures
 + 
 +The Editor-in-Chief shall supervise the organization of each issue in regards
 +to grammatical and syntactical errors, flow of content, and overall layout of
 +presentation. ​ The Editor-in-Chief and Associate Editor shall form a review
 +panel whose function it shall be to referee literary work which the Editor
 +in-Chief has deemed to be of advanced technical and/or social merit. The Editor
 +in-Chief and disC=overy, the Journal of the Commodore Enthusiast, shall retain
 +copyright solely on the unique and particular presentation of its included body
 +of literary work in its entirety. ​ Authors shall retain all copyrights and
 +responsibilities with regards to the content of their particular literary
 +work.  Authors shall be required to submit their works to the Editor-in-Chief
 +approximately two weeks prior to publication.
 +
 +
 +Article 4 : Peer Review
 + 
 +To the best of our knowledge, disC=overy shall be the first Commodore 8-bit
 +journal with a review panel dedicated to uphold the technical integrity and
 +legitimacy of its content. ​ The Editor-in-Chief and the Associate Editor
 +shall be responsible for the formation of the panel. ​ The appointed
 +panelists shall have the option of anonymity if desired. ​ The panel shall
 +review works primarily for technical merit if the Editor-in-Chief and
 +the Associate Editor deem it necessary. ​ Authors may be asked to modify
 +their works in accordance with the panel'​s recommendations. ​ The Editor-in-
 +Chief shall have final discretion regarding all such "​refereed"​ articles.
 +
 +
 +Article 5 : Distribution
 +
 +Although we welcome open distribution by non-commercial organizations,​ there
 +are currently two "​secure"​ distribution channels available to interested
 +parties. ​ This journal may be obtained by directly mailing the Editor-in-Chief
 +or via the World Wide Web at http://​www.eskimo.com/​~drray/​discovery.html
 +
 +
 +Article 6 : Disclaimers
 + 
 +The Editor-in-Chief and disC=overy, the Journal of the Commodore Enthusiast,
 +retain all copyrights regarding the presentation of its articles. ​ Authors
 +retain all copyrights on their specific articles in and of themselves,
 +regarding the full legal responsibility concerning the originality of their
 +works and its contents.
 +
 +The Editor-in-Chief and disC=overy, the Journal of the Commodore Enthusiast,
 +grants the reader an exclusive license to redistribute each issue in its
 +entirety without modification or omission under the following additional
 +stipulations:​
 + 
 +      - If distribution involves physical media and is part of a commercial,
 +        not-for-profit,​ or PD distribution,​ the maximum allowable monetary
 +        charge shall not exceed $4 1996 United States Dollars per issue
 +        unless more than one issue is distributed on a single media item
 +        (i.e., two or more issues on one disk), in which case maximum
 +        allowable charge shall not exceed $4 1996 United States Dollars per
 +        media item.  All dollar values given assume shipping costs are
 +        -included- as part of the maximum allowable charge.
 + 
 +      - If distribution involves non-physical media and is part of a
 +        commercial, not-for-profit,​ or PD distribution,​ the maximum
 +        allowable charge shall be limited to the actual cost of the
 +        distribution,​ whether said cost be in the form of telephony or
 +        other electronic means.
 + 
 +It is understood that distribution denotes acceptance of the terms listed and
 +that under no condition shall any particular party claim copyright or public
 +domain status to disC=overy, the Journal of the Commodore Enthusiast, in its
 +entirety.
 + 
 +The Editor-in-Chief and disC=overy, the Journal of the Commodore Enthusiast,
 +reserve the right to modify any and all portions of the Preamble and the
 +Articles of Operation.
 +
 +
 +:::::::::::​d:​i:​s:​C=:​o:​v:​e:​r:​y:::::::::::::::::​i:​s:​s:​u:​e::​1::::::::::::::::::::​
 +::::::::::::::::::::::​T A B L E  O F  C O N T E N T S:::::::::::::::::::::::::​
 +:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ​
 +
 +
 +-Software Section-
 +
 +/S01 - "​Explorations on IFLI"
 +$d000   by Adrian Gonzalez and Mike Gordillo
 +
 +/S02 - "​TRI-FLI:​ A new video mode '​abrewing?"​
 +$d000   by George Taylor and Mike Gordillo
 +
 +/S03 - "​Heaven in the net, an unedited excerpt of IRC on #c-64"
 +$d000   by Mike Gordillo
 +
 +/S04 - "A complete dissection of Gfx-Zone"​
 +$d000   by "​XmikeX"​
 +
 +/S05 - "A Beginner'​s Guide to the JCH Editor V2.53, NewPlayer V14.G0"​
 +$d400   by Sean M. Pappalardo
 +
 +/S06 - "An inside look at MODplay 128"
 +$d400   by Nate Dannenberg and Mike Gordillo
 +
 +/S07 - "Some preliminary data on VDC timing"​
 +$d600   by Steven L. Judd
 +
 +/S08 - "​Software analysis and reconstructive therapy, a historical view
 +$dd00   on '​cracking'"​
 +        by Pontus Berg
 +
 +/S09 - "A Quick Overview of CP/M"
 +0100h   by Mike Gordillo
 +
 +/S10 - "The BIOS-R62a/​ZPM3/​ZCCP Commodore 128 CP/M 3.0+ Upgrade Package
 +0100h   and a bunch load of utilities!"​
 +        by Mike Gordillo
 +
 +
 +-Hardware Section-
 +
 +/H01 - "​BEYOND STEREO - The POWER-SID Model 2400 : It May Not be THX but
 +        it's Taking the Commodore One Dimension Closer"​
 +        by Shaun Halstead
 +
 +/H02 - "The 8 bit Modplay 128 Board"
 +        by Nate Dannenberg
 +
 +/H03 - "​Upgrading your C128's VDC memory to 64K"
 +        by Mike Gordillo
 +
 +/H04 - "The Metal Shop"
 +        with SMS Mike Eglestone
 +
 +
 +:::::::::::​d:​i:​s:​C=:​o:​v:​e:​r:​y:::::::::::::::::​i:​s:​s:​u:​e::​1::::::::::::::::::::​
 +/​S01::​$d000:::::::::::::::::::​S O F T W A R E:::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +
 +                            Explorations on IFLI
 + 
 +                    by Adrian Gonzalez and Mike Gordillo
 + 
 + 
 +Adrian Gonzalez is a true Commodorian,​ a rare breed in his native country of
 +Mexico. ​ He has spent the past year or so converting .gif and .jpeg files into
 +the IFLI format on the C64.  His endeavours have allowed many a C64 owner to
 +enjoy high quality images.
 +
 + 
 +> Adrian, before we start, can you give us some background on what IFLI is and
 +> how it achieves such stunning images?
 + 
 +    Sure thing. ​ A little multicolor bitmap mode and FLI mode background is in
 +order too.  Images in the '​regular'​ multicolor bitmap mode (MCBM from now on)
 +are divided in cells or blocks that are 4 pixels wide and 8 pixels tall.  The
 +screen is split into 40 columns of these blocks horizontally and 25 vertically,
 +giving a total of 1000 4x8 pixel cells or blocks. ​ A pixel in one of these
 +blocks can have any one of 3 colors common to the entire block, or the
 +background color, common to the entire screen. ​ A FLI picture is similar to a
 +regular MCBM picture in that it has the same resolution (160x200), however, it
 +is more flexible in terms of how many colors you can use in each 4x8 character
 +block. ​ This flexibility is achieved through complex timing tricks which I'd
 +rather explain in a future article, but I'll give a very brief overview of what
 +they make the VIC-II do.  Basically, the trick is to fool the VIC chip into
 +fetching the screen memory data on every rasterline. ​ This screen memory data
 +is responsible for 2 of the 4 colors available on each 4x8 character block in
 +MCBM (bit pairs '​01'​ and '​10'​). ​ So this basically divides each 4x8 cell of
 +MCBM into eight 4x1 cells, making the VIC chip fetch a different pair of colors
 +from screen memory for each rasterline (each 4x1 cell). ​ This trick gets rid of
 +most of the restrictions that MCBM imposes, since now 2 of the 4 pixels in
 +every cell can have any one of the 16 available colors. ​ Chances are the colors
 +needed for the other two pixels will be available from either screen memory,
 +color memory or the background color. ​ This flexibility,​ of course, does not
 +come without a price: ​ storage. ​ This technique multiplies the amount of memory
 +needed for screen data times 8, adding 7000 bytes when you compare with a
 +standard koala paint file.  Fortunately,​ the 8000 bytes needed for screen
 +memory and the 8000 for the bitmap fit just right on one 16k bank (remember the
 +VIC can only '​see'​ 16k at a time).
 + 
 +    If you are new to these software screen modes, I recommend you read the
 +previous part again, especially because once you get the grasp of FLI mode,
 +IFLI is a snap.  IFLI mode is basically two FLI pictures being rapidly
 +alternated to give the illusion of more colors. ​ So where does the added
 +resolution come in?  Thanks to the VIC-II'​s hardware, it is possible to shift
 +the screen up to 7 hi-res pixels horizontally,​ even when in MCBM.  The trick in
 +IFLI is to display one FLI picture for an entire screen refresh, then display
 +the second FLI picture shifted one hi-res pixel to the right on the next
 +redraw. ​ The effects of this are not so obvious, so I'll illustrate with an
 +example. ​ Suppose you have the first line of FLI picture A and FLI picture B
 +and it looks like this:
 + 
 +First line of FLI picture A:
 +Ü  K  Ü  G  Ü  Y  Ü  O  Ü . . .
 + 
 +First line of FLI picture B:
 +Ü  G  Ü  G  Ü  Y  Ü  O  Ü . . .
 + 
 +When you alternate them, shifting picture B one hi-res pixel to the right you
 +get:
 +Ü  K  Ü  G  Ü  Y  Ü  O  Ü. . .
 +   ​Ü ​ G  Ü  G  Ü  Y  Ü  O  Ü
 +------------------------------
 +ÜK ÜKGÜG ÜG ÜGYÜY ÜYOÜO Ü. . .
 + 
 +Where:
 +K = Black pixel
 +G = Green pixel
 +Y = Yellow pixel
 +O = Orange pixel
 + 
 +The resulting line has pixels that are as wide as high resolution pixels, and
 +that may have colors that are combinations of the c64's 16 standard colors. It
 +is evident from this example that IFLI's strengths lie in reproducing images
 +with smooth color shades. ​ The downside of IFLI is that it flickers, and
 +depending on the colors that are being alternated, the flicker can go from
 +barely noticeable to a stroboscopic light show.  With this in mind, however,
 +this display mode can produce some of the most stunning images that have ever
 +been displayed on our beloved C64.  After this brief introduction I hope the
 +interview will make a little bit more sense, so let's get on with it.
 +
 + 
 +> Adrian, I know you do the bulk of your conversions on other platforms for
 +> the sake of expiediency. ​ However, I'm more generally interested in how
 +> the pictures get down to the C64 in terms of the actual display on the C64.
 + 
 +Well, I start out by doing careful color analysis on my Amiga. ​ This involves
 +pre-processing the images in programs such as The Art Department Professional,​
 +in order to adjust the brightness, contrast, color and size of the source
 +images. ​ After that, I feed the images to a conversion utility I wrote that
 +tries (as best as possible) to map the colors from the original image to
 +combinations of the 16 colors of the c64, taking many factors into
 +consideration,​ such as flicker. ​ The conversion program has several settings,
 +which have to do mostly with dithering and flicker reduction. ​ It is not always
 +perfect, and the problem of IFLI flicker is never truly defeated, but I'm
 +generally satisfied with the results.
 +
 + 
 +> Yes, they are beautiful conversions,​ but I could never get them to display
 +> with any other IFLI viewer.
 + 
 +Since there is no standard data format for IFLI pictures I had to come up with
 +my own.  My ifli's load at $2000, then the code moves them to the higher memory
 +and depending on how big they are, of course, they get depacked accordingly.
 +
 + 
 +>Argh, they are packed?
 + 
 +Of course they are packed. ​ When was the last time you saw two of them having
 +the same size? :)
 +
 + 
 +> What kind of packer did you use?
 + 
 +They are packed using a very simple RLE routine. ​ If you want you can use the
 +routines in my viewer to depack them for you.  They'​ll set everything up in the
 +right place. (e.g. $4000-7fff, $c000-$ffff and $d800-$dbff). ​ If anybody is
 +interested in these routines or the source code for the viewer, feel free to
 +mail me and I'll send them your way.
 +
 + 
 +> Why did you split the data over those addresses? ​ Is it safe to assume that
 +> IFLI data is composed of two 16 kbyte blocks for pic data and then comes the
 +> color info at $d800 on up?
 + 
 +Yeah, you can look at it that way.  It's actually two 8k blocks containing the
 +bitmaps and two 8k blocks containing the screen memory.
 +
 + 
 +> Ah, I see.  There is one FLI pic portion in each 8k bitmap and one 1k block
 +for color memory that is common to both images.
 + 
 +Yes, but you know, it might be interesting if it were possible to change color
 +memory as well.  It would give us a slight boost in the number of apparent
 +colors.
 +
 + 
 +> Could you explain exactly how, and wouldn'​t any further memory tweaking
 +> complicate matters more?  Maybe you would need to not use the entire screen?
 + 
 +Oh, just mumbling out loud :).  In practice there is no time to change color
 +memory on the fly.  Also, it doesn'​t matter if you do IFLI's smaller than the
 +entire screen (say 1/3 screen IFLI) because you still have data scattered all
 +over the same ranges I described earlier. ​ The IFLI data must be placed at
 +certain spots in memory so that the VIC-II chip can properly fetch it.
 +
 + 
 +> Ok, I understand, but this 1/3 IFLI screen proposal intrigues me greatly.
 +> I hear "less than full-screen"​ IFLI's may be doubled-over onto themselves,
 +> thereby giving even more colors or perhaps leading to run-time IFLI
 +> animations.
 + 
 +This is a possibility,​ but you would have even more flicker than regular IFLI.
 +I'm not even sure if the logistics involved will allow even a 1/3 IFLI to be
 +doubled over.
 +
 + 
 +> Well, if the CPU proves too slow, what about using the speedy REU to do the
 +> job?
 + 
 +Interesting,​ the problem is that since I'm not lucky enough to own one, I do
 +not know how much overhead it takes to set up the REU for multiple transfers. ​
 +For example, if I wanted to transfer 512 bytes of screen memory, then reprogram
 +the REU to transfer another 512 bytes, I would need to know how many cycles it
 +would take for each request I sent to the REU and then fit it into the IFLI
 +code.  As I hinted at earlier, IFLI data (except for the bitmaps of course) is
 +scattered in little chunks.
 +
 + 
 +> I purloined some standard pre-code from George Taylor. ​ It sets up the REU
 +> transfer with regards to screen memory, as follows:
 +
 +> lda #0
 +> sta control ; to make sure both addresses are counted up
 +> lda #<$0400
 +> sta c64base
 +> lda #>$0400
 +> sta c64base + 1
 +> lda #0
 +> sta reubase
 +> sta reubase + 1
 +> sta reubase + 2
 +> lda #<$0400
 +> sta translen
 +> lda #>$0400
 +> sta translen + 1
 +> lda #​%10010000; ​ c64 -> REU with immediate execution
 +> sta command
 +>
 +> Total cycle count is around 60 cycles in this case, but if you shave off
 +> some formalities (direction, transfer length) you can cut it to 30 cycles,
 +> as follows:
 +
 +> lda #<​any64addy
 +> sta c64base
 +> lda #>​any64addy
 +> sta c64basehi
 +> lda #<​anyReuaddy
 +> sta reubase
 +> lda #>​anyReuaddy
 +> sta reubasehi
 +> lda #$91
 +> sta command
 +
 +
 +> So if you implemented a set up time of 30 cycles per transfer, would this
 +> allow some IFLI doubling or animations?
 + 
 +Hmm, you need 8 requests for screen mem + 1 for color + 2 bitmaps. ​ So, 30
 +cycles just for the setup and then 1 byte per cycle transfer... that's quite
 +good.  I think even my most optimized copy routine for internal memory moves
 +would not match this, at least for large transfers (you'​ve gotta love DMA :-).
 +
 + 
 +> But even with 60 cycles or less, could the reu copy memory much faster with
 +> all the little bits and pieces involved.
 + 
 +Yeah, either that or use 2 mhz mode on a 128, which would not be something I'd
 +like to do.  I think the REU is a better vehicle for doubled-IFLI or even IFLI
 +animations, although I do not think full-screen IFLI's could be coaxed into it.
 +
 + 
 +> Well, just shrink an IFLI pic to the dimensions of a sprite and double it or
 +> animate it over several times :)
 + 
 +Come to think of it, pc users watch video in postage stamp-sized windows :).
 +But there are other factors to consider though, such as the effect of the
 +picture alternation on the animation. ​ The IFLI color effect could be lessened
 +by an animation with a high frame rate.  It would be a very good experiment,
 +though. ​ Who knows, maybe with the upcoming 20mhz boards we could even have an
 +MPEG player for the c64 :).  As for me, all I need now is somebody to donate
 +their REU in the name of IFLI research :-).
 +
 +--
 +For more information,​ gripes, etc, Mr. Adrian Gonzalez may be reached at the
 +following internet addresses: al170866@academ01.mty.itesm.mx
 +                              agonzalez@nlaredo.globalpc.net
 +
 +
 +/​S02::​$d000:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +                   ​TRI-FLI : A new video mode '​abrewing?​
 + 
 +                     by George Taylor and Mike Gordillo
 + 
 + 
 +George Taylor can be described as one of the few hard-core Commodore 64
 +purist coders. ​ His mission is to advance the applicable knowledge base
 +and utility of the C64 by bringing to bear a deep understanding of the
 +hardware and software behind it.  It is often said that chance favors the
 +prepared mind, but in George'​s case, the prepared mind leaves nothing to
 +chance.
 + 
 +> George, I am very curious about your proposed tri-fli technique. ​ I hear
 +> that it will "go beyond"​ what is currently available in terms of VIC-II
 +> video on the 64.  I would be honored if you would take the time to clarify
 +> things for me and our readers.
 + 
 +Basically, I have an idea that allows no flicker unlike true IFLI, while still
 +increasing the amount of perceived colors on screen. ​ Right now I am testing
 +the idea with 4 interlaced hires (not FLI) screens. ​ Unfortunately,​ the colors
 +are so close together I can hardly tell them apart. ​ In other words, I get
 +4096 colors but I can't even see them all.  When I scale the project up, and
 +work out the problems, it may evolve into what I call "​tri-fli"​.
 + 
 +> Sounds nifty. ​ Let's backtrack a little though. ​ Your current testbed is
 +> 4 interlaced hires (320*200?) screens. ​ Just HOW are you getting even this
 +> set up to NOT flicker?
 + 
 +You seem to think this part of it is difficult, Mike. :)
 + 
 +> Yes, I do -sans flicker-. ​ I'll be amazed if you can scale it up to the FLI
 +> domain where timing and other concerns label the process to be difficult.
 + 
 +Even if they were FLI, there would be no problem with timing..
 + 
 +> Over my head.. fli =! timing?
 + 
 +Generally speaking, interlace switching occurs in the borders, so you get
 +lots of time even on an NTSC machine. ​ The idea is that -one- FLI screen
 +takes careful timing, but interlacing several FLI screens is NO problem!
 + 
 +> So your technique is basically IFLI revisited?
 + 
 +Hmm... well..yes and no.  I should clarify a few things :).
 + 
 +> Please do, Professor Taylor :).
 + 
 +Multicolor mode is a bitmap + a color map, FLI is a bitmap + * color maps.
 + 
 +> I'm with you so far.
 + 
 +Normally, each color map byte affects an -8x8- area.  In FLI, the color map is
 +changed each line with a raster. ​ Thus, 8 color maps are used in 8 lines, and
 +each byte of each color map now affects an -8x1- area.  This is why FLI gives
 +a better placement of colors. ​ However, there is more to this.  For example,
 +to switch the color maps in fli requires a trick, otherwise FLI would be easy
 +and not need any special timing. ​ This trick is called a DMA retrigger (among
 +many other names for it) and it is necessary because the VIC-II video chip
 +normally only reads where the color map is every 8 lines. ​ Therefore, if you
 +switch the color map WITHOUT the DMA retrigger, nothing would happen. ​ The
 +retrigger requires a certain POKE if you will at an -exact- moment in time on
 +each line in order to function. ​ This is where most of the whines about FLI
 +coding arise. ​ Please note that the DMA retrigger takes up 43 cycles on each
 +line it occurs, thereby adding to the timing woes.  FLI is just four lines
 +of code that are tricky to time :).
 + 
 +> Ouch, but what exactly does the DMA retrigger do?  It sounds like a sermon
 +> into "​bad-lines"​ theology would be required to explain it :).
 + 
 +Hmm.. I can explain DMA later someday, somewhere :).  For now all you need to
 +know is that it is a trick to cause the color map location to be read on each
 +scan line, instead of every 8 scan lines.
 + 
 +> Hey, a layman reponse! ​ I can deal with it.
 + 
 +There'​s no point in being a beanie head if you can't interface with normal
 +types, Mike :​))))). ​ I will take this opportunity to explain one pecularity
 +about the DMA retrigger that will hopefully enlighten the hard-core as well
 +as the laymen. ​ When people learned of this DMA trick, they found that the
 +first three bytes of the FLI picture were seen as garbage. ​ To compensate,
 +they left the left columns of the FLI as blank and to make the picture
 +symmetrical,​ the same was done to the right columns. ​ Thus, FLI pics are
 +usually cropped significantly. ​ I figured out just why the garbage bytes
 +occur and by the same token, how to avoid cropping FLI pics in the future.
 + 
 +Very simply, the colors shown during those first three bytes normally come
 +from color memory, but due to a bug they are actually coming from the opcode
 +being executed at that moment! ​ Therefore, to fix the colors, you just need
 +to write opcodes that represent the proper colors. ​ I looked at it, and there
 +is code you can write to make all 16 colors.
 + 
 +> Wow...that is nice detective work.
 + 
 +I'm sure somebody must have figured this out before, but I do not see it in
 +the software I currently have.  The problem is that most tricks are discovered
 +by experiment and accident, few people actually know why they work.
 + 
 +> The C= community tends to echo that.
 + 
 +This is very true.  It's due to talking to many others that I understand
 +a lot of what is going on today. ​ I put my knowledge and that of others and
 +try to push the limits on this old tank (64) :).  Let me tell you, it is as
 +complicated as any computer, even more so.  In order to fully understand the
 +64, you would have to study it as if it were the culmination of an advanced
 +engineering degree.
 + 
 +> I understand completely. ​ Without the innovations pursued by a horde of
 +> enthusiasts we would not be having this conversation today. ​ But just how
 +> are the advancements of the past being intergrated or improved upon in
 +> your current project?
 + 
 +Ok.. I wanted to finish the point about timing so you understand why even
 +four screens is no big deal.  Let's take a look at basic IFLI first and then
 +contrast it with what I am trying to accomplish. ​ IFLI is two screens of FLI,
 +but alternating with each other like a continuous animation. ​ Frame B follows
 +frame A follows frame B follows frame A, etc., in an endless loop.  The result
 +is that the two FLI pics switch places with each other so rapidly that they
 +seem to blend together to the human eye.  Therefore an apparent increase in
 +the number of colors is the prime result. ​ The standard IFLI technique is
 +fast enough to do this but not fast enough to eliminate flickering as the
 +two pics are flipped. ​ Please remember from before that -each- FLI screen
 +requires careful timing for the FLI/DMA stuff but this is completely unique
 +and independent to that one particular FLI screen. ​ The other FLI screen is
 +just the same thing. ​ In other words, setting up each FLI is tricky, but
 +alternating them is not a problem. ​ No more, no less code or timing, just
 +different screens, ok?
 + 
 +> Yup, understood.
 + 
 +Ok.. Now, regardless of what textbooks say about the persistance of vision
 +being 1/30 of a second, you can see much higher flicker rates and therefore
 +my idea of using more than two screens should flicker quite a bit!
 + 
 +> Well that depends, George. ​ The resolution of the object and how "​bright"​
 +> the object is to begin with has to be a paramount concern in regards to
 +> flicker reduction. ​ The retina has three types of neurons and one of those
 +> types is responsible for "​edge-assessment"​ of objects. ​ This is where
 +> brightness (contrast, etc) and flicker-effects are born in addition to
 +> persistance of vision arguments.
 + 
 +Exactly, I use two ideas to reduce flicker, and they work.  One idea is just
 +what you hinted at, to reduce contrast between colors. ​ Thus I choose colors
 +that have the same brightness but different tints, so only the color is
 +changing.
 + 
 +> The other idea is ?
 + 
 +[...long pause...]
 + 
 +This one is hard to explain. ​ Imagine I am flickering between two colors, A
 +and B.  Typically, a standard IFLI pic will have them like this:
 + 
 +For colors A and B
 + 
 +        frame 1: AAAAAAA ​ frame 2: BBBBBB
 + 
 +but I do this:
 + 
 +        frame 1: ABABABA ​ frame 2: BABABA
 + 
 +Think of it as marquee lights. ​ The even and odd lights turn on and off.
 + 
 +> Ah ha!  You are decreasing the "​granularity"​ of your interlacing on the
 +> temporal axis ! ! !
 + 
 +Exactly!!! ​ You understand :​))))))))))) ​ This technique has even more
 +de-flickering power than choosing colors of the same brightness, and together
 +both methods work even better.
 + 
 +Now that we have settled that, my idea for "​tri-fli"​ is very simple. ​ If I can
 +make IFLI -not- flicker, then I should be able to squeeze in another screen.
 +I am currently using a testbed using four hires (not FLI, IFLI) screens because
 +I can more easily experiment upwards and downwards and see how much flicker I
 +am getting.
 + 
 +> Ok, so you have set up a baseline with four hires screens... and?
 + 
 +I haven'​t seen any flicker yet.. and this is mixing four colors in real-time.
 +But let me first specify -exactly- how to produce non flickering colors.
 +
 +Definitions:​
 +bitplane 0: the screen buffer which is shown on frame 0,2,4...
 +bitplane 1: the screen buffer which is shown on frame 1,3,5..
 +1: indicates foreground color in a 2 color mode
 +0: indicates background color in a 2 color mode
 +
 +flashcolor: a color which is not one of the standard 16 colors, produced
 +by mixing 2 of the standard colors with this technique
 +palette: consists of n standard color and n-1 flash color
 +
 +3 color hires mode
 +------------------
 +Screen buffer setup:
 +two frames are initialized,​ such that the bitmaps contain 0 (all
 +background color). ​ The color assignment is such that both background
 +colors (1 per buffer) are the same.  The other 2 foreground colors are 
 +the same also.
 +An example would be black+white for each buffer.
 +To plot color 0 (black):
 +bp0: 00000000
 +bp1: 00000000
 +to plot color 1 (medium grey, flash color of black+white):​
 +bp0: 01010101
 +bp1: 10101010
 +to plot color 2 (white):
 +bp0: 11111111
 +bp1: 11111111
 +
 +7 color multi mode
 +------------------
 +both buffers have the same color maps
 +An example would be black+dark grey+light grey+white.
 +color 0 (black):
 +bp0: 0000
 +bp1: 0000
 +color 1 (dark dark grey, flash color of dark grey+black):​
 +bp0: 0101
 +bp1: 1010
 +color 2 (dark grey):
 +bp0: 1111
 +bp1: 1111
 +color 3 (medium grey, flash color of dark grey+light grey):
 +bp0: 1212
 +bp1: 2121
 +color 4 (light grey):
 +bp0: 2222
 +bp1: 2222
 +color 5 (light light grey, flash color of light grey+white):​
 +bp0: 2323
 +bp1: 3232
 +color 6 (white):
 +bp0: 3333
 +bp1: 3333
 +
 +Note: although there are other combinations,​ such as:
 +medium grey, flash color of white+black
 +I do not reccomend them, as they produce nearly the same result
 +yet with extra flicker. ​ Flash colors should only be made in the
 +nearest combinations of luminance. ​ Colors are mixed nearly 50%/50%
 +but not exactly.
 +The wide pixels of multicolor mode increase flicker.
 +Flicker is seen most at the edges of a flashcolor where the dither
 +pattern is broken, and also when your eyes move.  The sensors of 
 +your eye which detect movement will see the trailing patterns
 +caused by the low frame rate of the effect, and this breaks
 +the dither as well as lets you see the flicker.
 +
 +What about a four color hires mode?
 +
 +You would have 1 standard and 3 flashcolors,​ yet you can't dither
 +them properly. ​ For example color 1 would require:
 +bp0: 01010101
 +bp1: 10101010
 +with bp0 colors=black+medium grey, bp1 colors=black+light grey.
 +The result will be :
 +abababab
 +where a= dark grey, flash color of black+medium grey,
 +b=dark medium grey, flash color of black+light grey.
 +So you cannot create a constant shade, only a normal dithered one.
 +You could create a constant shading with:
 +bp0: 00000000
 +bp1: 11111111
 +
 +Yet remember that this combination is not 100% flicker free.  An alternative
 +is in modes where you can change the palette at some other resolution,
 +for example in hires IFLI you could draw a constant shade of flashcolor
 +plus a 2 standard shades in any 8x1 area.  For example,
 +a byte with one half flash color and one half constant color is:
 +bp0: 01010011 (1=white, 0=black)
 +bp1: 01011100 (1=black, 0=white)
 +to make this more clear:
 +bp0: bWbWbbWW
 +bp1: WbWbbbWW (b=black, W=white)
 +with this result:
 +11110022 (0=black, 1=medium grey, 2=white)
 +It is possible to have a horizontal resolution of changing shades
 +averaging 8/3 pixels, for the example the above byte could have
 +been
 +00011122 (0=black, 1=dark dark grey, 2=dark grey)
 +and then:
 +01112222 (0=dark medium grey, 1=medium grey, 2=light medium grey)
 +so you can make shading bands of up to 9 shades.
 + 
 +> But how effective is the mixing? ​ Does blue + green = bluegreen?
 + 
 +As I stated earlier, I can now get 4096 colors but they are somewhat useless.
 +The colors are only mixtures of the original 16 color and I can hardly tell the
 +difference between blue-blue green and blue-green or green-green blue.  Right
 +now, I think the best use would be for grey shades.
 + 
 +> Hmm.. You may have to bite the bullet and introduce colors that vary a little
 +> in brightness?
 + 
 +Well, the point of my whole idea is to eventually make standard IFLI to be
 +non-flickerable. ​ If that occurs successfully,​ I should then be able to
 +interlace it yet again in alternative fashion and be left with minor flicker
 +but with many more colors :).  We shall see...
 + 
 +--
 +For further information,​ gripes, etc., Mr. George Taylor may be reached via
 +email at the following internet address: ​ aa601@ccn.cs.dal.ca
 + 
 +
 +/​S03::​$d000:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +
 +           ​Heaven in the net, an unedited excerpt of IRC on #c-64
 +
 +                            by Mike Gordillo
 +
 +
 +As a self-proclaimed "demo freak",​ the following transcript (largely unedited)
 +represents one of the most interesting discussions concerning C-64 that I have
 +ever witnessed on IRC (Internet Relay Chat) or any other venue. ​ I present
 +this to the reader in the hopes of encouraging further participation and
 +patronage of IRC channel #​c-64. ​ We begin in the middle of a dissection of
 +VIC chip internals by Firefoot.
 +
 +> Can anything go on system-wise when a bad line is being "​serviced"​ so to
 +> speak?
 +
 +<​firefoot>​ "​BAD"​ lines are just another way of specifying the lines where the
 +           VIC steals 40 cycles from the CPU to do a screen refresh. ​ You can
 +           delay the bad lines, and push the whole screen down (FLD). ​ You can
 +           force them to occur every line (FLI). ​ You can turn them off
 +           ​(blanking the screen). ​ You can move them horizontally (VSP).
 +
 +<​firefoot>​ The CPU isn't halted, it is busy helping the VIC chip out.
 +           Any code that you are executing is "​halted"​.
 +
 +<​Waveform>​ I never understood VSP?
 +
 +<​Waveform>​ I thought the VIC brought the CPU off-line so it could sweep in all
 +           the data for the bitmap in those 40 cycles (for the next 8 lines).
 +
 +<​firefoot>​ No, nothing can go on system-wise when a bad line is being serviced,
 +           not in terms of the CPU anyway.
 +
 +<​firefoot>​ Wave - I guess that would be functionally identical. ​ I guess it
 +           ​depends on whether or not you consider the bus part of the cpu.
 +
 +<​Waveform>​ The VIC reads its data independent of the CPU, but...I still never
 +           ​understood VSP. =)
 +
 +> Yeah, but the CPU and the VIC chip can't share the bus at once.
 + 
 +<​firefoot>​ I never understood VSP well. There is something about how tricky
 +           stuff with $d011 can cause the VIC to think it has started a new
 +           ​scanline,​ when, infact, it has not.
 +
 +> Well..explain FLD for me then, Firefoot. :)
 + 
 +<​Waveform>​ FLD is easy but FLI is not as easy and VSP scares me.
 +
 +<​firefoot>​ I've coded VSP, but never understood it either. ​ However I do
 +           ​understand FLD.  You just keep playing with $d011 (every scan
 +           line) so that the VIC keeps thinking that the *NEXT* scan line is
 +           the one where it is supposed to do the refresh of screen memory.
 +           when you stop doing this, it starts drawing the screen where it
 +           left off.
 +
 +<​Waveform>​ Exactly, FLD is very easy to understand but what about VSP?
 +
 +<​firefoot>​ Actually, I stumbled across VSP when coding FLI.
 +
 +<​Waveform>​ FLI is essentially the same thing as FLD. Except that instead of
 +           ​making the VIC think the next scan line is where its supposed to
 +           draw the screen, FLI makes the VIC think the current line is
 +           the one to draw on - but you do it on every line.
 +
 +<​firefoot>​ Well, wave, think of VSP as the same thing as FLD except instead
 +           of pushing the screen down scan lines, you push it across cycles.
 +           Also, try changing the delay at the beginning of an FLI routine,
 +           and you will see the screen shift over... voila, vsp!
 +
 +<​Waveform>​ Well, I just recently got a stable raster (double interrupt style)
 +           so I haven'​t actually done anything that specific (FLI for example)
 +           ​though FLD is very forgiving. You can do nifty FLD with virtually
 +           no timing at all.
 +
 +> No timing for FLD?  ok... Why am *I* having such a hard time putting
 +> sprites over FLD then!
 +
 +<​firefoot>​ FLI can be made very forgiving as well (no stable raster needed).
 +
 +<​Waveform>​ Firefoot: It actually uses the CPU's Phi cycle as well as the VIC
 +           Phi cycle.
 +
 +<​Waveform>​ Fire: That is probably what you are remembering.
 +
 +<​firefoot>​ Well, with FLI it *is* nice to use a stable interrupt.
 +           I use the double raster method as well, always seemed the
 +           ​cleanest to me.
 +
 +<​firefoot>​ Oh, it is not easy to put sprites over FLD.  You have to make sure
 +           that your delay each line is exactly correct. ​ very weird code...
 +           I did that and sprite over FLI with almost the same routine. ​ ugh.
 +
 +<​firefoot>​ Wave: That's *exactly* what I am remembering.
 +
 +<​Waveform>​ Fire: the phi thing?
 +
 +> When the FLD bounces down...there -seems- to be a screen area behind it!
 +
 +<​firefoot>​ Mike, basically what I did is constructed a section of unrolled
 +           ​FLI/​FLD code, and played with the delay instructions each time
 +           I moved the sprites so that the timing was always correct.
 +
 +<​firefoot>​ Wave, yes, the phi thing. ​ From the appendix about the vic chip.
 +           It was very informative.
 + 
 +> Ok...I'​ve heard these $xfff addies pop up over and over and I guess they
 +> explains why the some of my pics have those lines behind the FLD!
 + 
 +<​firefoot>​ Mike, the area behind the FLD is taken from the last byte of the
 +           video bank ($3fff, $7fff, $bfff, or $ffff). ​ It is also what you
 +           see when you open up the borders.
 +
 +> Gawd, those annoying lines... I couldn'​t figure out where they were coming
 +> from.
 + 
 +<​Waveform>​ Make VICBASE+$3fff equal to 0... or is it $FF?... and the lines
 +           will vanish.
 +
 +> I also ran a few old demos..and someone (tfo?) was blabbing about how this
 +> border was opened up via FLD and the other one wasn'​t..etc.,​ etc?  How does
 +> FLD open up a border?
 +
 +<​[Style]>​ Is it true it becomes +$x9ff when extended color mode is on?
 +
 +<​firefoot>​ Style, I have never heard that, but I have never used extended color
 +           mode while doing any of those.
 +
 +<​firefoot>​ Mike, the "fld opening up the side borders"​ thing basically uses
 +           the stable raster created with the fld to open the side borders.
 +           ​easier that other methods, like the double raster method, but
 +           ​sloppy,​ in my opinion. ​ besides, you can't get text or gfx....
 +
 +> Firefoot, that is all well and good..but "How do you open up the nice
 +> sideborders?​...period"​... Apparently, you are telling me that the FLD
 +> is used as an "​index"​ in this case.
 +
 +<​firefoot>​ Oh... well... Do you know how to open the top/bottom borders (the
 +           ​theory behind it)?
 +
 +<​Waveform>​ Well, if you time it right, you make the screen 38 columns instead
 +           of 40 right at the last cycle on the raster.
 +
 +> Only thing I know how to do is 38/40 column it... :D
 +
 +<​Waveform>​ Then on the next cycle, the vic thinks it has already started
 +           ​displaying the border... so it doesn'​t start.
 +
 +<​[Style]>​ Which location is the gfx behind an open side border???
 +
 +<​CRoth>​ Waveform: ​ I've tried to do that, failed miserably.
 +
 +<​Waveform>​ Style: VICBASE + $3fff
 +
 +<​Waveform>​ Anytime you open a border or open screen space and the vic doesn'​t
 +           have normal info to fill it will it takes the last byte in its
 +           ​address space and sticks it in there.
 +
 +<​firefoot>​ Croth: Did you make a stable raster first? ​ Without that you will
 +           fail miserably.
 +
 +<​CRoth>​ Firefoot: ​ I couldn'​t figure it out.  Had a friend of mine explain it
 +        to me, he was a genius when it came to that.  :)
 +
 +> What about TWO FLD'​s? ​ I could swear I have seen one FLD bounce and then
 +> another bounce the screen behind it!  Is this lunacy on my part?
 +
 +<​Waveform>​ No it isn't, you stop one FLD...The VIC starts drawing...then
 +           later on, you start another FLD... You get two open spaces on
 +           your screen!
 +
 +<​[Style]>​ And if you can be bothered, you can make a FLD on every line & slice
 +          the picture up :D
 +
 +<​Waveform>​ FLD make the whole screen data move down and up. You can achieve
 +           ​similar effects with sprites... just make all the Y coords go
 +           up and down.
 +
 +> Ok..can you limit how WIDE the FLD is ?  Or is it always full-screen?​
 +
 +<​Waveform>​ You can't FLD on every line... can you? doesn'​t that pooch your pic?
 +           ​I'​ve seen every eight lines... but every line?​!?​! ​ I thought that
 +           if you FLD after the VIC draws on the next line, you get a STRETCH,
 +           ​don'​t you?
 +
 +<​[Style]>​ Wave, check out "​Finely Sliced"​ by Christopher Jam.
 +
 +<​firefoot>​ Mike, I think the FLD is always fullscreen wide.  I can't see how
 +           it wouldn'​t be.
 +
 +<​firefoot>​ Same here Wave, I've only seen every 8 lines as well. Perhaps you
 +           could do some sort of weird cross between FLI and FLD to get every
 +           ​line. ​ Of course, the timing would be most annoying.
 +
 +<​firefoot>​ Wave, I've seen that, but it seems to "​stretch"​ every two lines?
 +           like that one arson demo, forget the name, and the one foe demo,
 +           and a few others as well.
 +
 +<​firefoot>​ [Style], is "​Finely Sliced"​ NTSC fixed?
 +
 +<​Waveform>​ I think I accidentally did a stretch when trying to code FLD and
 +           it seemed like it did every two lines as well...weird.
 +
 +> Indulge me, what is a "​stretch"​ ?
 +
 +<​[Style]>​ Maybe it is every two lines.. Its been a while since I've seen it.
 +          I think Albion made a demo called ache! that did pretty much the
 +          same thing.
 +
 +<​[Style]>​ Fire: I dont know if it is NTSC fixed...
 +
 +<​firefoot>​ Mike, a stretch is an FLD with some slight modifications so that it
 +           "​stretches"​ the screen data.
 +
 +[---end of transcript---]
 +
 +
 +/​S04::​$d000:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +                     A complete dissection of Gfx-Zone
 + 
 +                                by XmikeX
 + 
 + 
 +The Graphics-Zone demo was released August 31, 1995.  It was received with
 +open arms and despite its simplicity, its unabashed unorthodoxy allowed it to
 +reach the third highest spot in the Dec95. NTSC demo ballots. Gfx-Zone and
 +the other two files included in the gfx-zone.sfx package were the culmination
 +of ten days of self-taught assembly programming. ​ I could not have done it
 +however without the guidance obtained from the following sources;
 +
 +- Coder'​s World 1,2, and 3 by '​Wrongway and The Phantom',​ FOE Press :)
 +
 +- 128 Machine Language for Beginners by Richard Mansfield
 +
 +- Mapping the Commodore 128 by Ottis R. Cowper
 +
 +- Inspiration from 'The Last Digital Excess Demo', '​Skeletor Movie',​ '​Digital
 +  Acid', C=Hacking - Issue #7, the people on the IRC channel #c-64, '​SYS4096'​
 +  music by AMJ, and Thinktank who tragically passed away months prior to the
 +  demo but had released his amazing Commodore/​Graphics low-res (40 by 25)
 +  artwork to the public a few years before.
 +
 +Graphics-Zone is not an overtly arrogant and complicated demonstration. ​ It
 +consists of 21 Commodore/​Graphics (i.e., low resolution PETSCII) full-screen
 +drawings (that happen to be *well-drawn*) placed in synch with a very nice
 +SID tune running in the background. ​ There is little if any 'Top Code' in
 +the demo and since I wrote it as a beginner, there should not be anything
 +exceedingly fancy in the code itself that would preclude its use as a training
 +vehicle for those not fully skilled in 6502 ML.  In fact, there are some half-
 +baked methods in the code that are rather simplistic even for a beginner.
 +With this in mind, I hope to share some of the triumphs and pitfalls so as
 +to instill a motivative spirit in those who seek to learn, and perhaps render
 +a smile in those who already know :).
 +
 +As a great deal of you have already seen, running Graphics-Zone is a matter
 +of loading it and typing "​run"​. ​ The first two screens pop up to form the intro
 +sequence where two C/G pictures are flipped back and forth slowly to match
 +the tempo of the music. ​ When the music speeds up, the intro pics are abandoned
 +for the most part and the rest of the C/G pics in memory fly at you in a mad
 +attempt to keep up with the tempo. ​ After a minute or two of this, the music
 +and pics loop back to their start sequences and begin anew.  There is nothing
 +mind shaking about it.  The whole demo is basically a planned sequence of
 +memory moves for the pics with an interrupt (IRQ) driven music player behind
 +it.
 + 
 +The main block of C/G pics are located from $3000 to $bfff with three
 +additional pics at $0800-$0fff,​ $2800-$2fff,​ and $c800-$cff0. ​ Each C/G pic
 +occupies 2 kilobytes (KB), the first KB is the screen data while the last
 +KB represents color memory, as follows:
 + 
 +; Memory Structure - C/G pictures
 +;
 +; -------------------------------$3000 ​ - 0 kilobyte, start of picture 1
 +; !   char data  for C/G pic 1
 +; -------------------------------$3400 ​ - 1 kilobyte, picture 1
 +; !   color data for C/G pic 1
 +; -------------------------------$37ff ​ - 2 kilobytes, picture 1 ends
 +;
 +;
 +; -------------------------------$3800 ​ - 0 kilobyte, start of picture 2 
 +; !   char data  for C/G pic 2
 +; -------------------------------$3c00 ​ - 1 kilobyte, picture 2
 +; !   color data for C/G pic 2
 +; -------------------------------$3fff ​ - 2 kilobytes, picture 2 ends
 + 
 +In actuality, the screen and color data do not extend right up to the next
 +page boundary (i.e., at the $xxff - $xx00 junctions in hex), they in fact end
 +at $xxe7 (e.g., $33e7, $37e7, $3be7, $3fe7, etc).  For simplicity'​s sake, I
 +did not worry about the extra bytes at the end, and I started the each block
 +of pic data (screen/​char or color data) at a page boundary $xx00.
 + 
 +But C/G pics are simply petscii text and color, right? ​ Yes, they do not come 
 +organized as shown above and for a short time, the prospect of extracting them
 +into a more usable form seemed daunting. ​ After a few minutes, the solution
 +came to me.  I read them off the disk and printed them to the forty column
 +screen on my 128.  When this was done, I peeked an image of VIC screen memory
 +($0400-$07e7) and VIC color memory ($d800-$dbe7) and poked the image to
 +$3000-$33e7 (screen mem) and $3400-$37e7 (color mem).  Then I binary-saved
 +them to disk using the monitor (via the 80 column display of course). ​ I
 +repeated this step twenty-one times because I was fortunate enough to have
 +twenty-one quality C/G pics at my disposal :).  In retrospect, I later found
 +out that certain "​taboo"​ areas of memory such as the area under the kernel
 +could have been used to store even more data, but at the time I was quite
 +happy to have been able just to switch out Basic and use the space it took up.
 + 
 +What about the rest of the demo, the music and code, eh?  Not a problem there.
 +The music player/data starts at $1000 and heads up to around $26b0 while the
 +main code for the demo itself starts at $c000. ​ I took all the converted pic
 +files (the ones I had binary-saved) and used a packer to relocate them to
 +their final destinations in memory, along with the music and code.  Also,
 +because packers conveniently compress all data and code into a run-time
 +executable, I didn't have to worry about providing a front-end ability to
 +be able to "​RUN"​ the ML from basic. ​ The packer took care of all this for me,
 +all I had to do was specify a start address for the machine-language (ML) code.
 + 
 +The following is a disassembly of the ML code itself. ​ Although I won't go
 +through it 100% step by step, important points shall be perused for the
 +purposes of clarification,​ and to be honest, for a little self-introspection
 +on my part.
 + 
 +The program starts out quite simply with the start address and a labelling
 +of important memory locations (generally used as pointers throughout the
 +program).
 + 
 +;​---------------------------------------
 +         *= $c000; start of program
 +;​---------------------------------------
 +point    = $fb    ; LSB = point   ($fb)
 +                  ; MSB = point+1 ($fc)
 +temp     = $cfff  ; MSB byte storage ​
 +temp2    = $cffe  ; used by FLD routine
 +temp3    = $cffd  ; $cffa/cffb for TBB/AMJ player uses these.
 +looper ​  = $ccfc  ; see "​pause"​ subroutine
 +hit      = $ccf9  ; see "​pause"​ subroutine
 +;​---------------------------------------
 + 
 +init     lda #$36 ; #$36 is our kill-basic value, so
 +         sta $01  ; store the kill-basic value into $01 and move the
 +                  ; basic rom out of the way, exposing the ram underneath.
 +
 +[AssEd. Note : For general edification,​ location $01 works as follows in C64]
 +[  - bit 0: ROM/RAM at $a000  1=Basic ​ 0=RAM]
 +[  - bit 1: ROM/RAM at $e000  1=Kernal 0=RAM]
 +[  - bit 2: ROM or I/O block  1=I/O    0=ROM]
 +[  - bits 3,4,5 are cassette related........]
 +[  - bits 6 & 7 are not connected in the C64]
 +[  - bit 6 checks the status of the caps lock (ascii/cc) key on C128.]
 +
 +         lda #$00 ; ok...set up accumulator as #$00
 +         sta $d020; change screen and
 +         sta $d021; border to black (i.e., #$00)
 +         sta point; store LSB of pointer (which is now #$00)
 +         lda #$00 ; initialize the looper
 +         sta looper
 + 
 +Ok... So what is going on here?  Basically, we are telling Basic to take a
 +hike so that we can use the memory it once inhabited. ​ We are also setting
 +up the LEAST SIGNIFICANT BYTE pointer for the indirect Y function. ​ This
 +is a powerful tool in 6502 assembly and we will get to it later :).  The
 +"​looper"​ is just a memory location that the program will use in its "​pause"​
 +subroutine. ​ Right now, it is set at zero (#$00).
 + 
 + 
 +UGLY     lda #$fa ; try and tell tbb/amj music player
 +         sta $105b; what scanline to play at
 + 
 +amjtune ​ jsr $1000; jsr call to sys4096/​amj'​s TBB player at $1000
 +
 + 
 +This part is really UGLY.  Basically, I tried to extract the music player
 +and tried to incorporate it here, but I failed for some unknown reason. ​ I
 +decided that since it was proving to be uncooperative that I should just call
 +it from here and let it go off on its own.  This presented two problems for
 +me later. ​ The first was that the music was playing at raster lines that were
 +outside the border area.  In layman'​s terms this means that it would play
 +in the middle of the screen and a slight flicker could be seen as the main
 +code flipped through the pics.  I rectified the situation by finding out where
 +it was polling its raster info ($105b) and sticking an #$fa in there. ​ #$fa
 +is raster line 250, which should correspond to the lower border on the screen.
 +Yes, I could have modified the player code itself, but I was getting a bit
 +paranoid at this juncture and decided not to modify it.  The second problem
 +is that by giving up control to the player subroutine, I lost control of
 +timing, an annoyance that which we shall discuss later. ​ Anyways, as you can
 +see I call the player in the '​amjtune'​ subroutine and let it do its thing,
 +but even though it is not in the main code, I've included the player here
 +for the benefit of the reader. ​ As this code is from someone else, I cannot
 +assure a 100% correct disassembly,​ but read on..
 +
 + 
 +TBB player from SYS4096 tune by AMJ starts at $1000 and proceeds as follows:
 +(By the way, TBB is AMJ's brother...trivia mode over).
 + 
 +<start of player code>
 + 
 +>        sei        ; disables interrupts
 +>        lda #$01
 +>        sta $d01a  ; set up for scan line
 +>        lda #$7f
 +>        sta $dc0d  ; enable timer interrupts
 +>        lda #$35   ; lets play with roms
 +>        sta $01     
 +>        lda #$00
 +>        ldx #$00
 +>        ldy #$00
 +>        jsr $1100  ; jsr to musix init ?
 +>        lda #$37   ; let's play with roms
 +>        sta $01    ​
 +>        lda #<​irq ​ ; LSB of irq
 +>        sta $0314  ; stash it
 +>        lda #>irq
 +>        sta $0315  ; MSB of irq
 +>        lda #$3a
 +>        sta $d012
 +>        lda #$1b   ; normalize the screen i think
 +>        sta $d011 
 +>        cli        ; re-enables interrupts
 +>        rts        ; it used to jmp back to itself, infinite loop
 +>                   ; as its irq routine played in the backgroud
 +>
 +>​irq ​    lda #$01   ; the irq routine
 +>        sta $d019
 +>        lda #$35   ; let's play with roms again 
 +>        sta $01    ​
 +>        dec $d020
 +>        jsr $1103  ; $1103 (!) I think this jsr's to musix data 
 +>        inc $d020
 +>        lda #$37   ; let's play with roms yet again
 +>        sta $01
 +>        inc selfmod+1 ; self-modifying code!!!
 +>selfmod lda #$xx   ; #$xx = this is the byte changed by 'inc selfmod+1'​
 +>        and #$01
 +>        tax
 +>        lda #​$105b,​x ​ ; goes to the scan line table ?
 +>        sta $d012  ; sets up the scan line for irq to occur
 +>        jmp $ea31  ; go to normal c= irq return
 + 
 +<end of player code>
 + 
 +From $105c to $10a0 or so beyond this there is some program data of unknown
 +function. At around $1100 there is an embedded message by the authors and then
 +the music data follows, ending somewhere around $26b0 if I recall correctly. ​
 +Please note that this tune is double-speed (i.e., plays twice per frame).
 + 
 +<back to main program code>
 + 
 +The initialization steps have executed and the music player has been told
 +to start playing. ​ What is left now is to present the C/G pictures to the
 +viewer in a meaningful way.
 + 
 +The main1 routine that follows conducts the sequence of the C/G displays. ​ Its
 +responsibility is to load and store the MOST SIGNIFICANT BYTE of the address
 +(location) of each starting pic for a given pattern of displays and then branch
 +out to the pattern subroutines,​ which display c/g pics sequentially given a
 +predetermined sequence. ​ Again, the MSB as with the LSB we encountered earlier
 +deals with the indirect Y function that we shall explore later.
 + 
 + 
 +main1    lda #$30 ; starting pic MSB
 +         sta temp ; store MSB in temp
 +         jsr pattern
 + 
 +         lda #$30 ; starting pic MSB
 +         sta temp ; store MSB in temp
 +         jsr pattern0
 + 
 +         lda #$c0 ; this MSB is being stored but pattern1 does not use it
 +         sta temp 
 +         jsr pattern2
 +         jsr pattern1; fld bounce of the first intro pic only
 +                     ; located at $3000-$37e7
 +                     ; fld effect is quite annoying, so its done only once
 +         lda #$38
 +         sta temp
 +         jsr p0      ; p0 routine is a part (subset) of pattern0 routine
 + 
 +         lda #$c0    ; the rest of these are more of the same... calls to
 +         sta temp    ; pattern subroutines
 +         jsr pattern2
 + 
 +         lda #$38
 +         sta temp
 +         jsr pattern0
 + 
 +         lda #$c0
 +         sta temp
 +         jsr pattern2
 + 
 +         lda #$30
 +         sta temp
 +         jsr pattern0
 + 
 +         lda #$c0
 +         sta temp
 +         jsr pattern2
 + 
 +         lda #$30
 +         sta temp
 +         jsr pattern0
 + 
 +         lda #$c0
 +         sta temp
 +         jsr pattern2
 + 
 +         lda #$38
 +         sta temp
 +         jsr p0
 + 
 +         lda #$c0
 +         sta temp
 +         jsr pattern2
 + 
 +         lda #$38
 +         sta temp
 +         jsr p0
 + 
 +         lda #$c0
 +         sta temp
 +         jsr pattern2
 + 
 +         jsr pattern3; last pattern before music loops back on itself
 + 
 +         jmp main1   ; by now, music has looped...time to slow down again
 +                     ; with the original pattern at the start of main1 routine
 +                     ; (i.e., pattern routine that follows is called at the
 +                     ; start of main1)
 + 
 + 
 +"​pattern"​ is the first of the pattern subroutines. ​ It's responsibility is
 +to take care of the first and second intro pics at the start of the program.
 +It pulls the MSB from the temp memory location (the first intro pic), jsr's
 +to the viewpic routine, and loads a "​hit"​ value which the "​pause"​ routine
 +will then compare with an "​looper"​ value. ​ This determines how long the first
 +intro pic will be shown. ​ After which, "​pattern"​ will change the MSB value
 +(without affecting the MSB in temp) to point to the second intro pic, and
 +then it repeats this process until the music tempo increases, upon which time
 +"​pattern"​ gives up control to another "​patternX"​ subroutine.
 + 
 +I mentioned earlier that I lost control of timing when I gave up some control
 +to the music player code.  That is to say, because I could not (at the time)
 +incorporate the player code in here, I had no way of properly synching the
 +pictures to the beat of the music as it played. ​ I corrected this deficiency
 +in true '​newbie'​ fashion. ​ I used delay loops to form the core basis of what
 +I could approximate as being a "​beat"​ of music. ​ The "​pattern"​ subroutines use
 +the "​pause"​ subroutine (which includes the core delay loops along with "​hit"​
 +and "​looper"​ comparison) in order to determine how long a C/G pic should be
 +displayed as the music plays in the background. ​ I had to manually figure out
 +how long it would take to go from its initial slow tempo to a faster tempo
 +and then calibrate the "​pattern"​ routine to give up control at the transition.
 + 
 + 
 +pattern ​ lda temp    ; this sets up the initial -slow- flipping pattern of the
 +         jsr viewpic ; pics to match the -slow- tempo start to the AMJ tune
 +         lda #$11
 +         sta hit
 +         jsr pause
 +         lda #$08
 +         jsr viewpic
 +         lda #$11
 +         sta hit
 +         jsr pause
 +         lda temp
 +         jsr viewpic
 +         lda #$11
 +         sta hit
 +         jsr pause
 +         lda #$08
 +         jsr viewpic
 +         lda #$11
 +         sta hit
 +         jsr pause
 +         rts
 + 
 + 
 +The other "​patternX"​ routines and their subsets (p0, p10, etc.) basically
 +perform addition or subtraction operations on the MSB they initially pull
 +from the temp location. ​ By doing so, you can display a number of different
 +pictures in sequence with a minimum of effort. ​ Recall that the pics are
 +saved into memory initially with some organization behind it. That pre-planning
 +combined with addition (adc) or subtraction (sbc) operations allowed me to
 +display pictures in the order I desired.
 + 
 +For example, assume that picture 1 is entitled "​Boy",​ picture 2 is entitled
 +"​meets",​ and picture 3 is entitled "​Girl"​. ​ "​Boy"​ is at $3000, "​meets"​ is
 +at $3800, and "​Girl"​ is at $4000. ​ The MSB represents the first 2 digits
 +of the hex addresses I have just given, so "​Boy"​ MSB is $30, "​meets"​ is $38,
 +and "​Girl"​ is $40.  Notice that each of these MSB's is precisely #$08 hex
 +numbers apart! ​ Since we haven'​t gone into the indirect Y function yet this
 +may be a little premature, but it is logical to assume that if we had an
 +indexing system in place all we would have to do in order to move from
 +picture to picture would be to either add or subtract #$08!  So basically
 +our pictures are 8 units apart, for simplification as follows:
 + 
 +lda 30       : Our house is at 30 main street :)
 +jsr viewpic ​ : Ask a photographer to photograph and display our house
 +adc  8       : Inform the photographer that the next house is 8 blocks down
 +jsr viewpic ​ : Ask the photographer to photograph and display -that- house
 + 
 +In actual code, if I wanted the pictures to come out sequentially as
 +Boy meets Girl (remember the addresses we specified above) it would be
 + 
 +lda #$30     : tell viewpic that "​Boy"​ is at $3000  (#$30 = MSB = first two
 +             : digits of the hex number).
 +jsr viewpic ​ : display "​Boy"​
 +clc          : CLC - Clears the Carry Flag.. required step before addition
 +adc #$08     : add another #$08 to the "​Boy"​ address..#​$30 + 08 = #$38
 +             : in other words, the address for "​meets"​ which is $3800.
 +jsr viewpic ​ : display "​meets"​
 +clc          : required
 +adc #$08     : add another #$08 to the "​meets"​ address..#​$38 + 08 = #$40
 +             : in other words, the address for "​Girl"​ which is $4000.
 +             : REMEMBER, we are adding in HEXADECIMAL...
 +jsr viewpic ​ : display "​Girl"​
 + 
 +Running this routine (and for now, don't worry about how viewpic works) within
 +this program would allow us to display "Boy meets Girl"​. ​ Simple, eh?  The
 +basic concepts hold for patternX routines that use subtraction except that
 +instead of CLC, you are required to do a SEC before a subtraction operation.
 + 
 +You will notice that the patternX routines jsr to the delay loop (e.g., loop1)
 +routines more directly than the "​pattern"​ routines. ​ This is because "​pattern"​
 +required a much longer delay and this is why "​hit"​ and "​looper"​ were created.
 + 
 + 
 +pattern0 lda temp
 +         jsr viewpic
 +         jsr loop1
 + 
 +         lda #$08 ; Load oddball MSB
 +         jsr viewpic
 +         jsr loop1
 + 
 +p0       lda temp ; Load MSB from temp
 +         clc
 +         adc #$08 ; Add #$08 to it
 +         sta temp ; Store MSB in temp
 +         jsr viewpic
 +         jsr loop1
 +         lda temp ; Bring back MSB
 +         cmp #$b8 ; Is the MSB at the
 +         bne p0   ; final pic? $b800
 +         rts
 + 
 +pattern1 lda #$30
 +         jsr viewpic
 +         jsr fldmain
 +         jsr loop2
 +         rts
 + 
 +pattern2 lda #$c8 ; Load 2nd oddball MSB
 +         jsr viewpic
 +         jsr loop1
 + 
 +p10      lda temp
 +         sec
 +         sbc #$08
 +         sta temp
 +         cmp #$30
 +         beq p10
 +         jsr viewpic
 +         jsr loop1
 +         lda temp
 +         cmp #$28
 +         bne p10
 +         rts
 + 
 +pattern3 lda #$c8
 +         jsr viewpic
 +         jsr loop1
 +         lda #$78
 +         jsr viewpic
 +         jsr loop1
 +         lda #$a0
 +         jsr viewpic
 +         jsr loop1
 +         lda #$40
 +         jsr viewpic
 +         jsr loop1
 +         lda #$38
 +         jsr viewpic
 +         jsr loop1
 +         lda #$30
 +         jsr viewpic
 +         jsr loop1
 +         lda #$08
 +         jsr viewpic
 +         jsr loop1
 +         lda #$60
 +         jsr viewpic
 +         jsr loop1
 +         lda #$a8
 +         jsr viewpic
 +         jsr loop1
 +         lda #$68
 +         jsr viewpic
 +         jsr loop1
 +         lda #$70
 +         jsr viewpic
 +         jsr loop1
 +         lda #$80
 +         jsr viewpic
 +         jsr loop1
 +         lda #$90
 +         jsr viewpic
 +         jsr loop1
 +         lda #$88
 +         jsr viewpic
 +         jsr loop1
 +         jsr loop1
 +         jsr loop1
 +         jsr loop1
 +         jsr loop1
 +         ldx #$30
 +         jsr d1
 +         rts
 + 
 + 
 +Ah, here we have reached the famous "​viewpic"​. ​ You will notice it doesn'​t
 +do much.  In fact, all it does is store the MSB pointer for the indirect Y
 +function and "​passes the buck" so to speak to the display routine. ​ :)
 + 
 +viewpic ​ sta point+1; Store MSB pointer
 +         jsr display
 +         rts
 + 
 + 
 +WARNING : INELEGANT timing solutions up ahead...be afraid, be very afraid...
 +          ---------
 + 
 +pause    jsr loop1
 +         inc looper
 +         lda looper
 +         cmp hit
 +         bne pause
 +         lda #$00
 +         sta looper
 +         rts
 + 
 +loop1    ldx #$fd
 +         jmp d1
 + 
 +loop2    ldx #$01
 +         jmp d1
 + 
 +d1       ldy #$ff
 +d2       dey
 +         bne d2
 +         dex
 +         bne d1
 +         rts
 + 
 +"​loop1"​ encompasses "​d1",​ and "​d2"​. ​ The whole scheme is a loop within
 +a loop, with the idea being to be able to get "​loop1"​ to approximately
 +equal one beat of the music playing in the background. ​ After about 30+ (!!!)
 +recompiles, I got it almost perfect on an NTSC machine. ​ The music plays
 +17% slower on a PAL (european, australian) machine and so this demo is
 +horribly out of synch in PAL.  For those of you who are wondering, Mr. George
 +Taylor calculated the delay loops to be about 2.8% slower on a PAL machine
 +when taking into consideration the slower PAL CPU and the penalties incurred
 +due to "bad lines" (when the vic chip steals cpu cycles on the bus).  As
 +mentioned earlier, the "​pause"​ routine encompasses everything "​loop1"​ has
 +to offer and extends the delay even further. ​ The "​loop2"​ routine would
 +seem to be useless but it is called by the fld-bounce routines. ​ The fld
 +takes longer than a regular display so I figured I would only need to call
 +a delay routine that was a fraction of a music "​beat"​ (which is what
 +"​loop1"​ tries to be).
 + 
 + 
 +Now we get to the real nitty gritty of the whole thing. ​ The "​display"​ routine
 +and its subsets. ​ These make use of the indirect Y function which Mensch and
 +company thankfully chose to implement in the 6502.
 + 
 +But wait, we haven'​t really gone into the indirect Y, have we?  Nope, because
 +it is tricky to explain. ​ Like with movies or sports events, you have to be
 +there in order to get the feel for it.  In general, it is an index system
 +that uses a zero page pointer of your choice in order to jump around to
 +this or that memory location. ​ But that's too vague...let'​s really explore it.
 + 
 +Do you recall that at the start of the code we defined a few labels and
 +basically equated them as memory locations? We said that "point = $fb" among
 +other things. That is our memory (zp) pointer for the Least Significant Byte
 +(LSB) and in the "​display"​ routine below you will see a reference to point+1
 +which is our memory (zero-page) pointer for the Most Significant Byte (MSB).
 + 
 +An address in memory is made up of two bytes, namely the MSB and LSB.
 +Think of the MSB as the first two digits and the LSB as the last two digits,
 +as follows:
 +                $c000 = $c0 MSB + 00 LSB
 + 
 +                $00c0 = $00 MSB + c0 LSB
 + 
 +The two together make up a 16-bit address and due to how the 6502 works,
 +it is one reason why 64 kilobytes can be accessed directly (2^16 = 65536).
 + 
 +The indirect Y function allows you to set up an MSB and LSB pointer in zero
 +page (ie., the first 256 bytes of memory from $0000 to $00ff). ​ Note : You
 +can't set a pointer in locations $0000, $0001, and $00ff. ​ The LSB pointer
 +I chose was $fb and by definition, the MSB pointer is automatically one memory
 +location higher than the LSB pointer, so my MSB pointer is at $fc (point + 1).
 + 
 +The "​display"​ routines make use of the pointer functions as an index to copy
 +C/G picture data to screen and color memory. ​ But how does it do it, right?
 + 
 +The "​viewpic"​ routine we encountered earlier sets the MSB to the MSB of the
 +picture that is about to be displayed. ​ So for the first intro pic at $3000
 +this would be an MSB of #$30.  Our LSB was set to zero (#$00) at the start of
 +the program. ​ So we have an MSB of #$30 and an LSB of #$00 = $3000 address.
 +"​display"​ now sets the Y register to zero (ldy #$00), "​pa1"​ is now ready to
 +copy memory.
 + 
 +NOTE : For all the examples shown, we will use the MSB of the first intro pic
 +       ​($3000 = $30 MSB = first two digits). ​ The rest of the program changes
 +       the MSB on the fly so that when the "​display"​ routine is reached, new
 +       pics can be displayed. ​ If the MSB didn't change beyond the simple
 +       ​incrementations you will see below, we'd be stuck with displaying
 +       one pic.
 + 
 +display ​ ldy #$00  ; "​display"​ encompasses all the memory moves that follow
 +
 +;​--------screen data moves--------------
 +
 +pa1      lda (point),y ; $x000  $x800
 +         sta $0400,y
 +         iny
 +         bne pa1
 + 
 +As you can see "​pa1"​ takes the LSB of the pointer and uses the Y register to
 +increment it (with INY) and then uses the same increment to store values to
 +screen memory (which starts at $0400). ​ In long form, this routine is just
 +doing this :
 + 
 +        LDA $3000  ; take the first byte from the stored pic in memory
 +        STA $0400  ; put the first byte to the first screen memory location
 + 
 +        LDA $3001  ; take the second byte from the stored pic in memory
 +        STA $0401  ; put the second byte to the second screen memory location
 + 
 +        LDA $3002  ; take the third byte from the stored pic in memory
 +        STA $0402  ; put the third byte to the third screen memory location
 + 
 +The INY instruction can only increment 256 times before the LSB runs out and
 +it starts looping back to zero, so what we do now is increment the MSB !
 +(Remember, the BNE instruction checks when Y is equal to zero and moves on
 +to the next routine -- Also, remember that Y itself does not change the
 +LSB pointer, it only adds to the LSB *value* during the loop.  LSB pointer
 +itself stays the same, which means we can use it in the next routine without
 +resetting it - the one we do increment is the MSB - via the INC instruction).
 + 
 +         ldy #$00
 +         inc point+1
 + 
 +The previous routine "​pa1"​ filled the first 256 bytes of screen memory with
 +the first 256 bytes of our stored pic (i.e., it copied memory locations from
 +$3000-$30ff to $0400-$04ff). ​ We have just increased our MSB by one (using
 +the INC point+1 - remember point+1 = our MSB in zero page). ​ "​pa2"​ will now do
 +the same thing as "​pa1"​ except it is now working on the next 256 bytes (i.e.,
 +it will copy memory locations from $3100-$31ff to $0500-$05ff).
 + 
 +pa2      lda (point),y ; $x100  $x900
 +         sta $0500,y
 +         iny
 +         bne pa2
 + 
 +         ldy #$00
 +         inc point+1
 + 
 +The MSB pointer is incremented again... ​ $3200-$32ff to $0600-06ff.
 +Please remember we are using the MSB of the first pic in this example.
 + 
 +pa3      lda (point),y ; $x200  $xa00
 +         sta $0600,y
 +         iny
 +         bne pa3
 + 
 +         ldy #$00
 +         inc point+1
 + 
 +The MSB pointer is incremented again... ​ $3300-$33ff to $0700-$07ff ($07e7)
 +Please remember we are using the MSB of the first pic in this example.
 + 
 +pa4      lda (point),y ; $x300  $xb00
 +         sta $0700,y
 +         iny
 +         bne pa4
 + 
 +;​--------color data moves----------------
 + 
 +         ldy #$00
 +         inc point+1
 + 
 +Are we seeing a pattern here?  :)  The MSB keeps getting incremented so as
 +to allow yet another 256 byte copy-fill to occur. ​ But now things change a
 +little since we will now copy color memory. ​ Not a problem because when we
 +first organized our pictures in memory we put color data "RIGHT BEHIND"​ the
 +screen data!! ​ Recall, screen data takes up the first 1 KB while color data
 +takes up the last KB  (2 KB total per pic).  So what do we do?  We keep
 +incrementing the MSB until the end of the pic is reached, but now we redirect
 +our copy to the VIC color memory area ($d800-$dbff).
 + 
 +"​cpa1"​ copies $3400-$34ff to $d800-$d8ff
 +Please remember we are using the MSB of the first pic in this example.
 + 
 +cpa1     lda (point),y ; $x400  $xc00 ; we are now in the second kilobyte
 +         sta $d800,​y ​  ; of our stored pic data in memory.. in other words
 +         ​iny ​          ; this continual MSB incrementation has gone through
 +         bne cpa1      ; the first KB and has now hit the second KB where
 +                       ; color memory for the pictures resides
 + 
 +         ldy #$00
 +         inc point+1 ​  ; increment that MSB yet again..
 +cpa2     lda (point),y ; $x500  $xd00
 +         sta $d900,​y ​  ; copies $3500-35ff to $d900-$d9ff
 +         iny
 +         bne cpa2
 + 
 +         ldy #$00
 +         inc point+1 ​  ; increment that MSB yet again..
 +cpa3     lda (point),y ; $x600  $xe00
 +         sta $da00,​y ​  ; copies $3600-36ff to $da00-$daff
 +         iny
 +         bne cpa3
 + 
 +         ldy #$00
 +         inc point+1 ​  ; increment that MSB for the last time!
 +cpa4     lda (point),y ; $x700  $xf00
 +         sta $db00,​y ​  ; copies $3700-$37ff to $db00-$dbff ($dbe7)
 +         iny
 +         bne cpa4
 +         ​rts ​          ; return back to original calling routine, whatever
 +                       ; that may be!
 +
 +;​---------------------------------------
 + 
 +nullpic ​ ldy #$00 ; this is useless, i never did anything with nullpic
 +                  ; i wanted to expand this to build some kind of random
 +                  ; pic or blank screen.. but i forgot about it..
 + 
 +;​--------fld routine--------------------
 +
 +FLD is known as Flexible Line Distancing and the routine that follows is an
 +amalgam of something The Phantom/FOE did in a Coder'​s World 3 article. I will
 +refer the reader to that article and a more comprehensive analysis of FLD in
 +C= Hacking Issue #7.  In brief summary, FLD is basically a raster trick that
 +bounces the whole screen up and down quickly without having to engage in
 +moving screen memory or vertically scrolling the actual picture data.  This
 +illustrates a good point about coding on the C-64.  The best "​coders"​ may
 +not necessarily be the ones who best know the 6510 CPU.  Generally, at least
 +in the 'demo world',​ talent is assessed on how well the individual knows how
 +to properly abuse the ancillary chips VIC, SID, CIA, etc.
 +
 +The FLD technique from my standpoint was an exercise in trial and error. ​ I
 +sadly did not use a sine table to coordinate the bounce-effect. ​ I basically
 +sat there tweaking it left and right until it did what I wanted it to do on
 +my NTSC machine. ​ In other words, once I got it to bounce the first intro
 +pic a few times and gracefully depart, I was content. ​ On PAL machines the
 +effect is quite skewed and is not recommended for young viewers in the
 +audience as it is rather grotesque :).
 +
 +
 +fldmain ​ lda #$00
 +         sta temp2
 + 
 +fld      lda #$2a
 +         cmp $d012
 +         bne fld
 +         lda temp2
 +         cmp #$4f
 +         beq fldmain2
 + 
 +start    ldx temp2
 +bounce ​  ldy $d012
 +         cpy $d012
 +         dey
 +         tya
 +         and #$07
 +         ora #$10
 +         sei
 +         sta $d011
 +         cli
 +         dex
 +         bne bounce
 +         ldy #$15
 +         sty $d018
 +         lda temp2
 +         clc
 +         adc #$07
 +         sta temp2
 +         jmp fld
 + 
 +fldmain2 lda #$1b  ; recovers first scn
 +         sta $d011 ; row from fld trick
 +         clc
 +         rts
 + 
 +
 +This is it!  The end of this article and the end of what I hope was an
 +enjoyable experience for you.  Part of the disC=overy project is to
 +stave off entropy for as long as possible. ​ The best way to do this is
 +to convert more order out of chaos in our local domain - the world of
 +64 :).  In effect, by increasing the interest and drive we put into these
 +old tanks, we shift entropy and chaos to the rest of the computer world.
 +Because the universe is a closed system, this is the best we can do and
 +is perhaps a lost cause ultimately, but I'll wager no one thought we would
 +get this far.
 +
 +XmikeX
 +
 +
 +/​S05::​$d400:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +A Beginner'​s Guide to the JCH Editor V2.53, NewPlayer V14.G0
 +            by Sean M. Pappalardo (Pegasus/​RPG)
 +
 + 
 +      The JCH (Jens-Christian Huus) Editor for the C-64
 +  is probably the most advanced sound creator and music
 +  tracking program of the group of software I like to call
 +  "Next Generation"​ software. ​ This is software that pushes
 +  the Commodore past the limits the original designers placed
 +  on the hardware. This program has two main functions: to
 +  create and play high-definition analog synthesized sounds,
 +  and to arrange these sounds in music tracks. The program
 +  uses the following features of the SID (Sound Interface
 +  Device - the "Sound Blaster"​ of the Commodore): Three
 +  simultaneous synthesized voices (viewed as tracks by the
 +  editor), the four basic analog waveforms the SID produces
 +  (triangle, sawtooth, pulse, and noise, hereafter referred to
 +  as "​simple sounds"​),​ ring modulation, and filters.
 +
 +      The secret to the -editor'​s- ability to produce quality
 +  high-definition sounds is the rapid cycling of simple sounds
 +  through the SID, one right after another, so fast that your
 +  ears more or less fuse the sounds into one complex sound.
 +  For instance, a standard snare drum sound is made up of 5 or
 +  more simple sounds that get played so rapidly that you hear
 +  one sound. The whole process takes only .0026 seconds, which
 +  is how this technique can be accomplished. For reference, a
 +  digital sound is in essence the same idea, except you hear
 +  about 12,000 simple sounds per second as opposed to 360. The
 +  only problem is that digital sound uses vast amounts of
 +  memory (12K per second of sound), whereas a 3 or 4 minute
 +  JCH song takes only 4K, give or take a K or two. Clearly,
 +  JCH songs are the more economical choice.
 +
 +      The -player- is designed to be called from another program
 +  exactly once per screen refresh. The standard NTSC screen
 +  redraws itself 60 times per second, and so the player
 +  expects to be called 60 times per second, with equal time
 +  between the calls.
 +
 +      The number of simple sounds that get played per second
 +  can be doubled through what is known as a "​double-speed"​
 +  player. This simply means that the player gets called twice
 +  per screen refresh, or 120 times per second, so playing
 +  about 720 simple sounds per second. This is done to create
 +  higher definition sounds (like raising the sampling rate of
 +  a digitizer.) The drawback is that twice as much processor
 +  time per screen refresh is taken to play the tune as with
 +  the single-speed player. This technique has been applied in
 +  creating 3, 4, 5, 6, even 8-speed players, each one having a
 +  difference in sound quality, and a proportional increase in
 +  rastertime use. Mind you, the quality is only as good as the
 +  creator of the sound, as the sounds have to be constructed
 +  by the composer, and the faster the player, the more detailed
 +  the sounds must be to sound their best. It is a shame that
 +  we can't just use a digitizer at a very low sampling rate to
 +  capture sounds instead of having to engineer each one carefully!
 + 
 + 
 +  The Main Menu
 + 
 +  F1 - Load Tables or Music
 +  F2 - Save Tables
 +  F3 - Save Entire Tune
 +  F5 - Send Disk Command
 +  F7 - View Disk Directory
 +  F8 - Enter the Editor
 + 
 +      The F1 key on this menu allows you to load up one of
 +  three things: an unpacked tune you wish to continue working
 +  on (or to view), a set of tables that contain instrument
 +  definitions,​ or another NewPlayer (A routine that actually
 +  plays the music. Different versions have different features
 +  and drawbacks. For example, 14.G0 uses more rastertime than
 +  the 19.G0 player, and they sound close in quality. If I'm not
 +  mistaken, the tune in 19.G0 sounded better!)
 +
 +      The F2 key allows you to save the current instrument
 +  definition tables from the computer to the disk drive, for
 +  use in other tunes, so you don't have to re-engineer all of
 +  the sounds again for each tune.
 +
 +      The F3 key simply saves all of the instrument
 +  definitions and music data in one unpacked file for later
 +  editing or packing (to be used in a demo or otherwise.) My
 +  particular version of the editor saves 147-block files, but
 +  I understand other versions save 64-block files. The size
 +  you get should match one of these.
 +
 +      The F5 key will allow you to send any valid DOS command
 +  to your disk drive. (Such as a Change Partition command for
 +  CMD device users.)
 +
 +      The F7 key obviously displays a directory of the current
 +  disk/​partition.
 +
 +      The F8 key is used to go into the actual editing area.
 + 
 + 
 +  The Editor Itself
 +
 +      Once you make the bold move into the editor, you will
 +  see a screen covered with lines and numbers. This is the
 +  editing area, and once you understand it, you will get to
 +  like it. (I was a beginner too, you know!)
 +
 +      To start, the windows with the light grey "​8000"​ and
 +  green dashes are where the sequence of notes in a particular
 +  tune is displayed. Under that, there are two more windows
 +  with sets of zeroes in them. (These are actually hex bytes
 +  and each has a specific purpose, depending on the specific
 +  NewPlayer in use. For the purposes of this documentation,​
 +  I will assume you are using NewPlayer V14.G0 because that
 +  one seems to be most popular.) Each of the digits can be set
 +  from 0-9 and A-F.
 +
 +  To describe all of the keys used in the editor: ​
 + 
 +    V - Toggles whether or not the cursor moves when editing any
 +  hex bytes. (Useful for testing different values while
 +  playing a tune.) This value is displayed at the bottom right
 +  of the screen. The C+ means that the cursor will move, and
 +  C0 means that it won't.
 + 
 +  <​Commodore Key> - Toggles keyboard lock. When it's enabled,
 +  only the cursor keys can be used. This is useful for testing
 +  instruments out without screwing up anything you've entered.
 +  It's also good to keep your kid brother from destroying your
 +  tune while you're in the bathroom. When the lock is on, you
 +  will see two white stars at the top left of the screen.
 + 
 +  \ - <Used while the cursor is in a track> Sets a marker in
 +  the three tracks at the block which the cursor is in.
 + 
 +  F1 - Begin playing tune from the marker set with the \ key.
 + 
 +  F2 - Use the computer like a piano, with the current
 +  instrument. (Cursor to the line of the instrument you want.)
 +  This is obviously useful for testing instrument sounds.
 + 
 +  F3 - Begin playing the tune at the beginning.
 + 
 +  F4 - Stop all sound.
 + 
 +  F5 - Switch between block arrangement and block edit.
 + 
 +  F6 - Delete a note in the current block, or delete a block.
 + 
 +  <INS> - Insert a note in a block, or insert a block when
 +  editing block arrangement.
 + 
 +  F7 - Increase octave.
 + 
 +  F8 - Decrease octave.
 + 
 +  <​SHIFT>​ D - Increase speed of tune.
 + 
 +  <​SHIFT>​ S - Decrease speed of tune.
 + 
 +  The speed value is displayed above the cursor toggle
 +  display. (Bottom right) It can range from 0 to 9, so you'll
 +  see S0 if the speed is 0, S9 if it's 9, etc. 0 is the
 +  fastest speed, and 9 is the slowest. The octave is displayed
 +  above the speed, and can range from 0 to 7. Hence you'll see
 +  O0 if the octave is 0, the lowest, O7 if it's 7, the
 +  highest, etc.
 + 
 +  Z - Toggle to the instrument parameter window.
 + 
 +  X - Toggle to the glide parameter window. ​
 + 
 +  -After using slash (/) to pop up the wave/​pulse/​filter
 +  window, L, colon (:), and semicolon (;) will bring you to
 +  the waveform, pulse, and filter windows, respectively.
 + 
 +  = - Go to the top of the tune. <CLR> will bring you to the
 +  top and put the cursor in the dashes, if it's not already
 +  there.
 + 
 +  <​SHIFT>​ F - Fine tuning. This feature allows you to make
 +  miniscule adjustments to the pitch of each track, so as to
 +  prevent/​create sound wave interference between tracks. The
 +  values that appear can be set from $00 to $FF. Press
 +  <​RETURN>​ after each one to set it.
 + 
 +  <​SHIFT>​ C - Clear all. This will prompt you first, and upon
 +  a positive response, will erase the block sequences, and set
 +  all the blocks to whatever was in the first block (# 00.)
 + 
 +  <​SHIFT>​ X - Leave the editor and return to the main menu.
 +  (So you can save.)
 + 
 +  <​SHIFT>​ <​RETURN>​ - While in a block, this will insert 16
 +  ($10) blank spaces in that block at the cursor position.
 +  WARNING: Don't make any block longer than 5 screens (80
 +  lines). If you do, it will corrupt when packed. NEVER make a
 +  block 8 screens long! (128 lines) This scrambles data from
 +  other blocks in RAM and destroys the tune. If you save it,
 +  you'll never be able to pack it, as the packer will crash.
 +  Even if you delete the long block, the data remains
 +  scrambled and the packer will still crash. You'll have to
 +  rewrite the tune from scratch if you do this. I recommend a
 +  4-screen limit on blocks. (64 lines)
 + 
 +  <​SHIFT>​ A - Copy block sequence into buffer.
 + 
 +  <​SHIFT>​ Z - Copy buffer into block arrangement.
 + 
 +  <​SHIFT>​ . - Copy current block into buffer.
 + 
 +  <​SHIFT>​ I - Copy buffer into the current block.
 + 
 +  <​CONTROL>​ 1/2/3 - Toggle voice 1,2,3 on/off.
 + 
 +  <back arrow> - Fast forward (while a tune is playing. Hold
 +  it down.)
 + 
 +      The left window, which is longer than the other (and
 +  contains 8 bytes) is the instrument pointer window. The byte
 +  before the colon is the instrument number. Each row is a set
 +  of data for that particular instrument. The editor supports
 +  up to 32 ($1F) instruments. The first nybble in each row
 +  (the first digit of the first byte) is the Attack control.
 +  (Attack is how long it takes a sound to reach maximum
 +  volume.) The second digit is the Decay control. (Decay is
 +  how long it takes for the sound to go from maximum volume to
 +  the sustain volume, if one is set.) The first digit of the
 +  second byte controls the Sustain level. (The volume at which
 +  the note is held until it is released.) The second digit
 +  controls the Release of the sound. (Release is how long it
 +  takes the note to fade to silence after it has ceased
 +  playing.) A value of 9 or higher in this nybble will create
 +  an echo effect. All four of these nybbles will be fastest if
 +  they are set to 0, and slowest if set to F. (This also
 +  applies to the vibrato bytes, which will be discussed next.)
 +
 +To recap:
 +          00:00 00 00 00 00 00 00 00
 +             ^^ ^^
 +             AS DR
 + 
 +      The next byte is the Vibrato Speed byte. The first
 +  nybble controls how quickly the vibrato cycles up and down.
 +  The second controls how long the note must be sustained
 +  before the vibrato kicks in.
 +
 +      The following byte is the Vibrato Control byte. The
 +  first nybble controls how much the note is oscillated from
 +  its original pitch, with 0 being none and F being the most.
 +  The second nybble'​s function is still unclear to me, and
 +  changing the value has small but strange effects on the
 +  behavior of the player.
 +
 +Review:
 +          00:00 00 00 00 00 00 00 00
 +                   ^^ ^^
 +       ​Vibrato Speed   ​Vibrato Control
 + 
 +      The next byte is the '​effects'​ byte. The first nybble
 +  has some applications that are unclear to me, but setting it
 +  to a '​1'​ will keep the note played a constant pitch, no matter
 +  what note the track data says to play. (This is useful for
 +  drums as they have a constant frequency, except for tom-toms.)
 +  The second nybble controls how the filter information is to be
 +  applied to the sound. It chooses the high-pass, low-pass,
 +  band-pass, etc. filters.) A value of '​0'​ in this nybble will
 +  shut off the filter for that instrument.
 +
 +      The next three bytes point to filter parameters, pulse
 +  parameters, and the waveform sequence for this instrument,
 +  respectively. These bytes are set depending on where in the
 +  waveform, pulse, or filter tables you wish the sound to get
 +  its data from. (Explained in a moment.)
 +
 +Review: ​                      plse
 +                               ^^
 +          00:00 00 00 00 00 00 00 00
 +                        //  ^^    ^^
 +                       ​fx ​ filter ​ waveform
 + 
 +      Now, press the slash (/) key. You will now see a new
 +  trio of windows, the leftmost of which is the waveform
 +  sequence. The bytes preceding the colons are reference
 +  numbers, which are used in the afore mentioned waveform
 +  pointer byte. The same idea applies to the middle window
 +  which is the pulse parameters, and the right window, which
 +  is for the filter parameters.
 +
 +      The 2-byte waveform sequence lines each represent a
 +  simple sound. It is in this sequence where all the magic of
 +  detailed synthesized sound occurs. The first byte controls
 +  how much the pitch of that particular sound is offset from
 +  the actual note listed in the track data (That is, if the
 +  first nybble of the effects byte is not set to 1, otherwise
 +  these sounds are offset from a constant note.) A value of 00
 +  makes the pitch exactly equal to the listed note, and as the
 +  number increases, so does the pitch. (You can't offset the
 +  note downwards.)
 +
 +      The first nybble of the second byte selects the waveform
 +  of this particular simple sound. Values are as follows:
 +      1 = Triangle
 +      2 = Sawtooth
 +      4 = Pulse
 +      8 = White Noise
 +  Other values would create interesting sounds.
 +
 +      The second nybble controls the ring modulation and sound
 +  nature. For instance, a value of 0 in this nybble will cause
 +  the simple sound to take the resounding volume from the
 +  previous sound and use that to make the current sound, as
 +  opposed to putting a 1 in this nybble, which will cause the
 +  sound to generate its own volume, and "stand alone",​ if you
 +  will. Other values control the usage and nature of ring
 +  modulation.
 +
 +             ​offset
 +Review: ​     ^^
 +          00:​00-00 ​ 00:00 00 00 00  00:00 00 00 00
 +         // ​    ^^
 +      ref#      ^fx
 +          waveform
 + 
 +      Now, to explain the pulse byte settings (Second window
 +  from the left in the pop-up set. By the way, you can use the
 +  slash key (/) to toggle these windows on or off, if you
 +  decide you wish to see more of the tracks.) The leftmost
 +  byte is the maximum value that the pulse will reach or cycle
 +  to, depending on the counting direction nybble. The nybbles
 +  are switched in this byte (as well as in the rightmost byte,
 +  which is the width at which the pulse wave will start
 +  cycling from.) So if you place E3 into either of these
 +  bytes, the pulse width represented is $03E0. The second byte
 +  from the left controls the speed of the wave. Often,
 +  interesting waves can be constructed if you set this to a
 +  high value, resulting in some wave interference,​ like
 +  out-of-phase standing waves. Finally, the first nybble of
 +  the third byte is the counting direction nybble. Different
 +  values will cause the pulse value to stay steady at the
 +  start value, go up to the max value, go up then back down,
 +  infinitely oscillate, etc. The second nybble controls the
 +  amplitude of the sound wave. Remember, you must have some of
 +  the waveform data contain a 4 in the first nybble of the
 +  second byte, because that 4 tells the player to use the
 +  pulse values specified by the pointer in the instrument data
 +  window (seventh byte.) See how all this ties together?
 +
 +      The filter byte settings are exactly the same as those
 +  for the pulse, except they control the filter (obviously.)
 +  Remember that in order to use a filter, you must have placed
 +  some number (other than 0) in the second digit of the fifth
 +  byte in the instrument data window, and have set the pointer
 +  (sixth byte) to point to the filter parameters you wish to
 +  use for that particular instrument.
 +
 +Review: ​         speed  amplitude
 +                    ^^  ^
 +    00:​00-00 ​ 00:00 00 00 00  00:00 00 00 00
 +             // ​ ^^    ^  ^^ <same for these>
 +           ​ref# ​ end  dir start
 + 
 +      Regarding the main track windows, the first three dashes
 +  are for commands that will be acted upon when the music
 +  reaches that point. These commands can be one of the
 +  following: instrument change, note slide, or legato. To
 +  change the instrument, simply type an '​I'​ in the first
 +  position, then type the number of the instrument you wish to
 +  change to. (The number preceding the colon in the lowest,
 +  longest window.) To use the note slide (or "​glide",​) type an
 +  S in the first position, then the number of the glide
 +  parameter you wish to use at that point (explained later.)
 +  The slide will affect only the note at that position. (It
 +  can be extended to other notes if the legato is used.) To use
 +  the legato, simply type a star (*) in the first position,
 +  and move off of the line. (The star will change into three.)
 +  Place this in front of each note that you wish to continue
 +  from the previous one. The second set of dashes is where the
 +  actual notes are placed. All you have to do is cursor to the
 +  desired position, and use the top two rows of the keyboard
 +  as a piano keyboard in entering the notes, as follows:
 + 
 + 2 3   5 6 7   9 0   - \ <​HME> ​     - black piano keys
 +Q W E R T Y U I O P @ * ^     <​DEL>​ - white piano keys
 +^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^       ^
 +C D E F G A B C D E F G A       B
 + 
 +  Pressing <​SHIFT>​ and <​RETURN>​ while the cursor is on the
 +  second set of dashes will put a sustain flag into that note
 +  position. (Much like a sustain pedal. It is represented by
 +  three plus signs +++.)
 +
 +      The number after each note is the octave, which can be
 +  raised using F7, and lowered using F8.
 +
 +Review:
 +
 +     8000 --- ---
 +Inst.#00- I00 C#4 - Note: C sharp (#), octave 4
 +          --- +++ - Sustain
 +Slid.#00- S00 +++ - Sustain same note, acted on by slide
 +          --- +++ - "
 +          --- --- - Nothing (release of previous note)
 +          --- D-4 - New note, same instrument
 +          --- +++ - Sustain
 +Legato- ​  *** E-4 - New note, sustained from previous
 +          --- +++                     (no attack/​decay)
 + 
 +      The glide parameter window is the rightmost one on the
 +  bottom of the screen. (And it can be reached by pressing X.)
 +  The numbers before the colon are the reference numbers for
 +  each of the glide definitions. The first byte controls the
 +  direction and extremity of the slide. The second byte
 +  controls the speed. A wide range of slides is possible with
 +  these -two- bytes, which can each be set from $00 to $FF.
 +  (That'​s #$ff * #$ff = 65,536 combinations!)
 +
 +      Editing the arrangement of blocks is fairly easy. The
 +  light grey numbers have certain significance:​ The first two
 +  digits act as a separate byte controlling the transpose
 +  value of the block. In other words, that byte will increase
 +  the key of all of the notes in the block by a half-step for
 +  each number increased. (Don't decrease the number...it has
 +  strange undesirable effects on the editor or the sounds.)
 +  The second pair of digits is the number of the block. This
 +  can range from $00 to $72. Don't go any further, or you'll
 +  get strange undesirable effects again. (This is probably
 +  due to the fact that a certain amount of RAM was sectioned
 +  off for blocks and if you exceed that, you scramble other
 +  parts of the tune/​program.)
 +
 +      To end your tune, place a block at the end numbered
 +  $FF00. (This is usually done automatically by the editor.)
 +  This number causes the player to repeat the music either
 +  from the beginning or from the set mark, depending on
 +  whether you have pressed F1 or F3 to start the tune.
 +
 +      To create more than one tune in the same player
 +  (conserves space) all you need to do is make the tunes one
 +  right after the other, then insert a block numbered $FF00
 +  between each of them, and save.
 + 
 +      Well, that should be plenty to get you started and on your
 +  way to making tunes! If you have no desire to create sounds
 +  yourself, you can take them from other JCH tunes very easily
 +  by using one of the sound ripper utilities, or using a
 +  depacker and then saving the sound data tables, provided you
 +  have the same player that the depacked tune was written for.
 +  The best thing to do is to set up some basic sound
 +  definitions,​ and basically play around with some of the
 +  values, such as the pulse and filter parameters. Once you
 +  train your ears to break down complex sounds in our world
 +  into combinations of the four simple sounds, you will be
 +  able to recreate those sounds in the JCH editor. In some
 +  cases, you may desire or need a multiple-speed player. All
 +  you need to do is pick up a one-block program that alters
 +  the editor to play in multiple speed. (You may even be able
 +  to alter it yourself.)
 +
 +Enjoy!
 +-----
 +The following is a uuencoded file of Sean's first JCH tune;
 +  ​
 +begin 600 NewBeginning
 +MÀ0@K"​ÀÀÀES@P."​PR,​C4ZES<​W-2PP.I<​U,​S(X,"​PP.I<​U,​S(X,​2PP.IDBDP!E
 +M"​À$ÀF2(<​P,#​ÀP,#​ÀP,​À?​U<​3%Q,​D<​P!_5Q,​7$R1SÀ'​]7$Q<​3)',​À?​U<​2[',​À?​
 +MU<​D<​P,#​ÀP,#​ÀP,​ÀÀHÀ@"​À)DBD8'​ÀP,#​ÀP,#​ÀP)K'​U<​3$RX'​ÀFL?​5Q,​3+@<":​
 +MQ]7$R<​B!P)K'​(,​V!P)K'​R('​ÀP,#​ÀP,#​ÀPÀ#;"​À,​ÀF2*1GL#​ÀP,#​ÀP,#​ÀFM3'​
 +MGL#​ÀP,":​Q\>>​P,#​ÀP)K'​QY[ÀFLC(GL":​QRÀ@S=3(GL#​ÀP,#​ÀP,#​ÀÀ!0)!À"​9
 +M(I&​9P,#​ÀP,#​ÀP,​À%Q\K&​QLF9PÀ74RL;​)F<#​À!=3*QLO9F<​À%U-G-("#​9F<#​À
 +MP,#​ÀP,#​ÀÀ$\)!0"​9(I$>​P,#​ÀP,#​ÀP,"​5RL;&​R<​@>​P)74U<​3+'​L#​ÀE=35Q,​G9
 +M'​L"​5U-D>​P)7-(-D>​P,#​ÀP,#​ÀP,​ÀÀCÀD&​À)DBD9KÀP,#​ÀP,#​ÀP,#​ÀP('​(V9KÀ
 +M@<?'​FL#​ÀP,"​!Q\>:​P('​(R)KÀ@<?​(FL#​À@=3(FL#​ÀP,#​ÀP,#​ÀÀ,​D)!P"​9(I&<​
 +MP,#​ÀP,#​ÀP,">​U<;&​R\B<​P)['​RL;&​R9SÀGL?'​G,">​R,​B<​P)['​R)SÀP)['​R)SÀ
 +MP,#​ÀP,#​ÀPÀÀ&"​@@ÀF2*1'​\#​ÀP,#​ÀP,#​À!<​K&​TL;​+'​\À%RL;​2QLL?​PÀ7*RQ_À
 +M!<​K+'​\À%RLL?​P,​À%RLL?​P,#​ÀP,#​ÀP,​ÀÀ-ÀH)À)DB("​À@("​À@("​À@("​À<​4""<​
 +M02"​64"">​4"​À%02!,​()Y!()92()Q$(!Q/​À'​(*"​@"​9(A$@'​%"​64D6>​4T5.!513
 +M($].(#​4OGC(Q+Y8Y-!PZ(!*7)YA!FRÀ%3D57($)%1TE.3DF;​3IA'​ER<​ÀIÀH+
 +MÀ)DB("​À@("​À@("​À@("​À@("​À@("​À@("​À@("​À@$II!GRÀ%1U)%050@5%5.GT6:​
 +M(0#​9"​@PÀF2(1'​BV9/​05214Q%05-%1"​!/​3B!42$4@1$%9($E4(%=!4R!#​3TU0
 +M3$541429/​1XMÀ!<​+#​0"​9(A&<​1Y9219E%5$D%3D=3(%1/​FSH@ETH>​19]&​F48@
 +M!4)!F4.?​3QY,​ET\@*!Q:​GTF<​4AY#'​S";​*2PÀ4@L.À)DB("​À@("​À@("​À%4I9!
 +M0QQ(14P@2$5,​1T664T\%3ILL(À5!GTX?​1T5,​3R!"​24%.0Y](!4F;​+À"​4"​P\À
 +MF2*1("​À@("​À@("​À%5)E/'​DT@2T$>​39E)!4Z;​+"​À%19E$GU>:​29=.G"​!6'​T&​5
 +M3BÀ<​4X%%EDZ;​5)Y%!4Z;​+À#​*"​QÀÀF2)!3D0@04Q,​($]&​($U9($]42$52($92
 +M245.1%,​@04Y$($-/​3E1!0U13(CJ>,​SÀW,​@#​A"​Q$ÀGC,​P-S4Z@4&​R,​*0V.H(Z
 +MB3$WÀÀÀÀ_P#​_À/​\À_P#​_À/​\À_P#​_À/​\À_P#​_À/​\À_P#​_À/​],​0ÀQ,​V@P!À@0/​
 +M0#/​K:​1@5$0'​\/​C0PÀÀÀÀÀ/​[^_@ÀÀ("​U03$%915(@0ED@2D-(+BXN+DU54TE#​
 +M($)9(%E/​52$M"​@H*J*(ÀN>​\3G4X3G503N?​À3G5$3G5<​3R,​CHXÀ/​0YZ(ÀCDT3
 +MN>​\3C0L,​C7L3C7P3C7T3G=D3[DT3K0L,&'​GO$XT+#​!AM31/​HX!#​0YZT@#/​ÀK
 +MH@*Y\!.-31,​]6A.=!@S*$/​$L31,​0%:​(ÀN?​$3G503N?​(3G5<​3R,​CHXÀ/​0[:​ÀÀ
 +MF)DÀU,​CÀ&​]#​XJ)E^$YEF$\CÀ#​-#​UK0D,​C1C48*("​O6D3R0+0++QR$[EC%+Q@
 +M$YD%U+QR$[ED%+Q@$YD&​U*U*%/​À)K4D4F0343À\-O7@3F034RA#​*I?​M(I?​Q(
 +MH@*]!@S0ÀTRÀ$KUO$_À(WF\3T!-,​O0Z\<​A.Y9A0I#​]U[$_À&​WGL33)H/​G6\3
 +MO743G7L3O4X3A?​N]41.%_*ÀÀF)UL$['​[$À\*G8$3_DX3TÀ/​^41/​(L?​NHN9<​5
 +MA?​NYT16%_+QF$['​[,"​CP',​E^\ÀZ=?​A.]RA/​P"​=[*$TR7#?​YL$ZG_G6,​3T&​RI
 +M_IUC$_YL$]!B2"​G@R8#​0&​6A(*1"​=;​!-H*0^HN=D3G7L3G743_F83T+'​)H-À,​
 +M:​ÀH*"​IUR$_YF$]"​A:"​D_"​JBYM!2=P1.YLQ1(*1^=Q!-H2"​FÀG<<​3J0&​=RA.I
 +MÀ)W0$YW3$V@I(-#​._LH3T,​G^9A.\9A.Q^\E_T"​VIÀ)UF$ZB]3A,​8:​0&​=3A.%
 +M^[U1$VDÀG5$3A?​RQ^\G_TÀR]5!.=3A.]5Q.=41/​)_MÀ.J0"​=!@R\8!.9!-1,​
 +M@!*];​!/​P([UO$]À;​O6,​3G1H,​O7X3G10,​O8$3G1<,​O<​H3G<​T3G6D33)H/​O&​À3
 +MK4@4F074F0;​4O6\3\"​],​@!*\8!.]>​!,​I_ID$U+QR$[EC%+Q@$YD%U+QR$[ED
 +M%+Q@$YD&​U+UX$YD$U$P$#​[UC$YT:#​+U^$YT4#​+V!$YT7#​+W*$YW-$YUI$[UL
 +M$_À#​3)H/​O&​À3K4<​4F074F0;​4K4H4\ÀNM210I_ID$U$P$#​[UX$RG^F034O'​(3
 +MF)T=#​+EJ%)V^$[EI%)VK$ZBIÀ)VN$[E5%"​FÀR8#​P#​[E6%$@I\)VQ$V@I#​YVT
 +M$[QR$[EG%*ÀÀ*0_P&,​D(\!,​*"​@H*#​0D,​C1C4R*T*#​!U:​$]À'​R*T*##​U=$XT7
 +MU(T*#,​À!T!Z\<​A.Y:​!2-NQ.HN4D4*8#​)@-À&​N4H4C;​T3J0"​-O!.IÀYUI$ZU*
 +M%-À#​3,<​0WFD33(À2O:​X3\À;>​KA-,​\À^\JQ.Y4Q1(2DI*2IV?​$V@I#​YVB$[E4
 +M%)VE$[E5%(U-$RD_"​IVN$RQ-$QÀ4N5842"​GPG;​$3:"​D/​G;​03J0"​=J!,​L31-P
 +M!Y@8:​02=JQ.]J!/​0&;​VQ$QA]I1.=L1.]M!-IÀ)VT$]VB$]ÀA\!>​]L1,​X_:​43
 +MG;​$3O;​03Z0"​=M!/​=GQ/​0"​+VH$TD!G:​@3XÀ#​PÀTS'​$*V\$_À&​SKP33)H0K+L3
 +MN4<​42"​GPC;<​3:​ÀH*"​@J-N!.Y2!2-N1.Y212-31,​I/​PJ-O!,​L31,​0)*T*#"​D/​
 +MC4T3N4H42"​GPC;​T3:​ÀH*"​@H-31.-"​@R-%]2IÀ(VZ$RQ-$WÀ'​F!AI!(V[$ZVZ
 +M$]À1K;​T3&&​VY$XV]$\VX$YÀ9LÀ^MO1,​X[;​D3C;​T3S;<​3LÀBMNA-)À8VZ$[QR
 +M$[EG%"​GPR1#​0'​[R^$[G_$\E_TÀJY(Q2=OA.HN?​\3G0\,​J0"​=#​ÀQ,,​1&​\OA.Y
 +M_Q,​P$,​E_T!*Y(Q2=OA.HN?​\3$À8*HÀ%,&​Q$8?​10,"​AA]%PR@À(Q-$ZBYC1(8
 +M?​=83G0P,​N8X2:​0"​=#​PR\OA.Y(Q2=>​!/​^OA.]S1/​P4[W'​$]À6O=À3&'​W!$YW0
 +M$[W3$WW$$YW3$TQP$;​W0$SC]P1.=T!.]TQ/​]Q!.=TQ.M31/​0$[T,#​!A]T!.=
 +M#​ÀR]#​PQ]TQ.=#​PR]:​1/​)À?​À#​WFD33%82O6D3\#​[)À?​À&​WFD33%82O'​(3N684
 +M2DI*2IV'​$SCIÀ9V$$ZDÀG9À3G983G9D3N6442"​GPG9P3:"​D/"​IV3$]YI$TQ6
 +M$KV'​$_!YWI,​3,​À-,​5A+^DQ.]#​PQ*2DJ-"​PR]G!,​8;​0L,​G8H3J0!IÀ)V-$]Z$
 +M$QÀ.O9À320&​=D!.]AQ.=A!.]D!/​0%KV6$QA]BA.=EA.]F1-]C1.=F1-,​0Q*]
 +MEA,​X_8H3G983O9D3_8T3G9D3O0P,&'​V6$YT,#​+T/#'​V9$YT/#​+Q@$[VQ$YD"​
 +MU+VT$YD#​U*V]$XT6U+T,#​)DÀU+T/#​)D!U+UX$ST:#​)D$U,​HPÀTP:#​6B%_&​B%
 +M^VÀ6À2<​!.À%+À5\!<​P&​*À:​$!N@'​4À?​À!#​@(MÀDX"<​0*6ÀKT"​YP(3ÀT(#​=À.I
 +MÀ^À#&​P1:​!)L$X@0L!7L%S@4G!H4&​ZÀ91!\$'​-PBT"#<​)QÀE7"​O4*GÀM.#​ÀD-
 +MTÀVC#​H(/;​A!H$6X2B!.O%.L5.1><&​!,:​H1M&'​00?​W"#​0(MPD$"​=>​*=8K<​BXX
 +M,​28T0C>,​.@@^N$&​@1;​A)($Z\4JQ7Y%QP8DQHA&​X8=1!\<​(-ÀBW"​30)QXI5BO
 +MR+G@Q)C0"​-TPZB#​X+OTÀN@1/&​!D9M@%,&​!D9À0($_OW[ÀÀ<​._O[^ÀÀL"​ÀÀÀÀ
 +MÀ0$!ÀÀÀÀÀÀÀ@$Q,​_04$A#​P,'​-#​ÀÀÀÀÀÀ__\ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ
 +MÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ&​!@À$À1V@X,​À"​@H(À+À/​À90:​W@$!%0ÀÀÀÀÀÀ
 +MÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ!À@,'"​P\3%QL?​(R<​K+S,​W.S\ÀÀÀ#​\/​À&​V%À$5
 +M3!4#​![84À15,​%?​__À'​_?​$@[?#'​_?"​@@&​!0!_<​!]P?​PÀÀ?​P!_ÀÀ0'?​PÀ%!W\À
 +MÀ@=_00"​!$$"​À$À6!$!À0$ÀÀ(@1&​À$4$A%$$6(2$A&"​$A(1PA(2$@#​PÀ)À0IÀ
 +M@@0ÀÀÀÀÀÀÀ#​_"​ÀÀÀ_]\ÀÀ@):​ÀÀÀÀÀ"​4IÀÀÀÀÀÀ@À#​N4ÀÀ!ÀÀÀÀ@("​ÀÀÀ$ÀÀÀ
 +MÀ@54ÀÀ(1!À0//​_@ÀÀÀÀÀÀ!,/​J0ÀÀÀÀÀÀ%@53ÀÀÀÀÀÀÀ8!5,​ÀÀÀÀÀÀ!P%4PÀÀ
 +MÀÀÀÀ(ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ@À"​ÀÀÀ,​À!0À'​!PD)"​PL-"​P\/​$1$ÀÀÀ,​À!0À'​!PD)
 +M"​PL-"​P\/​$1$ÀÀÀ,​À!0À'​!PD)"​PL-"​P\/​$1$ÀÀÀ,​À!0À'​!PD)"​PL-"​P\/​$1'​_
 +M@À&​ÀÀ00!!@$("​ÀH*#​ÀP.#​!À0$A(!À00!!@$("​ÀH*#​ÀP.#​!À0$A(;'​!T>'​RÀA
 +M(B,​D)24F)R@H*2D!À00!!@$("​ÀH*#​ÀP.#​!À0$A+_@À*ÀÀ@("​À@("​À@("​À@("​
 +MÀ@("​À@(3$Q,​3$Q05%146%Q<​7&​!D9&​1H3$Q,​3$Q05%146%Q<​7&​!D9&​1HP,​3(P
 +M,​SÀT,​34Q-C$W-C@Q.3'​_"​QDI+CM*5V9S@H^>​J[K'​UN/​R_PXF/​55LA)NSRM3;​
 +MY/'​Z!RÀY4FMXA9*KQ,​G.T=37VN#​EZ_'​W_0,​)#​Q86%A86%A86%A86%A86%A86
 +M%A87%Q<​7%Q<​7%Q<​7%Q<​7%Q@8&​!@8&​!@8&​!@8&​!@8&​!@8&​!@8&​!@9&​1F@@#"​$
 +MÀ(ÀWAÀ"​À-(0À?​Z""​À(ÀTAÀ"​À,​(0À@#>​!À'​^/​À($À?​XÀPAÀ"​À-X0À@#​6$À'​^"​
 +MÀ(ÀUAÀ"​À,​(0À@#>​!À'​^À,​(0À@#>​$À(ÀRAÀ!_@@"​À,​H0À@#"​$À(ÀW@0!_@"​V$
 +MÀ(ÀTAÀ"​À,​H0À?​X(À@#​*$À(ÀMAÀ"​À-($À?​XÀMAÀ"​À-(0À@#&​$À'​^"​À(ÀQAÀ"​À
 +M+80À@#​2!À'​^À*80À@#"​$À(ÀMAÀ!_@@"​À+80À@"​F$À(ÀP@0!_@"​F$À(ÀPAÀ"​À
 +M*X0À?​X(À@"​N$À(ÀIAÀ"​À,​($À?​XÀKAÀ"​À,​H0À@#"​$À'​^"​À(ÀPAÀ"​À*X0À@#​*!
 +MÀ'​^À*X0À@#​*$À(ÀOAÀ!_@@"​À+X0À@"​N$À(ÀR@0!_I(À8AÀ"​À&​($À@!B!À**À
 +M&​($ÀI(À3@0!_I(À8AÀ"​À&​($À@!B!À**À&​($À@!B!À'​^D@!6$À(À5@0"​À%8$À
 +MHHÀ5@0"​D@!"​!À'​^D@!6$À(À5@0"​À%8$ÀHHÀ5@0"​À%8$À?​Z2À$80À@!&​!À(À1
 +M@0"​B@!&​!À*2À#​($À?​Z2À$80À@!&​!À(À1@0"​B@!&​!À(À1@0!_I(À3AÀ"​À$X$À
 +M@!.!À**À$X$ÀI(À.@0!_I(À3AÀ"​À$X$À@!.!À**À$X$À@!.!À'​^E@#​R*À(À^
 +MAÀ!_A0"​À0(HÀ?​X!!B@"​À0X0À?​X!!AÀ"​À0(0À@#​Z$À'​^À0(HÀ@#​Z$À'​^À0(0À
 +M@#​R$À(ÀWAÀ!_@#​F!À(!À@0"​À/​H$À@$"​!À(ÀY@0"​À0($À?​XÀ^@0"​À0($À@#​F!
 +MÀ(!À@0"​À/​H$À@$"​!À'​^À.8$À@$"​!À(À]@0"​À0($À@#​F!À(!À@0!_@#​V!À(!À
 +M@0"​À.8$À@$"​!À(À]@0"​À0($À?​XÀUB@"​À-8$À@#​6!À'​^À-80À@#>​$À(À\AÀ!_
 +M@#​6$À(ÀYAÀ"​À/​(0À?​XÀW@0"​À/​($À@#​Z!À(ÀW@0"​À/​($À@#​Z!À'​^À-X$À@#​N!
 +MÀ(À^@0"​À-X$À@#​N!À(À^@0!_CP"​!À'​^/​À($À?​XÀÀ?​XÀÀ?​XÀÀ?​XÀÀ?​Z://​(%^
 +M?​X]^@7Y_IX\\@7Y_J(\\@7Y_IX\Y@7Y_IH\Y@7Y_IH\U@7Y_J(\U@7Y_IX\W
 +M@7Y_IH\W@7Y_&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +M&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +9&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +À
 +end
 +
 +
 +/​S06::​$d400:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +                      An inside look at MODplay 128
 + 
 +                           ​+-+ ​    ​by ​    +-+
 + 
 +                    Nate Dannenberg and Mike Gordillo
 + 
 + 
 +Nate Dannenberg is an expert at digitizing sounds on the Commodore 64 and 128.
 +For the past year or so, he has been the heart and soul of probably the most
 +revolutionary program in Commodore 64/128 audio since Mark Dickenson'​s Stereo
 +Sid Player. MODplay is the name and it will rock your system to the core. You
 +are the first priviledged readers to get a sneak peek at this exciting bit of
 +software.
 +--
 + 
 +> Nate, you are the author of the world'​s first and only .mod player on the
 +> 8 bit Commodores. ​ I am curious to explore some of its inner workings.
 +>
 +> But first... What exactly IS a "​mod"​ anyways?
 + 
 +Mike, you probably know the answer to that one already. ​ A mod is simply
 +a music file format which started on the Amiga line of computers and spread
 +to many other systems. ​ It is a very efficient format in which music is sampled
 +or cut into discrete portions and later reassembled in many different ways to
 +create varied tunes and patterns to form a musical score. ​ The module format
 +can be summed up as a form of musical archive. ​ A few instruments may be
 +sampled only once, but their samples can be manipulated in thousands of ways
 +that may not be possible on the actual instruments. ​ For example, a sample of
 +a flute can form an entire orchestral piece in and of itself without much
 +effort. ​ However, in order to achieve this, a computer requires a moderate
 +amount of speed and memory. ​ Many have discounted the possibility of .mod
 +playback on our machines and have therefore not explored the true limits of
 +hardware in this regard, until now.
 + 
 + 
 +> The C128 is not known for top speed and memory though.
 + 
 +Fortunately,​ it has just enough speed and memory when combined with a 17xx Ram
 +Expansion Unit (REU). ​ To be perfectly honest, my modplayer can only function
 +with an "​REU"​ and a C128 running at 2 MHz.  But it functions well enough to
 +keep tempo with the majority (if not all) the 4 track "​mods"​ out there and
 +it can even output sound in 8 bits!  In the future I may try to support the
 +Ramlink/​Ramdrive units and perhaps one or two of the more popular internal
 +ram (256k to 1 megabyte) expansions. ​ Although the Ramlink/​Ramdrive units
 +may not have enough speed for the task, I do believe the CMD Super 64 and 128
 +accelerators will change this and allow for potentially both C64 and C128
 +accelerated modplayers in the future.
 + 
 + 
 +> But for many years, I have heard (from Amiga users primarily) that our little
 +> machines did not have the CPU horsepower necessary to simultaneously process
 +> and play back the module format. ​ Amiga users cannot be wrong! ​ How did you
 +> manage to do it?
 + 
 +You have to know a little about how the module format works, but without going
 +into too much detail, imagine all samples within a .mod file as being organized
 +into rows and patterns. ​ These rows and patterns determine what, when, and how
 +sample data gets played back to the user.  In my player, rows and patterns are
 +centered around their respective tracks (channels). ​ The basic procedure is
 +described as follows :
 + 
 +   Get the 16 byte row data from the ram expansion unit. Now divide the row
 +   into four 4-byte subsections where each subsection represents a track
 +   ​(1,​2,​3,​4). ​ Get the current 1 KB pattern data into memory and extract the
 +   next 16 byte stub from that pattern. ​ Divide the pattern stub as the row
 +   was divided before (into four 4-byte subsections) to match each track.
 + 
 +Within each four byte track, pattern information about a row is divided into
 +a sample number, a note period, an effect command, and an effect parameter.
 +The sample number directs the program to use a certain sample for whatever row
 +(i.e., notes) are being played in that track. ​ The sample number is derived
 +as follows : "​zeroth"​ high nybble byte + (second high nybble byte/​16). ​ It is
 +then used to index a data table where info such as sample length and start
 +address inside the ram expansion unit are obtained. ​ The note period, on the
 +other hand, tells the CPU how many 3.5 MHz ticks to count down before sending
 +out the next sample byte.  The note period is then used as a lookup into a
 +frequency stepper table in order to determine the pitch of the note.  A value
 +of 254 for example would be the equivalent of concert pitch A-4.  The effect
 +command modifies the pitch, playback time of the note or the whole pattern,
 +and the volume if needed. ​ You can use it to apply an array of effects to 
 +each note, including vibrato, portamento, arpeggio, etc.  The effect parameter
 +in turn modifies the effect command. ​ For example, if the effect command is
 +a zero and its parameter is a zero as well, then any effect for that track
 +will be cancelled immediately. ​ Likewise, if the effect command is zero and
 +its parameter is something other than zero, then the effect command is treated
 +as an arppegio using the supplied parameter value. ​ For reference, if any
 +pattern value for a given row is zero then the pattern data for the previous
 +row is used.
 + 
 +After all is said and done, my program grabs all the module data in little
 +spurts from the ram expansion unit at approximately 459,200 bytes per second
 +leading to (after processing) an effective 8.2 KHz play-back rate.  It is
 +interesting to note that my modplayer could reach nearly twice the sample
 +rate it has now if it were to pull its data from the 128's internal memory.
 +Alas, there are few .mod files that could comfortably fit in 128 kilobytes.
 +If I decide to allow the player to grab data from internal memory, it would
 +probably be in support only for internal ram expansions.
 + 
 + 
 +> How would internal ram be faster as compared to the ram expansion unit?
 + 
 +The ram expansion unit (REU) is a marvelous blessing. ​ It allows my program
 +to naturally store huge .mod files and has the fastest transfer rates of any
 +ram storage device in the Commodore 8 bit market. ​ Despite this, it does
 +carry overhead penalties that simply do not exist when accesing internal
 +memory. ​ For example, I must calculate a three-byte value into the ram
 +expansion unit (LSB, MSB, RamBank) and copy it to the ram expansion address
 +pointer and also into internal memory. ​ I have to toggle down to 1 MHz while
 +accesing the REU.  I then toggle back up to 2 MHz while copying the module
 +data into the C128 as I do a 4-level deep interleave on the module data
 +itself. ​ As this entire sequence is repeated many many times, you can see
 +how much time is lost.  If I were doing all this from internal memory, I
 +would have to again calculate the three-byte pointer but this time I could
 +keep it in zero page and would never have to copy it anywhere (except to
 +copy the bank pointer to the memory mangement unit inside the C128). ​ I
 +would never have to switch to 1 MHz mode.  Furthermore,​ I would not need to
 +access the module data in small chunks as it would all be easily available
 +in internal memory. ​ As it stands now, data is cached into the C128 as
 +described earlier for logistical reasons concerning ram expansion overhead
 +times. ​ A more direct method of accessing the module data would be simple
 +with internal memory.
 + 
 + 
 +> You mentioned that your modplayer outputs in 8 bits.  Could you explain
 +> how you squeezed 8 bit audio out of the C128.
 + 
 +Originally, I used a technique called Pulse Width Modulation to do it.
 +Remember that early 64/128 digiplayers used the $d418 reg. for 4 bit digis.
 +I used $d402 instead as the DAC register while toggling the test bit in $d404
 +for each sample byte.  I then filtered voice 1 and WHAM, instant 8-bits. ​ The
 +techinique is interesting and might be of use to you, as follows :
 + 
 +Simply put, just set voice 1 to produce a pulse waveform for the current
 +sample rate.  This pulse will range from zero to maximum width. ​ At the
 +sample rate of my player, max. width corresponds to 127 cycles. ​ Now start
 +stuffing numbers into $d402. ​ Each time you do that, put a hexadecimal 49
 +and then 41 into $d404 and be sure to filter voice 1 with a low pass..voila.
 +Your timing needs to be good and steady. ​ Needless to say, the whole operation
 +works best in 2 MHz mode.
 + 
 +Using pulse width modulation, the pulses can range from 1 cycle to about 127
 +cycles wide at the 8.2 KHz sample rate.  That is equivalent to 7 bits and the
 +filter gives you a boost in quality (i.e., effective 8 bit resolution).
 + 
 +The one major drawback with the PWM technique is that it leaves behind a
 +residual squeal that is audible at the current sample rate.  I am currently
 +working on a methodology to completely eliminate the squeal and the most
 +promising option appears to be an extension of the PWM technique known
 +as PCM or Pulse Code Modulation. ​ There is also a minor problem with low
 +volume output but this is easily corrected by amplification at the user's
 +sound system.
 + 
 + 
 +> These 8 bit techniques you mentioned are for use with the SID chip.  Do you
 +> have any other ideas in mind?
 + 
 +If the SID had a volume register from 0 to 255, I could have used the standard
 +$d418 DAC technique for 8 bit resolution. ​ As this is not the case, PWM/PCM
 +is necessary for the quality I hope to get out of the SID without resorting
 +to additional hardware. ​ I do provide standard 4 bit and dithered 4 bit sound
 +output in the program and will fully implement 8 bit SID sound when I feel it
 +has met my requirements. ​ However, I have not discounted other options. ​ As
 +seen elsewhere in this first issue of disC=overy, I have gone into detail on
 +an 8 bit DAC board that is very simple to build and program. ​ The modplayer
 +already supports this particular board as a low cost alternative. ​ I am
 +also working on a more advanced dual DAC -- ADC board that will be available
 +for sale along with the modplayer. ​ It will have four tracks, each of 8 bits
 +and with an 8 bit linear volume control yielding an effective 16 bits of
 +resolution per channel :).
 + 
 + 
 +> Before we depart, I would like you to emphasize the difficulty in what you
 +> have done, a C= 6510/8502 modplayer! ​ :)
 + 
 +The task was not terribly difficult in theory. ​ In practice it has sometimes
 +become quite a hassle and it is still in progress. ​ If you want a comparison,
 +for a no-frills .raw digi format (not the module format) you could probably ​
 +get away with over 80 (eighty) KHz in simple 4 bit mono on a C128 at 2 Mhz
 +and you can do about 60KHz 4 bit mono from the ram expansion unit.  On a C64
 +you should be able to do at least 30 KHz mono 4 bits from the ram expansion
 +and about 44 KHz from memory. ​ Obviously, these would be short samples but the
 +drive home point is that the module format is indeed a computation-intensive
 +exercise when compared to .raw digis. ​ Regardless, my player can handle
 +up to 31 samples, up to 255 patterns, 4 to 8 bits, 4 tracks, and up to
 +two megabytes of .mod file if you have the 2 meg REU expansion. ​ I have not
 +yet implemented the sliding routines yet, and its sample rate of 8.2 KHz,
 +although not exceedingly high, is quite adequate for many .mod files. ​ I do
 +believe that the new SuperCPU 64 and 128 accelerators from CMD will allow
 +for even greater sample rates and generally make my task easier overall. ​ I
 +will take a close look at them and at internal memory expansions. ​ If I find
 +these "​vehicles"​ to be proper and good, I may support them in the modplayer.
 + 
 +> I'd like to thank you for granting this interview, Nate.
 + 
 +Well, just don't let it go to your head, Mike.  :)
 + 
 +> ;)
 + 
 +-- 
 +For more information on this one of a kind product, you may reach Nate at
 +the following addresses:
 + 
 +Dannenberg Concepts, Ltd.
 +"​Bringing your Commodore 128 one step closer!"​
 + 
 +Email: ​  ​tron@wichita.fn.net
 +Phone: ​  (316) 777-0248
 +Snail: ​  ​Dannenberg Concepts, Ltd.
 +         c/o Mr. Nate Dannenberg
 +         306 S. 1st Ave
 +         ​Mulvane,​ KS   67110
 +FidoNet: 1:291/25
 +         ​Groups: ​ CBM, CBM-128, and CBM-GEOS
 +Usenet: ​ comp.sys.cbm,​ alt.binaries.sounds.mods
 +
 + 
 +/​S07::​$d600:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +  ​
 +Some preliminary data on VDC timing by SLJ 1995/96 (comments -> sjudd@nwu.edu)
 +-----------------------------------
 +                                    With some very helpful commentary from
 +                                    Andreas Boose!
 + 
 +        The 80-column VDC chip on the C128 is one of the least documented
 +features of the 128.  All documentation I have found echoes the 128 PRG,
 +so that the general features and programming of the chip is well known,
 +but as far as I can tell there is zero information on timing, internal
 +operation of the VDC, etc.  In an attempt to gain some insight into
 +the timing and operation of the VDC I wrote a series of simple experiments.
 +Later I received some helpful suggestions and comments from Andreas Boose:
 +any comments indented with a '>'​ are from him.
 +
 +        My personal interest is in using the VDC as a graphics coprocessor.
 +As anyone who has programmed the VDC knows, all communication with the
 +VDC is done through two memory locations, $D600 and $D601, and entails
 +the use of a busy-loop to determine when the VDC is ready to be read or
 +written to.  My idea was to have the 8502 doing something useful instead
 +of sitting around waiting for the VDC, so that I could for instance do some
 +calculations while the screen is being cleared.
 +
 +        Attached are some simple programs I wrote to get a feel for VDC
 +timing. ​ There is an ML program to do the VDC operations, and a BASIC
 +program to generate a little statistical analysis of data.  Eight tests
 +are performed and timed using CIA #2 timer A.  In retrospect some are
 +pretty naive, but I include them all for the sake of completeness:​
 + 
 +        Test 1: This is a simple calibration test to determine how many
 +                cycles are used in starting/​stopping the timer. ​ It
 +                simply starts the timer, executes 5 NOP instructions,​
 +                and stops the timer. ​ By subtracting 10 cycles from the
 +                time elapsed, you get the overhead.
 + 
 +        Test 2: Load a register (Reg 18) -- This test simply times how
 +                long it takes to tell the VDC which register you want
 +                to operate on -- no reads or writes are performed. ​ The
 +                idea is to calculate how long it takes the VDC to find
 +                a register. ​ Note that the register is not loaded with
 +                anything -- by "​loading a register"​ I simply mean making
 +                it read/write accessible.
 + 
 +        Test 3: Load a single register twice. ​ My idea here was to see
 +                how '​smart'​ the VDC was, i.e. if it already had the
 +                register loaded, would it spend any extra time reloading
 +                it.  In principle this should be twice Test 2 above.
 + 
 +        Test 4: Load all registers. ​ This test starts at register 36 and
 +                goes down to zero.  The idea here is to see if different
 +                registers take different amounts of time to fetch, i.e.
 +                will we just get 37 * Test 2 here?
 + 
 +        Test 5: Two reads of register 18.  The whole point of this test is
 +                to see if _reading_ from a loaded VDC register affects
 +                subsequent loads in any way (the expectation is that
 +                it would not).  In principle this test should be Test 3
 +                plus an additional 8 cycles for the 2 LDA's.
 + 
 +        Test 6: Read a single VDC memory location ($1919). ​ This is a test
 +                to see how long it takes to find and read a memory location
 +                within the VDC RAM.  Location $1919 was used simply because
 +                the value $19 was already in the accumulator :).  This one
 +                should take a little more time than three register accesses.
 + 
 +        Test 7: Loop memory fill.  Using a loop on the 8502 side, this test
 +                fills 256 bytes of VDC memory, starting at location 0,
 +                using the auto-increment feature of the VDC.
 + 
 +        Test 8: Block memory fill.  This test uses the block-write feature
 +                of the VDC to fill 256 bytes of VDC memory (0-255). ​ Naturally
 +                the idea is to compare it to Test 7.
 + 
 +        Just to make sure the test 7 was doing what I wanted it to do I
 +stored the VDC memory location after the loop, to make sure it was $0100
 +(which it was :).
 +
 +        The BASIC program runs these tests a bunch of times (parameter N
 +in the program) and calculates a few averages. ​ The data is all stored
 +in arrays so that it can be viewed, sorted, or whatever.
 +
 +        The first time I ran these experiments I did so in SLOW mode and in
 +FAST mode.  In slow mode an extra 43 cycles would pop up from time to
 +time.  As several people informed me,
 + 
 +>This has not anything to do with interrupts, it's the VIC-IIe'​s DMA which
 +>halts the 8502 on any bad-line for 40-43 cycles. To avoid this jitter
 +>switch off the screen before measuring, lda#​$0b:​sta$d011:​lda$d012:​bne*-3.
 +>Note the loop after switching the screen off. It's important to wait until
 +>the raster counter is out of the text area as switching off the screen
 +>​doesn'​t affect the current screen. After measuring you can switch on the
 +>screen with lda#​$1b:​sta$d011.
 + 
 +These extra cycles disappear in 2MHz mode, however:
 + 
 +>Yes, switching to 2MHz forces the VIC-IIe to leave the phi1/2 DMA cycles
 +>​(almost) untouched. This is a very brutal way to get rid of the 40-43 DMA
 +>cycles since the VIC's core doesn'​t know that you want him to leave these
 +>cycles untouched until you have switched off the screen. So it still tries
 +>to perform DMA. As this would mean a bus collision with the 8502 a
 +>​protection circuit inside the VIC shuts down its address lines, AEC and BA
 +>on DMA times. The VIC never gets the data it wanted to display a picture,
 +>it gets the data the 8502 has accessed - this gives are real bogus screen.
 +>:-)
 + 
 +As a comparison, two runs follow; the second run is in SLOW mode, with VIC
 +turned off, and the first is in FAST mode.  Both runs do 120 repetitions
 +(N=120):
 + 
 +        FAST mode, N=120:
 + 
 +        Test 1: Overhead = 1.4 (expected=1.5)
 +        Test 2: Single register = 4.9 (expected=5)
 +        Test 3: Single reg twice = 10.14166... (expected= 9.8)
 +        Test 4: total time= 304.166...
 +                minus loop overhead= 212.166...
 +                div 37 BIT-loops = 27.166...
 +                => bit-loop repetions = 7.7619
 +        Test 5: Two reads REG 18 = 14.36
 +                Expected = 13.8 (twice Test 2)
 +        Test 6: One memory fetch = 115.66...
 +                Expected = 20.7  diff = 94.966...
 +                Probable waits for VDC Reg 31 fetch = 27.133...
 +        Test 7: Loop memory fill= 10755.766...
 +                Extra VDC waits= 8347.866...
 +                Avg BIT-loop repetitions = 9.3168
 +        Test 8: Total block fill= 179.94166...
 +                => Approx VDC time spent on 256 byte block fill= 153.24166...
 + 
 +        I include the above just for the sake of comparison; my '​expected'​
 +values are very naive, and the numbers themselves are not terribly insightful.
 + 
 +        SLOW mode, VIC disabled, N=120:
 + 
 +        Test 1: Overhead = 3 (expected=3)
 +        Test 2: Single register = 10 (expected=10)
 +        Test 3: Single reg twice = 20
 +        Test 4: total time= 554
 +                minus loop overhead= 370
 +                div 37 BIT-loops = 0
 +                => bit-loop repetions = 0
 +        Test 5: Two reads REG 18 = 28
 +                Expected = 28 (twice Test 2)
 +        Test 6: One memory fetch = 118.766...
 +                Expected = 42  diff = 76.766...
 +                Probable waits for VDC Reg 31 fetch = 10.966...
 +        Test 7: Loop memory fill= 11614.5333
 +                Extra VDC waits= 6747.533...
 +                Avg BIT-loop repetitions = 3.76536458
 +        Test 8: Total block fill= 197
 +                => Approx VDC time spent on 256 byte block fill= 143
 + 
 +Comments: Tests six and seven are the only tests which showed variation;
 +all other tests stay constant throughout all trials, with one notable
 +exception:
 + 
 +Test #8 weirdness: _Very_ occasionally a spurious number will come up,
 +and always only on the first trial. ​ It is possible to duplicate:
 +from the BASIC program, set N=5 say (so you don't have to wait
 +forever). ​ When the first tests are reported and the program pauses
 +for input, hit run/stop -- the cursor should now be red.  Then rerun
 +the program, and watch the last number printed. ​ It will usually be
 +200, but sometimes numbers such as 1019, 1012, 592, and 963 pop up on
 +the first trial. ​ If you break the program at other places, though,
 +these numbers don't come up.  This is a mystery to me.
 + 
 +        1MHz mode with VIC turned off is the most reliable indicator of
 +VDC's performance:​
 +
 +        Test 3 is indeed just twice Test 2, which is not surprising for
 +register 18, since the BIT-loop is never executed. ​ (Twice Test 2?  Timid
 +termites tremble, eliciting tempting titilations. ​ Temperance!)
 +
 +        Test 4 again suggests that no registers take longer to come up
 +than others. ​ In effect, it doesn'​t seem to take up any time to set up
 +a register.
 +
 +        Test 5 verifies our intuition that reading $D601 doesn'​t alter
 +timings of subsequent operations.
 +
 +        Test 6 is an interesting one.  A typical memory fetch takes a
 +fair amount of time!  Test 4 tells us that just setting up the register
 +doesn'​t take any time; it is the write to the registers, which then
 +causes VDC to go and fetch the data, that slows everything down.  This
 +will be discussed below.
 +
 +        Test 7 shows that memory writes are somewhat time consuming. ​ Test 8
 +shows that the block-fill is a two order of magnitude improvement over
 +Test 7 though! ​ 143 cycles versus 11000 -- wow!  Also of interest is that
 +there were some BIT-loop repetitions;​ I expected them to not be necessary.
 + 
 +        Andreas Boose provides a lot of insight into some of the issues
 +raised above:
 + 
 +>​Stephen,​ 2MHz mode is not so easy as you might think. There are two facts
 +>you have to take in account:
 +>
 +>#1 In 2MHz mode a single raster line consists of 65 phi1 and 65 phi2
 +>cycles. But the 8502 doesn'​t get all cycles! During the last 5 phi1 cycles
 +>of any raster line the VIC-IIe must refresh the system'​s DRAM and so the
 +>8502 is switched to 1MHz on these cycles. Simply counting the cycles of
 +>the code and dividing them by 2 is not accurate. For a serious measurement
 +>you would have to synchronize the test loop to the VIC-IIe'​s refresh and
 +>to periodically count 120 cycles @2MHz and then 5 cycles @1MHz.
 +>
 +>#2 In 2MHz mode accessing VIC-IIe, SID, CIAs or $DE00-$DFFF forces the
 +>8502 back into 1MHz mode. But it is not simply done by counting these IO
 +>​accesses as 2 2MHz mode cycles: It is different whether the IO access
 +>occurs during phi1 or phi2. If it happens on phi1 the VIC-IIe expands the
 +>cycle into phi2 and we get 2 2MHz cycles. If it hits on phi2 the VIC-IIe
 +>delays the IO request to phi1 and then the 1MHz mode access is performed.
 +>So this consumes 3 2MHz cycles instead the expected 2 cycles.
 +>
 +>For exact measurement 1MHz mode with switched off screen might be the
 +>best reference. But even with accurate 1MHz 8502 you will not get rid of
 +>odd values, the VDC has its own clocking frequency derived from a separate
 +>16MHz source which slides relatively to the 8502's system clock. Therefore
 +>there will be always some 1/2 or 1/4 cycle jitter on any $d6xx access.
 +>
 +>Also for exact measurement you have to align your routine to the VDC
 +>timing. In the moment you rely on the fact that the VDC can execute the
 +>same command in the same time regardless on what the VDC doing on the
 +>screen - but surely that matters. CBM engineers were 2MHz-DRAM-bandwidth-
 +>weenies and the VDC occupies lots of its RAM bandwidth for drawing the
 +>picture and refreshing the DRAM. So it must delay "​foreign"​ RAM access of
 +>the 8502 to certain timing slots like the horizontal or vertical retrace
 +>or so.
 + 
 +        Clearly, my experiments have just scratched the surface of the VDC.
 +We can make a few conclusions however:
 + 
 +        - In many cases the usual BIT-loops are unnecessary. ​ The things which
 +          seem to make them necessary are the things which can tie VDC up,
 +          namely any operations which need to talk to his memory (did I
 +          mention that VDC is a '​he'?​).
 + 
 +        - Some operations, such as a fill, are not only efficient but take
 +          a consistent amount of time to execute. ​ Others, such as the
 +          memory fetch, do not.
 + 
 +The VDC strikes me as being 'the final frontier'​ of the C= world, in that
 +it is not terribly well understood and there is still much to be explored.
 +There are two things which I think would be very nice to have, concerning
 +VDC: first an understanding into the internal operation of the chip, and
 +second a list of timings for various operations involving VDC, with the
 +goal of really utilizing VDC for the graphics coprocessor that he can be.
 + 
 + 
 +Source + 2 binaries to follow.
 +-------------------------------------------------------------------------
 + 
 +
 +* vdctimes.s ​
 +
 +* The purpose of this program is to gather some timing ​
 +* information on the VDC chip.  It simply uses CIA #1 
 +* timer A to measure the time to perform a series of VDC 
 +* operations. ​ A BASIC program will then statistically ​
 +* assemble the data. 
 +
 +* Stephen Judd 
 +* 8/​3/​95 ​
 + 
 + ORG $1300 
 + 
 +TIMALO EQU $DD04 ;Timer A, CIA #2 
 +TIMAHI EQU $DD05 
 +CIACRA EQU $DD0E ;Control register A 
 + 
 +* Now some macros ​
 + 
 +SETREG MAC  ;Set a VDC register ​
 + STX $D600 
 +L1 BIT $D600 
 + BPL L1 
 + <<< ​
 + 
 +ELAPSE MAC  ;Calculate time elapsed ​
 + ​SEC ​
 + LDA #$FF 
 + SBC TIMALO ​
 + STA ]1 
 + LDA #$FF 
 + SBC TIMAHI ​
 + STA ]1+1 
 + <<< ​
 + 
 + ​SEI ​
 +INITTIM LDA #$FF ;Stick 65535 into 
 + STA TIMALO ;timer latch 
 + STA TIMAHI ​
 + LDA #%00011001 ;Start timer 
 + LDY #%00001000 ;Stop timer 
 + 
 +CALIBRAT STA CIACRA ;Figure out overhead in 
 + ​NOP ​ ;​starting/​stopping timer 
 + ​NOP ​
 + ​NOP ​
 + ​NOP ​
 + ​NOP ​ ;Elapse 10 cycles ​
 + STY CIACRA ​
 + LDA #$FF 
 + ​SEC ​
 + SBC TIMALO ​
 + STA TEST 
 + 
 +* First test: No OP; just load a register ​
 + 
 +REGTEST ​
 + LDX #18 ;Register 18 
 + LDA #​%00011001 ​
 + STA CIACRA ;Start timer 
 + >>>​ SETREG ;A single reg 
 + STY CIACRA ​
 + >>>​ ELAPSE,​REG1 ​
 + LDA #​%00011001 ​
 + STA CIACRA ​
 + >>>​ SETREG ;Do it twice 
 + >>>​ SETREG ​
 + STY CIACRA ​
 + >>>​ ELAPSE,​REG2 ​
 + LDX #36 ;Now we will do them all 
 + LDA #​%00011001 ​
 + STA CIACRA ​
 +:LOOP >>>​ SETREG ​
 + ​DEX ​
 + BPL :LOOP ;Sub 5*37-1 cycles from total 
 + STY CIACRA ​
 + >>>​ ELAPSE,​ALLREG ​
 + 
 +READVDC ;Just a quick test to see if 
 + LDX #18 ;anything weird happens by a 
 + LDA #%00011001 ;read 
 + STA CIACRA ​
 + >>>​ SETREG ​
 + LDA $DC01 
 + >>>​ SETREG ​
 + LDA $DC01 
 + STY CIACRA ​
 + >>>​ ELAPSE,​READ18 ;This should be REG2+8 ​
 + 
 +WRITEVDC ;Various tests of writing to 
 + LDA #%00011001 ;the VDC 
 + STA CIACRA ​
 + >>>​ SETREG ;Now read an actual memory ​
 + STA $D601 ;​location ​
 + ​INX ​
 + >>>​ SETREG ;Three setregs total 
 + STA $D601 ;Overhead: 6+6 cycles ​
 + LDX #31 
 + >>>​ SETREG ​
 + STY CIACRA ​
 + >>>​ ELAPSE,​READ31 ​
 + LDX #18 ;Now test memory fills 
 + LDA #00 
 + >>>​ SETREG ​
 + STA $D601 
 + >>>​ SETREG ​
 + STA $D601 
 + LDA #​%00011001 ​
 + LDY #00 
 + LDX #31 
 + STA CIACRA ​
 + LDA #$66 ;Screen code 102 
 +:LOOP >>>​ SETREG ​
 + STA $D601 
 + ​INY ​
 + BNE :LOOP ;Overhead: 2+2+5*256-1 ​
 + ;(or 9*256 if sta is counted) ​
 + LDY #​%00001000 ​
 + STY CIACRA ​
 + >>>​ ELAPSE,​FILLSLOW ​
 + 
 + LDX #18 
 + LDA #00 
 + >>>​ SETREG ​
 + STA $D601 
 + ​INX ​
 + >>>​ SETREG ​
 + STA $D601 
 + LDA #​%00011001 ​
 + LDX #31 
 + STA CIACRA ;Here we go... 
 + 
 + LDA #$66 
 + >>>​ SETREG ​
 + STA $D601 
 + LDX #24 
 + LDA #​%00000000 ​
 + >>>​ SETREG ​
 + STA $D601 
 + LDX #30 
 + LDA #$FF ;Total of 256 writes ​
 + >>>​ SETREG ​
 + STA $D601 ;Off it goes! 
 + LDX #18 
 + >>>​ SETREG ;Hopefully this will wait until 
 + STY CIACRA ;the fill is done! 
 + LDA $D601 ;Just to make sure, check the 
 + STA MEMADDR ;last address written to 
 + ​INX ​
 + >>>​ SETREG ​
 + LDA $D601 
 + STA MEMADDR+1 ​
 + >>>​ ELAPSE,​FILLFAST ​
 + ​CLI ​
 + ​RTS ​ ;​Whew! ​
 + 
 +TEST DS 1 ;​Calibration test 
 +REG1 DS 2 ;Single register test 
 +REG2 DS 2 ;Same register twice 
 +ALLREG DS 2 ;All 37 registers ​
 +READ18 DS 2 ;Two reads of register 18 
 +READ31 DS 2 ;Three reads minus 12 cyceles ​
 +FILLSLOW DS 2 ;256 writes ​
 +MEMADDR DS 2 ;lo/hi of memory fill (a check) ​
 +FILLFAST DS 2 ;One block write of 256 chars 
 + 
 +--
 + 
 +begin 644 time1.0f.uu
 +M 1P7' $ F2 BFY-0051)14Y#​12XN+B( )1P" $ZR,​3(P.D.R,​ !6' , _B8Z
 +M1K(Q.I<​@-3,​R-C4LPB@U,​S(V-2D@KR R,​SDZCR!455).($]&​1B!624,​ 91P$
 +M (\@1D%35#​I&/​3( H1P% (8@5#​$H3BDL5#​(H3BDL5#,​H3BDL5#​0H3BDL5#​4H
 +M3BDL5#​8H3BDL5#<​H3BDL5#​DH3BDL058H."​D ]AP* %1%4U2RT2@B,​31#​.2(I
 +M.E(QLE1%4U2J,​3I2,​K)2,:​HR.D%2LE(RJC(Z4C.R05*J,​CI2-+)2,​ZHR.D93
 +MLE(TJC(Z34&​R1E.J,​CI&​1K)-0:​HR #H=# !!5B@Q*1H:&​AH:&​AH:&​AH:&​AH:​
 +M&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +M&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +8&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 + 
 +end
 + 
 +begin 666 vdctest1.0d.o
 +M !-XJ?​^-!-V-!=VI&:​ (C0[=ZNKJZNJ,#​MVI_SCM!-V-R12B$JD9C0[=C@#​6
 +M+ #​6$/​N,#​MTXJ?​_M!-V-RA2I_^T%W8W+%*D9C0[=C@#​6+ #6$/N. -8L -80
 +M^XP.W3BI_^T$W8W,​%*G_[07=C<​T4HB2I&​8T.W8X UBP UA#[RA#UC [=.*G_
 +M[03=C<​X4J?​_M!=V-SQ2B$JD9C0[=C@#​6+ #6$/NM =R. -8L -80^ZT!W(P.
 +MW3BI_^T$W8W0%*G_[07=C=$4J1F-#​MV. -8L -80^XT!UNB. -8L -80^XT!
 +MUJ(?C@#6+ #​6$/​N,#​MTXJ?​_M!-V-TA2I_^T%W8W3%*(2J0"​. -8L -80^XT!
 +MUHX UBP UA#​[C0'​6J1F@ *(?C0[=J6:. -8L -80^XT!ULC0\J (C [=.*G_
 +M[03=C=04J?​_M!=V-U12B$JD C@#6+ #6$/N- =;HC@#6+ #6$/N- =:I&:(?
 +MC0[=J6:. -8L -80^XT!UJ(8J0"​. -8L -80^XT!UJ(>​J?​^. -8L -80^XT!
 +MUJ(2C@#6+ #6$/N,#MVM =:​-UA3HC@#​6+ #6$/NM =:​-UQ0XJ?​_M!-V-V!2I
 +M_^T%W8W9%%A@ ​                      :&​AH:&​AH:&​AH:&​AH:&​AH:&​AH:​
 +1&​AH:&​AH:&​AH:&​AH:&​AH:&​AH ​
 + 
 +end
 +
 +
 +/​S08::​$dd00:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +               ​Software analysis and reconstructive therapy,
 +                      a historical view on "​cracking"​.
 +
 +                             by Pontus Berg
 + 
 + 
 +Cracking was defined as the removal of copy-protection,​ and for this reason the
 +product had to feature protection in the first place! Most "​originals"​ of today
 +do not feature any protection, but I guess what most people are after is just
 +introlinking and crunching (correct me if I'm wrong)! I'll brief you on the
 +whole train of thought!
 + 
 +Cracking was much about being able to analyze someone elses code. This did
 +not mean that you had to be able to understand exactly what each instruction
 +did, but from the context you had to be able to tell the main purpose of a
 +section of code. From this followed that you had to be able to know A LOT
 +about coding. The better you knew how to code, the better was your chance of
 +getting decent as a cracker. This was a very difficult thing, mind you.  How
 +could you detect a loader routine from the rest of the code if you didn't
 +know 6502?  The answer is that you simply couldn'​t! ​ A lot of people had to
 +learn on the fly.  By digging into other people'​s code you got a feeling for
 +6502, and this experience built many a legend. If you ever saw a good cracker
 +in action they could scan the memory with the I* command of their monitor
 +utilities and tell what parts of the memory did what and how. :)
 +
 +This is all nice but what exactly went on in the mind of the cracker? ​ Well,
 +let's explore briefly the generalities on cracking tape games, as they are
 +virtually non-existent in our Commodore world of 1996 and are therefore not
 +a political hot-potato so to speak :).
 +
 +For tapegames, the fact that the original is on tape is the hardest part.
 +There are transfers that copies tapedata to disk for most common
 +tapeloaders. Doing it by hand is not something you have to do every day,
 +but it's something you must be able to do if you want to call yourself a
 +cracker! Mind that it's not all that easy! If you take a look at the
 +persons who call themselves crackers today, only a very limited few are
 +able to do this!
 + 
 +Tapetransfer
 + 
 +SYS 63276
 + 
 +This loads the header into the tapebuffer at $033c. You get the name on
 +screen and can press space/CBM key to get back to the prompt. It won't
 +start loading as it would have if you had written LOAD. You can now modify
 +the tapebuffer. The five first bytes are 03 (Not relocatable file),
 +Low/High startaddress,​ Low/High endaddress
 + 
 +f.ex. 03,​9f,​02,​3c,​03
 + 
 +This loads a file at $029f ending at $033c. If you modify this into
 + 
 +03,​9f,​12,​3c,​13
 + 
 +You'd get it on a place where it won't start in your face (i.e. $129F)! By
 +the way, if the start says 03,​01,​08,​XX,​YY then the game loads to basic, and
 +you can then just type LOAD and after loading it won't autostart (unless
 +you pressed shift+runstop),​ but can be saved normally to disk (unless it
 +exceeds the limits of basic by loading over $a000). Why $129F - Well as
 +it's easier to disassemble the code if the lowbytes are the same as the
 +original.
 + 
 +SYS 62828
 + 
 +Will load the file at the address you asked for with the pointers! (i.e.
 +$129F)
 + 
 +From here you are on your own, as no two tape loaders are exactly the same!
 +I cannot say anything general about tapeloaders! If you decidper the loader
 +and find no startaddress in it, then it might be as it's overloaded during
 +loading. Selfmodifying loaders are frequet to prevent you from tempering
 +with them. I usually resource the loader and place it elsewhere in memory.
 +I can then safely transfer the files!
 + 
 +The tapes don't usually feature any protections more that the fact that
 +they are on tape. I seen a few games that set the timers before loading and
 +checked them afterwards to ensure you hadn't interrupted the loading but
 +This is rare! Last Ninja II was like this!
 + 
 +OK, after this you have the game on disk. A one-filer shall now work 100%,
 +no matter if it's transfered from tape or if you got it directly on disk.
 + 
 +A onefiler
 + 
 +1.      Depack it (if packed or crunched)
 +2.      Remove crap that only take room and is of no use! (This is what I do
 +GOOD that makes my cracks shorted than most of the others!)
 +3.      Scan for trainers! (I use Action Replay first. If it finds them,
 +I saved myself a lot of work!)
 +4.      Install the trainers in a trainer menu & put it in memory of the game!
 +There'​s almost always room for that!
 +5.      Pack the game
 +6.      Add the intro
 +7.      Pack the game again (only needed if you gain something from this!) ​
 +8.      Crunch
 + 
 + 
 +Multifile games
 + 
 +Additional work compared to the above:
 + 
 +1.      Locate the loader and remove it
 +2.      Analyse the code for the old loader and make yours load the correct
 +level from the internal levelcounter of the game!
 +3.      Replace the loader with your own one (featuring a decruncher) including
 +the information you got while analyzing the code (see 2)
 +4.      Crunch the levels
 + 
 + 
 +In detail
 + 
 +Ok you might then need some guidance in each of the steps! I guess
 +depacking is the most important part!
 + 
 +The depacker/​decruncher starts somewhere (usually basic, at $0801), and you
 +can then pretty easily follow the code in it. The action replay has the
 +AWSOME feature "Set Freeze"​. You disassemble the code in freezemode (N.B.)
 +and then enter a SF the the opcodes.
 + 
 +F.ex.
 + 
 +4000 AD FF 4E  LDA $4EFF
 + 
 +You modify to:
 + 
 +4000 SF FF 4E  LDA $4EFF
 +     ^^
 +and press return!
 + 
 +You now get:
 + 
 +4000 20 D3 DF  JSR $DFD3
 + 
 +(Or something like this)
 + 
 +I saw QED/​Triangle working, and he did a version of this using his Expert
 +Cartridge. He did pretty much the same but manually. He installed this
 +instead of the "​SF"​
 + 
 +CLC
 +BCC (To the CLC)
 + 
 +After a while, when the program was surely in the infinite loop, he slammed
 +RESTORE to enter his monitor. I have used this some times myself, when the
 +SF was not working for some reasons (mainly as $01 was set to something
 +that prevented SF from working).
 + 
 + 
 +Back to depacking
 + 
 +OK, back to the depacker! You enter this SF at the place where the
 +decruncher jumps to the next step in the process. It might be starting the
 +next depacker and it might be starting the game!
 + 
 +Remember that most decrunchers are different, so you cannot take for
 +granted that the skills from one apply on another one!
 + 
 + 
 +Some VERY GENERAL hints:
 + 
 +Most of the times, the startup looks something like this:
 + 
 +SEI/​CLI/​NOP ​    ;​Either of these
 +LDA #$3X        ;Where X is almost always 4-7 (most often 7)
 +STA $01
 +JMP $YYYY       ;​Where YYYY is the start address and the place to put your SF 
 +                ;Set on top of the $4C, i.e. the actual jump instruction.
 + 
 +Most decrunchers has this code in the area $0801-$0a00,​ but the AB cruncher
 +and CruelCrunch has it in the very end of the file (in the last two
 +blocks).
 + 
 +This is where I get to be so concrete that it would be best if I had an
 +example to show from!
 + 
 +This will have to be all for now.. :)
 +
 +Pontus Berg
 +
 +
 +/​S09::​0100h:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +
 +                      - A Quick Overview of CP/M -
 +
 +                            By Mike Gordillo
 + 
 +
 +What is CP/M?
 +
 +    CP/M is an operating system available for microcomputers using the
 +Zilog Z80 Microprocessor. ​  As an operating system, CP/M is responsible
 +for directing your computer'​s resources to fit your needs. ​  It executes
 +software (programs) in response to commands you enter through the keyboard
 +(console), and once executed, your programs can use CP/M to perform many
 +tasks. ​  For example, CP/M software can manage databases, copy files, process
 +spreadsheets,​ analyze your income tax, print your forms, or play your favorite
 +video games.
 + 
 +    CP/M 3.0+ on the Commodore 128 is simply a version of CP/M 3.0 that has
 +been altered to better fit the particular needs of the Commodore 128 and its
 +users. ​  Aside from a few cosmetic differences and the ability to use the
 +peripherals (drives, modems, etc) of the C-128 System, there is not much to
 +distinguish general CP/M from the C-128 version. ​  Your C-128 can execute
 +virtually all the software widely available for CP/M machines. ​ However, please
 +note that CP/M software intended specifically for a certain CP/M machine may
 +not necessarily run or run-as-intended on another CP/M machine.
 + 
 + 
 +How do I start CP/M?
 + 
 +    Unlike the C-64 and C-128 native modes, CP/M must be started from the CP/M
 +3.0+ System Diskette. ​  The standard start-up procedure requires you to have
 +one drive set to device #8.   All you do is insert the System Diskette into
 +the drive and type BOOT from within the C-128'​s Basic 7.0 mode.   CP/M should
 +now "boot up" from the diskette. ​  If this does not happen, clear memory
 +by turning off the C-128 and the drive. ​  Put the CP/M System Diskette in the
 +drive and turn the C-128 and the drive back on.   You should now see CP/M
 +assume its normal diagnostic "boot up" procedure. ​  Once that is complete,
 +CP/M will announce itself proudly as "CP/M 3.0 on the Commodore 128" and
 +provide you with its version date.   The 28 May 87 CP/M 3.0+ version, for
 +example, is the last and most popular official version for the C-128. ​ Other
 +"​non-official"​ versions exist for the C-128, most notably the BIOS6-ZPM3-ZCCP ​
 +enhancements -- but that's the subject of another article.
 +
 +
 +CP/M is a command-line interface!
 + 
 +    CP/M is a command-line interface. ​  This means that your instructions to
 +CP/M must be entered as commands to the system from the keyboard (as opposed
 +to mouse control in popular Windowing environments like GEOS). ​  You enter
 +commands via the A>, B>, C>, D>, E>, or M> prompts. ​  These prompts tell you
 +which disk drive (device) you are currently using as well as letting you know
 +that CP/M is ready to receive your orders as soon as possible. ​  For example,
 +if I see the A> prompt, I am using device 8, but if I see the B> prompt, I am
 +using device 9, and so on.   I can change between devices by simply entering
 +the appropriate letter and a colon, as follows:
 + 
 +     A> B:                       ​(Changes from Drive A to Drive B)
 + 
 +     B> C:                       ​(Changes from Drive B to Drive C)
 + 
 +     C> A:                       ​(Changes from Drive C to Drive A)
 + 
 +     ​A> ​                         (Back to Drive A)
 + 
 +The E> and M> prompts are special cases. ​  Drive E is not a real drive/​device,​
 +rather, it is a Virtual Drive used for copying purposes when only a single
 +real drive is available. ​  Drive M is not a physical drive at all.   It
 +is assigned to the Ram Expansion Unit as a RAM drive.
 + 
 + 
 +How is the CP/M Command Structure organized?
 + 
 +    CP/M has six built-in commands: DIR, DIRSYS, ERASE, RENAME, TYPE, USER.
 +These commands are part of your CCP.COM file (Command Console Processor) and
 +they make it easy for us to perform basic level housekeeping. ​  DIR allows
 +us to call up a disk's directory of files. ​  ​DIRSYS does the same thing except
 +it shows us only files tagged with a system-flag (eg. hidden files). ​  ERASE
 +and RENAME allow us to erase and rename files while TYPE is used to display
 +text files on the screen. ​  USER lets us switch between different user sections
 +on a diskette. ​  A CP/M diskette can have 16 user sections (0 to 15) in which
 +files placed in one section are logically separate from files in different
 +sections. ​  User sections are CP/M's way of allowing for better organization
 +of files through partitioning.
 + 
 +    Any other "​commands"​ you might run into are known as transient-utility
 +commands. ​  ​Transient-utility commands are simply executable programs that
 +reside on a diskette instead of being built into CP/M itself. ​  They are
 +usually identifiable on the diskette by virtue of their .COM extensions.
 +For example, if I call up a disk directory using the DIR command, as follows:
 + 
 +     A> DIR
 +     ​BASIC.COM ​    ​DISC=OV.ERY ​    ​ISAGREAT.MAG ​   SORT.COM ​   TERM.COM
 + 
 +This tells me that on Drive A (device 8), the files basic.COM, sort.COM, and
 +term.COM are transient-utility command files. ​  ​Notice that there is no DIR.COM
 +available to call up a directory because the DIR command is a built-in command.
 + 
 + 
 +Does my System Diskette have Transient-Utility (T-U) Commands?
 + 
 +    Yes, Commodore put several useful T-U commands into the CP/M 3.0+
 +System Diskette. ​  You should have the following in order to begin to
 +effectively use CP/M on the C-128, as follows:
 + 
 +     A> DIR
 +     ​C1571.COM ​   CONF.COM ​   FORMAT.COM ​   KEYFIG.COM ​   HELP.COM ​   PIP.COM
 + 
 +C1571.COM is a neat T-Utility that will double your 1571's SAVE speed
 +by disabling the automatic verification involving the saving of a file
 +to the diskette, as follows:
 + 
 +     A> C1571 [a               ​(Disables auto-verify on Drive A - Device 8)
 + 
 +CONF.COM is a GREAT T-Utility that permits us to change many system-default
 +parameters like baud rate, screen colors, printer assignments,​ etc.   When I
 +first started, I was very very frustrated at what appeared to be immutable
 +artifacts in the operation of the C-128'​s CP/M.   In other words, I could
 +not CONFigure the system as I wanted. ​   This utility changed all of that.
 +For example, I used to have a 4040 dual drive which I hooked up to the system
 +intent on using it under CP/M.   I found to my dismay that I could only access
 +one out of the two drives huddled in the 4040 bay.   CP/M had no way of knowing
 +that the single device it saw (the 4040) had more than one drive! ​  Along came
 +CONF.COM to the rescue! ​  I simply typed up CONF DRVB = 8-1 and voila, the
 +second drive in the 4040 became Drive B (which would normally be device 9).
 +CONF is also great at modifying CP/M itself when needed. ​  I recall one time
 +when I was using another T-Utility that had problems with the Ram Expansion
 +Unit under its normal device assignment. ​  In other words, the utility I was
 +using could not handle a drive M.   I used CONF's POKE ability to change
 +the drive M assignment of the R.E.U. into a drive B assignment, as follows:
 + 
 +     A> CONF POKE fbd3 = 96fb       ​(Reassigns the REU from drive M to B)
 + 
 +FORMAT.COM allows you to format your diskettes in a variety of CP/M formats,
 +all of which can be read by the C-128'​s CP/M.
 + 
 +KEYFIG.COM is a T-Utility which allows you to redefine ALL keys on the C-128
 +except the SHIFT and SHIFT-LOCK keys, the 40/80 DISPLAY key, the CONTROL key,
 +and the COMMODORE key.   You can assign keys to have up to four different
 +values/​functions to suit your needs.
 + 
 +HELP.COM is a good manual of CP/M commands and command syntax. ​  It serves as
 +an index of commands and tells you how to properly use them.
 + 
 +PIP.COM is the standard file-copy T-Utility. ​  I use it routinely to create
 +backups of my files as well as creating new system diskettes in cooperation
 +with the FORMAT.COM utility, as follows:
 + 
 +     A> FORMAT ​            (Use the Format utility to format drive B)
 + 
 +     A> PIP B:​=A:​CPM+.SYS ​ (Copies the CP/M system file from Drive A to B)
 + 
 +     A> PIP B:​=A:​CCP.COM ​  ​(Copies the CCP.COM file from Drive A to B)
 + 
 + 
 +Is that all I can do with CP/M?
 + 
 +    No, Commodore packaged CP/M for the C-128 with just the basic entry
 +level material necessary to begin to use CP/M effectively. ​  CP/M can do
 +much more but like all things concerning computers, you need a good measure
 +of software to make the best use of what you've got.   There is nothing
 +harder for the novice than to accumulate enough software to increase his and
 +his system'​s proficiency. ​  I recall many times thinking how useless CP/M
 +was to me.   After all, I could do so much more in C-64 and C-128 modes!
 +However, once my software base had risen beyond what the System Diskette
 +offered, my analysis of CP/M changed from useless to useful.
 + 
 + 
 +In other words, CP/M productivity is in software?
 + 
 +    CP/M's strength lies in the large software base available for it.   CP/M
 +is the first operating system to showcase the functionality of microcomputer
 +database and spreadsheet applications on a large scale. ​  I regularly keep
 +large databases and spreadsheets on the C-128'​s CP/M and then use other CP/M
 +productivity programs to transfer them to and from other types of systems.
 +Furthermore,​ some of the best software compression programs and computer
 +languages are only available for the C-128 whilst in CP/M mode.   With over
 +ten thousand software titles to choose from, there is nothing you can't do!
 + 
 + 
 +Where can I get CP/M software?
 + 
 +    You can get good CP/M public domain software from CP/M User's Groups
 +throughout the United States and Canada. ​  There is also substantial CP/M
 +support in Japan and in Europe. ​  ​Commercial software is readily available
 +from appropriate vendors (usually listed in user group publications). ​  The
 +most substantial concentrated source of CP/M software is undeniably the
 +Internet. ​  The Internet is a collection of various computer networks linked
 +together throughout the world. ​  There are thousands of megabytes of CP/M
 +programs (from 1976-1993) available there. ​ A few popular 'CP/M sites' are
 +as follows;
 +
 +            oak.oakland.edu ​    /​pub/​cpm
 +            ccnga.uwaterloo.ca ​ /​pub/​cbm/​os/​cpm
 +
 + 
 +And pray tell, how do I transfer CP/M software into the C-128?
 + 
 +    Well, there are a number of ways.   The most efficient way is to
 +copy files from one CP/M disk onto another. ​  The C-128'​s CP/M can read
 +the CP/M diskettes from Epson, IBM, Kaypro, and Osborne CP/M machines.
 +You can also use terminal programs if your CP/M's version-date is later than
 +4 DEC 85 (ie., earlier versions lacked access to the modem port) in order to
 +transfer material via the phone lines. ​  The most inconvenient way, however,
 +is to use transfer programs (from either CP/M or other modes) to read material
 +onto your CP/M diskettes.
 +
 +
 +Come on, I'm looking for something simple. ​ Is there a CP/M CD-ROM?
 +
 +   Sure is!  A few people out there decided to put several megabytes of
 +CP/M software on CD-ROM (!) and just a few months ago, someone wrote a
 +CD-ROM reader for C128 users with a CMD Hard Drive (SCSI port)! ​ The
 +"​Walnut Creek" CD-ROM and "​CD-ROM Commander"​ are two very exciting products
 +for CP/M 128 users, as these items allow access to hundreds of megabytes of
 +CP/M software. ​ (Please consult the internet newsgroup '​comp.sys.cbm'​ for
 +more details).
 + 
 + 
 +Final thoughts...
 + 
 +    CP/M complements the C-64 and C-128 modes very well.  I feel that in the
 +productivity area, the C-128 would be very deficient otherwise. ​  I have
 +yet to see productivity packages in the native modes that are as efficient as
 +the ones I use under CP/M.   The structure of the CP/M operating system is
 +also more amenable to file transfer and file management. ​  My Ram Expansion
 +Unit has never been as easy to work with in the C-64 and C-128 native modes
 +as it has been under CP/M.   CP/M may seen complicated at first but it is
 +actually quite easy to understand. ​  Once you've mastered it, you may never
 +go back.
 + 
 + 
 +----- 
 +Mike Gordillo is an expert in CP/M and Z80 programming as well as a devout
 +Commodore fanatic over the past twelve years. ​ He may be reached on the
 +internet as s0621126@dominic.barry.edu for general comments or questions.
 +
 +
 +/​S10::​0100h:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +      The BIOS-R62a/​ZPM3/​ZCCP Commodore 128 CP/M 3.0+ Upgrade Package
 +                      and a bunch load of utilities!
 + 
 +                             by Mike Gordillo
 + 
 + 
 +                                  Preamble
 + 
 +    This package was an in-house project for mostly myself and a few of
 +my friends. ​ I released this last year to the general internet community,
 +and as far as I know, all software therein is public domain.
 + 
 +What to do:
 + 
 +FTP to ccnga.uwaterloo.ca
 +Directory is /​pub/​cbm/​os/​cpm
 + 
 +Download (remember to set binary flags) the following:
 + 
 +        zpm-user0.zip
 +        zpm-user1.zip
 +        upgrade-user0.zip
 + 
 +Unzip them on your unix/​vms/​dos box and put them on a C128 CP/M 
 +1571 or 1581 boot disk (eg., BBR 4.1) in the following manner:
 + 
 +All files from zpm-user0.zip go to USER 0 on your CP/M boot disk.
 +All files from zpm-user1.zip go to USER 1 on your CP/M boot disk.
 + 
 +IF you have any of these: Swiftlink cartridge, an ASCII printer, ​
 +absolutely NO ram expansion whatsoever, a 1581 drive, you will probably ​
 +need to take a look at upgrade-user0.zip. ​ It contains replacement files 
 +that satisfy the hardware I just listed. ​ IF so, you MUST use the 
 +replacement files to insure proper operation. ​ All replacement files MUST 
 +go to USER 0 on your CP/M boot disk.  Please READ the read.lis file in the
 +upgrade-user0.zip archive for more details.
 + 
 +Note: If you unzip these archives on a VMS system, chances are that 
 +CPM+.SYS will be renamed to CPM.SYS. ​ You MUST make sure that you rename ​
 +it back to CPM+.SYS on your CP/M boot disk, otherwise CP/M will not boot.
 + 
 +For more information on BIOSR6 and ZPM3/ZCCP enhancements please consult
 +Randy Winchester'​s CP/M article in the online magazine, C= Hacking issue #5.
 + 
 + 
 +                                  Abstract
 + 
 +  This package is provided as a courtesy to C128 users. ​  ​Meaningful CP/M
 +system-generation utilities are not provided with the C128 CP/M System ​
 +diskette. ​  Most C128 users would therefore have difficulty in assembling
 +a package like this.   Also, the lack of easily available sources for CP/M
 +software brings its own share of hardships. ​  The utilities included are
 +meant to provide new tools for the C128 user and maximize the features of
 +BIOS-R62a, ZPM3, and ZCCP.  ​
 + 
 + 
 +                                  Filelist
 + 
 +zpm-user0.zip:​
 + 
 + ​Length ​   Date    Time    Name ("​^"​ ==> case
 + ​------ ​   ----    ----    ----   ​conversion)
 +    512  01-03-95 ​ 11:41   ​autotog.com
 +   ​4480 ​ 01-03-95 ​ 11:41   ​b5-driv3.com
 +    512  01-03-95 ​ 11:41   ​bye.com
 +    128  01-03-95 ​ 11:41   ​c128-xgr.z3t
 +   ​1024 ​ 01-03-95 ​ 11:41   ​c1571.com
 +   ​3200 ​ 01-03-95 ​ 11:41   ​ccp.com
 +  24576  01-03-95 ​ 11:41   ​cpm+.sys
 +   ​1152 ​ 01-03-95 ​ 11:41   ​echo.com
 +   ​3840 ​ 01-03-95 ​ 11:41   ​format.com
 +  16384  01-03-95 ​ 11:41   ​format22.com
 +    640  01-03-95 ​ 11:41   ​format81.com
 +   ​3328 ​ 01-03-95 ​ 11:41   ​if.com
 +   ​3456 ​ 01-03-95 ​ 11:41   ​loadseg.com
 +   ​5376 ​ 01-03-95 ​ 11:41   ​mkdir32.com
 +    256  01-03-95 ​ 11:41   ​names.ndr
 +  17536  01-03-95 ​ 11:41   ​qterm.com
 +  17408  01-03-95 ​ 11:41   ​rdcbm.com
 +   ​8192 ​ 01-03-95 ​ 11:41   ​salias.com
 +   ​3456 ​ 01-03-95 ​ 11:41   ​setpth10.com
 +   ​1024 ​ 01-03-95 ​ 11:41   ​startzpm.com
 +   ​8192 ​ 01-03-95 ​ 11:41   ​superzap.com
 +  24320  01-03-95 ​ 11:41   ​trans128.com
 +   ​7424 ​ 01-03-95 ​ 11:41   v.com
 +  15488  01-03-95 ​ 11:41   ​vde.com
 +   ​2816 ​ 01-03-95 ​ 11:41   ​verror.com
 +  15744  01-03-95 ​ 11:41   ​vlu.com
 +   ​2048 ​ 01-03-95 ​ 11:41   ​zdt12.cfg
 +   ​7936 ​ 01-03-95 ​ 11:41   ​zdt12.com
 +  15232  01-03-95 ​ 11:41   ​zfiler.com
 +   ​1536 ​ 01-03-95 ​ 11:41   ​zinstal.zpm
 + ​------ ​                   -------
 + ​217216 ​                   30     
 + 
 + 
 +zpm-user1.zip:​
 + 
 + ​Length ​   Date    Time    Name ("​^"​ ==> case
 + ​------ ​   ----    ----    ----   ​conversion)
 +    128  01-03-95 ​ 14:47   ​clrhist.com
 +   ​3328 ​ 01-03-95 ​ 14:47   ​conf.com
 +   ​5996 ​ 01-03-95 ​ 14:47   ​conf.hlp
 +   ​3072 ​ 01-03-95 ​ 14:49   ​copy.com
 +   ​3200 ​ 01-03-95 ​ 14:49   ​date.com
 +   ​2816 ​ 01-03-95 ​ 14:50   ​del.com
 +   ​3712 ​ 01-03-95 ​ 14:51   ​diff.com
 +   ​3712 ​ 01-03-95 ​ 14:51   ​dir.com
 +   ​1280 ​ 01-03-95 ​ 14:52   ​dirnames.com
 +   ​2944 ​ 01-03-95 ​ 14:52   ​diskinfo.com
 +   ​1664 ​ 01-03-95 ​ 14:53   ​image.com
 +   ​6912 ​ 01-03-95 ​ 14:53   ​lt.com
 +  12928  01-03-95 ​ 14:55   ​pmext.com
 +   ​3712 ​ 01-03-95 ​ 14:58   ​ren.com
 +   ​1792 ​ 01-03-95 ​ 14:58   ​rsxdir.com
 +   ​4736 ​ 01-03-95 ​ 14:59   ​unarc.com
 +  12288  01-03-95 ​ 15:00   ​unarj.com
 +   ​1408 ​ 01-03-95 ​ 15:02   ​undel.com
 +   ​3456 ​ 01-03-95 ​ 15:03   ​unzip.com
 + ​------ ​                   -------
 +  79084                    19     
 + 
 + 
 +upgrade-user0.zip :
 + 
 + ​Length ​   Date    Time    Name ("​^"​ ==> case
 + ​------ ​   ----    ----    ----   ​conversion)
 +  24576  01-03-95 ​ 15:41   ​cpm+.sys
 +   ​3840 ​ 01-03-95 ​ 15:40   ​f1581.com
 +    256  01-03-95 ​ 15:41   ​names.ndr
 +  17536  01-03-95 ​ 15:46   ​qtermsl.com
 +    732  01-03-95 ​ 14:08   ​read.lis
 +   ​1024 ​ 01-03-95 ​ 15:41   ​startzpm.com
 + ​------ ​                   -------
 +  47964                    6      ​
 + 
 + 
 + 
 +                              Condensed History
 + 
 +BIOS-R62a- Default System Baud Rate set at 134.  Warning: Term programs will
 +           ​modify this.  Higher Baud = Faster Keyboard Scanning = Slow CP/M
 +           ​Re-implemented support for PETSCII printers (code from BIOS R4)
 +           LST Settings : PRT1=Dev #4, PRT2=Dev #5, Secondary Address = 7
 +           CONF utility'​s PRT assignment options will not work because of
 +           ​changes made back in BIOS R4.   ASCII printers are available with
 +           the ASC-PRT implementation of BIOS-R62a (included..see BIOS R5).
 + 
 +           ​-CPM+.SYS for ASCII printers is included in upgrade-user0.zip
 + 
 + 
 +BIOS-R62 - Default System Baud Rate set at 75 (not enough Keyboard Scanning).
 +           Added support : C=1581 Official Format! (F1581.COM will allow you
 +           to make/create 1581 boot disks... included in upgrade-user0.zip).
 +           MAXI 71 and GP 1581 Format supported (see BIOS R5).
 +           ASCII printers still default.
 +           ​-Randy Winchester
 +           
 +BIOS R5  - Added support for new hardware: Quick Brown Box (E:), Drive D:
 +           Added new definitions to the disk-parameter-table. ​ Maxi 1571,
 +           GP 1581 formats. ​ Use format22 & format81 with these MFM
 +           ​types. ​ ASCII printers now default. ​ PETSCII tables not supported.
 +           LST Settings : PRT-D4=Dev #4, PRT-D5=Dev #5, Secondary Address = 5
 +           ​-Randy Winchester
 + 
 +BIOS R4  - Removed the 40 column routines, the virtual drive, and Drive D:.
 +           ​Removed Printer Buffer (Lord knows why!?)
 +           Added a screen dump feature.
 +           Fixed several BIOS errors as well.
 +           ​-James Waltrip IV           
 + 
 +ZPM3 BDOS- (see below)
 +           ​-Simeon Cran
 + 
 +ZCCP CCP - (see below)
 +           ​-Simeon Cran
 + 
 + 
 +                                **DISCLAIMER**
 +**
 +**You are free to distribute this package with the following conditions;
 +**
 +**   A) This package cannot be sold.   A copying/​handling
 +**      fee of no more than $5 1993 US dollars is allowed.
 +**
 +**   B) This package shall remain whole. ​  No item may be
 +**      distributed apart from the rest of the package.
 +**      There is a degree of hidden cross-dependency between
 +**      some items. ​  Split them apart and you may get
 +**      unpredictable results!
 +**
 +**This package is NOT under any warranty or guarantee of ANY kind!
 + 
 + 
 +                                 ​Description
 + 
 + 
 +   BIOS Upgrade - The C128 28 May 87 CP/M 3.0+ Version BIOS was reworked to
 +                  remove useless code (40col screen and Virtual Drive...not
 +                  really useless to some of us?  Argghhhh! :) and to correct
 +                  a few CP/M 3.0 BIOS errors while adding a screen dump feature
 +                  (ALT key is used as a toggle). ​  End Result = Faster, more
 +                  "​peppy"​ CP/M 3.0+ operation.
 + 
 +   BDOS Upgrade - This is the ZPM'​ing of CPM!  Think of this as a way-overdue
 +                  correction for an anachronism. ​  Much of the original BDOS
 +                  is written in slower Intel 8080 code.   The ZPM3 BDOS upgrade
 +                  rewrites things in faster, richer Zilog Z80 code while
 +                  adding some goodies (eg., command history buffer, enhanced
 +                  command line editing, automatic command prompting) and
 +                  correcting some CP/M 3.0+ BDOS errors.
 + 
 +   ZCCP Upgrade - The last nail in the coffin. ​  The original CCP.COM is
 +                  replaced by a more flexible beast. ​  Neat things are now
 +                  at your beck and call.   ZCCP features :
 + 
 +                      ZCPR 3.3 Compatibility (see below)
 +                        -Does not support FCP but supports flow control
 +                           ​internally with an IF.COM utility present.
 +                        -RCP is not implemented (That'​s what REUs are for :)
 +                        -Cannot load ZCPR 3.4 "type 4" programs
 +                        -Cannot re-execute loaded programs sans re-loading
 +                      Z3T Termcap (ZCPR 3.3 graphics support)
 +                      Named User Groups/​Directories
 +                      Command Search Path
 +                      System Environment Block
 +                      Flow control processing for batch files
 +                      Extended Command Processor for batch files
 +                      Multiple commands on one line
 +                      Superior error handling
 +                      Up to 4 Shell stack levels may be defined
 +                      Direct loading of .RSX files without GENCOM (LOADSEG)
 +                 
 +Put these all together and you have the ultimate CP/M system for your C128.
 + 
 + 
 +                               ​Compatibility
 + 
 +BIOS R62a - 99.00% Compatible with stock CP/M 3.0+ C128 system.
 +                 -A problem concerning printing is listed in the
 +                  Condensed History section.
 +            (Note: Programs that call the 40col screen will see a NULL40
 +            label -i.e., They will run but they won't be able to do anything
 +            in 40cols)
 + 
 +ZPM3 BDOS - Fully 100% compatible with stock CP/M 3.0+ BDOS segments.
 +            (Note: Some rare programs *demand* the CP/M 2.2 BDOS..yuck!)
 + 
 +ZCCP CCP  - ZCPR 3.3 compatibility as seen in the Description section.
 +            Environment info is larger than before. ​  ​Slightly more TPA is
 +            used or some additional high memory is being toyed with.  For
 +            example, I shortened TRANS128'​s buffer and that did the trick.
 +            (Note: Some of Steve Goldsmith'​s C128 specific programs will
 +             will crash with the ZCCP.RSX in operation).
 + 
 +                              Additional Notes
 + 
 +    -Look at the ALIAS (included) batch file (type SALIAS STARTZPM on the
 +     ​command-line). ​  ​Notice how it optimizes the system for REU use.
 +     You may change this as long as you keep the following in mind :
 + 
 +       ZCCP *requires* : LOADSEG commands for NAMES.NDR and *.Z3T Termcaps.
 +                         At least *ONE* SETPTH drive search/path entry.
 + 
 +       Quick Summary of STARTZPM batch file (included):
 +           1) Loads up Directory names.
 +           2) Loads up Directory paths. ​ ($$$$ = Current Drive/User DIR)
 +           3) Executes a few .COM files.
 +           4) Copies all Command Utilities to M1: (COMMAND Directory).
 + 
 +    -Utilities copied over to the REU (as seen in STARTZPM) are general
 +     ​purpose utilities meant to replace the built-in commands of the
 +     ​standard CCP.COM. ​ With the excellent path setups in ZCCP, utilities
 +     in the speedy REU become transparent.
 + 
 +     ​(Note:​ If you have NO ram expansion (eg., a drive M:) you NEED to 
 +     take a look at upgrade-user0.zip,​ as mentioned earlier).
 + 
 +    -Multiple commands on the command line must be separated by semi-colons.
 +     ​(Note:​ Semi-Colons are used in CP/M 3.0+ to append file passwords. Use the
 +     ​SET.COM utility (SET [DEFAULT=PASSWORD]) to set a password which can be
 +     used without your intervention on every file you access. ​ In any case,
 +     you can assign passwords to user groups (under ZCCP) with the mkdir32
 +     ​utility,​ which is simpler than dealing with CP/M 3.0+ SET.COM password
 +     ​assignment schemes.)
 + 
 +    -The following keys have been already configured to work best with ZCCP:
 +     They are user-definable with KEYFIG or LOAD/​SAVEKEY utils (not included).
 + 
 +    -CRSR-UP/​DOWN - CRSR-LEFT/​RIGHT ​ KEYS
 +     UP = CTRL-E ​  DOWN = CTRL-X ​  LEFT = CTRL-S ​  RIGHT = CTRL-D
 +     ​CTRL-E and CTRL-W = Forward and Backtrack through Command-History Buffer.
 +     ​CTRL-X = Delete everything to the left of the cursor.
 + 
 +    -ARROW KEYS (at the top of the keyboard)
 +     UP = CTRL-E ​  DOWN = CTRL-X ​  LEFT = CTRL-A ​  RIGHT = CTRL-F
 +     ​CTRL-A and CTRL-F = Autotab left and right.
 + 
 +    -CLR/HOME = CTRL-H (BackSpace)
 +     ​INST/​DEL = CP/M RUBOUT KEY
 + 
 +    -ZCCP does not support printable control characters (eg., ESC, CTRL-Z)
 +     on the command line.  In order to change screen display characteristics
 +     use the CONF.COM utility (included) instead of, for example, using
 +     ​^[^[^[<​screen/​char color code>​. ​  Also, although CTRL-Z will not clear
 +     the screen anymore, you can use the built-in CLS command instead.
 +     ​(Note:​ You can still use printing codes in programs.)
 + 
 +    -Consult the C128 system manual for the full list of ADM-3A to C-128 key
 +     ​assignments and sequences.
 +
 +--
 +For general comments on this article, feel free to contact Mike Gordillo
 +at s0621126@dominic.barry.edu
 +
 + 
 +:::::::::::​d:​i:​s:​C=:​o:​v:​e:​r:​y:::::::::::::::::​i:​s:​s:​u:​e::​1::::::::::::::::::::​
 +\H01::::::::::::::::::::::::::​H A R D W A R E:::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +                               ​BEYOND STEREO
 + 
 +           The POWER-SID Model 2400 : It May Not be THX, but it's
 +                  Taking the Commodore One Dimension Closer
 +
 +                        A preview by Shaun Halstead
 + 
 +
 +    A few months back, as I was working on some music using Robert Stoelle'​s
 +Stereo Sid Editor, I got to thinking about how many voices I would need
 +for this and that, and I realized that I was going to need more than twice as
 +many as I had available. ​ I called up Nate Dannenberg (a.k.a. _Tron_) to see
 +if he knew of any way to get more voices; he said that the only feasible way
 +was to add more chips, of course. ​ So, being the annoying pest I am, I got
 +to thinking of ways to do just that, and the concept of surround sid board 
 +was born.  Carrying eight, count 'em, eight, sid chips, at three voices each,
 +combined to give four main channels (front and rear, with left and right on
 +each), working in tandem with the computers stock sid chip, which acts as
 +a center channel, the Power-Sid is carrying the Commodore into a new dimension
 +of sound.
 + 
 +    Well, to make a long story short, between the two of us, we developed
 +the basic components, layout, and operation, including addressing options.
 +Currently, the board is designed to mount vertically, similiar to the 
 +Super-CPU developed by CMD.  This was done mainly to conserve space behind
 +computer, but has another advantage: by mounting the card vertically, a
 +pass-through port is easily installed (it was a given from the start that
 +a pass-through be available). ​ Until recently, we were having considerable
 +difficulty in solving the pass-through mounting problem (i.e. where to put 
 +it), until Nate found a way around it, based on the Super-CPU. ​ The actual ​
 +construction will not be easy, by any means, but it should be quite strong, ​
 +durable, and nice in overall appearance.
 + 
 +    The model described here (model 2400) will measure roughly 4-by-4 ​
 +inches, contain eight sid chips, two stereo jacks, addressing and support ​
 +circuitry. ​ The support circuitry includes an enable/​disable switch, activity ​
 +LED, an addressing switch, selectable between $DE00 and $DF00, and a pair 
 +of LEDs indicating the current address, a two/​four-channel selection switch ​
 +and dual-color LED to indicate the current mode.  The only difference between
 +the model 2400, described here, and the model 1200 is that the 1200 carries
 +only 4 chips, and offers fewer voices per channel, but is none the less, fully
 +featured. ​ Currently, software is being developed by Nate and I, and we are
 +working on a port to support his up and coming digital output card for the
 +expansion port.  Look for an extensive follow up in this journal when the
 +board enters the prototyping stage.
 +
 +--
 +The author, Shaun Halstead, can be reached at tesla@onyx.southwind.net,​
 +and Nate Dannenberg can be reached at tron@wichita.fn.net,​ or catch them
 +on IRC channel #C-64, as _Tesla_ and _Tron_, respectively).
 +
 +
 +\H02::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 + 
 +                     ​* ​ The 8 bit Modplay 128 Board  *
 +                                    by
 +                           -- Nate Dannenberg --
 +
 + 
 +Have you ever listened to Digital sound on your Commodore and wondered
 +where all the noise is coming from?
 + 
 +Ever tried messing with Pulse Width Modulation, only to realize that it
 +just doesn'​t have the clarity and impact you need for a particular project?
 + 
 +Want to make your Commodore sound better than it ever has using 8 bit sound?
 + 
 +Well, now's your chance...
 + 
 +Included here is the procedure for building a two channel 8 bit DAC
 +circuit to plug into a Commodore 64 or 128 (works in both modes), which
 +outputs in stereo two-channel sound. ​ Actually, the 8 bit DAC chip we will
 +be installing does four tracks, which are mixed using four 1K resistors
 +into two channel stereo sound with a total resolution of 9 bits per
 +channel, or 8 bits per track.
 + 
 +This circuit is based around the Maxim Electronics MAX505xCNG chip, where
 +x refers to a number of chip-packaging options provided by Maxim. ​ The
 +recomended chips are the MAX505 A- or B- CNG (24 DIP Narrow Plastic package).
 + 
 +This chip contains four 8 bit DAC circuits, each with 5 volt rail-to-rail
 +swing, internally buffered and coupled with precision unity-gain followers
 +that slew at 1V/uS (If you can understand all that jazz, you're a better
 +man than I).  Each DAC accepts it's own reference voltage input (not to
 +exceed the power supply voltage, which is 5 volts in this project), and
 +each generates it's own buffered output.
 + 
 +Originally, this circuit was designed to work on a Commodore 128 with the
 +upcoming MODplay 128 software, also one of my projects. ​ Using this
 +software, and outputting to this circuit, I get about 8.2 Khz out of it in
 +four track, two channel, 8 bit-per-track (9 bit total) stereo.
 + 
 +Since this circuit is relatively simple to access, it can be used in many
 +other applications,​ from audio output from a simple RAW or WAVE player
 +type of program, to more complex applications requiring a controllable
 +analog signal. ​ With the right timing, you could probably use it to
 +control the sync signals to an RGBI monitor!
 + 
 +Anyways, let's get on with it.
 + 
 +First we need to get the legal stuff out of the way...
 + 
 +Disclaimer: ​ I take no responsibility for any loss or damages occuring
 +from the use of this device, or from the instructions and proceedures
 +described in this text.  Any damage resulting from the use of this text
 +is purely the responsibility of the builder/​user.
 + 
 +[Ed. Note : The editor nor disC=overy magazine is not reponsible for any loss
 + or damages occuring from the use of this device, or from the instructions and
 + ​procedures described in this text.]
 +
 +Here is the parts list:
 + 
 +1) Maxim Electronics MAX505ACNG (or -BCNG) DAC chip.
 +1) 12/24 .156" Female edge connector.
 +1) 1/8" stereo (three-conductor) miniplug.
 +4) 1K, 1/8 or 1/4 Watt resistors of either 5% or 10% tolerance.
 +*  a bit of thin wire (preferrably wire-wrapping-wire)
 +*  a bit of heavier wire (about 20 guage)
 +*  solder (silver-based is preferred, but lead based works too)
 +*  A low-wattage soldering iron (mine is only 20 watts)
 + 
 +Optionally, you may build this onto a printed circuit board, which will
 +require a piece of double-sided copper clad board about 1" by 2.5", a
 +resist-ink pen or dry transfers, and some Ferric Chloride (PCB etchant).
 + 
 +[Ed. Note : Maxim Electronics : 1-800-998-8800 ; Radio Shack has the jack
 + and they do carry a .156" connector but with 22/44 leads. ​ I had to cut
 + it to 12/24 in order to match the userport. ​ Also, it must be noted that
 + ​soldering to a socket is less of a risk than soldering to the chip itself.]
 + 
 +I built the prototype by mounting the chip directly to two pins of the
 +user port connector. ​ Since the design is so simple, I will describe the
 +procedure for building the circuit using the prototype method, without
 +using a printed circuit board.
 + 
 +Here we go:
 + 
 +1) Turn the edge connector to point the solderable pins towards you.  Cut
 +   off pin 1, pins 3-7, and pins 10-12. ​ These are on the TOP row, with
 +   pin 1 being on the left end when the connector is held as above.
 + 
 +     ​left ​  ​1 ​  ​2 ​  ​3 ​  ​4 ​  ​5 ​  ​6 ​  ​7 ​  ​8 ​  ​9 ​ 10  11  12   right
 + 
 +2) Cut off pin A and B.  This is on the bottom row, second from the left.
 +   ​Remember that as with most Edge connectors, there are no pins G or I.
 +   ​Instead the pins are lettered like this:
 + 
 +     ​left ​  ​A ​  ​B ​  ​C ​  ​D ​  ​E ​  ​F ​  ​H ​  ​J ​  ​K ​  ​L ​  ​M ​  ​N ​  right
 + 
 +3) Align pins 12 and 13 of the Max chip, with pins H and F (respectively)
 +   on the User Port plug.  Make sure the chip and plug are right side up.
 +   now bend the chip's pins around and under the plug's pins, and solder.
 + 
 +4) Using a series of short wires, connect the following using ordinary
 +   ​point-to-point soldering.
 + 
 +      Chip   Plug
 +       ​16 ​     C
 +       ​15 ​     D
 +       ​14 ​     E
 +       ​13 ​     F  (already soldered)
 +       ​12 ​     H  (already soldered)
 +       ​11 ​     J
 +       ​10 ​     K
 +        9      L
 + 
 +5) Using more point to point soldering, connect the following:
 + 
 +      Chip   Plug
 +       ​22 ​    two
 +       ​19 ​     M
 +       ​18 ​   nine
 +       ​17 ​   eight
 +        8      N
 + 
 +6) Turn the device upside down and make the following connections on the
 +   back side of the chip.  Be sure not to confuse your pin-layout!
 +   ​Again,​ plain old point-to-point soldering is the key.
 + 
 +   Pin 20 to pin 21, Pin 21 to Pin 22, Pin 22 to Pin 4, Pin 4 to Pin 5.
 +   Pin 8 to Pin 7, Pin 7 to Pin 6, and Pin 6 to pin 3.
 + 
 +7) Turn the circuit back right-side-up again, and connect one end of each of
 +   the four 1K resistors, to the Max chip, pins 1, 2, 23, and 24.
 + 
 +8) Now Take the resistors connected to pins 2 and 23, and connect the free
 +   ends together. ​ Connect this point to the Miniplug TIP tab.
 + 
 +9) Take the resistors connected to pins 1 and 24, and connect the free
 +   ends together. ​ Connect this point to the Miniplug SLEEVE tab.
 + 
 +10) Connect the Max chip's Pin 6 to the Miniplug GROUND tab.
 + 
 +11) Take a piece of the heavier wire, fashion a simple pull-handle by
 +    running a wide loop of it between the holes at each end of the plug.
 +    For strength I recommend soldering the ends together.
 + 
 +[Ed. Note : Please observe : Pins 1 and 24 are used as RIGHT output and pins
 + 2 and 23 are used as LEFT output. ​ On a 1/8" stereo miniplug jack from Radio
 + Shack (#​274-249a),​ you will see three prongs. ​ The prong closest to the
 + ​opening of the jack is the GROUND, and for reference'​s sake we will consider
 + that this prong is at the base of the jack.  The other two prongs are on
 + the back of the jack and are aligned one '​above'​ the other. ​ The one that
 + is on the base is the SLEEVE and the one above it is the TIP.]
 + 
 +Your 4 channel DAC circuit is now ready to use.  To test the circuit, you
 +can run this short BASIC program on a Commodore 64, or a Commodore 128 in
 +64 or 128 mode.  In 128 80-column mode, you may want to type '​fast'​ and
 +hit return before running, to make the test higher pitched and a bit more
 +accurate.
 + 
 + 
 +10 u=56577: poke u+1,63: poke u+2,100: input "​channel (1-4)";​c$:​ c = val(c$)
 +20 if c<1 or c>4 then 10
 +30 if c=1 then ch=248
 +40 if c=2 then ch=252
 +50 if c=3 then ch=240
 +60 if c=4 then ch=244
 +70 poke u-1, ch
 +80 for x=0 to 255: pokeu,x: next
 +90 get a$: if a$=""​ then80
 +100 goto 10
 + 
 + 
 +What you should hear coming out from the desired channel is a sawtooth wave,
 +simialar to the sawtooth save the SID chip produces, but of course a tad
 +* distorted * since this is in BASIC. ​ Press any key to stop the test.
 + 
 +In machine language, these instructions should produce a similar test..
 +POKE 250,speed: POKE 251, chan_index: SYS 3072.. ​ speed will control the
 +pitch of the sound. ​ Chan_index is 248 for channel 1, 252 for channel 2, 240
 +for channel 3, and 244 for channel 4.  Press the spacebar to stop the test.
 + 
 + 
 +        Hexadecimal ​    ​Decimal equivalent
 + 
 +START   * = $0C00; ​     3072
 +        SEI
 +        LDA #$3F;       63
 +        STA $DD02; ​     56578
 +        LDA #$FF;       255
 +        STA $DD03; ​     56579
 +        LDA $00FB; ​     251
 +        STA $DD00; ​     56576
 +        LDY #$00;       0
 +LOOP    STY $DD01; ​     56577
 +        LDX $00FA; ​     250
 +DELAY   DEX
 +        BNE DELAY
 +        INY
 +        LDA $DC01; ​     56321
 +        CMP #$EF;       239
 +        BNE LOOP
 +        CLI
 +        RTS
 + 
 + 
 +Accessing the board via your own software is very simple..
 + 
 +You need to use Machine code if you are planning to access more than one 
 +channel of the board. ​ If you plan to use a single channel, just POKE 
 +56576,248 and run your player routine. ​ This will select channel 1 (left 
 +side) to send your output through.
 + 
 +In machine code, you use a single LDA:STA pair to select the channel, and 
 +just stuff your data into $DD01, something like the above.
 + 
 +The hardware will take care of the output, and will see to it that the byte
 +you send out is properly clocked and that it goes to the correct channel.
 + 
 +The User port contains a total of 10 easily programmable data lines (the 
 +others require more complicated methods to use).  These lines are broken ​
 +into two sets.  The first set, the data bus as I like to call it, 
 +consists of the 8 lines than make up the User Port's PB0-7 area.  These 
 +bits are all present at location $DD01. ​ The data direction regiter for 
 +this location is at $DD03. ​ A 1 bit there means an input, while a 0 bit
 +signifies an output.
 + 
 +The other set consits of two bits that sit at location $DD00, these bits 
 +are PA2 and PA3, also known as RS232 data out, and Serial ATN in, 
 +respectively. ​ These two bits serve as a mini-address bus, and are used 
 +to select the correct channel to comminicate with.
 + 
 +Since the hardware inverts the output of PA3, it was necessary to 
 +re-invert this bit in software, which is why the channels are being 
 +selected with such odd numbers.
 + 
 +Also, since location $DD00 controls the 16K memory bank seen by the VIC-II ​
 +chip, you must keep the VIC pointing to bank 0 (by setting bits 6 and 7) if
 +you want to keep the VIC 40 column display in proper order. ​ This explains
 +why all of these numbes are 240 (#$C0) or higher.
 + 
 +Most DAC chips require some sort of clock signal to pass data into the 
 +chip.  The MAX505 is no exception. ​ In order to lessen the time needed by 
 +the computer, we wil ise the User Port's PC2 line, a low active clock 
 +line that fires every time a byte is sent or received via the PB0-7 lines.
 + 
 +This line was intended to drive the /FLAG input of another C64, or other 
 +hardware device, however, it also serves as a useful clock signal for our 
 +chip.
 + 
 +The MAX505 requires you to select the channel first, write the data byte to 
 +it's data bus, and then pull the /WR line low for a brief moment. ​ Thus we 
 +write our code like this, to do these actions in proper order:
 + 
 +LDA #$Cn            ; n is 8, C, 0, or 4, for Channels 1, 2, 3, and 4 
 +                    ; respectively. ​ Channels 1 and 4 are wired for left 
 +                    ; output, while 2 and 3 are wired for right.
 +STA $DD00           ; This actually sets the channel number.
 +LDA your_data_here ​ ; Use whatever method you need to get the next byte of
 +                    ; Sample data into the accumulator.
 +STA $DD01           ; Send the byte to the User port, automatically ​
 +                    ; firing PC2.
 + 
 +That's pretty much it!
 + 
 +The MAX505 chip is designed to handle in excess of 100,000 samples per 
 +second, per channel. ​ In fact, according to the specs, it can go as high 
 +as 1 million samples per second, per channel.
 + 
 +Below you will find a pinout diagram for the MAX505 chip, to aid in
 +performing the steps given above for assembling this circuit. ​ This is a
 +duplicate of the diagram found on page 1 of the spec booklet that comes
 +with the MAX505 family. ​
 + 
 + 
 +              TOP VIEW
 +              ___   ___
 +             ​Ü. ​ À-' ​  Ü
 +   VOut B [ 1Ü         Ü24] VOut C
 +   VOut A [ 2Ü         Ü23] VOut D
 +      VSS [ 3Ü         Ü22] VDD
 +   VRef B [ 4Ü  MAXIM  Ü21] VRef C
 +   VRef A [ 5Ü MAX 505 Ü20] VRef D
 +     AGND [ 6Ü         Ü19] A0
 +     DGND [ 7Ü         Ü18] A1
 +    /LDAC [ 8Ü         Ü17] /WR
 + (MSB) D7 [ 9Ü         Ü16] D0 (LSB)
 +       D6 [10Ü         Ü15] D1
 +       D5 [11Ü         Ü14] D2
 +       D4 [12Ü         Ü13] D3
 +             ​Ü_________Ü
 + 
 +             ​DIP/​SO/​SSOP
 + 
 + 
 +Have fun with this circuit! ​ I built mine in about 30 minutes, and it has
 +become my default playback device for my Modplayer. ​ I will also write in
 +full support for this device in Sound Studio 4.0 (commercial),​ as well as 
 +any other digital sound programs I happen to write later.
 + 
 +The MAX505 chip will also be used in another board I am designing, called
 +the E-8 (Enhanced-8) board. ​ This board will use two MAX505'​s to provide an 
 +effective output resolution of 16 bits per channel. ​ The board will also 
 +feature a pair of National Semiconductor ADC0820BCN chips, for sampling ​
 +in 8 bit two channel stereo (Unless I find a better chip to use).  No 
 +release date or pricing has been set for this board as of yet.
 + 
 +-- 
 +For more information on this or general commentary, you may reach Nate at
 +the following addresses:
 + 
 +Dannenberg Concepts, Ltd.
 +"​Bringing your Commodore 128 one step closer!"​
 + 
 +Email: ​  ​tron@wichita.fn.net
 +Phone: ​  (316) 777-0248
 +Snail: ​  ​Dannenberg Concepts, Ltd.
 +         c/o Mr. Nate Dannenberg
 +         306 S. 1st Ave
 +         ​Mulvane,​ KS   67110
 +FidoNet: 1:291/25
 +         ​Groups: ​ CBM, CBM-128, and CBM-GEOS
 +Usenet: ​ comp.sys.cbm,​ alt.binaries.sounds.mods
 + 
 +
 +\H03::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +
 +                    Upgrading your C128's VDC memory to 64K
 +
 +                               by Mike Gordillo
 +
 +
 +
 +This will be a quick "​how-to"​ on upgrading your VDC memory from 16K to 64K.
 +Those of you who have C128-DCR'​s should already have this upgrade from the
 +factory, but those who own original flat C128's or original C128D'​s may wish
 +to undertake the following VDC ram expansion. ​ First off, the last time I
 +checked, you needed two 64x4 DRAM's and the prices for such ram chips were
 +as follows:
 + 
 +   LA Trade - 1-800-433-3726
 +   64x4 DRAM - 80 nanoseconds = $3.75
 + 
 +   ​Nevada Computer - 1-800-982-2925
 +   64x4 DRAM - 100 nanoseconds = $2.45
 + 
 +   ​COMP-USA !!!  1-800-COMP-USA
 +   64x4 DRAM - 100 nanoseconds = $1.50 ! ! ! !
 +
 + 
 +The instructions for installing them into your machine quite simple. ​ Just
 +open up your C-128, remove the shielding, keyboard connector, etc.  You should
 +now see a metallic box around the center of the C-128'​s motherboard. ​ Remove
 +the lid on that box with the keyboard facing you, revealing the following:
 + 
 + 
 +>>>>>>>​ Back of C-128 <<<<<<<​
 +
 +        ---**--- ​    ​------ ​            /
 +        -      -     - LC -             /
 +        -  8   ​- ​    ​- ​   -             /
 +        -  5   ​- ​    ​- ​   -             /
 +  VDC   ​- ​ 6   ​- ​    ​--**-- ​            / ​  VIC Chip
 +  Chip  -  3   ​- ​                       /   ​Circuitry
 +        -      -     ​------ ​    ​------ ​ /   to the right
 +        -  V   ​- ​    - 16 -     - 16 -  /
 +        -  D   ​- ​    ​- ​ x -     ​- ​ x -  /
 +        -  C   ​- ​    ​- ​ 4 -     ​- ​ 4 -  /
 +        -      -     ​- ​   -     ​- ​   -  /   <​---These two 16x4 DRAM's
 +        -      -     ​-DRAM- ​    ​-DRAM- ​ /       are to be replaced with
 +        -------- ​    ​--**-- ​    ​--**-- ​ /       64x4 DRAM'​s.
 + 
 +                          ** = designates the directional notch on the chip
 + 
 +>>>>>>>​ Front of C-128 <<<<<<<​
 + 
 + 
 +In your machine you will see two 16 by 4 DRAM chips (16 kbytes total). ​ Your
 +task is to replace them with 64 by 4 DRAM chips (64 kbytes total) that you can
 +get cheaply at CompUsa for example :)...no minimum order.. :)).  The hard part
 +is now at hand.  The 16 by 4 chips are not on stacks! ​ This means you have to
 +unsolder them.  If you have never played with a soldering iron before this is
 +going to be a BIG pain in the rear and you may damage your C-128 in the
 +process. ​ (See, isn't it neat to find out for FREE instead o paying Slick Wile
 +up front?)
 + 
 +If you have some experience with a soldering iron, remove the C-128'​s
 +mother board from the case, flip it over, and find the pins for the 16
 +by 4 DRAMs on the back.  Unsolder them and remove the chips. ​ Solder the 64
 +by 4 DRAM chips in the same exact spots as the 16 by 4 chips, remembering to
 +keep the notch on the 64 by 4 chip facing the notch on the original 16 by 4
 +chip.
 + 
 +Solder in stacks/​sockets first, and then plug in the 64 by 4 chips, because
 +it is safer to solder in the sockets AND if a memory chip goes bad, you won't
 +have to unsolder again (just pop out the ram chip from its socket.)
 + 
 +18-Pin Stacks/​Sockets are 50 cents each at Radio Shack.
 + 
 + 
 +DISCLAIMER :
 + 
 +You undertake this procedure at your own risk.  If you destroy your machine,
 +its your cross to bear.  I did this to a C-128 last Sunday. ​ It took 2 hours
 +with the simple soldering tools I have.  It may take you less time or more time
 +depending on your equipment and experience. ​ DRAMs are a pain to remove in any
 +case.  I sped up removal by just cutting the legs on the original 16 by 4 chips
 +with a manicurist'​s scissors.
 +
 + 
 +Definitions :
 + 
 +16 by 4 (16 x 4) = 8 Kbytes of memory
 +64 by 4 (64 x 4) = 32 Kbytes of memory
 +DRAM = Dynamic Random Access Memory
 +8563 VDC = The C-128'​s 80 column video chip.
 +LC = Logic chip next to VDC, more specifically,​ its a 74LS244.
 + 
 +Specific labelling on the original 16 by 4 DRAM:
 + 
 +You should either see TMS4416 on them or MB81416. ​ They are usually 120
 +nanosecond chips, so you must buy 64 by 4 chips that are at least 120 nano-
 +second variety. ​ I chose 100 nanoseconds because it was the least expensive
 +64 by 4 DRAM speed that I could find. 
 + 
 +-- 
 +For general comments on this article, feel free to contact Mike Gordillo
 +at s0621126@dominic.barry.edu
 +
 +
 +\H04::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +
 +
 +                      >> The Metal Shop ---
 +                                *+*
 +                         --- with SMS Mike Eglestone <<
 +                                of Diamondback BBS
 +                                   ​(305)258-5039
 +
 +
 +Senior Master Sergeant Mike Eglestone has been a devout C= Hardware guru
 +for over ten years and is the Sysop of one of the most active BBS's on the
 +Commnet Commodore BBS network. ​ Mr. Eglestone has written for illustrious
 +magazines in the Commodore 8 bit community such as dieHard magazine and the
 +very distinguished Commodore World. ​ We are pleased to have him entertain
 +our questions pertaining to hardware repair. ​ As always, neither the editors,
 +the staff of disC=overy, nor Mr. Eglestone are responsible for the use or
 +misuse of any information presented in this article.
 +--
 +
 +
 +>> Dear SMS Mike,
 +>>
 +>> ​   My CMD Hard Drive refuses to undergo its power-up sequence at irregular
 +>> intervals and is belching out a whole series of errors and bad blocks.
 +>> Unfortunately,​ my drive is long past its warranty period and I have no
 +>> idea what is wrong with it.  What do you think?
 +>>
 +>> MG
 +
 +MG,
 +
 + First of all, I would give CMD a call about this even if your drive is out
 +of warranty. They know their drives better than anyone, but with that said,
 +I have run into a total of 5 (was 4) Hard Drives produced by CMD that had
 +cold solder joints on the main circuit board. They were discovered at the
 +connection point for the Power Supply, and were all on the 12VDC connectors
 +for the drive motor.
 + 
 + There is a 4 pin DIN plug attached to the main circuit board which is the
 +plug for the power supply to the drive. The connection on the bottom of the
 +board (remove it and turn it over) has a tendency to be bad or loose from
 +poor solder joints (cold joints).
 + 
 + This cold or loose joint will cause strange problems with the drive motor,
 +and you will notice SCSI errors, or a sudden accumulation of Bad Blocks. It
 +can even result in the complete failure of the drive to start up, or it might
 +just shut down (stop turning) without warning.
 + 
 + The solution is very simple. Remove the drive and circuit board. Turn the
 +board over, and re-solder the joints. Takes about 15 minutes from start to
 +finish...
 + 
 + The way the main circuit board is attached to the case is one of the
 +problems. The rear support point is in front of the DIN plug but close to an
 +inch away from it. Each time you insert the plug into the DIN connector, it
 +puts pressure on those connection points and BENDS the board slightly. After a
 +while, the connections loosen up at the solder joints. Cold Joints or joints
 +that were just slightly tacked, will crack or just seperate from the foil.
 + 
 + I have now fixed 5 drives with this same problem, and they work perfectly
 +again... CMD is aware of the situation, but they think it's an isolated
 +problem with one batch of boards. I don't think so. I think it's going to
 +happen to all of them sooner or later. That rear support and the location of
 +the DIN seem to be a failure point.
 +-- 
 +
 +
 +>> Dear SMS Mike,
 +>>
 +>> ​   I am about to throw my C128's keyboard out my balcony. ​ For the past
 +>> year, a key has been failing to work properly about once a month. ​ I now
 +>> have to put up with at least 12-15 keys that either refuse to work at all
 +>> or require some deep-felt pounding in order to generate a character.
 +>>
 +>> What can I do about this aside from buying another keyboard??
 +>>
 +>> SK
 +
 +SK,
 + 
 + I have cleaned and restored hundreds of keyboards over the last 10 years.
 +I have piles and piles of boards and board parts (64 and 128) sitting around
 +my computer/​repair room. Not to mention around 10 extra mother boards for both
 +types of computer.
 + 
 + After playing around with the carbon contacts on both the circuit board
 +itself, and the carbon impregnated (rubber contacts) on the end of the key
 +plungers, I have come to the conclusion that the only cleaner required is
 +de-natured alcohol. It works on every part of the board, and works perfectly.
 + 
 + When I do a cleaning job, I remove (strip) every key down to its component
 +parts. The keys themselves go into a bleach solution. The rubber pads and
 +plungers go into a pan of denatured alcohol. The key springs (if not rusted)
 +are lightly sprayed with WD-40 and rinsed with alcolol later. If they are
 +rusted, they go into a solution of phosphoric and dichromate acid. Brand name
 +is OSPHO (any True Value Hardware Store has it).
 + 
 + The circuit board itself is washed with de-natured alcohol and lightly dried
 +with a blower.
 + 
 + ​Seldom do the carbon spots on the circuit board go bad. If they do, you can
 +use a product which contains silver loaded epoxy, and mix that with carbon
 +powder; Graphite. There is also a spray carbon compound that's available, but
 +I don't remember the name at the moment. It's used by the aircraft industry.
 + 
 + Once, I couldn'​t find any silver loaded epoxy. I just used a hobby type (two
 +part) epoxy and mixed in huge quanitities of graphite. It worked perfectly.
 +Dab on a drop, let it setup, lightly sand the surface to break the glaze..
 +(wham), a new conductive contacting surface.
 + 
 + It was trial and error for a long time, but I now have it down to a science.
 +I normally get four years out of an overhauled keyboard; using original parts
 +and proper cleaning solutions.
 + 
 + Oh sure, I have written off a few keyboards as not worth fixing, but that
 +isn't the norm. When one comes in that has been abused to the point that I
 +don't even want to attempt a repair, it becomes parts for other boards.
 + 
 + One thing always needs to be done with keyboards (prior to re-assembly).
 + 
 +  Plug in the circuit board, turn on the computer, then touch each keypad to
 +a contact (one by one) and make sure it's working. This is done by hand.
 + 
 + Blank un-assembled (open) circuit board, with keypads held in the fingers.
 +It takes about 5 minutes, and it's well worth the effort involved.
 + 
 + NO electrical voltages are present, that will harm you. There are only a
 +couple of volts of DC present, and that is the output of the CIA (Complex
 +Interface Adaptor) which is the Keyboard control chip.
 + 
 + You can't run a conditivity test on the rubber keypads with a tester. It's
 +got to have a slight DC voltage present to make it work. A standard VOM will
 +not do the job. The computer itself makes a dandy test bed.
 +-- 
 +
 +>> Dear SMS Mike,
 +>>
 +>> ​   Every now and then I'll be sitting peacefully in front of my 128 when
 +>> I start to hear crackling noises out of the monitor'​s speaker and I'll
 +>> notice that the 40 column screen starts to go wacky on me at the same
 +>> time.  Sometimes I'll see color changes and sometimes I'll see little
 +>> random characters appear on screen. ​ The crackling noises appear to always
 +>> be a consistent low pop-pop-click and occur in both 64 and 128 modes.
 +>> A few rare times, 128 mode will crash and hang when these events occur,
 +>> although 64 mode will be a-ok (except for the crackling and popping).
 +>> I know my monitors and cable are working 100% so I am at a loss to explain
 +>> this phenomena.
 +>>
 +>> RR
 +--
 +
 +RR, 
 + 
 + There are three possibilities,​ and one of them is going to sound a bit odd.
 + 
 + The 128 uses a two stage video output system. The VIC chip and a seperate
 +Vidio Controller. Both are located inside the metal Box (with lid) in the back
 +left hand side of the circuit board. There is a screw hole dead center of the
 +metal box.. The VIC chip would be my first choice. It's on the right hand side
 +of the box. IC-U21 is the number on the board. The Vidio Controller is mostly
 +for RGB displays and 80 col memory enhancement,​ but it does work WITH the VIC
 +chip in some area of Composite color IC-U22 (Left hand side of the box).
 + 
 + Here is the "​odd"​ choice, but one that I have found in quite a few 128 video
 +and "​Crackling Sound" problems.. ->  The ON/OFF switch for the 128 itself.
 + 
 + As you are aware, the 64 and 128 use a dual voltage power supply system. The
 +computer has the second stage on the Circuit board. That On/Off switch can
 +become dirty inside, or limited in movement enough so that it doesn'​t make
 +contact perfectly in the ON position. Sometimes it's just a matter of
 +flipping the switch on HARD to make good contact, and sometimes it's
 +necessary to actually remove the switch and clean the contacts internally.
 + 
 + On 6 different 128's, where I have come across this problem, I have had to
 +remove the circuit board and File out the switch Hole "​larger"​ at the top
 +because the computer CASE itself was interfearing with the movement of the
 +switch. A "not quite closed"​ contact in that switch will cause the 9VAC
 +section to ARC slightly. This will drop colors and cause the sound you were
 +talking about. It will affect your internal clocking and cause both video and
 +audio problems.
 + 
 + ​It'​s always best to check the IC's by substitution. Take a known good IC and
 +replace the one in use. If that doesn'​t solve the problem then do the same
 +thing with the other chip. Sometimes, just pulling the chip out and putting it
 +back in will fix contact problems. Humidity will cause minor corrosion on the
 +legs of an IC over a period of time. Re-seating the IC will normally fix this
 +sort of thing. A quick shot of contact cleaner in the IC socket never hurts.
 + 
 + Those are your three choices guy.
 + 
 + Well, there is ONE more, but it's a remote possibility. The DIN socket on the
 +composite video OUT side. You can give that socket a shot of contact cleaner
 +and see if the problem clears up. It will sometimes build up a slight film and
 +cause similar problems to the one you are talking about.
 + 
 + Last thing. If you remove the RF shield (the metal cover over the circuit
 +board) LEAVE it OFF. The computer will run cooler and you really don't need
 +that hunk of metal. I normally throw the darn things away. Although it is used
 +as an RF shield and a heat sink, it causes more problems than it solves.
 + 
 + SMS MIKE
 +--
 +Mr. Mike Eglestone may be reached for questions or comments at Diamondback BBS
 +(305)258-5039 or through the editors of disC=overy.
 +
 +
 +\END:::::::​d:​i:​s:​C=:​o:​v:​e:​r:​y:::::::::::::::::​i:​s:​s:​u:​e::​1::::::::::::::::::::​
 +:::::::::::::::::::::::::::::::​May ​ 17, 1996::::::::::::::::::::::::::::::::::​
 +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::​
 +</​code>​
magazines/discovery1.txt · Last modified: 2015-04-17 04:35 (external edit)