;Shock collar debug program for Sega Genesis
;CC Furrtek 2012

    cpu 68000
    supmode on

WRAM           equ  $FF0000    ; Work RAM

DPORT          equ  $C00000    ; VDP Data
CPORT          equ  $C00004    ; VDP Command

 org    $0
 
; Vector table (most point to an RTS)

 dc.l   $00FFFFFE,     Start, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   HBlankInt, Interrupt, VBlankInt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.l   Interrupt, Interrupt, Interrupt, Interrupt
 dc.b   "SEGA MEGA DRIVE "
 dc.b   "GPL/AL 2011     "
 dc.b   "Joypad comm test for shock collar               "
 dc.b   "Joypad comm test for shock collar               "   ; Name (export)
 dc.b   "GM T-000006-01"                                     ; Serial
 dc.w   $0000
 dc.b   "                "
 dc.l   $00000000, $000003FF
 dc.l   $00FF0000, $00FFFFFF
 dc.l   $00000000, $00000000, $00000000
 dc.b   "            "
 dc.b   "D                                       "
 dc.b   "E               "

; Variables

     org WRAM
MENU:          ds.b 1
OLD_JP1:       ds.b 1
VBL:           ds.b 1
TIMER:         ds.w 1

     org $400

HBlankInt:
     rte
     
VBlankInt:
     st.b   VBL
     rte

Interrupt:
     rts

Start:
     move.w  #$2700,sr              ; No IRQs

     move.b  $A10001,d0             ; "SEGA" @ $A14000 if version > 0
     andi.b  #$0F,d0
     beq     .version_0
     move.l  $100,$A14000
.version_0:

     lea    VDPinit,a0              ; VDP registers init
     moveq  #19-1,d0
.initvdp:
     move.w (a0)+,CPORT
     dbra   d0,.initvdp

     lea    WRAM,a0                 ; Empties 4*$FF of RAM
     move.l #$FF-1,d0
.clram:
     clr.l  (a0)+
     dbra   d0,.clram

     move.l #$50000003,CPORT        ; VRAM WRITE @ $D000 (H Scroll tables)
     move.l #28-1,d0                ; 28 tile lines
.clscrolls:
     move.w #0,DPORT                ; Scroll A=0
     move.w #0,DPORT                ; Scroll B=0
     dbra   d0,.clscrolls
     
     move.l #$40000003,CPORT        ; VRAM Write @ $C000 (BG Map A)
     move.l #(64*32)-1,d0
.cltilesa:
     move.w #$8000,DPORT
     dbra   d0,.cltilesa

     move.l #$60000003,CPORT        ; VRAM Write @ $E000 (BG Map B)
     move.l #(64*32)-1,d0
.cltilesb:
     move.w #0,DPORT
     dbra   d0,.cltilesb

     move.l #$60000000,CPORT        ; VRAM Write @ $2000 (tile 256)
     lea    alpha,a0                ; Load alphabet
     move.l #(64*32/4)-1,d7         ; 64 tiles
.ldalpha:
     move.l (a0)+,DPORT
     dbra   d7,.ldalpha

     move.l #$C0000000,CPORT        ; CRAM Write (Color RAM)
     lea    palette,a1
     move.l #16-1,d0                ; 16 colors
.ldpal:
     move.w (a1)+,DPORT
     dbra   d0,.ldpal
     
     move.l #$42060003,CPORT        ; Title text
     lea    txt_title,a0
     jsr    disptext
     move.l #$4C240003,CPORT        ; Not even ashamed
     lea    txt_cc,a0
     jsr    disptext

     move.l #$44960003,CPORT        ; Short zap P1 text
     lea    txt_zap1s,a0
     jsr    disptext
     move.l #$45160003,CPORT        ; Short zap P2 text
     lea    txt_zap2s,a0
     jsr    disptext
     move.l #$45960003,CPORT        ; Short zap both text
     lea    txt_zap3s,a0
     jsr    disptext
     move.l #$46160003,CPORT        ; Zap P1 text
     lea    txt_zap1,a0
     jsr    disptext
     move.l #$46960003,CPORT        ; Zap P2 text
     lea    txt_zap2,a0
     jsr    disptext
     move.l #$47160003,CPORT        ; Zap both text
     lea    txt_zap3,a0
     jsr    disptext

     move.w #$2000, sr              ; IRQs on

