; VM -a- Sketch v1.4 ; ; An Etch-a-Sketch simulator for the VM ; ; by Richard Munn / RAMTronics Software ; http://go.to/rvmu ; richard.munn@bigfoot.com ; ; portions based upon marcus comstedt's tiny tetris source ; http://marcus.mangakai.org/dc/ ; ; plotxy code taken from john maushammer's vmu gong source ; http://www.tidalwave.net/~maushammer/vmu.html ; ; History: ; v1.0 - First beta release - on http://go.to/rvmu and within the Amiga VMU Devkit release 1.2 ; v1.1 - Adjusted delay so that it runs at a better speed in SoftVMS v1.6 ; v1.2 - The "draw spot" is now white when moving, to make it easier to find, and to add some realism! ; v1.3 - adjusted header title to the correct 32 characters ; - changed clock speed to Marcus' suggestion to save power ; - adjusted code to allow for diagonal movement (hopefully!) ; v1.4 - diagonal movement really works now! .include "sfr.i" ;; Reset and interrupt vectors .org 0 jmpf start .org $3 jmp nop_irq .org $b jmp nop_irq .org $13 jmp nop_irq .org $1b jmp t1int .org $23 jmp nop_irq .org $2b jmp nop_irq .org $33 jmp nop_irq .org $3b jmp nop_irq .org $43 jmp nop_irq .org $4b clr1 p3int,0 clr1 p3int,1 nop_irq: reti .org $130 t1int: push ie clr1 ie,7 not1 ext,0 jmpf t1int pop ie reti .org $1f0 goodbye: not1 ext,0 jmpf goodbye ;; Header .org $200 .byte "VM -a- " .byte " Sketch " .byte "VM -a- Sketch by RAMTronics " ;; Icon data generated by Brush2VMUICON.pprx by Richard Munn ;; Icon Header .org $240 .word 1,10 ; 1 frame ;; Icon Palette .org $260 .word $f000, $f111, $f222, $f333, $f444, $f555, $f666, $f777 .word $f888, $f999, $faaa, $fbbb, $fccc, $ffff, $ffff, $ffff .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc .byte $cc,$c9,$ac,$cc,$b7,$78,$66,$bc,$cb,$9b,$cc,$b6,$cc,$ac,$c8,$cc .byte $cc,$63,$6b,$8c,$54,$c4,$69,$b7,$30,$03,$c7,$46,$cc,$2c,$b2,$bc .byte $c2,$6b,$cc,$69,$0b,$c4,$9c,$ca,$62,$bc,$95,$cc,$cc,$1b,$b3,$cc .byte $c1,$ac,$c9,$51,$7c,$b1,$ab,$cc,$62,$cc,$39,$cc,$cc,$1b,$b1,$cc .byte $c6,$4b,$cb,$06,$cc,$a0,$06,$cc,$62,$cc,$0c,$cc,$cc,$08,$43,$cc .byte $cc,$61,$68,$31,$bc,$80,$cc,$cc,$63,$cc,$2b,$cc,$cb,$16,$34,$cc .byte $cc,$cb,$46,$64,$7c,$73,$c7,$6c,$61,$cc,$65,$cc,$b9,$0a,$63,$cc .byte $cc,$76,$39,$68,$5c,$81,$34,$9c,$71,$cc,$b3,$5a,$69,$0a,$83,$cc .byte $cc,$66,$bc,$bb,$7c,$b6,$6c,$cc,$b9,$cc,$cc,$55,$7c,$6b,$bc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc .byte $cc,$cc,$cc,$cc,$ca,$aa,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc .byte $cc,$cc,$cc,$cc,$ca,$d6,$88,$88,$88,$88,$88,$88,$88,$88,$cc,$cc .byte $cc,$cc,$cc,$cc,$ca,$aa,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$88,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$88,$88,$88,$88,$88,$88,$88,$88,$88,$8c,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$c8,$cc,$cc .byte $cc,$cc,$cc,$88,$88,$88,$88,$88,$88,$88,$88,$88,$88,$88,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc .byte $cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$cc,$8c,$cc,$cc,$cc cursx = $30 cursy = $31 seed = $32 loop = $34 delneed = $33 keyspressed = $35 ;; Main program start: mov #$a3,ocr mov #$09,mcr mov #$80,vccr clr1 p3int,0 clr1 p1,7 mov #$ff,p3 ld t0l st seed mov #24,cursx mov #16,cursy mov #1,delneed mov #introscreen,trh call setscr waitstart: call getkeys and #$30 ; Wait for A+B bnz waitstart call clrscr sketchloop: ld cursx st B ld cursy call plotxy call docursor bz sketchloop ld cursx st B ld cursy call unplotxy ld delneed bz .nodel mov #$70,acc .delay: dbnz acc,.delay ; delay loop to temper the VMU's awesome speed .nodel jmp sketchloop docursor: call getkeys ; check for presses st keyspressed bn keyspressed,4,.shake ; A button press bn keyspressed,5,.clear ; B button press mov #1, delneed mov #0,b bn keyspressed,2,.moveleft .ld bn keyspressed,1,.movedown .lu bn keyspressed,0,.moveup .lr bn keyspressed,3,.moveright .exit ld b ret .moveright: ld cursx ; make sure we don't go off screen be #47,.exit ; already at right edge? then don't move inc cursx ; move the dot to the right mov #1,b br .exit .moveleft: ld cursx ; check to make sure we don't go off-screen be #0,.ld ; it's already at left edge dec cursx ; move dot left mov #1,b br .ld .movedown: ld cursy ; make sure we don't go off screen be #31,.lu ; it's already at bottom edge inc cursy ; move dot down mov #1,b br .lu .moveup: ld cursy ; check to make sure we don't go off-screen be #0,.lr ; it's already at top edge dec cursy ; move dot up mov #1,b br .lr .shake mov #0, delneed mov #50, loop .shakelop clr1 PSW,1 ld $01D set1 PSW,1 st C call random ror and #%00011111 st B call random add C and #%00001111 add B st B call random and #%00011111 call unplotxy dec loop ld loop bnz .shakelop br .exit .clear call clrscr br .exit * ---------------------------------------------------------------------- * getkeys - a fancy 'ld p3' instruction that handles mode button (quit), * dreamcast connection, and sleep. * getkeys: bp p7,0,quit ; If dreamcast is connected, then quit ld p3 ; read the keys bn acc,6,quit ; mode key quits bn acc,7,sleep ; sleep key sleeps for a bit ret ; otherwise, return the current key (if any) quit: jmp goodbye ; long jump in case branch can't make it to 'goodbye' sleep: set1 pcon,0 ; Enter HALT mode for a bit of time (save power) bn p3,7,sleep ; Wait for SLEEP to be released mov #0,vccr ; Blank LCD sleepmore: set1 pcon,0 ; Enter HALT mode for a bit of time bp p7,0,quit ; Docked? bp p3,7,sleepmore ; No SLEEP press yet mov #$80,vccr ; Reenable LCD waitsleepup: set1 pcon,0 ; Enter HALT mode for a bit of time (save power) bn p3,7,waitsleepup br getkeys ; continue waiting for the keypress program asked for * --------------------------------------------------------------------------- * Simple plotxy, using tables to speed up operation * * inputs: B = x coordinate (0-47) * acc = y coordinate (0-31) * * messes up: acc, R3, xbnk * preserves: B * * Average of about 28 cycles. * plotxy: mov #0,xbnk ; assume on top half of screen bn acc,4,.pltop ; we were right mov #1,xbnk ; we were wrong- learn to live with it. .pltop mov #ylookup&$ff,trl mov #ylookup>>8,trh ldc ; lookup st 3 ; this now points to start of line we need to modify ld B ; get x coord ror ror ror and #$1F ; drop bits that we rolled around to calc bytes into line add 3 ; add address of beginning of line (stored in register 2) st 3 ; now point to byte we need to modify mov #xlookup&$ff,trl * mov #xlookup>>8,trh ; not be needed if placed correctly ld B ; 48 possibilities * and #7 ; 8 possibilities (if ommited, need larger table) ldc ; get bitmask to use mov #$81,ocr or @R3 ; add to what's already on-screen st @R3 ; plot pixel mov #$a3,ocr ret unplotxy: mov #0,xbnk ; assume on top half of screen bn acc,4,.pltop ; we were right mov #1,xbnk ; we were wrong- learn to live with it. .pltop mov #ylookup&$ff,trl mov #ylookup>>8,trh ldc ; lookup st 3 ; this now points to start of line we need to modify ld B ; get x coord ror ror ror and #$1F ; drop bits that we rolled around to calc bytes into line add 3 ; add address of beginning of line (stored in register 2) st 3 ; now point to byte we need to modify mov #xlookup2&$ff,trl mov #xlookup2>>8,trh ; not be needed if placed correctly ld B ; 48 possibilities * and #7 ; 8 possibilities (if ommited, need larger table) ldc ; get bitmask to use mov #$81,ocr and @R3 ; erase what's already on-screen st @R3 ; unplot pixel mov #$a3,ocr ret *----- * tables used by plotxy and unplotxy *----- .cnop 0,$100 ; pad to an even number of pages (so that the high byte doesn't need to be reloaded between using tables) ylookup: .byte $80,$86,$90,$96,$a0,$a6,$b0,$b6,$c0,$c6,$d0,$d6,$e0,$e6,$f0,$f6 .byte $80,$86,$90,$96,$a0,$a6,$b0,$b6,$c0,$c6,$d0,$d6,$e0,$e6,$f0,$f6 xlookup: .byte $80,$40,$20,$10,$08,$04,$02,$01 .byte $80,$40,$20,$10,$08,$04,$02,$01 ; These extra elements used if .byte $80,$40,$20,$10,$08,$04,$02,$01 ; 'and #7' is ommited (faster) .byte $80,$40,$20,$10,$08,$04,$02,$01 .byte $80,$40,$20,$10,$08,$04,$02,$01 .byte $80,$40,$20,$10,$08,$04,$02,$01 xlookup2: .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE ; These extra elements used if .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE ; 'and #7' is ommited (faster) .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE .byte $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE *------------------------------------------------------ * Clear screen * clrscr: push acc push xbnk push 2 mov #0,xbnk mov #$81,ocr .cbank: mov #$80,2 ; beginning of LCD memory .cloop: mov #0,@R2 inc 2 ld 2 and #$f bne #$c,.cskip ld 2 add #4 st 2 .cskip: ld 2 bnz .cloop bp xbnk,0,.cexit mov #1,xbnk br .cbank .cexit: mov #$a3,ocr pop 2 pop xbnk pop acc mov #$a3,ocr ret setscr: mov #$81,ocr push acc push xbnk push c push 2 mov #$80,2 xor acc st xbnk st c .sloop: ldc st @R2 inc 2 ld 2 and #$f bne #$c,.sskip ld 2 add #4 st 2 bnz .sskip inc xbnk mov #$80,2 .sskip: inc c ld c bne #$c0,.sloop pop 2 pop c pop xbnk pop acc mov #$a3,ocr ret random: push b push c ld seed st b mov #$4e,acc mov #$6d,c mul st b ld c add #$39 st seed ld b addc #$31 pop c pop b ret introscreen: .byte %11111000,%01110001,%10000110,%11111100,%00000000,%00000000 .byte %11001100,%01110001,%11001110,%00110000,%00000000,%00000000 .byte %11001100,%11011001,%11001110,%00110000,%00000000,%00000000 .byte %11111000,%11011001,%11111110,%00110110,%00100010,%01001011 .byte %11001100,%11111001,%10110110,%00110101,%01010101,%01010010 .byte %11001101,%10001101,%10110110,%00110110,%01010101,%01010001 .byte %11001101,%10001101,%10110110,%00110101,%00100101,%01001011 .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 .byte %00000000,%00000010,%00101000,%10000000,%00000000,%00000000 .byte %00000000,%00000010,%00101101,%10000000,%00000000,%00000000 .byte %00000000,%00000001,%01001010,%10000001,%10000000,%00000000 .byte %00000000,%00000001,%01001010,%10111100,%11011110,%00000000 .byte %00111110,%00011000,%10001000,%10000001,%01000000,%11000000 .byte %01100011,%00011000,%10001000,%10011000,%11000000,%11000000 .byte %11000001,%10011000,%00000000,%00011000,%00000000,%11000000 .byte %11000001,%10011001,%11001111,%01111110,%01111000,%11011100 .byte %11000000,%00011011,%10011001,%10011000,%11001110,%11100110 .byte %01111100,%00011011,%00110000,%11011001,%10000110,%11000110 .byte %00011111,%00011110,%00110000,%11011001,%10000000,%11000110 .byte %00000001,%10011111,%00111111,%11011001,%10000000,%11000110 .byte %11000001,%10011011,%00110000,%00011001,%10000000,%11000110 .byte %11000001,%10011001,%10110000,%11011001,%10000110,%11000110 .byte %01100011,%00011001,%10011001,%10011000,%11001100,%11000110 .byte %00111110,%00011001,%11001111,%00001110,%01111000,%11000110 .byte %00000000,%00000000,%00000000,%00000000,%00000000,%00000000 .byte %00000000,%00000000,%00110011,%00110010,%01000111,%00000110 .byte %00000000,%00000000,%00101010,%10100100,%10000101,%00100101 .byte %00000000,%00000000,%00110011,%00110110,%11000111,%01110110 .byte %00000000,%00000000,%00100010,%10100010,%01000101,%00100101 .byte %00000000,%00000000,%00100010,%10110100,%10000101,%00000110 .byte "$VER: sketch 1.4 (14.2.2000)" .cnop 0,$200 ; pad to an even number of blocks