2. Horizontal shifting

This is the secod codesnippet I upload here. This time we will look at horizontal shifting, something that is also used in games with scrolling background.

THIS DEMO

Download LHA-package.

Horizontal shifiting on pixel-level is built-in into the Amiga chipset, but it is only 16 pixels wide. We will look at two different horizontalshifts, one is only 16px, but the other one is 80px. Both shiftings are 100% made with the Amiga chipset, the CPU only tells the Copper what to do in a copperlist, and the Copper then adjusts the shifting.

16px shifting is made by putting a value in the interval of [0,15] into BPLCON1-hardwareregister ($dff102). Bits [0,3] are Playfield 1 horizontal scrollvalue, and bits [4,7] are for Playfield 2. If playfields aren't setup, then the same value has to be set for both PF1 and PF2, otherwise colormissmatching (on binary level) will occour.

In this demo there are copperbars put behind the moving images, but are not important for the effect. At the end of each image the Hscroll-value is set to 0, as otherwise graphics after moving image would float sideways according to the last set Hscroll-value.

The 80px H-shift is a little more problematic. 80px is a chosen value, calculated from 4*16px + 16px, of which the lonely 16px is the same 16px shifting as above. 4*16px is done by using the modulo-value of bitplanes, modulo-shifting isn't smoothscrolling, but take for example a shift of 58px => 3*16px +10px, this will be 48px moduloshift and then 10px Hshift.
For this to work the bitplanes have to be setup to be larger than the wisible part, in the case of max 80px shifting a 320px wide screen has to be made at least 320px + 64px = 384px (moduloshifting values are dependant on the difference of the width of the bitplane and the screen).
In this demo, the screen is 320px wide and the bitplanes are 384px wide, the difference is then 64px, which is 8bytes, thus giving a modulo of 8. If the modulo is changed mid-screen, to f.ex. 6 will shift all coming scanlines 16px to the left/scanline, 10 will shift all coming lines 16px to the right/scanline. This should make it clear that we HAVE TO change the modulo back to the standard value on the next scanline, unless we want to make an additional moduloshift. This behaviour can be seen in the sourcecode when we are looking for the next lines scrollvalue and with that value we we change the modulo accordingly, before the next line starts as modulo is used only after horizontal-blanking.

There are 2 modulovalues, one for the odd numbered bitplanes and one for the even numbered bitplanes. These values have to be put into the hardwareregisters at $dff108 and $dff10a.

I chose to add an alternate effect into the demo as well, as many demos used the shaky horizontalshifting effect. It is done by subtracting the real Hscroll-value from the maximum scrollvalue (f.ex. 79 - 23 = 56, when max-value is 79 and real-value is 23). This is rather easy for max 15px scrollvalues, but for larger values some extra coding has to be made for checking the next lines modulovalue.