; Main loop

.mainlp:
     tst.b  VBL
     beq    .mainlp                 ; Wait for VBlank
     clr.b  VBL

     tst.w  TIMER                   ; Don't touch timer if already at zero
     beq    .nodec
     subq.w #1,TIMER
     
     cmp.w  #150,TIMER              ; Display "THREE" if timer = 150
     bne    .no300
     move.l #$49160003,CPORT
     lea    txt_premier,a0
     jsr    disptext
     bra    .nodec
.no300:
     cmp.w  #100,TIMER              ; Display "TWO" if timer = 100
     bne    .no200
     move.l #$49220003,CPORT
     lea    txt_milieu,a0
     jsr    disptext
     bra    .nodec
.no200:
     cmp.w  #50,TIMER                Display "ONE" if timer = 50
     bne    .no100
     move.l #$492A0003,CPORT
     lea    txt_dernier,a0
     jsr    disptext
     bra    .nodec
.no100:
     cmp.w  #1,TIMER                ; Clear text if timer = 1 and...
     bne    .nodec
     move.l #$49160003,CPORT
     lea    txt_eff,a0
     jsr    disptext

     cmp.b  #0,MENU                 ; ...execute selection
     bne    .no0
     jsr    zap1s
.no0:
     cmp.b  #1,MENU
     bne    .no1
     jsr    zap2s
     bra    .nodec
.no1:
     cmp.b  #2,MENU
     bne    .no2
     jsr    zap1s
     jsr    zap2s
     bra    .nodec
.no2:
     cmp.b  #3,MENU
     bne    .no3
     jsr    zap1
     bra    .nodec
.no3:
     cmp.b  #4,MENU
     bne    .no4
     jsr    zap2
     bra    .nodec
.no4:
     cmp.b  #5,MENU
     bne    .nodec
     jsr    zap1
     jsr    zap2

.nodec:


     clr.l  d0                      ; Display arrow in front of selected item
     move.b MENU,d0
     lsl.w  #7,d0                   ; *128 (64 tiles * 2 bytes per line)
     addi.l #$4492,d0               ; Offset of first item
     move.w d0,CPORT
     move.l #$0003,d0
     move.w d0,CPORT
     move.w #$8100+'>'-32,DPORT     ; Put > character in BG map

     ; Read joypad 1
     move.b #$40,$A10006            ; SELECT of port 1 is an output
     move.b #$40,$A10003            ; SELECT high
     nop
     nop
     move.b $A10003,d0              ; Get xxCBRLDU
     andi.b #$3F,d0                 ;     00CBRLDU
     nop
     nop
     move.b #$00,$A10003            ; SELECT low
     nop
     nop
     move.b $A10003,d1              ; Get xxSA00DU
     andi.b #$30,d1                 ;     00SA0000
     lsl.b  #2,d1                   ;     SA000000
     or.b   d1,d0                   ;     SACBRLDU
     eori.b #$FF,d0
     move.b OLD_JP1,d1
     move.b d0,OLD_JP1
     eor.b  d0,d1
     and.b  d0,d1                   ; Keep rising edges

     btst   #0,d1
     beq    .nou                    ; Up
     jsr    clrm                    ; Clear last arrow
     subq.b #1,MENU
     cmp.b  #$FF,MENU
     bne    .nou
     move.b #5,MENU                 ; Wrap cursor to 5
.nou:

     btst   #1,d1
     beq    .nod                    ; Down
     jsr    clrm                    ; Clear last arrow
     addq.b #1,MENU
     cmp.b  #6,MENU
     bne    .nod
     clr.b  MENU                    ; Wrap cursor to 0
.nod:

     btst   #6,d1
     beq    .noa                    ; A
     move.w #160,TIMER              ; Start up timer
.noa:

     bra    .mainlp
     
; Zapping routines

