The other week, I constructed a simple BASIC game of Dodging the Rocket around the Grumpy faces, which I thought worked quite nicely.
10 MODE 0:DEFINT a-z:INK 0,11:INK 1,26:BORDER 11:PEN 1
20 RANDOMISE TIME:RANDOMIZE RND
30 FOR a=1 TO 25
40 x=INT(RND*20)+1
50 LOCATE x,1
60 PRINT CHR$(225)
61 GOSUB 1000
70 NEXT a
80 x=10:y=12:PEN 3:LOCATE x,y:PRINT CHR$(239)
90 d=1
100 WHILE d=1
101 IF INKEY(1)=0 THEN IF x<20 THEN LOCATE x,y:PRINT" ":x=x+1:LOCATE x,y:PEN 3:PRINT CHR$(239)
102 IF INKEY(=0 THEN IF x>1 THEN LOCATE x,y:PRINT" ":x=x-1:LOCATE x,y:PEN 3:PRINT CHR$(239)
110 ax=INT(RND*20)+1
120 LOCATE ax,1:PEN 1
130 PRINT CHR$(225)
135 IF TEST((x-1)*32+4,238)=1 THEN d=0
140 LOCATE x,y:PRINT" "
150 GOSUB 1000
160 LOCATE x,y:PEN 3:PRINT CHR$(239)
170 WEND
180 END
1000 LOCATE 1,1:PRINT CHR$(11)
1010 RETURN
The aim of this simple game was to write something similar in Assembly and thought it would make a good demonstration of coding in Assembly and make use of some Collision Detection code I recently wrote.
Though when I tried to do the same thing with my Rocket in Assembly, it looked as if the Rocket didn't have time to display itself, so I ended up with this, so it looks like there's 2 Rockets onscreen. It appears the Scroll routine I'm using here is very slow too, which makes use of SCR SW ROLL. My BASIC version seems to be kicking the Assembly versions butt.
org &8000
ld a,0
call &bc0e
call genseed
ld a,1
call &bb90
ld b,24
.drawobstacles
push bc
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,225
call &bb5a
call scroll
pop bc
djnz drawobstacles
call printrocket
.maingame
call scroll
ld hl,(ypos2)
call &bb75
ld a,32
call &bb5a
call printrocket
call updateobstacle
call collision
ld a,(dead)
cp 0
jr z,skip
ld a,1
call &bb1e
jr z,checkleft
ld a,(xpos)
cp 16
jr z,checkleft
inc a
ld (xpos),a
ld (xpos2),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
add hl,de
ld (ex),hl
.checkleft
ld a,8
call &bb1e
jr z,skip
ld a,(xpos)
cp 1
jr z,skip
dec a
ld (xpos),a
ld (xpos2),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
and a
sbc hl,de
ld (ex),hl
.skip ld a,(dead)
and a
jr nz,maingame
ld a,(dead)
inc a
ld (dead),a
ret ;; Return to BASIC
.removerocket
ld hl,(oy)
call &bb75
ld a,32
call &bb5a
ret
.printrocket
ld hl,(ypos)
call &bb75
ld a,3
call &bb90
ld a,239
call &bb5a
ret
.updaterocket
ld hl,(ypos)
call &bb75
ld a,32
call &bb5a
call scroll
ld hl,(ypos)
call &bb75
ld a,3
call &bb90
ld a,239
call &bb5a
call updateobstacle
ret
.updateobstacle
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,1
call &bb90
ld a,225
call &bb5a
ret
.collision
ld hl,(ex)
ex hl,de
ld hl,(ey)
call &bbf0
cp 1
jr nz,endcoll
ld a,(dead)
dec a
ld (dead),a
.endcoll
ret
.genseed
ld a,r
ld (seed),a
ret
.rand ld a,(seed)
ld b,a
add a,a
add a,a
add a,b
inc a
ld (seed),a
ret
.scroll
ld b,0
ld a,0
ld h,0
ld d,19
ld l,0
ld e,24
call &bc50
ret
.scalenum
ld a,(seed)
srl a
srl a
srl a
srl a
inc a
ld (result),a
ret
.ypos defb 12
.xpos defb 10
.oy defb 12
.ox defb 10
.ypos2 defb 13
.xpos2 defb 10
.dead defb 1
.seed defb 0
.result defb 0
.ex defw 292
.ey defw 238
I notice that .updaterocket is never called, but that doesn't really matter.
SCR_SOFTWARE_ROLL is indeed the culprit, regarding the speed.
Try SCR_HARDWARE_ROLL &BC4D instead. The speed difference is phenomenal.
Quote from: ervin on 14:05, 18 April 18
I notice that .updaterocket is never called, but that doesn't really matter.
I was using it initially to generate a PRINT rocket/Enter MainLoop/Delete Rocket/Scroll/PRINT Rocket scenario. At that stage, I hadn't added any controls and it was just checking for a collision and to exit the Loop if one had occurred. Unfortunately at that stage I couldn't see where the Rocket was until the Obstacle was either Deleted by it (which told me the collision failed), or the Program stopped and Rocket finally displayed.
QuoteSCR_SOFTWARE_ROLL is indeed the culprit, regarding the speed.
I'm guessing then it's not really meant for games, I used it in my introductory animated sequence for the game I coded a couple of years ago, which worked fine, but not strictly meant for during gameplay. Still, coding this simple assembly game and experimenting with different aspects is an interesting experience.
Last night I updated the scroll routine with a LDI scroll routine I made up a couple of years ago, though I thought the result was similar to the SCR_SW_ROLL, obviously substituting that code to the ".scroll" routine within my Dodging Obstacles code:
;; LDI Scroll - This shifts the screen down in rows at a time.
;; Top Row needs to be blank so contents don't push it all the way down the screen
org &4000
xor a ;; Position for Loop equals 0.
.loop
ld hl,(adr_hl) ;; This holds the address pointer and is place into HL
ld e,(hl) ;; Though the Contents from that address goes into DE
inc hl ;; Cause it's 16bit data this is the only way I know
ld d,(hl) ;; How to do it, there maybe other ways. I dunno.
ex de,hl ;; The data above needs to go into HL and not DE
push hl ;; I need to protect my data in HL
ld hl,(adr_de) ;; This holds the address pointer and is place into HL
ld e,(hl) ;; Though the Contents from that address goes into DE
inc hl ;; Cause it's 16bit data this is the only way I know
ld d,(hl) ;; How to do it, there maybe other ways. I dunno.
pop hl ;; But restore it again for this routine
repeat 80
ldi ;; Moves things along.
rend
ld hl,(adr_hl) ;; Increment Start Position to the next spot
inc hl
inc hl
ld (adr_hl),hl ;; And store it in that pointer variable.
ld hl,(adr_de) ;; Increment Destination to the next position
inc hl
inc hl
ld (adr_de),hl ;; And store it in that pointer variable
inc a ;; Increment Loop
cp 192 ;; Check if this equals 192.
jp nz,loop ;; returns if not equal to 192, otherwise exit
ld hl,begin ;; Restores pointer to the beginning
ld (adr_hl),hl ;; should the user want to continue calling routine
ld hl,dest ;; Restores pointer to the Destination
ld (adr_de),hl ;; should the user want to continue calling routine
ret ;; exit routine
.adr_hl defw begin ;; pointer position to where the start position is for HL register
.adr_de defw dest ;; pointer position to where the start position is for DE register
;; Below these are Screen co-ordinate positions for DE, move from bottom to top of the screen
.dest defw &C780,&CF80,&D780,&DF80,&E780,&EF80,&F780,&FF80
.begin defw &C730,&CF30,&D730,&DF30,&E730,&EF30,&F730,&FF30
defw &C6E0,&CEE0,&D6E0,&DEE0,&E6E0,&EEE0,&F6E0,&FEE0
defw &C690,&CE90,&D690,&DE90,&E690,&EE90,&F690,&FE90
defw &C640,&CE40,&D640,&DE40,&E640,&EE40,&F640,&FE40
defw &C5F0,&CDF0,&D5F0,&DDF0,&E5F0,&EDF0,&F5F0,&FDF0
defw &C5A0,&CDA0,&D5A0,&DDA0,&E5A0,&EDA0,&F5A0,&FDA0
defw &C550,&CD50,&D550,&DD50,&E550,&ED50,&F550,&FD50
defw &C500,&CD00,&D500,&DD00,&E500,&ED00,&F500,&FD00
defw &C4B0,&CCB0,&D4B0,&DCB0,&E4B0,&ECB0,&F4B0,&FCB0
defw &C460,&CC60,&D460,&DC60,&E460,&EC60,&F460,&FC60
defw &C410,&CC10,&D410,&DC10,&E410,&EC10,&F410,&FC10
defw &C3C0,&CBC0,&D3C0,&DBC0,&E3C0,&EBC0,&F3C0,&FBC0
defw &C370,&CB70,&D370,&DB70,&E370,&EB70,&F370,&FB70
defw &C320,&CB20,&D320,&DB20,&E320,&EB20,&F320,&FB20
defw &C2D0,&CAD0,&D2D0,&DAD0,&E2D0,&EAD0,&F2D0,&FAD0
defw &C280,&CA80,&D280,&DA80,&E280,&EA80,&F280,&FA80
defw &C230,&CA30,&D230,&DA30,&E230,&EA30,&F230,&FA30
defw &C1E0,&C9E0,&D1E0,&D9E0,&E1E0,&E9E0,&F1E0,&F9E0
defw &C190,&C990,&D190,&D990,&E190,&E990,&F190,&F990
defw &C140,&C940,&D140,&D940,&E140,&E940,&F140,&F940
defw &C0F0,&C8F0,&D0F0,&D8F0,&E0F0,&E8F0,&F0F0,&F8F0
defw &C0A0,&C8A0,&D0A0,&D8A0,&E0A0,&E8A0,&F0A0,&F8A0
defw &C050,&C850,&D050,&D850,&E050,&E850,&F050,&F850
defw &c000,&c800,&d000,&d800,&e000,&e800,&f000,&f800
Quote
Try SCR_HARDWARE_ROLL &BC4D instead. The speed difference is phenomenal.
Yep, so I replaced the SCR_SW_ROLL with SCR_HW_ROLL, and braced for impact. To give my rocket a chance I placed it lower down the screen (line 24). I've brought ".updaterocket" back into play too (I can now see a blinking Red Rocket), and the HW ROLL Scrolls twice, to prevent the vast number of obstacles which were onscreen. I still had to put a couple of MC_FRAME_WAIT (&BD19s) after that, I had some after the Obstacles were drawn too, but I've since removed. So this is what I've currently done:
org &8000
ld a,0
call &bc0e
call genseed
ld a,1
call &bb90
ld b,24
.drawobstacles
push bc
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,225
call &bb5a
call scroll
call scroll
pop bc
djnz drawobstacles
call printrocket
.maingame
call updaterocket
call collision
ld a,(dead)
cp 0
jr z,skip
ld a,1
call &bb1e
jr z,checkleft
ld a,(xpos)
cp 16
jr z,checkleft
inc a
ld (xpos),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
add hl,de
ld (ex),hl
.checkleft
ld a,8
call &bb1e
jr z,skip
ld a,(xpos)
cp 1
jr z,skip
dec a
ld (xpos),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
and a
sbc hl,de
ld (ex),hl
.skip ld a,(dead)
and a
jr nz,maingame
ld a,(dead)
inc a
ld (dead),a
ret ;; Return to BASIC
.removerocket
ld hl,(oy)
call &bb75
ld a,32
call &bb5a
ret
.printrocket
ld hl,(ypos)
call &bb75
ld a,3
call &bb90
ld a,239
call &bb5a
ret
.updaterocket
call removerocket
call scroll
call scroll
call printrocket
call &bd19
call &bd19
call updateobstacle
ret
.updateobstacle
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,1
call &bb90
ld a,225
call &bb5a
ret
.collision
ld hl,(ex)
ex hl,de
ld hl,(ey)
call &bbf0
cp 1
jr nz,endcoll
ld a,(dead)
dec a
ld (dead),a
.endcoll
ret
.genseed
ld a,r
ld (seed),a
ret
.rand ld a,(seed)
ld b,a
add a,a
add a,a
add a,b
inc a
ld (seed),a
ret
.scroll
ld b,0
ld a,0
call &bc4d
ret
.scalenum
ld a,(seed)
srl a
srl a
srl a
srl a
inc a
ld (result),a
ret
.ypos defb 24
.xpos defb 10
.oy defb 24
.ox defb 10
.dead defb 1
.seed defb 0
.result defb 0
.ex defw 292
.ey defw 46
Nice one.
Much more playable that way!
Nice :)
roundabout 8 bytes smaller and lets say ... a few ... T-states faster:
org &8000
xor a
call &bc0e
call genseed
ld a,1
call &bb90
ld b,24
.drawobstacles
push bc
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,225
call &bb5a
call scroll
call scroll
pop bc
djnz drawobstacles
call printrocket
.maingame
call updaterocket
call collision
ld a,(dead)
or a
jr z,skip
ld a,1
call &bb1e
jr z,checkleft
ld a,(xpos)
cp 16
jr z,checkleft
inc a
ld (xpos),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
add hl,de
ld (ex),hl
.checkleft
ld a,8
call &bb1e
jr z,skip
ld a,(xpos)
dec a
jr z,skip
ld (xpos),a
call removerocket
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
and a
sbc hl,de
ld (ex),hl
.skip ld a,(dead)
and a
jr nz,maingame
ld a,(dead)
inc a
ld (dead),a
ret ;; Return to BASIC
.removerocket
ld hl,(oy)
call &bb75
ld a,32
jp &bb5a
.printrocket
ld hl,(ypos)
call &bb75
ld a,3
call &bb90
ld a,239
jp &bb5a
.updaterocket
call removerocket
call scroll
call scroll
call printrocket
call &bd19
call &bd19
jp updateobstacle
.updateobstacle
call rand
call scalenum
ld a,(result)
ld h,a
ld l,1
call &bb75
ld a,1
call &bb90
ld a,225
jp &bb5a
.collision
ld hl,(ex)
ex hl,de
ld hl,(ey)
call &bbf0
dec a
jr nz,endcoll
ld a,(dead)
dec a
ld (dead),a
.endcoll
ret
.genseed
ld a,r
ld (seed),a
ret
.rand ld a,(seed)
ld b,a
add a,a
add a,a
add a,b
inc a
ld (seed),a
ret
.scroll
xor a
ld b,a
jp &bc4d
.scalenum
ld a,(seed)
srl a
srl a
srl a
srl a
inc a
ld (result),a
ret
.ypos defb 24
.xpos defb 10
.oy defb 24
.ox defb 10
.dead defb 1
.seed defb 0
.result defb 0
.ex defw 292
.ey defw 46
Quote from: SRS on 20:31, 19 April 18
Nice :)
roundabout 8 bytes smaller and lets say ... a few ... T-states faster:
Appreciate the improvements. Was keeping the update & collision routines separate, so I could work on adding additional code to it. The collision for example isn't perfect and thought I could make the game check if a collision with an obstacle has occurred when you move your rocket left or right.
I can also remove some code to remove the Rocket from the screen by simply moving the rocket to the bottom of the screen too, which will reduce the flicker I hope. :)
I've made some more updates to my assembly code using a modified version David Hall's Ariom Sprites to work in with my assembly code. Unfortunately I encountered a problem when I tried to use it with SCR HW ROLL. Not only does SCR HW ROLL roll the screen, it shifts the screens offset, so the Sprite Driver didn't know where to draw the sprites, I tried to rectify this with a variable to store a new base address, so I could do the SCR HW ROLL, followed by SCR CHAR POSITION (&BC1A), to get the new offset position, subtract &54 to it to get my new base address, which initially worked, but then the game crashed (obviously because of some sensitive area was being poked). Aaarrrrruggghhh!
So I replaced that Scroll routine with my own, which appears to be running at the same pace as the SCR SW ROLL routine I was using earlier. So it looks like for this game to work I'll need to go back to SCR HW ROLL and use some of my other firmware routines to Draw the characters.
I'll be posting an updated DSK in my top post, the program is in Binary Format, so
MEMORY &7FFF
LOAD"obacles3.bin"
CALL &8000
or
MEMORY &7FFF
LOAD"obacles5.bin"
CALL &8000
To load either of those programs.
org &8000
xor a
call &bc0e ;; Mode 0
ld hl,colours
call setinks
call genseed ;; Randomize Seed
ld a,1
call &bb90 ;; Pen 1
ld b,24
.drawobstacles
push bc
call rand
call scalenum
ld a,(result)
ld (xpos1),a
ld a,2
ld (ypos1),a
ld a,3
ld (spr_num),a
call ariom_spr
call scroll
pop bc
djnz drawobstacles
call printrocket
.maingame
ld a,(dead)
or a
jr z,skip
ld a,1
call &bb1e ;; KM Test Key
jr z,checkleft
ld a,(xpos)
cp 16
jr z,checkleft
call clearrocket
ld a,(xpos)
inc a
ld (xpos),a
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
add hl,de
ld (ex),hl
.checkleft
ld a,8
call &bb1e ;; KM Test Key
jr z,skip
ld a,(xpos)
cp 1
jr z,skip
call clearrocket
ld a,(xpos)
dec a
ld (xpos),a
call printrocket
ld a,(xpos)
ld (ox),a
ld hl,(ex)
ld de,32
and a
sbc hl,de
ld (ex),hl
.skip call collision
call updaterocket
call updateobstacle
ld a,(dead)
and a
jr nz,maingame
call printexplosion
ld a,(dead)
inc a
ld (dead),a
ret ;; Return to BASIC
.printrocket
ld hl,(ypos)
ld (ypos1),hl
ld a,1
ld (spr_num),a
call ariom_spr
ret
.updaterocket
call clearrocket
call scroll
call printrocket
call &bd19 ;; FRAME
call &bd19
call &bd19
call &bd19
ret
.clearrocket
ld hl,(ypos)
ld (ypos1),hl
ld a,0
ld (spr_num),a
call ariom_spr
ret
.printexplosion
ld hl,(ypos)
ld (ypos1),hl
ld a,2
ld (spr_num),a
call ariom_spr
ret
.updateobstacle
call rand
call scalenum
ld a,(result)
ld (xpos1),a
ld a,2
ld (ypos1),a
ld a,3
ld (spr_num),a
call ariom_spr
ret
.collision
ld hl,(ex)
ex hl,de
ld hl,(ey)
call &bbf0 ;; TEST(ex,ey)
cp 0 ;; PEN:=0
jr z,endcoll ;; IF yes endcoll
ld a,(dead) ;;
dec a ;; You're Dead
ld (dead),a ;;
.endcoll
ret
.genseed
ld a,r
ld (seed),a
ret
.rand ld a,(seed)
ld b,a
add a,a
add a,a
add a,b
inc a
ld (seed),a
ret
.setinks
ld c,(hl)
ld b,c
push af
push hl
call &bc32
pop hl
pop af
inc hl
inc a
cp 16
jr c,setinks
ret
.scroll
ld b,192 ;; This is how many lines to scroll down.
.loop
push bc ;; This protects the Loop Counter (not required at this stage)
ld hl,(adr_hl) ;; This holds the address pointer and is place into HL
ld e,(hl) ;; Though the Contents from that address goes into DE
inc hl ;; Cause it's 16bit data this is the only way I know
ld d,(hl) ;; How to do it, there maybe other ways. I dunno.
ex de,hl ;; The data above needs to go into HL and not DE
push hl ;; I need to protect my data in HL
ld hl,(adr_de) ;; This holds the address pointer and is place into HL
ld e,(hl) ;; Though the Contents from that address goes into DE
inc hl ;; Cause it's 16bit data this is the only way I know
ld d,(hl) ;; How to do it, there maybe other ways. I dunno.
pop hl ;; But restore it again for this routine
ld bc,&40 ;; BC is used here to address the length of the data on screen upto &40.
ldir ;; This instruction shifts the screen.
pop bc ;; Restores Loop Counter value so loop can address it.
ld hl,(adr_hl) ;; Increment Start Position to the next spot
inc hl
inc hl
ld (adr_hl),hl ;; And store it in that pointer variable.
ld hl,(adr_de) ;; Increment Destination to the next position
inc hl
inc hl
ld (adr_de),hl ;; And store it in that pointer variable
djnz loop ;; returns to loop if any remaining lines, otherwise proceed to exit
ld hl,begin ;; Restores pointer to the beginning
ld (adr_hl),hl ;; should the user want to continue calling routine
ld hl,dest ;; Restores pointer to the Destination
ld (adr_de),hl ;; should the user want to continue calling routine
ret ;; exit routine
.scalenum
ld a,(seed)
srl a
srl a
srl a
srl a
inc a
ld (result),a
ret
;; Ariom Sprites by David Hall
.ariom_spr
ld a,(spr_num)
ld b,a ;; Sprite Number
ld de,&0020 ;; Incrementer for 8x8 sprite (4 x 8 = 32 or 20h)
ld hl,Rocket-&20
;; address of sprites - &20 = &7d18
.spr_table
add hl,de ;; add &20 to &7d18 to obtain start of sprite table
djnz spr_table ;; loop until spr_num = 0, each loop adds &20 to obtain the correct sprite data
push hl ;; preserve sprite detail
ld a,(xpos1)
ld b,a ;; xpos details
ld hl,&bfac ;; this address serves as a base
ld e,&04 ;; 4 is incremented as each byte holds 4 colours
.x_scr_pos
add hl,de ;;
djnz x_scr_pos ;; loop until b reaches zero
ld e,&50 ;; &50 is added to place sprite in screen memory
ld a,(ypos1)
ld b,a ;; ypos details
.y_scr_pos
add hl,de ;;
djnz y_scr_pos ;; loop until b reaches zero, by this stage hl holds an address somewhere on-screen
pop de ;; restore sprite detail in de
ld c,&08 ;; c = height of image
.nxt_line
push hl ;; preserve screen address in hl
ld b,&04 ;; b = width of image
.drw_spr
ld a,(de) ;; a = byte contents
ld (hl),a ;; draw byte contents to screen
inc hl ;; increase screen address
inc de ;; increase to next position of sprite
djnz drw_spr ;; loop until b = 0
pop hl ;; restore original screen address
ld a,&08 ;; with a = 8
add h ;; add to h to position to a new line
ld h,a ;; and placed into h
dec c ;; decrement the height of the image
jr nz,nxt_line ;; if this doesn't equal 0 proceed to next line
ret ;; return to BASIC or M/C routine
.ypos defb 10
.xpos defb 10
.ypos1 defb 2
.xpos1 defb 5
.ox defb 10
.dead defb 1
.seed defb 0
.result defb 0
.ex defw 296
.ey defw 270
.spr_num
defb 3
.colours
defb 0,24,20,6,26,0,2,8,10,12,14,16,18,22,13,3
.adr_hl defw begin ;; pointer position to where the start position is for HL register
.adr_de defw dest ;; pointer position to where the start position is for DE register
;; Sprites
.Rocket
defb &00,&15,&00,&00; line 0
defb &00,&3A,&2A,&00; line 1
defb &15,&64,&35,&00; line 2
defb &15,&30,&35,&00; line 3
defb &00,&3A,&2A,&00; line 4
defb &15,&3A,&3F,&00; line 5
defb &44,&44,&44,&00; line 6
defb &00,&00,&00,&00; line 7
.Explosion
defb &00,&FF,&00,&00; line 0
defb &55,&CC,&AA,&00; line 1
defb &EE,&60,&DD,&00; line 2
defb &EE,&C0,&DD,&00; line 3
defb &EE,&C0,&DD,&00; line 4
defb &55,&CC,&AA,&00; line 5
defb &00,&FF,&00,&00; line 6
defb &00,&00,&00,&00; line 7
.Bolder
defb &00,&FF,&00,&00; line 0
defb &00,&FF,&AA,&00; line 1
defb &55,&FF,&FF,&AA; line 2
defb &FF,&FF,&FF,&FF; line 3
defb &55,&FF,&FF,&FF; line 4
defb &7F,&FF,&FF,&BF; line 5
defb &15,&7F,&7F,&2A; line 6
defb &00,&15,&15,&00; line 7
.dest defw &C780,&CF80,&D780,&DF80,&E780,&EF80,&F780,&FF80
.begin defw &C730,&CF30,&D730,&DF30,&E730,&EF30,&F730,&FF30
defw &C6E0,&CEE0,&D6E0,&DEE0,&E6E0,&EEE0,&F6E0,&FEE0
defw &C690,&CE90,&D690,&DE90,&E690,&EE90,&F690,&FE90
defw &C640,&CE40,&D640,&DE40,&E640,&EE40,&F640,&FE40
defw &C5F0,&CDF0,&D5F0,&DDF0,&E5F0,&EDF0,&F5F0,&FDF0
defw &C5A0,&CDA0,&D5A0,&DDA0,&E5A0,&EDA0,&F5A0,&FDA0
defw &C550,&CD50,&D550,&DD50,&E550,&ED50,&F550,&FD50
defw &C500,&CD00,&D500,&DD00,&E500,&ED00,&F500,&FD00
defw &C4B0,&CCB0,&D4B0,&DCB0,&E4B0,&ECB0,&F4B0,&FCB0
defw &C460,&CC60,&D460,&DC60,&E460,&EC60,&F460,&FC60
defw &C410,&CC10,&D410,&DC10,&E410,&EC10,&F410,&FC10
defw &C3C0,&CBC0,&D3C0,&DBC0,&E3C0,&EBC0,&F3C0,&FBC0
defw &C370,&CB70,&D370,&DB70,&E370,&EB70,&F370,&FB70
defw &C320,&CB20,&D320,&DB20,&E320,&EB20,&F320,&FB20
defw &C2D0,&CAD0,&D2D0,&DAD0,&E2D0,&EAD0,&F2D0,&FAD0
defw &C280,&CA80,&D280,&DA80,&E280,&EA80,&F280,&FA80
defw &C230,&CA30,&D230,&DA30,&E230,&EA30,&F230,&FA30
defw &C1E0,&C9E0,&D1E0,&D9E0,&E1E0,&E9E0,&F1E0,&F9E0
defw &C190,&C990,&D190,&D990,&E190,&E990,&F190,&F990
defw &C140,&C940,&D140,&D940,&E140,&E940,&F140,&F940
defw &C0F0,&C8F0,&D0F0,&D8F0,&E0F0,&E8F0,&F0F0,&F8F0
defw &C0A0,&C8A0,&D0A0,&D8A0,&E0A0,&E8A0,&F0A0,&F8A0
defw &C050,&C850,&D050,&D850,&E050,&E850,&F050,&F850
defw &c000,&c800,&d000,&d800,&e000,&e800,&f000,&f800
.theend
defb 0