One last thing. In this demo the transitions from one effect to another isn't smooth. I didn't want to make it smooth, as then it would be a lot harder to read the code for how the effects were done. Smooth transitions can be made in two ways:

  • firstly by just making a long precalc-table of how the scrollvalues should be for a whole sequence of repeating animation (this isn't hard, but the precalc-tables can be long), this is the usual method used in old demos
     
  • I would recommend making a routine to transform from one precalc-table to another, it's a little hard to tell how it's done, but at some point I will make a tutorial of that as well (it can be done with divu-instructions, but for greater speeds a lot of branchconditions and bitshifting will take place)

 

D:\Amiga\Windows\AmigaVikke\h1.asm
   1 
; Copperbars-1
   2 
 
   3 
DMACONR        EQU        $dff002
   4 
ADKCONR        EQU        $dff010
   5 
INTENAR        EQU        $dff01c
   6 
INTREQR        EQU        $dff01e
   7 
 
   8 
DMACON        EQU        $dff096
   9 
ADKCON        EQU        $dff09e
  10 
INTENA        EQU        $dff09a
  11 
INTREQ        EQU        $dff09c
  12 
 
  13 
    incdir "windows:amigavikke/"
  14 
 
  15 
 
  16 
; MACROS
  17 
; Macros are used to make it easier and shorter to read the code.
  18 
; Every time you see a marcocall in the code, you can think of it more-or-less like a copy-paste of the Macro-code
  19 
; (the only difference is the usage of local labels in the macros, as otherwise double-labeling would occour).
  20 
 
  21 
get_and_set_modulo:    MACRO
  22 
        ; d7 is the linecounter
  23 
        ; d2 is the shiftvalue
  24 
        ; a6 is the copperlist pointer
  25 
        ; TRASH: d4
  26 
        btst.l #0,d7             ; test to see if bit0 is set
  27 
                                ; (if not set, even scanline ==> next scanline shaky possible)
  28 
        beq \@normal_hshift_80
  29 
        cmpi.b #1,hshift_mode     ; is hshift_mode is normal or shaky
  30 
        bne \@normal_hshift_80
  31 
        move.b #79,d4             ; shift = 79 - realshift
  32 
        sub.b d2,d4
  33 
        move.b d4,d2             ; and result aligned to match rest of the code
  34 
        \@normal_hshift_80:
  35 
        and.l #$70,d2         ; only bits 4, 5 & 6
  36 
        lsr.b #4,d2         ; 4LSB cut-off
  37 
        lsl.b #1,d2         ; *2 for b to w addressing
  38 
        cmp.b d0,d2
  39 
        beq \@modulo_1         ; if modulo = d2 ==> modulo_1
  40 
        move.b #8,d4         ; otherwise make moduloshifting, either left or right
  41 
        add.b d0,d4
  42 
        sub.b d2,d4
  43 
        move.w #$0108,(a6)+     ; these modulovalues are put into the registers on the scanline before
  44 
                                ; the line that will use them as modulo is only used at HorizontalBlanking
  45 
        move.w d4,(a6)+
  46 
        move.w #$010a,(a6)+     ; these modulovalues are put into the registers on the scanline before
  47 
                                ; the line that will use them as modulo is only used at HorizontalBlanking
  48 
        move.w d4,(a6)+
  49 
        move.b d2,d0
  50 
        bra \@modulo_0
  51 
        \@modulo_1:                        ; modulo = d2
  52 
        move.l #$01080008,(a6)+         ; set modulo = 8, the default value in this demo
  53 
        move.l #$010a0008,(a6)+         ; set modulo = 8, the default value in this demo
  54 
        \@modulo_0:
  55 
        ENDM
  56 
 
  57 
WAIT_nextline:    MACRO
  58 
    ; d7 is the linecounter
  59 
    ; d3 is the startline
  60 
    ; a6 is the copperlist pointer
  61 
    ; TRASH: d4
  62 
    move.w d7,d4         ; d4=d7
  63 
    add.w d3,d4         ; d4=d7+d3 (d7+startline)
  64 
    lsl.w #8,d4         ; d4=(d7+startline)*256
  65 
    add.w #$07,d4         ; d4=(d7+startline)<<256+07
  66 
    move.w d4,(a6)+     ; Wait - first line, ex: $6407
  67 
    move.w #$fffe,(a6)+ ; Mask
  68 
    ENDM
  69 
 
  70 
init:
  71 
; store hardware registers, store view- and copperaddresses, load blank view, wait 2x for top of frame,
  72 
; own blitter, wait for blitter AND finally forbid multitasking!
  73 
; all this just to be able to exit gracely
  74 
 
  75 
    ; store data in hardwareregisters ORed with $8000 (bit 15 is a write-set bit when
  76 
    ; values are written back into the system)
  77 
    move.w    DMACONR,d0
  78 
    or.w #$8000,d0
  79 
    move.w d0,olddmareq
  80 
    move.w    INTENAR,d0
  81 
    or.w #$8000,d0
  82 
    move.w d0,oldintena
  83 
    move.w    INTREQR,d0
  84 
    or.w #$8000,d0
  85 
    move.w d0,oldintreq
  86 
    move.w    ADKCONR,d0
  87 
    or.w #$8000,d0
  88 
    move.w d0,oldadkcon
  89 
 
  90 
    move.l    $4,a6
  91 
    move.l    #gfxname,a1
  92 
    moveq    #0,d0
  93 
    jsr    -408(a6)    ; oldOpenLibrary offset=-408 ... would OpenLibrary be better? offset=-552
  94 
    move.l    d0,gfxbase
  95 
    move.l     d0,a6
  96 
    move.l     34(a6),oldview
  97 
    move.l     38(a6),oldcopper
  98 
 
  99 
    move.l #0,a1
 100 
    jsr -222(a6)    ; LoadView
 101 
    jsr -270(a6)    ; WaitTOF
 102 
    jsr -270(a6)    ; WaitTOF
 103 
    jsr -456(a6)    ; OwnBlitter
 104 
    jsr -228(a6)    ; WaitBlit
 105 
    move.l    $4,a6
 106 
    jsr -132(a6)    ; Forbid
 107 
 
 108 
; end exit gracely preparations!
 109 
 
 110 
    ; clear Bitplanes from garbage - slow routine! should be done with the Blitter,
 111 
    ; or as an partly unrolled loop if used in the mainloop
 112 
    move.w #384/8*200/4,d0     ; d0 is a counter for number of longwords to get cleared
 113 
    move.l #bpl0,a0     ; bpl0 => a0
 114 
    move.l #bpl1,a1     ; bpl1 => a1
 115 
    move.l #bpl2,a2     ; bpl2 => a2
 116 
    move.l #bpl3,a3     ; bpl3 => a3
 117 
    screen_clear:
 118 
        move.l #0,(a0)+    ; #0 => (a0), and increment a0 to next longword (a0=a0+4)
 119 
        move.l #0,(a1)+    ; #0 => (a1), and increment a1 to next longword (a1=a1+4)
 120 
        move.l #0,(a2)+    ; #0 => (a2), and increment a2 to next longword (a2=a2+4)
 121 
        move.l #0,(a3)+    ; #0 => (a3), and increment a3 to next longword (a3=a3+4)
 122 
        subq.w #1,d0
 123 
        bne screen_clear
 124 
 
 125 
    ; copy bitmap to bitplanes (384 x 90 px - 4 bitplanes)
 126 
    move.w #384/8*90/4,d0
 127 
    move.l #bpl0,a0     ; bpl0 => a0
 128 
    move.l #bpl1,a1     ; bpl1 => a1
 129 
    move.l #bpl2,a2     ; bpl2 => a2
 130 
    move.l #bpl3,a3     ; bpl3 => a3
 131 
    move.l #img_amigavikke,a6
 132 
    add.l #8,a6
 133 
    copy_img1:
 134 
        move.l 384/8*90*3(a6),(a3)+        ; bpl3
 135 
        move.l 384/8*90*2(a6),(a2)+        ; bpl2
 136 
        move.l 384/8*90*1(a6),(a1)+        ; bpl1
 137 
        move.l (a6)+,(a0)+                ; bpl0
 138 
        subq.w #1,d0
 139 
        bne copy_img1
 140 
 
 141 
    ; copy bitmap to bitplanes (384 x 90 px - 4 bitplanes)
 142 
    move.w #384/8*90/4,d0
 143 
    move.l #bpl0+384/8*110,a0     ; bpl0 => a0
 144 
    move.l #bpl1+384/8*110,a1     ; bpl1 => a1
 145 
    move.l #bpl2+384/8*110,a2     ; bpl2 => a2
 146 
    move.l #bpl3+384/8*110,a3     ; bpl3 => a3
 147 
    move.l #img_amigavikke,a6
 148 
    add.l #12,a6
 149 
    copy_img2:
 150 
        move.l 384/8*90*3(a6),(a3)+        ; bpl3
 151 
        move.l 384/8*90*2(a6),(a2)+        ; bpl2
 152 
        move.l 384/8*90*1(a6),(a1)+        ; bpl1
 153 
        move.l (a6)+,(a0)+                ; bpl0
 154 
        subq.w #1,d0
 155 
        bne copy_img2
 156 
 
 157 
; setup displayhardware to show a 320x200px 4 bitplanes playfield,
 158 
; with zero horizontal scroll and zero modulos
 159 
; setup displayhardware to show a 320x200px 4 bitplanes view,
 160 
; but with a playfield size of 384x200, h-scroll=0, modulo=(384-320)/8=8
 161 
    move.w    #$4200,$dff100                ; 4 bitplane lowres
 162 
    move.w    #$0000,$dff102                ; horizontal scroll 0
 163 
    move.w    #$0008,$dff108                ; odd modulo 8
 164 
    move.w    #$0008,$dff10a                ; even modulo 8
 165 
    move.w    #$2c81,$dff08e                ; DIWSTRT - topleft corner (2c81)
 166 
    move.w    #$f4d1,$dff090                ; DIVSTOP - bottomright corner (f4d1)
 167 
    move.w    #$0038,$dff092                ; DDFSTRT - max overscan $0018 ; standard 0038 & 00d0
 168 
    move.w    #$00d0,$dff094                ; DDFSTOP - max overscan $00d8 ; max overscan: 368x283px in PAL
 169 
    move.w     #%1000010111000000,DMACON    ; DMA set ON
 170 
    move.w     #%0000000000111111,DMACON    ; DMA set OFF
 171 
    move.w     #%1100000000000000,INTENA    ; IRQ set ON
 172 
    move.w     #%0011111111111111,INTENA    ; IRQ set OFF
 173 
 
 174 
 
 175 
mainloop:
 176 
; increase framecounter by 1
 177 
    move.l frame,d0
 178 
    addq.l #1,d0
 179 
    move.l d0,frame
 180 
 
 181 
; change effect settings according to framecounter
 182 
    ; normal or "shaky" Hshift
 183 
    move.l d0,d1
 184 
    and.l #$1ff,d1             ; 511/50 ~ 10sec => every 10 sec speed changes +1, in interval [2,5]
 185 
    bne .10
 186 
    eori.b #1,hshift_mode
 187 
    .10:
 188 
 
 189 
 
 190 
; make copperlist
 191 
; doubblebuffering of copperlists, defined at copper1 and copper2, chosen by LSB in framecounter
 192 
; copper (and a6) will hold the address to the copperlist we will write to (not the one currently in use)
 193 
    and.l #1,d0
 194 
    bne usecopper2
 195 
    move.l #copper1,a6
 196 
    bra usecopper1
 197 
    usecopper2:
 198 
    move.l #copper2,a6
 199 
    usecopper1:
 200 
    move.l a6,copper
 201 
 
 202 
    ; bitplane 0
 203 
    move.l #bpl0,d0
 204 
    move.w #$00e2,(a6)+    ; lo-bits of start of bitplane
 205 
    move.w d0,(a6)+        ; go into $dff0e2
 206 
    swap d0
 207 
    move.w #$00e0,(a6)+    ; hi-bits of start of bitplane
 208 
    move.w d0,(a6)+        ; go into $dff0e0
 209 
 
 210 
    ; bitplane 1
 211 
    move.l #bpl1,d0
 212 
    move.w #$00e6,(a6)+    ; lo-bits of start of bitplane
 213 
    move.w d0,(a6)+        ; go into $dff0e6
 214 
    swap d0
 215 
    move.w #$00e4,(a6)+    ; hi-bits of start of bitplane
 216 
    move.w d0,(a6)+        ; go into $dff0e4
 217 
 
 218 
    ; bitplane 2
 219 
    move.l #bpl2,d0
 220 
    move.w #$00ea,(a6)+    ; lo-bits of start of bitplane
 221 
    move.w d0,(a6)+        ; go into $dff0e2
 222 
    swap d0
 223 
    move.w #$00e8,(a6)+    ; hi-bits of start of bitplane
 224 
    move.w d0,(a6)+        ; go into $dff0e0
 225 
 
 226 
    ; bitplane 3
 227 
    move.l #bpl3,d0
 228 
    move.w #$00ee,(a6)+    ; lo-bits of start of bitplane
 229 
    move.w d0,(a6)+        ; go into $dff0e6
 230 
    swap d0
 231 
    move.w #$00ec,(a6)+    ; hi-bits of start of bitplane
 232 
    move.w d0,(a6)+        ; go into $dff0e4
 233 
 
 234 
    ; colors
 235 
    move.l #$01800000,(a6)+    ; color 0: $000 into $dff180
 236 
    move.l #$01820000,(a6)+    ; color 1: $000 into $dff182
 237 
    move.l #$01840f00,(a6)+    ; color 2: $f00 into $dff184
 238 
    move.l #$01860f10,(a6)+    ; color 3: $fff into $dff186
 239 
    move.l #$01880f20,(a6)+    ; color 4: $000 into $dff188
 240 
    move.l #$018a0f30,(a6)+    ; color 5: $000 into $dff18a
 241 
    move.l #$018c0f40,(a6)+    ; color 6: $f00 into $dff18c
 242 
    move.l #$018e0f60,(a6)+    ; color 7: $fff into $dff18e
 243 
    move.l #$01900f70,(a6)+    ; color 8: $000 into $dff190
 244 
    move.l #$01920f80,(a6)+    ; color 9: $000 into $dff192
 245 
    move.l #$01940f90,(a6)+    ; color 10: $f00 into $dff194
 246 
    move.l #$01960fb0,(a6)+    ; color 11: $fff into $dff196
 247 
    move.l #$01980fc0,(a6)+    ; color 12: $000 into $dff198
 248 
    move.l #$019a0fd0,(a6)+    ; color 13: $000 into $dff19a
 249 
    move.l #$019c0fe0,(a6)+    ; color 14: $f00 into $dff19c
 250 
    move.l #$019e0ff0,(a6)+    ; color 15: $fff into $dff19e
 251 
 
 252 
    ; horizontal scroll
 253 
    move.l #$01020000,(a6)+    ; 0 for both odd and even numbered bpl (rightmost 2 zeros)
 254 
 
 255 
 
 256 
; *******************************
 257 
;
 258 
; 16 px horizontal shift - Amigas hardware can do it without any tricks
 259 
;
 260 
; *******************************
 261 
 
 262 
    move.l frame,d1         ; d1 is an anglespeed-value, here we give it the same value as the framecounter,
 263 
    lsl.l #2,d1             ; and multiply it by 2^2 = 4 (changing this multiplier will affect the starting angle)
 264 
    and.l #$ff,d1             ; and lastly we have to align it to be a byte value, as our sinus-table only has 256 values!
 265 
    move.l #sin255_15,a0
 266 
    move.l #colorcodes,a1
 267 
    move.b #44,d3
 268 
    move.l #0,d7
 269 
    loop_16px_hshift:
 270 
        WAIT_nextline         ; macro
 271 
        ; copper MOVE-instruction generation
 272 
        move.w #$0180,(a6)+
 273 
        move.w (a1)+,(a6)+
 274 
        move.b (a0,d1),d2
 275 
 
 276 
        btst.l #0,d7             ; test to see if bit0 is set (if set, odd scanline ==> shaky possible)
 277 
        bne normal_hshift16
 278 
        cmpi.b #1,hshift_mode     ; is hshift_mode is normal or shaky
 279 
        bne normal_hshift16
 280 
        move.b #$f,d4             ; shift = 15 - realshift
 281 
        sub.b d2,d4
 282 
        move.b d4,d2             ; and result aligned to match rest of the code
 283 
        normal_hshift16:
 284 
 
 285 
        move.b d2,d4             ; replicate value in bits[0,3] to bits[4,7]
 286 
        lsl.b #4,d2             
 287 
        add.b d4,d2
 288 
        move.w #$0102,(a6)+     ; horizontal scroll
 289 
        move.w d2,(a6)+         ; value 
 290 
        addq #4,d1                 ; d1 is an anglespeed-value giving longer or shorter sinuscurves
 291 
        and.l #$ff,d1
 292 
        addq #1,d7
 293 
        cmp.b #90,d7
 294 
        bne loop_16px_hshift
 295 
 
 296 
    WAIT_nextline                 ; macro
 297 
    move.l #$01800000,(a6)+
 298 
    move.l #$01020000,(a6)+
 299 
 
 300 
 
 301 
; *******************************
 302 
;
 303 
; 80 px horizontal shift - to get more than 16px horizontal scroll we need to apply modulos to the playfield
 304 
;
 305 
; *******************************
 306 
 
 307 
 
 308 
 
 309 
    move.l frame,d1         ; read above in 16px shift about anglespeed
 310 
;    lsl.l #1,d1             ; no multiplier used, thus the line is commented out of the source
 311 
    and.l #$ff,d1
 312 
    move.l #sin255_79,a0
 313 
    move.l #colorcodes,a1
 314 
    move.b #0,d0             ; d0 stores modulo value
 315 
    move.b #153,d3             ; startline - !!!! needs to start one line before the actual
 316 
                            ; image to get modulovalues correct (should be an empty line) !!!!
 317 
    move.l #0,d7
 318 
    loop_80px_hshift:
 319 
        WAIT_nextline         ; macro
 320 
        ; copper MOVE-instruction generation
 321 
        move.w #$0180,(a6)+
 322 
        move.w (a1)+,(a6)+
 323 
        move.b (a0,d1),d2
 324 
 
 325 
        btst.l #0,d7             ; test to see if bit0 is set (if set, odd scanline ==> shaky possible)
 326 
        bne normal_hshift80
 327 
        cmpi.b #1,hshift_mode     ; is hshift_mode is normal or shaky
 328 
        bne normal_hshift80
 329 
        move.b #79,d4             ; shift = 79 - realshift
 330 
        sub.b d2,d4
 331 
        move.b d4,d2             ; and result aligned to match rest of the code
 332 
        normal_hshift80:
 333 
 
 334 
        and.b #$f,d2             ; get bits[0,3] of scrollvalue ==> these are used for Hscroll-value
 335 
        move.b d2,d4             ; and then replicated to bits[4,7] 
 336 
        lsl.b #4,d2
 337 
        add.b d4,d2
 338 
        move.w #$0102,(a6)+     ; horizontal scroll
 339 
        move.w d2,(a6)+         ; value 
 340 
        addq #1,d1                 ; d1 is an anglespeed-value giving longer or shorter sinuscurves
 341 
        and.l #$ff,d1
 342 
 
 343 
        ;look at next lines scrollvalue - needed to calculate modulovalues for the next scanline
 344 
        moveq #0,d4
 345 
        move.b (a0,d1),d2
 346 
        get_and_set_modulo         ; macro
 347 
 
 348 
        addq #1,d7
 349 
        cmp.b #91,d7             ; counter has to be height of image +1, because of the extra line at the beginning!!!
 350 
        bne loop_80px_hshift
 351 
 
 352 
    ; HACK used to "undo" last changes to the copperlist, the pointer is moved 2 instructions back
 353 
    ; (faster than checking for last line every time)
 354 
    sub.l #4,a6     ; removing two MOVE-instructions intended for the next scanline,
 355 
                    ; but not wanted anymore as all lines have already been iterated 
 356 
 
 357 
    ; make WAIT-instruction for the next line
 358 
    WAIT_nextline
 359 
    move.l #$01800000,(a6)+
 360 
    move.l #$01020000,(a6)+
 361 
    move.l #$01080008,(a6)+
 362 
    move.l #$010a0008,(a6)+
 363 
    ; If you want to display parts of the bitplanes after the horizontal-moduloshifting process,
 364 
    ; the easiest way to get it to work correctly is to set up the the bitplane-pointers again,
 365 
    ; with newly calculated startingpoints and using the standard modulo-value.
 366 
    ; However, easiest would be to setup a whole new screen, with its own bitplanes and modulos.
 367 
    ; An empty line after the Hshifting area is a good idea, as you might have to change
 368 
    ; a lot of different hardwareregisters!
 369 
    ; The empty lines before and after Hshifting area are possible to remove by changing the code,
 370 
    ; but then the code will be a lot harder to read, and this is a part of a tutorial-series.
 371 
 
 372 
    ; end of copperlist (copperlist ALWAYS ends with WAIT $fffffffe)
 373 
    move.l #$fffffffe,(a6)+     ; end copperlist
 374 
 
 375 
 
 376 
    ; if mousebutton/joystick 1  or 2 pressed then exit
 377 
    btst.b #6,$bfe001
 378 
    beq exit
 379 
    btst.b #7,$bfe001
 380 
    beq exit
 381 
 
 382 
; display is ready, or atleast we have done everything we wanted and the copper continues on its own
 383 
; we have to wait for Vertical Blanking before making the next frame
 384 
 
 385 
waitVB:
 386 
    move.l $dff004,d0
 387 
    and.l #$1ff00,d0
 388 
    cmp.l #300<<8,d0
 389 
    bne waitVB
 390 
 
 391 
    ; use next copperlist - as we are using doubblebuffering on copperlists
 392 
    ; we now take the new one into use
 393 
    move.l copper,d0
 394 
    move.l d0,$dff080
 395 
    bra mainloop
 396 
 
 397 
exit:
 398 
; exit gracely - reverse everything done in init
 399 
    move.w #$7fff,DMACON
 400 
    move.w    olddmareq,DMACON
 401 
    move.w #$7fff,INTENA
 402 
    move.w    oldintena,INTENA
 403 
    move.w #$7fff,INTREQ
 404 
    move.w    oldintreq,INTREQ
 405 
    move.w #$7fff,ADKCON
 406 
    move.w    oldadkcon,ADKCON
 407 
 
 408 
    move.l    oldcopper,$dff080
 409 
    move.l     gfxbase,a6
 410 
    move.l     oldview,a1
 411 
    jsr -222(a6)    ; LoadView
 412 
    jsr -270(a6)    ; WaitTOF
 413 
    jsr -270(a6)    ; WaitTOF
 414 
    jsr -228(a6)    ; WaitBlit
 415 
    jsr -462(a6)    ; DisownBlitter
 416 
    move.l    $4,a6
 417 
    jsr -138(a6)    ; Permit
 418 
 
 419 
    ; end program
 420 
    rts
 421 
 
 422 
 
 423 
 
 424 
; *******************************************************************************
 425 
; *******************************************************************************
 426 
; DATA
 427 
; *******************************************************************************
 428 
; *******************************************************************************
 429 
 
 430 
 
 431 
; storage for 32-bit addresses and data
 432 
    CNOP 0,4
 433 
oldview:    dc.l 0
 434 
oldcopper:    dc.l 0
 435 
gfxbase:    dc.l 0
 436 
frame:        dc.l 0
 437 
copper:        dc.l 0
 438 
 
 439 
; storage for 16-bit data
 440 
    CNOP 0,4
 441 
olddmareq:    dc.w 0
 442 
oldintreq:    dc.w 0
 443 
oldintena:    dc.w 0
 444 
oldadkcon:    dc.w 0
 445 
 
 446 
    CNOP 0,4
 447 
; storage for 8-bit data and text
 448 
gfxname:    dc.b 'graphics.library',0
 449 
sin255_15:    dc.b 8,8,8,8,8,8,9,9,9,9,9,10,10,10,10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,12,12,12,12,12,12,12,11,11,11,11,11,11,10,10,10,10,10,10,9,9,9,9,9,9,8,8,8,8,8,7,7,7,7,7,6,6,6,6,6,6,5,5,5,5,5,5,4,4,4,4,4,4,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8
 450 
sin255_79: dc.b 40,41,42,43,44,45,46,47,48,49,50,50,51,52,53,54,55,56,57,58,58,59,60,61,62,63,63,64,65,66,66,67,68,68,69,70,70,71,71,72,73,73,74,74,74,75,75,76,76,76,77,77,77,78,78,78,78,78,79,79,79,79,79,79,79,79,79,79,79,79,79,78,78,78,78,78,77,77,77,76,76,76,75,75,74,74,73,73,72,72,71,71,70,69,69,68,67,67,66,65,64,64,63,62,61,61,60,59,58,57,56,55,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,25,24,23,22,21,20,19,19,18,17,16,16,15,14,13,13,12,11,11,10,9,9,8,8,7,7,6,6,5,5,4,4,4,3,3,3,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,3,3,3,4,4,4,5,5,6,6,6,7,7,8,9,9,10,10,11,12,12,13,14,14,15,16,17,17,18,19,20,21,22,22,23,24,25,26,27,28,29,30,30,31,32,33,34,35,36,37,38,39,40
 451 
 
 452 
 
 453 
hshift_mode:    dc.b 0
 454 
modulo:            dc.b 0
 455 
modulo_flag:    dc.b 0
 456 
 
 457 
    CNOP 0,4
 458 
colorcodes: dc.w $000,$001,$002,$003,$004,$005,$006,$007,$008,$009,$00A,$00B,$00C,$00D,$00E,$00F,$00E,$00D,$00C,$00B,$00A,$009,$008,$007,$006,$005,$004,$003,$002,$001,$000,$011,$022,$033,$044,$055,$066,$077,$088,$099,$0AA,$0BB,$0CC,$0DD,$0EE,$0FF,$0EE,$0DD,$0CC,$0BB,$0AA,$099,$088,$077,$066,$055,$044,$033,$022,$011,$000,$010,$020,$030,$040,$050,$060,$070,$080,$090,$0A0,$0B0,$0C0,$0D0,$0E0,$0F0,$0E0,$0D0,$0C0,$0B0,$0A0,$090,$080,$070,$060,$050,$040,$030,$020,$010,$000
 459 
 
 460 
 
 461 
 
 462 
    CNOP 0,4
 463 
copperlines1:    blk.w 100,0
 464 
 
 465 
 
 466 
 
 467 
    Section ChipRAM,Data_c
 468 
 
 469 
; bitplanes aligned to 32-bit
 470 
    CNOP 0,4
 471 
bpl0:    blk.b 384/8*200,0
 472 
bpl1:    blk.b 384/8*200,0
 473 
bpl2:    blk.b 384/8*200,0
 474 
bpl3:    blk.b 384/8*200,0
 475 
 
 476 
 
 477 
; datalists aligned to 32-bit
 478 
    CNOP 0,4
 479 
copper1:    
 480 
            dc.l $ffffffe     ; CHIPMEM!
 481 
            blk.l 1023,0     ; CHIPMEM!
 482 
    CNOP 0,4
 483 
copper2:    
 484 
            dc.l $ffffffe     ; CHIPMEM!
 485 
            blk.l 1023,0     ; CHIPMEM!
 486 
 
 487 
    CNOP 0,4
 488 
img_amigavikke:    incbin "amigavikke_new.raw"
 489