User Tools

Site Tools


magazines:chacking1

Differences

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

Link to this comparison view

magazines:chacking1 [2015-04-17 04:34] (current)
Line 1: Line 1:
 +====== C= Hacking #1 ======
  
 +<​code>​
 +  Sorry that this is later than I had hoped to get it out, but here it is --
 +Expect another one soon in a month or two depending on submissions... Praise,
 +Comments, (It sucks, I loved it, etc) are welcome ->
 +duck@pembvax1.pembroke.edu. ​ Many thanks to Craig Bruce for his article on line
 +drawing / dot plotting with the 80 column screen on the C=128.
 +
 +===============================================================================
 +Hacking / This Magazine
 +by Craig Taylor
 +duck@pembvax1.pembroke.edu
 +
 +Def:
 +  Hacker - Noun - A talented amateur user of computers.
 +  Source - Webster'​s New World Dictionary
 +
 +Correction:
 +  Hacker - Noun - A talented user of computers.
 +
 +
 +  There, now that we got that out of the way, let's see how some people
 +interpret the word hacker. In the 1980's newspapers, magazines, movies -
 +everywhere ya looked people were using the term "​Hacker"​ to denote a person who
 +maliciously tried to destroy / bore ill intent towards another computer system.
 +This was the result of the misunderstanding of the actual definition of
 +"​Hacker"​ (under my correction above).
 +
 +  This magazine will not tell people how to "​phreak",​ how to hack voice
 +mailboxes and other illegal activities. ​ However, it will attempt to reveal
 +some of the "​mystique"​ behind some of the new techniques and abilities found in
 +the Commodore 64 and Commodore 128 that are just now being revealed.
 +In the event that an article is submitted and there is a question about it's
 +ability to be applied towards illegal activites, the article will be carried
 +with a warning that the intent is not towards that activity. ​ Hopefully, these
 +will never come along. :-)
 +  The Commodore 64 came out in late 1982 (I believe) and was known to only
 +support 16 colors, 320 x 200 resolution graphics of 2 colors, 160x200
 +resolution graphics of 4 colors. ​ Since then people have pushed the Commodore
 +64 to its limits with apparent resolution of 320 x 200 with a resolution of 4
 +colors and even higher... more than 8 sprites on the screen... fast
 +high-quality digitized sounds....
 +  The Commodore 128 came out as an "​upgrade"​ from the Commodore 64 and with
 +it's unique memory management scheme and the Z80a chip still on there people
 +are still finding out unique and interesting ways to explore the C=128. One of
 +the most interesting has been that of the seperate video display chip which
 +makes it possible to dispaly 640x200 resolution graphics quickly and easily.
 +
 +**ATTENTION**
 +  This magazine is going to be a sourcebook of many people - If you know
 +anything about something, please feel free to submit it.  Just mail the article
 +to the following :
 + duck@pembvax1.pembroke.edu
 + and a subject of "​ARTICLE - " and then the article name.
 +
 +  The source code for all programs mentioned within articles will be provided
 +as well as any executables uuencoded sent out seprately. [Ed. Note - In this
 +issue, the source is not sent seperately due to only one article with files]
 +
 +  In addition, the magazine will go out when there are enough articles
 +collected. ​ Also, I'm currently in college - so - it will also be dependant on
 +few tests etc being around the release period.
 +
 +  In this issue:
 +
 +    Title                               ​Author(s)
 +------------------------------------------------------------------------------
 +Hacking - Definition Of duck@pembvax1.pembroke.edu
 +Learning ML - Part 1    duck@pembvax1.pembroke.edu
 +6502 Known/​Unknown Opcodes compilation of several
 +Dot Plotting & Bitmapping csbruce@ccnga.uwaterloo.ca
 +  the 8563 Screen.
 +
 +** All articles and files (C) 1992 by their respective authors.
 +=============================================================================
 +</​code>​
 +
 +====== Beginning ML - Part One ======
 +<​code>​
 +(C) 1992 by Craig Taylor
 +
 +  The best way to learn machine language is to actually code routines that you
 +don't think will work, hope that they work, and then figure out why they don't
 +work. (If they do work, you try to figure out why you didn't think they'd
 +work). ​ Ie: THE BEST WAY TO LEARN ANY PROGRAMMING LANGUAGE IS TO PROGRAM IN
 +THAT LANGUAGE. ​ And Machine Language is a programming language.
 +  Now, let's get a few terms and definitions out of the way:
 +
 +  Machine Language - Instructions that the computer understands at a primitive
 +     level and executes accordingly.
 +  Assembly Language - Instructions more understandable to humans than pure
 +     ​Machine Language that makes life easier.
 +
 +                      Assembly:​ Machine:​
 + Example:​ lda #$00                  $A9 $00
 +
 +  Huh? you might be saying at the moment. ​ Turns out that LDA stands for, or is
 +a mnemonic (computer people always come up with these big long words -- you'll
 +see mnemonic'​s often when dealing with machine language) for the following:
 +    "LOAD register A with the following value"
 +     ​^ ​ ^          ^
 +  Cool 'eh? Yeah, but there'​s somebody grumbling now about why not make it
 +LOADA etc.. Hey, that's life. (GRIN).
 +  ​
 +  Oh, more definitions:​
 +
 +  Register - A location inside the CPU that can be manipulated directly without
 +     ​having to access memory.
 +
 +  The "​A"​ register is often called the accumalator which indicates its
 +function: all math and logical manipulations are done to the "​A"​ register (from
 +hereon out it will be referred to as .A).
 +  There are two other registers inside the 6502 processor, specifically .X and
 +.Y.  These registers help act as counters and indexes into memory (sorta like
 +mem[x] in pascal but not quite...).
 +
 +  Now, let's add 3 and 5 and leave the result in the accumalator (.A).
 +
 + lda #3 ; Here .A = 3 (anything w/ a ; is a
 +   ; comment and will be ignored by the assembler... ​
 + clc ; hu? - This clears the carry. The 6502
 +  ; does addition *everytime* with the carry ... so if we clear it it won't
 +  ; affect the result.
 + adc #5 ; Now, .A = .A + 5
 +
 +  and we're done.  If the CLC confused you then consider that if you're adding
 +a column of #'s:
 +               
 +       12 <​--\__The 2 + 9 = 11, but we put the 1 down and set the carry to 1.
 +    +  89 <​---/ ​
 +       --
 +      101
 +   Then we say 1 + 8 + carry , which in this case happens to = 1 and we get 10
 +and again we set the carry and write down 0. Then it's just the carry and we
 +write that down.  If we didn't clear the carry we may have ended up with the
 +value of 9 instead 8 if the carry had happened to be set.
 +  ​
 +  Aaagh, Math - Let's continue - The CLC mnemonic stands for "CLEAR CARRY" and
 +the ADC stands for "ADD with CARRY"​. ​ On many processors there is a ADD
 +(without a carry) but unfortunately the 6502 processor inside the C=64 doesn'​t
 +have it.
 + So we've got:
 +    load reg A with the value 5      lda #5
 +    clear the carry clc
 +    add reg a and value 3 adc #3
 +
 + In Basic it's just: 
 +    A = 5+3 
 +
 +  One statement... In Machine Language you've got to break everything down into
 +smaller and smaller steps and quite often the ML listing will be far longer
 +than the BASIC or PASCAL or C equivlent.
 +
 + ​Definitions:​
 +   ​Assembler - Program takes source code in basic form or from a file and
 +writes to memory or a file the resulting executable. Allows higher flexibility
 +than a monitor (see below) due to use of labels etc and not having to keep
 +track of each address within the program.
 +
 +  Monitor - A program, resident in memory, invoked by a sys call from basic or
 +by hitting the restore key that will let you disassemble,​ assemble and examine
 +areas of memory and execute programs directly from the monitor. Useful for
 +debugging programs and for writing short programs.
 +  ​
 +  Let's enter the following into a monitor (if you don't have one then contact
 +duck@pembvax1.pembroke.edu and I'll send ya one):
 +
 +128: c64:
 +>a 1300 lda #$93     ​ >​a c000 lda #$93
 +>a 1302 jsr $ffd2 >a c003 jsr $ffd2
 +>a 1305 rts >a c005 rts
 +(exit monitor) (exit monitor)
 +bank15:​sys4864 sys 49152
 +
 +  Wow! It cleared the screen. Neat '​eh? ​ But see how much ya gotta break
 +problems down?  The first statement loads in $93 hex into the accumalator ($93
 +hex just happens to equal 147 which is also the Commodorscii code for clear
 +screen. ​ For a whole list just look in the back of the book that came with the
 +computer). ​ Then we jump to a system routine which Commodore so graciously
 +supplied us with that prints the value of the character in .A to the screen.
 +(jsr $ffd2) then we do a RTS (ReTurn from Subroutine) so that we will go back
 +to basic and the Ready prompt when we are finished with the sys call.
 +  You C= 128 people may be wondering why you had to do a bank 15 and assemble
 +the stuff at a different memory location. ​ Turns out that the C128 memory map
 +of where routines etc are at is much more complex than the C=64 and thus you
 +have to tell basic which bank you wish to have all sys, peek, and poke calls to
 +take place in. Also, $c000 as used on the C=64 is not an area that is free to
 +use on the C128 in this manner.
 +
 +  Assignment: Take a look @ the different commands as listed in 6502 Opcodes
 +and try to understand what they do. Experiment with the jsr $ffd2 routine by
 +using different values etc.
 +
 +  Next Time: Printing out strings, and understanding '​Indexing'​.
 +
 +===========================================================================
 +</​code>​
 +
 +====== 6502 Opcodes and Quasi-Opcodes ======
 +<​code>​
 +
 +  The following table lists all of the available opcodes on the 65xx line of 
 +micro-processors (such as the 6510 on the C=64 and the 8502 on the C=128)
 +
 +-----------------------------------------------------------------------------
 +Std Mnemonic Hex Value Description ​               Addressing Mode  Bytes/​Time ​
 +*   ​BRK ​     $00       Stack <- PC, PC <- ($fffe) (Immediate) ​     1/7
 +*   ​ORA ​     $01       A <- (A) V M               ​(Ind,​X) ​         6/2
 +    JAM      $02       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    SLO      $03       M <- (M >> 1) + A + C      (Ind,​X) ​         2/8
 +    NOP      $04       [no operation] ​            ​(Z-Page) ​        2/3
 +*   ​ORA ​     $05       A <- (A) V M               ​(Z-Page) ​        2/3
 +*   ​ASL ​     $06       C <- A7, A <- (A) << 1     ​(Z-Page) ​        2/5
 +    SLO      $07       M <- (M >> 1) + A + C      (Z-Page) ​        2/5
 +*   ​PHP ​     $08       Stack <- (P)               ​(Implied) ​       1/3
 +*   ​ORA ​     $09       A <- (A) V M               ​(Immediate) ​     2/2
 +*   ​ASL ​     $0A       C <- A7, A <- (A) << 1     ​(Accumalator) ​   1/2
 +    ANC      $0B       A <- A /\ M, C=~A7         ​(Immediate) ​     1/2
 +    NOP      $0C       [no operation] ​            ​(Absolute) ​      3/4
 +*   ​ORA ​     $0D       A <- (A) V M               ​(Absolute) ​      3/4
 +*   ​ASL ​     $0E       C <- A7, A <- (A) << 1     ​(Absolute) ​      3/6
 +    SLO      $0F       M <- (M >> 1) + A + C      (Absolute) ​      3/6
 +*   ​BPL ​     $10       if N=0, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​ORA ​     $11       A <- (A) V M               ​((Ind),​Y) ​       2/5'1
 +    JAM      $12       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    SLO      $13       M <- (M >. 1) + A + C      ((Ind),​Y) ​       2/8'5
 +    NOP      $14       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​ORA ​     $15       A <- (A) V M               ​(Z-Page,​X) ​      2/4
 +*   ​ASL ​     $16       C <- A7, A <- (A) << 1     ​(Z-Page,​X) ​      2/6
 +    SLO      $17       M <- (M >> 1) + A + C      (Z-Page,​X) ​      2/6
 +*   ​CLC ​     $18       C <- 0                     ​(Implied) ​       1/2
 +*   ​ORA ​     $19       A <- (A) V M               ​(Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $1A       [no operation] ​            ​(Implied) ​       1/2
 +    SLO      $1B       M <- (M >> 1) + A + C      (Absolute,​Y) ​    3/7
 +    NOP      $1C       [no operation] ​            ​(Absolute,​X) ​    ​2/​4'​1
 +*   ​ORA ​     $1D       A <- (A) V M               ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​ASL ​     $1E       C <- A7, A <- (A) << 1     ​(Absolute,​X) ​    3/7
 +    SLO      $1F       M <- (M >> 1) + A + C      (Absolute,​X) ​    3/7
 +*   ​JSR ​     $20       Stack <- PC, PC <- Address (Absolute) ​      3/6
 +*   ​AND ​     $21       A <- (A) /\ M              (Ind,​X) ​         2/6
 +    JAM      $22       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    RLA      $23       M <- (M << 1) /\ (A)       ​(Ind,​X) ​         2/8
 +*   ​BIT ​     $24       Z <- ~(A /\ M) N<-M7 V<-M6 (Z-Page) ​        ​2/​3 ​
 +*   ​AND ​     $25       A <- (A) /\ M              (Z-Page) ​        2/3
 +*   ​ROL ​     $26       C <- A7 & A <- A << 1 + C  (Z-Page) ​        2/5
 +    RLA      $27       M <- (M << 1) /\ (A)       ​(Z-Page) ​        ​2/​5'​5
 +*   ​PLP ​     $28       A <- (Stack) ​              ​(Implied) ​       1/4
 +*   ​AND ​     $29       A <- (A) /\ M              (Immediate) ​     2/2
 +*   ​ROL ​     $2A       C <- A7 & A <- A << 1 + C  (Accumalator) ​   1/2
 +    ANC      $2B       A <- A /\ M, C <- ~A7      (Immediate9 ​     1/2     
 +*   ​BIT ​     $2C       Z <- ~(A /\ M) N<-M7 V<-M6 (Absolute) ​      3/4
 +*   ​AND ​     $2D       A <- (A) /\ M              (Absolute) ​      3/4
 +*   ​ROL ​     $2E       C <- A7 & A <- A << 1 + C  (Absolute) ​      3/6
 +    RLA      $2F       M <- (M << 1) /\ (A)       ​(Absolute) ​      ​3/​6'​5
 +*   ​BMI ​     $30       if N=1, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​AND ​     $31       A <- (A) /\ M              ((Ind),​Y) ​       2/5'1
 +    JAM      $32       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    RLA      $33       M <- (M << 1) /\ (A)       ​((Ind),​Y) ​       2/8'5
 +    NOP      $34       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​AND ​     $35       A <- (A) /\ M              (Z-Page,​X) ​      2/4
 +*   ​ROL ​     $36       C <- A7 & A <- A << 1 + C  (Z-Page,​X) ​      2/6
 +    RLA      $37       M <- (M << 1) /\ (A)       ​(Z-Page,​X) ​      ​2/​6'​5
 +*   ​SEC ​     $38       C <- 1                     ​(Implied) ​       1/2
 +*   ​AND ​     $39       A <- (A) /\ M              (Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $3A       [no operation] ​            ​(Implied) ​       1/2
 +    RLA      $3B       M <- (M << 1) /\ (A)       ​(Absolute,​Y) ​    ​3/​7'​5
 +    NOP      $3C       [no operation] ​            ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​AND ​     $3D       A <- (A) /\ M              (Absolute,​X) ​    ​3/​4'​1
 +*   ​ROL ​     $3E       C <- A7 & A <- A << 1 + C  (Absolute,​X) ​    3/7
 +    RLA      $3F       M <- (M << 1) /\ (A)       ​(Absolute,​X) ​    ​3/​7'​5
 +*   ​RTI ​     $40       P <- (Stack), PC <​-(Stack) (Implied) ​       1/6
 +*   ​EOR ​     $41       A <- (A) \-/ M             ​(Ind,​X) ​         2/6
 +    JAM      $42       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    SRE      $43       M <- (M >> 1) \-/ A        (Ind,​X) ​         2/​8  ​
 +    NOP      $44       [no operation] ​            ​(Z-Page) ​        2/3
 +*   ​EOR ​     $45       A <- (A) \-/ M             ​(Z-Page) ​        2/3
 +*   ​LSR ​     $46       C <- A0, A <- (A) >> 1     ​(Absolute,​X) ​    3/7 ;According to AR Monitor and Grahams Table this should be LSR ZP instead of LSR $ffff,x
 +    SRE      $47       M <- (M >> 1) \-/ A        (Z-Page) ​        2/5
 +*   ​PHA ​     $48       Stack <- (A)               ​(Implied) ​       1/3
 +*   ​EOR ​     $49       A <- (A) \-/ M             ​(Immediate) ​     2/2
 +*   ​LSR ​     $4A       C <- A0, A <- (A) >> 1     ​(Accumalator) ​   1/2
 +    ASR      $4B       A <- [(A /\ M) >> 1]       ​(Immediate) ​     1/2
 +*   ​JMP ​     $4C       PC <- Address ​             (Absolute) ​      3/3
 +*   ​EOR ​     $4D       A <- (A) \-/ M             ​(Absolute) ​      3/4
 +*   ​LSR ​     $4E       C <- A0, A <- (A) >> 1     ​(Absolute) ​      3/6
 +    SRE      $4F       M <- (M >> 1) \-/ A        (Absolute) ​      3/6
 +*   ​BVC ​     $50       if V=0, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​EOR ​     $51       A <- (A) \-/ M             ​((Ind),​Y) ​       2/5'1
 +    JAM      $52       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    SRE      $53       M <- (M >> 1) \-/ A        ((Ind),​Y) ​       2/8
 +    NOP      $54       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​EOR ​     $55       A <- (A) \-/ M             ​(Z-Page,​X) ​      2/4
 +*   ​LSR ​     $56       C <- A0, A <- (A) >> 1     ​(Z-Page,​X) ​      2/6
 +    SRE      $57       M <- (M >> 1) \-/ A        (Z-Page,​X) ​      2/6
 +*   ​CLI ​     $58       I <- 0                     ​(Implied) ​       1/2
 +*   ​EOR ​     $59       A <- (A) \-/ M             ​(Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $5A       [no operation] ​            ​(Implied) ​       1/2 
 +    SRE      $5B       M <- (M >> 1) \-/ A        (Absolute,​Y) ​    3/7
 +    NOP      $5C       [no operation] ​            ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​EOR ​     $5D       A <- (A) \-/ M             ​(Absolute,​X) ​    ​3/​4'​1
 +    SRE      $5F       M <- (M >> 1) \-/ A        (Absolute,​X) ​    3/7
 +*   ​RTS ​     $60       PC <- (Stack) ​             (Implied) ​       1/6
 +*   ​ADC ​     $61       A <- (A) + M + C           ​(Ind,​X) ​         2/6
 +    JAM      $62       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    RRA      $63       M <- (M >> 1) + (A) + C    (Ind,​X) ​         2/8'5
 +    NOP      $64       [no operation] ​            ​(Z-Page) ​        2/3
 +*   ​ADC ​     $65       A <- (A) + M + C           ​(Z-Page) ​        2/3
 +*   ​ROR ​     $66       ​C<​-A0 & A<- (A7=C + A>>​1) ​ (Z-Page) ​        2/5
 +    RRA      $67       M <- (M >> 1) + (A) + C    (Z-Page) ​        ​2/​5'​5
 +*   ​PLA ​     $68       A <- (Stack) ​              ​(Implied) ​       1/4
 +*   ​ADC ​     $69       A <- (A) + M + C           ​(Immediate) ​     2/2
 +*   ​ROR ​     $6A       ​C<​-A0 & A<- (A7=C + A>>​1) ​ (Accumalator) ​   1/2
 +    ARR      $6B       A <- [(A /\ M) >> 1]       ​(Immediate) ​     1/2'5
 +*   ​JMP ​     $6C       PC <- Address ​             (Indirect) ​      3/5
 +*   ​ADC ​     $6D       A <- (A) + M + C           ​(Absolute) ​      3/4
 +*   ​ROR ​     $6E       ​C<​-A0 & A<- (A7=C + A>>​1) ​ (Absolute) ​      ​3/​6 ​
 +    RRA      $6F       M <- (M >> 1) + (A) + C    (Absolute) ​      ​3/​6'​5
 +*   ​BVS ​     $70       if V=1, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​ADC ​     $71       A <- (A) + M + C           ​((Ind),​Y) ​       2/5'1
 +    JAM      $72       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    RRA      $73       M <- (M >> 1) + (A) + C    ((Ind),​Y) ​       2/8'5
 +    NOP      $74       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​ADC ​     $75       A <- (A) + M + C           ​(Z-Page,​X) ​      2/4
 +*   ​ROR ​     $76       ​C<​-A0 & A<- (A7=C + A>>​1) ​ (Z-Page,​X) ​      2/6
 +    RRA      $77       M <- (M >> 1) + (A) + C    (Z-Page,​X) ​      ​2/​6'​5
 +*   ​SEI ​     $78       I <- 1                     ​(Implied) ​       1/2
 +*   ​ADC ​     $79       A <- (A) + M + C           ​(Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $7A       [no operation] ​            ​(Implied) ​       1/2
 +    RRA      $7B       M <- (M >> 1) + (A) + C    (Absolute,​Y) ​    ​3/​7'​5
 +    NOP      $7C       [no operation] ​            ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​ADC ​     $7D       A <- (A) + M + C           ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​ROR ​     $7E       ​C<​-A0 & A<- (A7=C + A>>​1) ​ (Absolute,​X) ​    3/7
 +    RRA      $7F       M <- (M >> 1) + (A) + C    (Absolute,​X) ​    ​3/​7'​5 ​
 +    NOP      $80       [no operation] ​            ​(Immediate) ​     2/2
 +*   ​STA ​     $81       M <- (A)                   ​(Ind,​X) ​         2/6
 +    NOP      $82       [no operation] ​            ​(Immediate) ​     2/2
 +    SAX      $83       M <- (A) /\ (X)            (Ind,​X) ​         2/6
 +*   ​STY ​     $84       M <- (Y)                   ​(Z-Page) ​        2/3
 +*   ​STA ​     $85       M <- (A)                   ​(Z-Page) ​        2/3
 +*   ​STX ​     $86       M <- (X)                   ​(Z-Page) ​        2/3
 +    SAX      $87       M <- (A) /\ (X)            (Z-Page) ​        ​2/​3 ​
 +*   ​DEY ​     $88       Y <- (Y) - 1               ​(Implied) ​       1/2
 +    NOP      $89       [no operation] ​            ​(Immediate) ​     2/2
 +*   ​TXA ​     $8A       A <- (X)                   ​(Implied) ​       1/2
 +    ANE      $8B       M <​-[(A)\/​$EE] /\ (X)/\(M) (Immediate) ​     2/2^4
 +*   ​STY ​     $8C       M <- (Y)                   ​(Absolute) ​      3/4
 +*   ​STA ​     $8D       M <- (A)                   ​(Absolute) ​      3/4
 +*   ​STX ​     $8E       M <- (X)                   ​(Absolute) ​      ​3/​4 ​
 +    SAX      $8F       M <- (A) /\ (X)            (Absolute) ​      3/4
 +*   ​BCC ​     $90       if C=0, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​STA ​     $91       M <- (A)                   ​((Ind),​Y) ​       2/6
 +    JAM      $92       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    SHA      $93       M <- (A) /\ (X) /\ (PCH+1) (Absolute,​X) ​    ​3/​6'​3
 +*   ​STY ​     $94       M <- (Y)                   ​(Z-Page,​X) ​      2/4
 +*   ​STA ​     $95       M <- (A)                   ​(Z-Page,​X) ​      2/4
 +    SAX      $97       M <- (A) /\ (X)            (Z-Page,​Y) ​      2/4
 +*   ​STX ​     $96       M <- (X)                   ​(Z-Page,​Y) ​      2/4
 +*   ​TYA ​     $98       A <- (Y)                   ​(Implied) ​       1/2
 +*   ​STA ​     $99       M <- (A)                   ​(Absolute,​Y) ​    3/5
 +*   ​TXS ​     $9A       S <- (X)                   ​(Implied) ​       1/2
 +    SHS      $9B       X <- (A) /\ (X), S <- (X)  (Absolute,​Y) ​    3/5
 +                       M <- (X) /\ (PCH+1) ​     ​
 +    SHY      $9C       M <- (Y) /\ (PCH+1) ​       (Absolute,​Y) ​    ​3/​5'​3
 +*   ​STA ​     $9D       M <- (A)                   ​(Absolute,​X) ​    3/5
 +    SHX      $9E       M <- (X) /\ (PCH+1) ​       (Absolute,​X) ​    ​3/​5'​3
 +    SHA      $9F       M <- (A) /\ (X) /\ (PCH+1) (Absolute,​Y) ​    ​3/​5'​3
 +*   ​LDY ​     $A0       Y <- M                     ​(Immediate) ​     2/2
 +*   ​LDA ​     $A1       A <- M                     ​(Ind,​X) ​         2/6
 +*   ​LDX ​     $A2       X <- M                     ​(Immediate) ​     2/2
 +    LAX      $A3       A <- M, X <- M             ​(Ind,​X) ​         2/6
 +*   ​LDY ​     $A4       Y <- M                     ​(Z-Page) ​        2/3
 +*   ​LDA ​     $A5       A <- M                     ​(Z-Page) ​        2/3
 +*   ​LDX ​     $A6       X <- M                     ​(Z-Page) ​        2/3
 +    LAX      $A7       A <- M, X <- M             ​(Z-Page) ​        2/3
 +*   ​TAY ​     $A8       Y <- (A)                   ​(Implied) ​       1/2
 +*   ​LDA ​     $A9       A <- M                     ​(Immediate) ​     2/2
 +*   ​TAX ​     $AA       X <- (A)                   ​(Implied) ​       1/2
 +    LXA      $AB       X04 <- (X04) /\ M04        (Immediate) ​     1/2
 +                       A04 <- (A04) /\ M04
 +*   ​LDY ​     $AC       Y <- M                     ​(Absolute) ​      3/4
 +*   ​LDA ​     $AD       A <- M                     ​(Absolute) ​      3/4
 +*   ​LDX ​     $AE       X <- M                     ​(Absolute) ​      3/4
 +    LAX      $AF       A <- M, X <- M             ​(Absolute) ​      3/4
 +*   ​BCS ​     $B0       if C=1, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​LDA ​     $B1       A <- M                     ​((Ind),​Y) ​       2/5'1
 +    JAM      $B2       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    LAX      $B3       A <- M, X <- M             ​((Ind),​Y) ​       2/5'1
 +*   ​LDY ​     $B4       Y <- M                     ​(Z-Page,​X) ​      2/4
 +*   ​LDA ​     $B5       A <- M                     ​(Z-Page,​X) ​      2/4
 +*   ​LDX ​     $B6       X <- M                     ​(Z-Page,​Y) ​      2/4
 +    LAX      $B7       A <- M, X <- M             ​(Z-Page,​Y) ​      2/4
 +*   ​CLV ​     $B8       V <- 0                     ​(Implied) ​       1/2
 +*   ​LDA ​     $B9       A <- M                     ​(Absolute,​Y) ​    ​3/​4'​1
 +*   ​TSX ​     $BA       X <- (S)                   ​(Implied) ​       1/2
 +    LAE      $BB       X,S,A <- (S /\ M)          (Absolute,​Y) ​    ​3/​4'​1
 +*   ​LDY ​     $BC       Y <- M                     ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​LDA ​     $BD       A <- M                     ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​LDX ​     $BE       X <- M                     ​(Absolute,​Y) ​    ​3/​4'​1
 +    LAX      $BF       A <- M, X <- M             ​(Absolute,​Y) ​    ​3/​4'​1
 +*   ​CPY ​     $C0       (Y - M) -> NZC             ​(Immediate) ​     2/2
 +*   ​CMP ​     $C1       (A - M) -> NZC             ​(Ind,​X) ​         2/6
 +    NOP      $C2       [no operation] ​            ​(Immediate) ​     2/2
 +    DCP      $C3       M <- (M)-1, (A-M) -> NZC   ​(Ind,​X) ​         2/8
 +*   ​CPY ​     $C4       (Y - M) -> NZC             ​(Z-Page) ​        2/3
 +*   ​CMP ​     $C5       (A - M) -> NZC             ​(Z-Page) ​        2/3
 +*   ​DEC ​     $C6       M <- (M) - 1               ​(Z-Page) ​        2/5
 +    DCP      $C7       M <- (M)-1, (A-M) -> NZC   ​(Z-Page) ​        2/5
 +*   ​INY ​     $C8       Y <- (Y) + 1               ​(Implied) ​       1/2
 +*   ​CMP ​     $C9       (A - M) -> NZC             ​(Immediate) ​     2/2
 +*   ​DEX ​     $CA       X <- (X) - 1               ​(Implied) ​       1/2
 +    SBX      $CB       X <- (X)/\(A) - M          (Immediate) ​     2/2
 +*   ​CPY ​     $CC       (Y - M) -> NZC             ​(Absolute) ​      3/4
 +*   ​CMP ​     $CD       (A - M) -> NZC             ​(Absolute) ​      3/4
 +*   ​DEC ​     $CE       M <- (M) - 1               ​(Absolute) ​      3/6
 +    DCP      $CF       M <- (M)-1, (A-M) -> NZC   ​(Absolute) ​      3/6
 +*   ​BNE ​     $D0       if Z=0, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​CMP ​     $D1       (A - M) -> NZC             ​((Ind),​Y) ​       2/5'1
 +    JAM      $D2       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    DCP      $D3       M <- (M)-1, (A-M) -> NZC   ​((Ind),​Y) ​       2/8
 +    NOP      $D4       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​CMP ​     $D5       (A - M) -> NZC             ​(Z-Page,​X) ​      2/4
 +*   ​DEC ​     $D6       M <- (M) - 1               ​(Z-Page,​X) ​      2/6
 +    DCP      $D7       M <- (M)-1, (A-M) -> NZC   ​(Z-Page,​X) ​      2/6
 +*   ​CLD ​     $D8       D <- 0                     ​(Implied) ​       1/2
 +*   ​CMP ​     $D9       (A - M) -> NZC             ​(Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $DA       [no operation] ​            ​(Implied) ​       1/2 
 +    DCP      $DB       M <- (M)-1, (A-M) -> NZC   ​(Absolute,​Y) ​    3/7
 +    NOP      $DC       [no operation] ​            ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​CMP ​     $DD       (A - M) -> NZC             ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​DEC ​     $DE       M <- (M) - 1               ​(Absolute,​X) ​    3/7
 +    DCP      $DF       M <- (M)-1, (A-M) -> NZC   ​(Absolute,​X) ​    3/7
 +*   ​CPX ​     $E0       (X - M) -> NZC             ​(Immediate) ​     2/2
 +*   ​SBC ​     $E1       A <- (A) - M - ~C          (Ind,​X) ​         2/6
 +    NOP      $E2       [no operation] ​            ​(Immediate) ​     2/2
 +    ISB      $E3       M <- (M) - 1,A <- (A)-M-~C (Ind,​X) ​         3/8'1
 +*   ​CPX ​     $E4       (X - M) -> NZC             ​(Z-Page) ​        2/3
 +*   ​SBC ​     $E5       A <- (A) - M - ~C          (Z-Page) ​        2/3
 +*   ​INC ​     $E6       M <- (M) + 1               ​(Z-Page) ​        2/5
 +    ISB      $E7       M <- (M) - 1,A <- (A)-M-~C (Z-Page) ​        ​2/​5  ​
 +*   ​INX ​     $E8       X <- (X) +1                (Implied) ​       1/2
 +*   ​SBC ​     $E9       A <- (A) - M - ~C          (Immediate) ​     2/2
 +*   ​NOP ​     $EA       [no operation] ​            ​(Implied) ​       1/2
 +    SBC      $EB       A <- (A) - M - ~C          (Immediate) ​     1/2
 +*   ​SBC ​     $ED       A <- (A) - M - ~C          (Absolute) ​      3/4
 +*   ​CPX ​     $EC       (X - M) -> NZC             ​(Absolute) ​      3/4
 +*   ​INC ​     $EE       M <- (M) + 1               ​(Absolute) ​      3/6
 +    ISB      $EF       M <- (M) - 1,A <- (A)-M-~C (Absolute) ​      3/6
 +*   ​BEQ ​     $F0       if Z=1, PC = PC + offset ​  ​(Relative) ​      ​2/​2'​2
 +*   ​SBC ​     $F1       A <- (A) - M - ~C          ((Ind),​Y) ​       2/5'1
 +    JAM      $F2       ​[locks up machine] ​        ​(Implied) ​       1/-
 +    ISB      $F3       M <- (M) - 1,A <- (A)-M-~C ((Ind),​Y) ​       2/8
 +    NOP      $F4       [no operation] ​            ​(Z-Page,​X) ​      2/4
 +*   ​SBC ​     $F5       A <- (A) - M - ~C          (Z-Page,​X) ​      2/4
 +*   ​INC ​     $F6       M <- (M) + 1               ​(Z-Page,​X) ​      2/6
 +    ISB      $F7       M <- (M) - 1,A <- (A)-M-~C (Z-Page,​X) ​      2/6
 +*   ​SED ​     $F8       D <- 1                     ​(Implied) ​       1/2
 +*   ​SBC ​     $F9       A <- (A) - M - ~C          (Absolute,​Y) ​    ​3/​4'​1
 +    NOP      $FA       [no operation] ​            ​(Implied) ​       1/2
 +    ISB      $FB       M <- (M) - 1,A <- (A)-M-~C (Absolute,​Y) ​    3/7
 +    NOP      $FC       [no operation] ​            ​(Absolute,​X) ​    ​3/​4'​1
 +*   ​SBC ​     $FD       A <- (A) - M - ~C          (Absolute,​X) ​    ​3/​4'​1
 +*   ​INC ​     $FE       M <- (M) + 1               ​(Absolute,​X) ​    3/7
 +    ISB      $FF       M <- (M) - 1,A <- (A)-M-~C (Absolute,​X) ​    3/7
 +
 +'1 - Add one if address crosses a page boundry.
 +'2 - Add 1 if branch succeeds, or 2 if into another page.
 +'3 - If page boundry crossed then PCH+1 is just PCH
 +'4 - Sources disputed on exact operation, or sometimes does not work.
 +'5 - Full eight bit rotation (with carry)
 +
 +Sources:
 +  Programming the 6502, Rodney Zaks, (c) 1983 Sybex
 +  Paul Ojala, Post to Comp.Sys.Cbm (po87553@cs.tut.fi / albert@cc.tut.fi)
 +  D John Mckenna, Post to Comp.Sys.Cbm (gudjm@uniwa.uwa.oz.au)
 +
 +Compiled by Craig Taylor (duck@pembvax1.pembroke.edu)
 +
 +</​code>​
 +====== Simple Hires Line Drawing Package for the C-128 80-Column Screen ======
 +<​code>​
 +Copyright (c) 1992 Craig Bruce <​csbruce@ccnga.uwaterloo.ca>​
 +
 +1. GRAPHICS PACKAGE OVERVIEW
 +
 +The graphics package this article explains is BLOADed into memory at address
 +$1300 on bank 15 and has three entry points:
 +
 +$1300 = move the pixel cursor or draw a line: .AX=x, .Y=y, .C=cmd
 +$1303 = activate graphics mode and clear the screen
 +$1306 = exit graphics mode and reload the character set
 +
 +To move the pixel cursor to the start point of a line, load the .AX registers
 +with the X coordinate (0-639), load the .Y register with the Y coordinate
 +(0-199), clear the carry flag, and call $1300. ​ (Make sure that Bank 15 is in
 +context). ​ This can be done in BASIC as follows:
 +
 +SYS 4864, X AND 255, X/256, Y, 0
 +
 +To draw a line from the pixel cursor location to a given point, load the .AX
 +and .Y registers like before, set the carry flag, and call $1300. ​ The pixel
 +cursor will then be set to the end point of the line just drawn, so you do not
 +have to set it again if you are drawing a continuous object (like a square).
 +
 +SYS 4864, X AND 255, X/256, Y, 1
 +
 +The activate and exit routines are called without any parameters and work very
 +simply. ​ You should be sure to call exit before returning to the program
 +editing mode or you will not be able to see what you are typing.
 +
 +A BASIC demonstration program is also included in the UU section for this
 +package. ​ It starts by putting the pixel cursor at the center of the screen
 +and then picks a random point to draw to, and repeats until you press a key
 +to stop it.  For an interesting effect, put a call to $1303 immediately before
 +the call to draw the line.
 +
 +The point plotting speed is about 4,100 pixels per second and the line drawing
 +speed is a bit slower than this because of all of the calculations that have
 +to be done to draw a line.  There are faster pixel plotting and line drawing
 +algorithms than the ones implemented here, but that is material for a future
 +article.
 +
 +2. INTRODUCTION TO THE VDC
 +
 +Programming the 8563 Video Display Controller is quite straight forward. ​ You
 +access it a bit indirectly, but it can still be done at relatively high speeds
 +using machine language. ​ The VDC contains 37 control registers and from 16K to
 +64K of dedicated display memory that is separate from the main processor. ​ The
 +memory must be accessed through the VDC registers.
 +
 +The important VDC registers for this exercise are:
 +
 +REG   ​BITS ​  DESC
 +---   ​---- ​  ----
 +$12   ​7-0 ​   VDC RAM address high byte
 +$13   ​7-0 ​   VDC RAM address low byte
 +$18   ​7 ​     Block copy / block fill mode select
 +$19   ​7 ​     Bitmap / Character mode select
 +$19   ​6 ​     Color / Monochrome mode select
 +$1a   ​7-4 ​   Foreground color
 +$1a   ​3-0 ​   Background color
 +$1e   ​7-0 ​   Copy / fill repetition count
 +$1f   ​7-0 ​   VDC RAM data read / write
 +
 +You access the VDC chip registers though addresses $D600 and $D601 on bank 15.
 +Location $D600 selects the VDC register to use on write and returns the VDC
 +status on read.  The only important status information is bit 7 (value $80)
 +which is the "​ready"​ flag.  The following two subroutines read or write the
 +value in .A to VDC register number .X:
 +
 +VdcRead: ​ stx $d600                  VdcWrite: stx $d600
 +WaitLoop: bit $d600                  WaitLoop: bit $d600
 +          bpl WaitLoop ​                        bpl WaitLoop
 +          lda $d601                            sta $d601
 +          rts                                  rts
 +
 +Once the current VDC register is selected at $d600, it remains selected. ​ You
 +may read or write it though $d601 as many times as you like as long as you
 +wait for the VDC to be "​ready"​ between accesses.
 +
 +In order to access the VDC RAM, you must first put the high and low bytes of
 +the VDC RAM address into registers $12 and $13 (high byte first) and then
 +read or write through register $1f to read or write the data in the VDC RAM.
 +After each access to register $1f, the VDC RAM address is incremented by one.
 +So, if you repeatedly read or write to register $1f you can read or write a
 +chunk of VDC memory very quickly.
 +
 +3. ENTERING GRAPHICS MODE
 +
 +Activating the graphics mode of the VDC is very simple - you just have to set
 +bit 7 of VDC register $19 and poof!  You should also clear bit 6 of that
 +register to disable the character color mode.  This graphics package supports
 +only monochrome graphics since the standard 16K VDC does not have enough space
 +to hold both the bitmap and the 8*8 pixel cell attributes. ​ The 640*200 pixel
 +display takes 128,000 bits or 16,000 bytes. ​ This leaves 384 bytes of VDC RAM
 +that is not needed by the bitmap but it is not large enough to do anything
 +with, so it is wasted.
 +
 +When you disable the character color mode, the VDC takes its foreground and
 +background color values from register $1a.  The foreground color is what color
 +the "​1"​ bits in the bitmap will be displayed in and the background color, the
 +"​0"​ bits.
 +
 +Now that the bitmap mode is set up, we must clear the VDC memory locations 0
 +to 15999 (decimal) to clear the bitmap screen. ​ This can be done very quickly
 +using the VDC fill mode.  If you poke a value into VDC register number $1e,
 +the VDC will fill its memory from the location currently in the VDC RAM
 +address registers for the number of bytes you just poked into register $1e
 +with the value that you last poked into the VDC RAM data register. ​ (This is
 +assuming that "​fill"​ mode is selected in register $18).  If you poke a 0 into
 +the repeat register it means to fill 256 bytes.
 +
 +So, to clear the bitmap, poke a zero into both of the VDC RAM address
 +registers since the bitmap starts at location 0.  Then poke a value of 0 into
 +VDC RAM data register. ​ This sets the fill value to 0 and pokes the first VDC
 +RAM location. ​ Then, go into a loop and put a zero into the VDC repeat
 +register 63 times. ​ This will fill 63 contiguous chunks of 256 bytes each.
 +We end up filling 16,129 bytes, but that is not a problem since we have 384
 +"​safety"​ bytes at the end of the bitmap. ​ Internally, the VDC will fill its
 +memory at a rate of about 1 Megabyte per second (if I remember my test results
 +correctly), so clearing the screen is a PDFQ operation.
 +
 +4. EXITING GRAPHICS MODE
 +
 +To exit from graphics mode we have to reload the character set from the ROM
 +on bank 14 and we have to go back into character mode and clear the text
 +screen. ​ The kernel provides its own character reload routine so I used that.
 +The only problem with it is that it is a lot slower than it has to be.  It
 +takes about 0.45 seconds whereas the same job can be done in about 0.09
 +seconds. ​ The kernel is so slow because it uses the kernel INDFETCH nonsense.
 +
 +Then you just set the bitmap mode bit to zero and the character color mode to
 +one.  This gets you back to normal character mode.  You also have to clear the
 +text screen since it will be filled with garbage from the graphing.
 +
 +5. POINT PLOTTING
 +
 +The pixels on the screen accessed by their X and Y coordinates,​ 0 <= X <= 639,
 +0 <= Y <= 199.  The formula to calculate the byte address in the VDC RAM given
 +the X and Y coordinates is made simple by the mapping of bytes to the pixels
 +on the screen. ​ The bytes of VDC memory go across the screen rather than in
 +8*8 cells like the VIC screen. ​ Each pixel row is defined by 80 consecutive
 +bytes of VDC RAM.
 +
 +The formula for the byte address of a pixel is: AD=Y*80+INT(X/​8),​ and the
 +formula for the bit number is simply BI=X AND 7.  The bit number can be used
 +as an index into a table of bit values: [$80,​$40,​$20,​$10,​$08,​$04,​$02,​$01],​
 +such that index 0 contains $80, since the highest bit is the leftmost bit.
 +
 +Calculating the bit number and looking up the bit value is very easy to do in
 +machine language, but the byte address calculation requires a little more
 +work.  First we have to multiply the Y value by 80, using a 16-bit word for
 +storage. ​ This is done by shifting the Y value left twice, adding the original
 +Y value, and shifting left four more times. ​ Then we have to shift the X value
 +right by three using a 16-bit word for storage to get INT(X/8), and we add the
 +two results together and we have the byte address.
 +
 +To plot the point, we have to peek into the VDC RAM at the byte address to see
 +what is "​behind"​ the pixel we want to plot.  Then OR the new bit value on to
 +the "​background"​ value and poke the result back into VDC RAM at the byte
 +address. ​ Unfortunately,​ since the VDC RAM address register auto-increments
 +after each reference, we will have to set it twice - once for the read and
 +once for the write. ​ That means that the VDC registers have to be accessed six
 +times for each pixel. ​ Fortunately,​ the VDC operates at its highest speed in
 +monochrome bitmap mode (it has less work to do than in color character mode,
 +so it is able to pay more attention to the CPU).
 +
 +Effects other than just plotting the point can be achieved by using functions
 +other than OR to put the point on the background. ​ EOR would "​flip"​ the pixel,
 +and AND-NOT (achieved by LDA bitval : EOR #$ff : AND background) would erase
 +the pixel.
 +
 +6. LINE DRAWING
 +
 +The line drawing routine that is implemented in the package is given by the
 +following BASIC code (in fact, I programmed it in BASIC first to get it
 +working; of course, the BASIC version is as slow as hell):
 +
 +10 dx=x-lx:​dy=y-ly
 +20 if abs(dx)>​abs(dy) then begin r=dx:​gy=dy/​abs(dx):​gx=sgn(dx)
 +30 bend:else r=dy:​gx=dx/​abs(dy):​gy=sgn(dy)
 +40 px=lx+0.5:​py=ly+0.5
 +50 fori=1to abs(r): <PLOT PX,PY> :​px=px+gx:​py=py+gy:​next
 +60 lx=x:ly=y
 +
 +This implements the Basic Incremental Algorithm for raster line drawing. ​ The
 +"​lx"​ and "​ly"​ are the position of the pixel cursor and "​x"​ and "​y"​ are the
 +coordinates to draw the line to.  The "​dx"​ and "​dy"​ are the differences in the
 +X and Y directions. ​ The idea is that we will increment the pixel cursor by
 +a constant of 1 in one direction and by a fraction 0.0 <= g <= 1.0 in the
 +other direction. ​ This fraction is actually the slope of the line.
 +
 +Lines 20 and 30 figure out the increments for the X and Y directions ("​gx"​ and
 +"​gy"​). ​ These are signed fractional numbers on the range -1.0 <= g <= 1.0.
 +We check the "​dx"​ and "​dy"​ to see which has the greatest absolute value and
 +that will be the direction that is incremented by 1, 0, or -1 and the other
 +direction will increment by the (fractional) slope of the line with respect to
 +the other direction.
 +
 +Line 40 starts the plotting at the current pixel cursor location PLUS 0.5.  We
 +add 1/2 to the X and Y positions to "​center"​ onto the pixel cell.  If we
 +didn't do this, we would notice dis-symmetry in plotting to the left and to
 +the right. ​ For example, 50.0 - 0.3 = 49.7 and 50.0 + 0.3 = 50.3.  If we
 +truncate these values, going left by 0.3 moves us to position 49 whereas going
 +right by 0.3 makes us stay in the same position. ​ This is dis-symmetry and
 +makes plots look a bit off.  Adding 0.5 corrects the problem.
 +
 +Line 50 goes into a loop for the longest dimension of the line (the one
 +incremented by 1).  The <PLOT PX,PY> is not exactly BASIC; you substitute
 +the call to the point plot routine described in the previous section. ​ It
 +repeatedly adds the X and Y increment values until the line is finished.
 +This algorithm draws the line in the direction that your end points imply.
 +
 +6.1. FRACTIONAL NUMBER REPRESENTATION
 +
 +There are only two real complications to the machine language implementation
 +are the representation of the signed fractional numbers and the division of
 +the fractional numbers. ​ To represent the numbers I use a 32-bit format with
 +a 16-bit signed integer portion (-32768 to +32767) and a 16-bit fractional
 +portion (0.0 to 0.99998474 in 0.00001526 increments). ​ The weight values of
 +the bit positions are as follows:
 +
 +POS     31... 22 21 20 19 18 17 16  15  14  13  12    11   ​10 ​    9 ...      0
 +VAL -32768... 64 32 16  8  4  2  1 1/2 1/4 1/8 1/16 1/32 1/64 1/128 ...1/65536
 +
 +For example, 0...00001011101.10011010000...0 (notice the BINARY point) is
 +64 + 16 + 8 + 4 + 1 + 1/2 + 1/16 + 1/32 + 1/128 = 93.6015625 in decimal. ​ Or,
 +as a short cut, you can consider the integer 16 bits and the fractional 16
 +bits as independent words and add 1/65536th of the second to the first. ​ Thus,
 +for the example above, the quantity is 93 + (32768+4096+2048+512)/​65536 =
 +93.6015625. ​ (Good, they both match). ​ The first calculation uses true base 2
 +whereas the second calculation uses base 65536.
 +
 +Two's complement representation is used to achieve signedness (,​Park!). ​ We
 +should all know about two's comp.  Well, it works just fine for fractional
 +binary numbers as well.  In fact, it makes no difference at all.  You can just
 +think of the quantity as an integer number of 65536ths of a pixel and you get
 +the integer operations of complement, add, and subtract for free.  The easy
 +way to get the two's comp. representation of a number is to take the positive
 +binary image of the number and subtract it from 0 (this makes perfect sense
 +since 0 - x = -x).
 +
 +Fractional binary division is a little more complicated. ​ There is no problem
 +with the binary point, since the laws of mathematics say we can multiply the
 +top and bottom by the same quantity (like 65536) without changing the result,
 +but handling the two's complement is a problem. ​ What I did was figure out
 +what the sign of the result of the division was going to be (by EORing the
 +sign bits together) and then converted the two operands to their positive
 +value if they were originally negative. ​ This lets me perform a 32-bit
 +unsigned division operation and then I convert the result to a negative if the
 +result is supposed to be negative. ​ The 32-bit divide is not all that
 +complicated;​ it is done the same way that you would do it on paper (remember
 +those days) except you use binary digits. ​ The divide subroutine does not
 +exactly rival supercomputer speeds, but it does get the job done.
 +
 +6.2. MACHINE LANGUAGE OPERATION
 +
 +While drawing the line, the X and Y coordinates are 32-bit signed fractional
 +numbers as well as the "​gx"​ and "​gy"​ vector components ("​go"​ values). ​ Lines
 +20 and 30 require quite a bit of work in 6502 machine language and use the
 +32-bit add, subtract, 2's complement, and divide operations described in the
 +previous section. ​ To find the ABSolute value of a number, check to see
 +whether it is positive or negative. ​ If it is positive, you are done.  If it
 +is negative, just do a 2's complement on it (makes sense: 0 - (-x) = x).
 +
 +Line 40 is done by simply taking the pixel cursor X and Y coordinates (which
 +are stored as unsigned integers and are remembered between line draw calls)
 +and put them into the high word of a 32-bit field and then put $8000 (32768)
 +into the low word (which gives V + 1/2 (or V + 32768/​65536)).
 +
 +Line 50 is easily implemented as a loop that decrements the "​r"​ word until it
 +reaches zero, while calling the point plot routine and doing the 32-bit add to
 +add the "​g"​ values to the X and Y coordinates. ​ When the line is finished, the
 +final X and Y coordinates are put back into the pixel cursor position storage
 +and the package is ready for the next call.
 +
 +7. CONCLUSION
 +
 +Ha!  This ain't no formal paper so I don't have to write a conclusion.
 +So there! [Ed.Note - He is currently working on his Masters thesis, so you'll
 +have to pardon 'im here.. (grin) ]
 +
 +================================================================================
 +begin 640 hires80.bin
 +M`!-,​`15,​$1-,​2!-,​$!-,​$!.S8*D`C0#​_J>"​B&​B#,​S:​F'​HAD@S,​VI`*(2(,​S-
 +MZ"#,​S:​D`(,​K-J2"​B&"#,​S:​D`HAZ@/​R#,​S8C0^F`@#,​ZIDR#​2_Z(9J4=,​S,​V$
 +M^H7\F*``A/​L*)OL*)OL89?​J0`N;​["​B;​["​B;​["​B;​["​B;​[A?​JE_(;​]1OUJ1OUJ
 +M1OUJ&&​7ZA?​JE_67[A?​NE_"​D'​JKV>​$X7\8(!`(!`(!`(!```@5Q.E^Z(2(,​S-
 +MI?​KH(,​S-(-C-!?​RHI?​NB$B#,​S:​7ZZ"#,​S9A,​RLVI`(5DA66%9H5GA5*%4X54
 +MHB`&​8"​9A)F(F8R92)E,​F5*54T`JE4L50I5/​E49`1.*52Y5"​%4J53Y5&​%4[`"​
 +MQE0F9"​9E)F8F9\K0R&"​$4*90$!`XA5"​I`.502(10J0#​E4*AH8$BI`(5@A6$@
 +MSQ-H$!DXJ0#​E9(5DJ0#​E985EJ0#​E9H5FJ0#​E9X5G8*4,​I`T@&​A2%^H3[I1"​D
 +M$2`:​%(7\A/​VE_,​7ZI?​WE^[!$I?​J%$H50I?​N%$X51I?​R%8J7]A6.E$2`Q%*(#​
 +MM625#​LH0^:​4-,​`JI`(4-J0&​%#​-`&​J?​^%#​84,​.*D`Y1*%$JD`Y1.%$V"​E_(42
 +MA5"​E_843A5&​E^H5BI?​N%8Z4-(#​$4H@.U9)4*RA#​Y3.H4+/​__+/​__+/​__I1$P
 +M"​JD`A1&​I`840T`:​I_X41A1!,​KA2P!X6+AHR$C6"​%!(8%A`BB!ZD`E0K*$/​LX
 +MI03EBX4,​I07EC(4-.*4(Y8V%$*D`L`*I_X41(%@4I8N%!*6,​A06I@(4#​A0>​I
 +M`(4"​A0:​EC84(J0"​%":​4$I@6D"""​H$Z42!1/​P.QBE`F4*A0*E`V4+A0.E!&​4,​
 +MA02E!64-A048I09E#​H4&​I0=E#​X4'​I0AE$(4(I0EE$84)YA+0N^833%05I02F
 +&​!:​0(3`,​5
 +`
 +end
 +================================================================================
 +begin 640 hires.demo
 +M`1PQ'&​0`BR#"​*-$H(C$S,​$8B*2D@L[$@T2@B0C,​B*2"​G(/​X1(DA)4D53.#​`N
 +M0DE.(@!!'&​X`GB#​1*"​(Q,​S`S(BD`4AQX`$12LM$H(C$S,#​`B*0!S'​((`GB!$
 +M4BPS,​C`@KR`R-34L,​S(PK3(U-BPQ,#​`L,​`"​%'​(P`6+*U*+LH,​2FL-C0P*0"​7
 +M'​)8`6;​*U*+LH,​2FL,​C`P*0"​R'​*``GB!$4BQ8(*\@,​C4U+%BM,​C4V+%DL,​0"​[
 +L'​*H`H2!!)`#​-'​+0`BR!!)+(B(B"​G(#​$T,​`#​='​+X`GB#​1*"​(Q,​S`V(BD```"​[
 +`
 +end
 +==============================================================================
 +;​*****************************************************************************
 +;*  "​HIRES80.BIN"​ hires line plotting package for the Commodore 128 80-col ​  *
 +;*  screen. ​                                                                 *
 +;*                                                                           *
 +;*  This package contains a couple of irregularities that I discovered ​      *
 +;*  while I was commenting it.  I left them in rather than start all over,   *
 +;*  since this package was written with a monitor rather than an assembler. ​ *
 +;​*****************************************************************************
 +
 +;​*****************************************************************************
 +;*  package entry points ​                                                    *
 +;​*****************************************************************************
 +
 +.$1300 ​ [4c 01 15]  jmp $1501     ;jmp to draw line/​position pixel cursor
 +.$1303 ​ [4c 11 13]  jmp $1311     ;jmp to enter hires mode
 +.$1306 ​ [4c 48 13]  jmp $1348     ;jmp to exit hires mode
 +.$1309 ​ [4c 10 13]  jmp $1310     ;​reserved
 +.$130c ​ [4c 10 13]  jmp $1310     ;​reserved
 +.$130f: $b3                       ;​library loaded identifier
 +.$1310 ​ [60      ]  rts
 +
 +;​*****************************************************************************
 +;*  enter hires mode                                                         *
 +;​*****************************************************************************
 +
 +.$1311 ​ [a9 00   ​] ​ lda #$00      ;switch to bank 15 (kernal bank)
 +.$1313 ​ [8d 00 ff]  sta $ff00
 +.$1316 ​ [a9 e0   ​] ​ lda #$e0      ;set color to light grey on black
 +.$1318 ​ [a2 1a   ​] ​ ldx #$1a
 +.$131a ​ [20 cc cd]  jsr $cdcc     ; ROM routine to write VDC register
 +.$131d ​ [a9 87   ​] ​ lda #$87      ;enter bitmap mode (note - for version 2 VDC)
 +.$131f ​ [a2 19   ​] ​ ldx #$19
 +.$1321 ​ [20 cc cd]  jsr $cdcc
 +.$1324 ​ [a9 00   ​] ​ lda #$00      ;set VDC RAM address high
 +.$1326 ​ [a2 12   ​] ​ ldx #$12
 +.$1328 ​ [20 cc cd]  jsr $cdcc
 +.$132b ​ [e8      ]  inx           ;set VDC RAM address low
 +.$132c ​ [20 cc cd]  jsr $cdcc
 +.$132f ​ [a9 00   ​] ​ lda #$00      ;set VDC RAM data register to $00
 +.$1331 ​ [20 ca cd]  jsr $cdca
 +.$1334 ​ [a9 20   ​] ​ lda #$20      ;select block fill mode
 +.$1336 ​ [a2 18   ​] ​ ldx #$18
 +.$1338 ​ [20 cc cd]  jsr $cdcc
 +.$133b ​ [a9 00   ​] ​ lda #$00      ;fill 256*63 VDC bytes with 0
 +.$133d ​ [a2 1e   ​] ​ ldx #$1e      ;  to clear the hires screen
 +.$133f ​ [a0 3f   ​] ​ ldy #$3f
 +.$1341 ​ [20 cc cd]  jsr $cdcc
 +.$1344 ​ [88      ]  dey
 +.$1345 ​ [d0 fa   ​] ​ bne $1341
 +.$1347 ​ [60      ]  rts
 +
 +;​*****************************************************************************
 +;*  exit hires mode                                                          *
 +;​*****************************************************************************
 +
 +.$1348 ​ [20 0c ce]  jsr $ce0c     ;​reload the character sets
 +.$134b ​ [a9 93   ​] ​ lda #$93      ;clear the text screen
 +.$134d ​ [20 d2 ff]  jsr $ffd2
 +.$1350 ​ [a2 19   ​] ​ ldx #$19      ;restore color text mode
 +.$1352 ​ [a9 47   ​] ​ lda #$47
 +.$1354 ​ [4c cc cd]  jmp $cdcc
 +
 +;​*****************************************************************************
 +;*calculate the bitmap byte address and bit value for pixel given x=.AX,y=.Y *
 +;​*****************************************************************************
 +
 +.$1357 ​ [84 fa   ​] ​ sty $fa       ;save .A and .Y
 +.$1359 ​ [85 fc   ​] ​ sta $fc
 +.$135b ​ [98      ]  tya           ;put pixel cursor y position into .A
 +.$135c ​ [a0 00   ​] ​ ldy #$00      ;clear pixel cursor y position high byte
 +.$135e ​ [84 fb   ​] ​ sty $fb
 +.$1360 ​ [0a      ]  asl a         ;​multiply pixel cursor y by 2 giving y*2
 +.$1361 ​ [26 fb   ​] ​ rol $fb       ; ​ and we must shift the high byte to
 +.$1363 ​ [0a      ]  asl a         ;​again,​ giving y*4
 +.$1364 ​ [26 fb   ​] ​ rol $fb
 +.$1366 ​ [18      ]  clc           ;add the original y, giving y*5
 +.$1367 ​ [65 fa   ​] ​ adc $fa
 +.$1369 ​ [90 02   ​] ​ bcc $136d
 +.$136b ​ [e6 fb   ​] ​ inc $fb
 +.$136d ​ [0a      ]  asl a         ;​multiply by 2 again, giving y*10
 +.$136e ​ [26 fb   ​] ​ rol $fb
 +.$1370 ​ [0a      ]  asl a         ;​again,​ giving y*20
 +.$1371 ​ [26 fb   ​] ​ rol $fb
 +.$1373 ​ [0a      ]  asl a         ;​again,​ giving y*40
 +.$1374 ​ [26 fb   ​] ​ rol $fb
 +.$1376 ​ [0a      ]  asl a         ;​again,​ giving y*80: ha!  we are done
 +.$1377 ​ [26 fb   ​] ​ rol $fb
 +.$1379 ​ [85 fa   ​] ​ sta $fa       ;save low byte of y*80
 +.$137b ​ [a5 fc   ​] ​ lda $fc       ;​restore x coordinate low byte
 +.$137d ​ [86 fd   ​] ​ stx $fd       ;set up x coordinate high byte
 +.$137f ​ [46 fd   ​] ​ lsr $fd       ;​divide the x coordinate by 2 giving x/2
 +.$1381 ​ [6a      ]  ror a         ; ​ we must ror the high byte, then the low
 +.$1382 ​ [46 fd   ​] ​ lsr $fd       ;​again,​ giving x/4
 +.$1384 ​ [6a      ]  ror a
 +.$1385 ​ [46 fd   ​] ​ lsr $fd       ;​again,​ giving x/8: done
 +.$1387 ​ [6a      ]  ror a
 +.$1388 ​ [18      ]  clc           ;now add y*80 and x/8
 +.$1389 ​ [65 fa   ​] ​ adc $fa
 +.$138b ​ [85 fa   ​] ​ sta $fa
 +.$138d ​ [a5 fd   ​] ​ lda $fd
 +.$138f ​ [65 fb   ​] ​ adc $fb
 +.$1391 ​ [85 fb   ​] ​ sta $fb       ;​giving us the pixel byte address in ($fa)
 +.$1393 ​ [a5 fc   ​] ​ lda $fc       ;get x mod 8
 +.$1395 ​ [29 07   ​] ​ and #$07      ;  ha! we can just extract the low three bits
 +.$1397 ​ [aa      ]  tax
 +.$1398 ​ [bd 9e 13]  lda $139e,​x ​  ;look up the bit value in the table
 +.$139b ​ [85 fc   ​] ​ sta $fc       ; ​ and save it at $fc
 +.$139d ​ [60      ]  rts           ;exit with address in ($fa) and value in $fc
 +
 +;​*****************************************************************************
 +;*  bit value table                                                          *
 +;​*****************************************************************************
 +
 +.$139e: $80  $40  $20  $10        ;bit values stored left to right
 +.$13a2: $08  $04  $02  $01
 +
 +.$13a6 ​ [00      ]  brk           ;​filler - I forget why I put it here
 +.$13a7 ​ [00      ]  brk
 +
 +;​*****************************************************************************
 +;*  plot pixel at x=.AX, y=.Y on bitmap screen ​                              *
 +;​*****************************************************************************
 +
 +.$13a8 ​ [20 57 13]  jsr $1357     ;​calculate the pixel address and value
 +.$13ab ​ [a5 fb   ​] ​ lda $fb       ;set VDC RAM address high to pixel address
 +.$13ad ​ [a2 12   ​] ​ ldx #$12
 +.$13af ​ [20 cc cd]  jsr $cdcc
 +.$13b2 ​ [a5 fa   ​] ​ lda $fa       ;set VDC RAM address low to pixel address
 +.$13b4 ​ [e8      ]  inx
 +.$13b5 ​ [20 cc cd]  jsr $cdcc
 +.$13b8 ​ [20 d8 cd]  jsr $cdd8     ;peek the VDC RAM address
 +.$13bb ​ [05 fc   ​] ​ ora $fc       ;OR on the new pixel value
 +.$13bd ​ [a8      ]  tay           ; ​ and save the result (byte to poke back)
 +.$13be ​ [a5 fb   ​] ​ lda $fb       ;​reset the VDC RAM address to the pixel
 +.$13c0 ​ [a2 12   ​] ​ ldx #$12      ;  address; this is necessary since the
 +.$13c2 ​ [20 cc cd]  jsr $cdcc     ; ​ VDC will increment its RAM address on
 +.$13c5 ​ [a5 fa   ​] ​ lda $fa       ; ​ every access
 +.$13c7 ​ [e8      ]  inx
 +.$13c8 ​ [20 cc cd]  jsr $cdcc
 +.$13cb ​ [98      ]  tya
 +.$13cc ​ [4c ca cd]  jmp $cdca     ;and poke the new pixel byte value
 +
 +;​*****************************************************************************
 +;*  perform the unsigned 32-bit divide with 16-bit denominator (bottom) ​     *
 +;*    [$63 $62 $61 $60] is the numerator (top)                               *
 +;*            [$51 $50] is the denominator (bottom) ​                         *
 +;*    [$67 $66 $65 $64] is the quotient (result) ​                            *
 +;*        [$54 $53 $52] is the remainder ​                                    *
 +;​*****************************************************************************
 +
 +.$13cf ​ [a9 00   ​] ​ lda #$00      ;set the result to 0
 +.$13d1 ​ [85 64   ​] ​ sta $64
 +.$13d3 ​ [85 65   ​] ​ sta $65
 +.$13d5 ​ [85 66   ​] ​ sta $66
 +.$13d7 ​ [85 67   ​] ​ sta $67
 +
 +.$13d9 ​ [85 52   ​] ​ sta $52       ;​clear the remainder
 +.$13db ​ [85 53   ​] ​ sta $53
 +.$13dd ​ [85 54   ​] ​ sta $54
 +
 +.$13df ​ [a2 20   ​] ​ ldx #$20      ;set the loop count to 32 bits
 +.$13e1 ​ [06 60   ​] ​ asl $60       ;​shift out the high bit of the numerator
 +.$13e3 ​ [26 61   ​] ​ rol $61
 +.$13e5 ​ [26 62   ​] ​ rol $62
 +.$13e7 ​ [26 63   ​] ​ rol $63
 +.$13e9 ​ [26 52   ​] ​ rol $52       ;​shift it into the remainder
 +.$13eb ​ [26 53   ​] ​ rol $53
 +.$13ed ​ [26 54   ​] ​ rol $54
 +.$13ef ​ [a5 54   ​] ​ lda $54       ;​check if the remainder is >= the denominator
 +.$13f1 ​ [d0 0a   ​] ​ bne $13fd
 +.$13f3 ​ [a5 52   ​] ​ lda $52
 +.$13f5 ​ [c5 50   ​] ​ cmp $50
 +.$13f7 ​ [a5 53   ​] ​ lda $53
 +.$13f9 ​ [e5 51   ​] ​ sbc $51
 +.$13fb ​ [90 11   ​] ​ bcc $140e     ;if not, go to next bit
 +.$13fd ​ [38      ]  sec           ;​subract the denominator from the remainder
 +.$13fe ​ [a5 52   ​] ​ lda $52
 +.$1400 ​ [e5 50   ​] ​ sbc $50
 +.$1402 ​ [85 52   ​] ​ sta $52
 +.$1404 ​ [a5 53   ​] ​ lda $53
 +.$1406 ​ [e5 51   ​] ​ sbc $51
 +.$1408 ​ [85 53   ​] ​ sta $53
 +.$140a ​ [b0 02   ​] ​ bcs $140e
 +.$140c ​ [c6 54   ​] ​ dec $54
 +.$140e ​ [26 64   ​] ​ rol $64       ;​shift a "​1"​ bit into the quotient. ​ Note
 +.$1410 ​ [26 65   ​] ​ rol $65       ; ​ the first "​rol"​ should have been preceeded
 +.$1412 ​ [26 66   ​] ​ rol $66       ; ​ by a "​sec";​ this is a BUG!  However, it
 +.$1414 ​ [26 67   ​] ​ rol $67       ; ​ will fail only if denom >=32768 which
 +                                  ;  cannot happen in this application.
 +.$1416 ​ [ca      ]  dex           ;go on to the next bit
 +.$1417 ​ [d0 c8   ​] ​ bne $13e1
 +.$1419 ​ [60      ]  rts
 +
 +;​*****************************************************************************
 +;*  get the absolute value of the 2's comp number in .AY -> .AY              *
 +;​*****************************************************************************
 +
 +.$141a ​ [84 50   ​] ​ sty $50
 +.$141c ​ [a6 50   ​] ​ ldx $50
 +.$141e ​ [10 10   ​] ​ bpl $1430     ;if the number is positive, exit
 +.$1420 ​ [38      ]  sec           ;else take the 2's complement of the negative
 +.$1421 ​ [85 50   ​] ​ sta $50       ; ​ value to get the positive value
 +.$1423 ​ [a9 00   ​] ​ lda #$00
 +.$1425 ​ [e5 50   ​] ​ sbc $50
 +.$1427 ​ [48      ]  pha
 +.$1428 ​ [84 50   ​] ​ sty $50
 +.$142a ​ [a9 00   ​] ​ lda #$00
 +.$142c ​ [e5 50   ​] ​ sbc $50
 +.$142e ​ [a8      ]  tay
 +.$142f ​ [68      ]  pla
 +.$1430 ​ [60      ]  rts
 +
 +;​*****************************************************************************
 +;*  perform the fractional signed 32-bit divide ​                             *
 +;​*****************************************************************************
 +
 +.$1431 ​ [48      ]  pha           ;​remember the sign of the result
 +.$1432 ​ [a9 00   ​] ​ lda #$00      ;set the numerator fractional portion to .0
 +.$1434 ​ [85 60   ​] ​ sta $60
 +.$1436 ​ [85 61   ​] ​ sta $61
 +.$1438 ​ [20 cf 13]  jsr $13cf     ;​32-bit divide
 +.$143b ​ [68      ]  pla           ;if the sign of the result is supposed to be
 +.$143c ​ [10 19   ​] ​ bpl $1457     ; ​ positive, then exit
 +.$143e ​ [38      ]  sec           ;if the sign of the result is negative, take
 +.$143f ​ [a9 00   ​] ​ lda #$00      ;  get the 2's complement of the positive
 +.$1441 ​ [e5 64   ​] ​ sbc $64       ; ​ result
 +.$1443 ​ [85 64   ​] ​ sta $64
 +.$1445 ​ [a9 00   ​] ​ lda #$00
 +.$1447 ​ [e5 65   ​] ​ sbc $65
 +.$1449 ​ [85 65   ​] ​ sta $65
 +.$144b ​ [a9 00   ​] ​ lda #$00
 +.$144d ​ [e5 66   ​] ​ sbc $66
 +.$144f ​ [85 66   ​] ​ sta $66
 +.$1451 ​ [a9 00   ​] ​ lda #$00
 +.$1453 ​ [e5 67   ​] ​ sbc $67
 +.$1455 ​ [85 67   ​] ​ sta $67
 +.$1457 ​ [60      ]  rts
 +
 +;​*****************************************************************************
 +;*  get the X and Y plotting increments and the pixels-to-plot count         *
 +;​*****************************************************************************
 +
 +.$1458 ​ [a5 0c   ​] ​ lda $0c       ;get ABS(DX)
 +.$145a ​ [a4 0d   ​] ​ ldy $0d
 +.$145c ​ [20 1a 14]  jsr $141a
 +.$145f ​ [85 fa   ​] ​ sta $fa
 +.$1461 ​ [84 fb   ​] ​ sty $fb
 +
 +.$1463 ​ [a5 10   ​] ​ lda $10       ;get ABS(DY)
 +.$1465 ​ [a4 11   ​] ​ ldy $11
 +.$1467 ​ [20 1a 14]  jsr $141a
 +.$146a ​ [85 fc   ​] ​ sta $fc
 +.$146c ​ [84 fd   ​] ​ sty $fd
 +
 +.$146e ​ [a5 fc   ​] ​ lda $fc       ;​compare ABS(DY) to ABS(DX)
 +.$1470 ​ [c5 fa   ​] ​ cmp $fa
 +.$1472 ​ [a5 fd   ​] ​ lda $fd
 +.$1474 ​ [e5 fb   ​] ​ sbc $fb
 +.$1476 ​ [b0 44   ​] ​ bcs $14bc     ;if ABS(DY) >= ABS(DX) then branch ahead
 +
 +.$1478 ​ [a5 fa   ​] ​ lda $fa       ;set pixels-to-plot count to ABS(DX)
 +.$147a ​ [85 12   ​] ​ sta $12
 +.$147c ​ [85 50   ​] ​ sta $50
 +.$147e ​ [a5 fb   ​] ​ lda $fb
 +.$1480 ​ [85 13   ​] ​ sta $13
 +.$1482 ​ [85 51   ​] ​ sta $51       ;set the numerator (top) to DY and the
 +.$1484 ​ [a5 fc   ​] ​ lda $fc       ; ​ denominator (bottom) to ABS(DX)
 +.$1486 ​ [85 62   ​] ​ sta $62
 +.$1488 ​ [a5 fd   ​] ​ lda $fd
 +.$148a ​ [85 63   ​] ​ sta $63
 +.$148c ​ [a5 11   ​] ​ lda $11       ;get the sign of DY - will be the sign of div
 +.$148e ​ [20 31 14]  jsr $1431     ;​perform the signed fractional division
 +.$1491 ​ [a2 03   ​] ​ ldx #$03      ;store the result in the Y increment value
 +.$1493 ​ [b5 64   ​] ​ lda $64,x
 +.$1495 ​ [95 0e   ​] ​ sta $0e,x
 +.$1497 ​ [ca      ]  dex
 +.$1498 ​ [10 f9   ​] ​ bpl $1493
 +.$149a ​ [a5 0d   ​] ​ lda $0d       ;get the X increment
 +.$149c ​ [30 0a   ​] ​ bmi $14a8
 +.$149e ​ [a9 00   ​] ​ lda #$00      ;if DX is positive, X inc is +1
 +.$14a0 ​ [85 0d   ​] ​ sta $0d       ; ​ (note that DX cannot be 0 here so we don't
 +.$14a2 ​ [a9 01   ​] ​ lda #$01      ;   have to worry about that case)
 +.$14a4 ​ [85 0c   ​] ​ sta $0c
 +.$14a6 ​ [d0 06   ​] ​ bne $14ae
 +.$14a8 ​ [a9 ff   ​] ​ lda #$ff      ;if DX is negative, X inc is -1
 +.$14aa ​ [85 0d   ​] ​ sta $0d
 +.$14ac ​ [85 0c   ​] ​ sta $0c
 +
 +.$14ae ​ [38      ]  sec           ;take the negative of the number of pixels
 +.$14af ​ [a9 00   ​] ​ lda #$00      ;  to plot and exit
 +.$14b1 ​ [e5 12   ​] ​ sbc $12       ;I don't remember exactly why I use the
 +.$14b3 ​ [85 12   ​] ​ sta $12       ; ​ negative; there is not much of a speed
 +.$14b5 ​ [a9 00   ​] ​ lda #$00      ;  improvement. ​ Oh well, t'is done.
 +.$14b7 ​ [e5 13   ​] ​ sbc $13
 +.$14b9 ​ [85 13   ​] ​ sta $13
 +.$14bb ​ [60      ]  rts
 +
 +.$14bc ​ [a5 fc   ​] ​ lda $fc       ;set the pixels-to-plot count to ABS(DY)
 +.$14be ​ [85 12   ​] ​ sta $12
 +.$14c0 ​ [85 50   ​] ​ sta $50
 +.$14c2 ​ [a5 fd   ​] ​ lda $fd
 +.$14c4 ​ [85 13   ​] ​ sta $13
 +.$14c6 ​ [85 51   ​] ​ sta $51       ;set the numerator (top) to DX and the
 +.$14c8 ​ [a5 fa   ​] ​ lda $fa       ; ​ denominator(bottom) to ABS(DY)
 +.$14ca ​ [85 62   ​] ​ sta $62
 +.$14cc ​ [a5 fb   ​] ​ lda $fb
 +.$14ce ​ [85 63   ​] ​ sta $63
 +.$14d0 ​ [a5 0d   ​] ​ lda $0d       ;get the sign of DX - will be the sign of div
 +.$14d2 ​ [20 31 14]  jsr $1431     ;do the 32-bit signed fractional division
 +.$14d5 ​ [a2 03   ​] ​ ldx #$03      ;store the result in the X increment
 +.$14d7 ​ [b5 64   ​] ​ lda $64,x
 +.$14d9 ​ [95 0a   ​] ​ sta $0a,x
 +.$14db ​ [ca      ]  dex
 +.$14dc ​ [10 f9   ​] ​ bpl $14d7
 +.$14de ​ [4c ea 14]  jmp $14ea     ;jump over the next section
 +;-------
 +.$14e1 ​ [2c ff ff]  bit $ffff     ;This section contained junk before and I
 +.$14e4 ​ [2c ff ff]  bit $ffff     ; ​ don't know how it got here.  I replaced
 +.$14e7 ​ [2c ff ff]  bit $ffff     ; ​ it with BITs and now jump over it.
 +;-------
 +.$14ea ​ [a5 11   ​] ​ lda $11
 +.$14ec ​ [30 0a   ​] ​ bmi $14f8
 +.$14ee ​ [a9 00   ​] ​ lda #$00      ;if DY is positive then Y inc is +1
 +.$14f0 ​ [85 11   ​] ​ sta $11       ; ​ (we do not have to worry about the case
 +.$14f2 ​ [a9 01   ​] ​ lda #$01      ;   of DY being zero since then the increment
 +.$14f4 ​ [85 10   ​] ​ sta $10       ; ​  would not be important)
 +.$14f6 ​ [d0 06   ​] ​ bne $14fe
 +.$14f8 ​ [a9 ff   ​] ​ lda #$ff      ;if DY is negative then Y inc is -1
 +.$14fa ​ [85 11   ​] ​ sta $11
 +.$14fc ​ [85 10   ​] ​ sta $10
 +.$14fe ​ [4c ae 14]  jmp $14ae     ;jump back to the exit
 +
 +;​*****************************************************************************
 +;*  main routine: draw line or set pixel cursor position ​                    *
 +;​*****************************************************************************
 +
 +.$1501 ​ [b0 07   ​] ​ bcs $150a     ;goto draw routine if .C=1
 +.$1503 ​ [85 8b   ​] ​ sta $8b       ;​store x and y pixel cursor coordinates
 +.$1505 ​ [86 8c   ​] ​ stx $8c
 +.$1507 ​ [84 8d   ​] ​ sty $8d
 +.$1509 ​ [60      ]  rts           ;exit set pixel cursor
 +
 +.$150a ​ [85 04   ​] ​ sta $04       ;save draw-to coordinates
 +.$150c ​ [86 05   ​] ​ stx $05
 +.$150e ​ [84 08   ​] ​ sty $08
 +.$1510 ​ [a2 07   ​] ​ ldx #$07      ;clear $0a-$0d and $0e-$11
 +.$1512 ​ [a9 00   ​] ​ lda #$00
 +.$1514 ​ [95 0a   ​] ​ sta $0a,x
 +.$1516 ​ [ca      ]  dex
 +.$1517 ​ [10 fb   ​] ​ bpl $1514
 +
 +.$1519 ​ [38      ]  sec           ;get dx value = DrawToX - PixelCursorX
 +.$151a ​ [a5 04   ​] ​ lda $04       ; ​ dx is at [$0d $0c . $0b $0a]
 +.$151c ​ [e5 8b   ​] ​ sbc $8b
 +.$151e ​ [85 0c   ​] ​ sta $0c
 +.$1520 ​ [a5 05   ​] ​ lda $05
 +.$1522 ​ [e5 8c   ​] ​ sbc $8c
 +.$1524 ​ [85 0d   ​] ​ sta $0d
 +
 +.$1526 ​ [38      ]  sec           ;get dy value = DrawToY - PixelCursorY
 +.$1527 ​ [a5 08   ​] ​ lda $08       ; ​ dy is at [$11 $10 . $0f $0e]
 +.$1529 ​ [e5 8d   ​] ​ sbc $8d
 +.$152b ​ [85 10   ​] ​ sta $10
 +.$152d ​ [a9 00   ​] ​ lda #$00
 +.$152f ​ [b0 02   ​] ​ bcs $1533
 +.$1531 ​ [a9 ff   ​] ​ lda #$ff
 +.$1533 ​ [85 11   ​] ​ sta $11
 +
 +.$1535 ​ [20 58 14]  jsr $1458     ;​calculate the X and Y plotting increments
 +
 +.$1538 ​ [a5 8b   ​] ​ lda $8b       ;set the drawing X position to x+0.5
 +.$153a ​ [85 04   ​] ​ sta $04       ; ​ X is at [$05 $04 . $03 $02]
 +.$153c ​ [a5 8c   ​] ​ lda $8c
 +.$153e ​ [85 05   ​] ​ sta $05
 +.$1540 ​ [a9 80   ​] ​ lda #$80
 +.$1542 ​ [85 03   ​] ​ sta $03
 +.$1544 ​ [85 07   ​] ​ sta $07
 +.$1546 ​ [a9 00   ​] ​ lda #$00
 +.$1548 ​ [85 02   ​] ​ sta $02
 +.$154a ​ [85 06   ​] ​ sta $06
 +.$154c ​ [a5 8d   ​] ​ lda $8d       ;set the drawing Y position to y+0.5
 +.$154e ​ [85 08   ​] ​ sta $08       ; ​ Y is at [$09 $08 . $07 $06]
 +.$1550 ​ [a9 00   ​] ​ lda #$00
 +.$1552 ​ [85 09   ​] ​ sta $09
 +
 +.$1554 ​ [a5 04   ​] ​ lda $04       ;get the pixel X and Y coordinates
 +.$1556 ​ [a6 05   ​] ​ ldx $05
 +.$1558 ​ [a4 08   ​] ​ ldy $08
 +.$155a ​ [20 a8 13]  jsr $13a8     ;plot the pixel
 +.$155d ​ [a5 12   ​] ​ lda $12       ;​check the pixels-to-plot count for zero
 +.$155f ​ [05 13   ​] ​ ora $13
 +.$1561 ​ [f0 3b   ​] ​ beq $159e     ;if no more pixels to plot, exit loop
 +.$1563 ​ [18      ]  clc           ;add the X increment to the X coordinate
 +.$1564 ​ [a5 02   ​] ​ lda $02
 +.$1566 ​ [65 0a   ​] ​ adc $0a
 +.$1568 ​ [85 02   ​] ​ sta $02
 +.$156a ​ [a5 03   ​] ​ lda $03
 +.$156c ​ [65 0b   ​] ​ adc $0b
 +.$156e ​ [85 03   ​] ​ sta $03
 +.$1570 ​ [a5 04   ​] ​ lda $04
 +.$1572 ​ [65 0c   ​] ​ adc $0c
 +.$1574 ​ [85 04   ​] ​ sta $04
 +.$1576 ​ [a5 05   ​] ​ lda $05
 +.$1578 ​ [65 0d   ​] ​ adc $0d
 +.$157a ​ [85 05   ​] ​ sta $05
 +.$157c ​ [18      ]  clc           ;add the Y increment to the Y coordinate
 +.$157d ​ [a5 06   ​] ​ lda $06
 +.$157f ​ [65 0e   ​] ​ adc $0e
 +.$1581 ​ [85 06   ​] ​ sta $06
 +.$1583 ​ [a5 07   ​] ​ lda $07
 +.$1585 ​ [65 0f   ​] ​ adc $0f
 +.$1587 ​ [85 07   ​] ​ sta $07
 +.$1589 ​ [a5 08   ​] ​ lda $08
 +.$158b ​ [65 10   ​] ​ adc $10
 +.$158d ​ [85 08   ​] ​ sta $08
 +.$158f ​ [a5 09   ​] ​ lda $09
 +.$1591 ​ [65 11   ​] ​ adc $11
 +.$1593 ​ [85 09   ​] ​ sta $09
 +.$1595 ​ [e6 12   ​] ​ inc $12       ;​increment the pixels to plot count
 +.$1597 ​ [d0 bb   ​] ​ bne $1554     ; ​ note that it is stored as the negative of
 +.$1599 ​ [e6 13   ​] ​ inc $13       ; ​ the count
 +.$159b ​ [4c 54 15]  jmp $1554     ;​repeat plotting loop
 +
 +.$159e ​ [a5 04   ​] ​ lda $04       ;exit - set the pixel cursor position to the
 +.$15a0 ​ [a6 05   ​] ​ ldx $05       ; ​ last pixel plotted on the line
 +.$15a2 ​ [a4 08   ​] ​ ldy $08
 +.$15a4 ​ [4c 03 15]  jmp $1503
 +==============================================================================
 +THE END
 +</​code>​
magazines/chacking1.txt ยท Last modified: 2015-04-17 04:34 (external edit)