zap1s:                              ; Short zap player 1
     move.b #$40,$A10009            ; SELECT of port 1 is an output
     move.l #6-1,d0                 ; 6 pulses (12 state changes)
.z1s:
     move.b #$40,$A10003            ; SELECT high
     nop
     move.b #$00,$A10003            ; SELECT low
     dbra   d0,.z1s
     rts
     
zap2s:                              ; Short zap player 2
     move.b #$40,$A1000B            ; SELECT of port 2 is an output
     move.l #6-1,d0                 ; 6 pulses (12 state changes)
.z2s:
     move.b #$40,$A10005            ; SELECT high
     nop
     move.b #$00,$A10005            ; SELECT low
     dbra   d0,.z2s
     rts

zap1:                               ; Long zap player 1
     move.b #$40,$A10009            ; SELECT of port 1 is an output
     move.l #8-1,d0                 ; 8 pulses (16 state changes)
.z1:
     move.b #$40,$A10003            ; SELECT high
     nop
     move.b #$00,$A10003            ; SELECT low
     dbra   d0,.z1
     rts
     
zap2:                               ; Long zap player 2
     move.b #$40,$A1000B            ; SELECT of port 2 is an output
     move.l #8-1,d0                 ; 8 pulses (16 state changes)
.z2:
     move.b #$40,$A10005            ; SELECT high
     nop
     move.b #$00,$A10005            ; SELECT low
     dbra   d0,.z2
     rts

; Arrow clearing

clrm:
     clr.l  d0
     move.b MENU,d0
     lsl.w  #7,d0
     addi.l #$4492,d0
     move.w d0,CPORT
     move.l #$0003,d0
     move.w d0,CPORT
     move.w #$8100+' '-32,DPORT
     rts

txt_title:
 dc.b "SHOCK COLLAR DEBUG",$00
txt_cc:
 dc.b "FURRTEK SYSTEMS 2012",$00
txt_zap1s:
 dc.b "SHORT ZAP PLAYER 1",$00
txt_zap2s:
 dc.b "SHORT ZAP PLAYER 2",$00
txt_zap3s:
 dc.b "SHORT ZAP BOTH PLAYER",$00
txt_zap1:
 dc.b "ZAP PLAYER 1",$00
txt_zap2:
 dc.b "ZAP PLAYER 2",$00
txt_zap3:
 dc.b "ZAP BOTH PLAYERS",$00
txt_premier:
 dc.b "THREE",$00
txt_milieu:
 dc.b "TWO",$00
txt_dernier:
 dc.b "ONE",$00
txt_eff:
 dc.b "             ",$00

palette:
 dc.w   $0700,$0EEE,$0060,$0066
 dc.w   $0600,$0606,$0660,$0666
 dc.w   $0EEE,$000E,$00E0,$00EE
 dc.w   $0E00,$0E0E,$0EE0,$000E

disptext:
     clr.w  d0
     move.b (a0)+,d0
     beq    .quit                   ; End of string on zero byte
     addi.w #($100-32)+$8000,d0     ; ASCII offset
     move.w d0,DPORT
     bra    disptext
.quit:
     rts

alpha:
 BINCLUDE "alpha.bin"               ; Alphabet characters (4BPP)
     
VDPinit:
 dc.w   $8004    ; Raster int:OFF, Full palette, TV out on
 dc.w   $8164    ; TV:ON, Vblank int:ON, DMA:OFF, V:240 pixels
 dc.w   $8236    ; Map A address
 dc.w   $8338    ; Window map address
 dc.w   $8407    ; Map B address
 dc.w   $857E    ; Sprite RAM address
 dc.w   $8700    ; Border color
 dc.w   $8A00    ; No raster interrupt
 dc.w   $8B00    ; Scroll mode
 dc.w   $8C81    ; H: 320 pixels, Shadow:OFF, interlace:OFF
 dc.w   $8D34    ; Scroll table address
 dc.w   $8F02    ; VRAM autoinc: +2
 dc.w   $9001    ; 64*32 tiles BG maps
 dc.w   $9100    ; Window width
 dc.w   $9200    ; Window height
 dc.w   $9300    ; DMA stuff...
 dc.w   $9400
 dc.w   $9500
