What Snake said. The vblank works fine in my 32X code. Here's the snippets:
Code: Select all
| At this point (0x800), the Work RAM is clear, the VDP initialized, the
| VRAM/VSRAM/CRAM cleared, the Z80 initialized, the 32X initialized,
| both 32X framebuffers cleared, the 32X palette cleared, the SH2s
| checked for a startup error, the adapter TV mode matches the MD TV
| mode, and the ROM checksum checked. If any error is detected, the
| carry is set, otherwise it is cleared. The 68000 main code is now
| entered.
jmp __start+0x00880000+0x3F0
| 68000 General exception handler at 0x806
jmp __except+0x00880000+0x3F0
| 68000 Level 4 interrupt handler at 0x80C - HBlank IRQ
jmp __hblank+0x00880000+0x3F0
| 68000 Level 6 interrupt handler at 0x812 - VBlank IRQ
jmp __vblank+0x00880000+0x3F0
__except:
move.l d0,-(sp)
move.l 4(sp),d0 /* jump table return address */
sub.w #0x206,d0 /* 0 = BusError, 6 = AddrError, etc */
| handle exception
move.l (sp)+,d0
addq.l #4,sp /* pop jump table return address */
rte
__hblank:
rte
__vblank:
move.l d0,-(sp)
move.l 0xF00FFC,d0
beq.b 1f
move.l a0,-(sp)
movea.l d0,a0
jmp (a0)
1:
move.l (sp)+,d0
rte
__start:
cmp.l #0x4D5F4F4B,0xA15120 /* M_OK */
bne.b __start /* wait for master ok */
| init MD VDP
lea 0xC00004,a0
move.w #0x8004,(a0) /* reg. 0 - Disable HBL INT */
move.w #0x8174,(a0) /* reg. 1 - Enable display, VBL INT, DMA + 28 VCell size */
move.w #0x8230,(a0) /* reg. 2 - Plane A =$30*$400=$C000 */
move.w #0x832C,(a0) /* reg. 3 - Window =$2C*$400=$B000 */
move.w #0x8407,(a0) /* reg. 4 - Plane B =$7*$2000=$E000 */
move.w #0x855E,(a0) /* reg. 5 - sprite table begins at $BC00=$5E*$200 */
move.w #0x8600,(a0) /* reg. 6 - not used */
move.w #0x8700,(a0) /* reg. 7 - Background Color number*/
move.w #0x8800,(a0) /* reg. 8 - not used */
move.w #0x8900,(a0) /* reg. 9 - not used */
move.w #0x8A01,(a0) /* reg 10 - HInterrupt timing */
move.w #0x8B00,(a0) /* reg 11 - $0000abcd a=extr.int b=vscr cd=hscr */
move.w #0x8C81,(a0) /* reg 12 - hcell mode + shadow/highight + interlaced mode (40 cell, no shadow, no interlace)*/
move.w #0x8D2E,(a0) /* reg 13 - HScroll Table = $B800 */
move.w #0x8E00,(a0) /* reg 14 - not used */
move.w #0x8F02,(a0) /* reg 15 - auto increment data */
move.w #0x9011,(a0) /* reg 16 - scrl screen v&h size (64x64) */
move.w #0x9100,(a0) /* reg 17 - window hpos */
move.w #0x92FF,(a0) /* reg 18 - window vpos */
| init joyports
move.b #0x40,0xA10009
move.b #0x40,0xA1000B
move.b #0x40,0xA1000D
| check for pad 1
lea 0xA10003,a0
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 0 0 */
bsr get_input /* - 1 c b m x y z - 0 s a 1 1 1 1 */
andi.w #0x000C,d1
lsr.w #2,d1
andi.w #0x000C,d0
or.w d1,d0
ror.w #4,d0
| At this point, the high four bits hold the pad type we use to ID the controller
| 0000 if 3 btn pad
| 1100 if 6 btn pad
| 1111 if nothing (or multi-tap)
move.w d0,0xA15128 /* controller 1 type */
| check for pad 2
lea 0xA10005,a0
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
bsr get_input /* - 1 c b r l d u - 0 s a 0 0 0 0 */
bsr get_input /* - 1 c b m x y z - 0 s a 1 1 1 1 */
andi.w #0x000C,d1
lsr.w #2,d1
andi.w #0x000C,d0
or.w d1,d0
ror.w #4,d0
move.w d0,0xA1512A /* controller 2 type */
| Copy 68000 main loop to Work RAM to keep contention for the ROM with
| SH2s to a minimum.
lea __m68k_start(pc),a0
lea 0x00F01000,a1
move.w #__m68k_end-__m68k_start-1,d0
cpyloop:
move.b (a0)+,(a1)+
dbra d0,cpyloop
move.l #0,0xA1512C /* clear the vblank count */
move.w 0xA15100,d0
or.w #0x8000,d0
move.w d0,0xA15100 /* allow SH2 access to MARS hw */
move.l #0,0xA15120 /* let Master SH2 run */
| jump to main loop in Work RAM
jmp 0xF01000.l
| this block of code must be pc relative as it's copied into Work RAM
__m68k_start:
lea vert_blank(pc),a0
move.l a0,0xF00FFC /* set vertical blank interrupt handler */
move.w #0x2000,sr /* enable interrupts */
main_loop:
move.l 0xA15120,d0 /* get COMM0 */
beq.b main_loop
/* process request from Master SH2 */
move.l #0,0xA15120 /* done */
bra main_loop
vert_blank:
move.l d1,-(sp)
/* read controllers */
lea 0xA10003,a0
move.w 0xA15128,d0
andi.w #0xF000,d0 /* type */
beq.b rd_3btn_1
cmpi.w #0xC000,d0
beq.b rd_6btn_1
bra.b no_pad_1
rd_3btn_1:
bsr.w get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
moveq #0,d0
bra.b common_1
rd_6btn_1:
bsr.w get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
bsr.w get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
bsr.w get_input /* - 1 c b r l d u - 0 s a 0 0 0 0 */
bsr.w get_input /* - 1 c b m x y z - 0 s a 1 1 1 1 */
andi.w #0x0F00,d0 /* 0 0 0 0 m x y z 0 0 0 0 0 0 0 0 */
ori.w #0xC000,d0 /* 1 1 0 0 m x y z 0 0 0 0 0 0 0 0 */
eori.w #0x0F00,d0 /* 1 1 0 0 M X Y Z 0 0 0 0 0 0 0 0 */
common_1:
andi.w #0x3F30,d1 /* 0 0 c b r l d u 0 0 s a 0 0 0 0 */
lsl.b #2,d1 /* 0 0 c b r l d u s a 0 0 0 0 0 0 */
move.w d1,d2
lsr.w #8,d1 /* 0 0 0 0 0 0 0 0 0 0 c b r l d u */
or.b d2,d1 /* 0 0 0 0 0 0 0 0 s a c b r l d u */
eori.b #0xFF,d1 /* 0 0 0 0 0 0 0 0 S A C B R L D U */
move.b d1,d0
move.w d0,0xA15128 /* controller 1 current value */
no_pad_1:
lea 0xA10005,a0
move.w 0xA1512A,d0
andi.w #0xF000,d0 /* type */
beq.b rd_3btn_2
cmpi.w #0xC000,d0
beq.b rd_6btn_2
bra.b no_pad_2
rd_3btn_2:
bsr.b get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
moveq #0,d0
bra.b common_2
rd_6btn_2:
bsr.b get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
move.w d0,d1
bsr.b get_input /* - 1 c b r l d u - 0 s a 0 0 d u */
bsr.b get_input /* - 1 c b r l d u - 0 s a 0 0 0 0 */
bsr.b get_input /* - 1 c b m x y z - 0 s a 1 1 1 1 */
andi.w #0x0F00,d0 /* 0 0 0 0 m x y z 0 0 0 0 0 0 0 0 */
ori.w #0xC000,d0 /* 1 1 0 0 m x y z 0 0 0 0 0 0 0 0 */
eori.w #0x0F00,d0 /* 1 1 0 0 M X Y Z 0 0 0 0 0 0 0 0 */
common_2:
andi.w #0x3F30,d1 /* 0 0 c b r l d u 0 0 s a 0 0 0 0 */
lsl.b #2,d1 /* 0 0 c b r l d u s a 0 0 0 0 0 0 */
move.w d1,d2
lsr.w #8,d1 /* 0 0 0 0 0 0 0 0 0 0 c b r l d u */
or.b d2,d1 /* 0 0 0 0 0 0 0 0 s a c b r l d u */
eori.b #0xFF,d1 /* 0 0 0 0 0 0 0 0 S A C B R L D U */
move.b d1,d0
move.w d0,0xA1512A /* controller 2 current value */
no_pad_2:
move.l 0xA1512C,d0
addq.l #1,d0
move.l d0,0xA1512C /* increment the vblank count */
move.l (sp)+,d1
movea.l (sp)+,a0
move.l (sp)+,d0
rte
| read single phase from controller
get_input:
move.b #0x40,(a0)
nop
nop
nop
move.b (a0),d0
move.b #0x00,(a0)
lsl.w #8,d0
nop
move.b (a0),d0
move.b #0x40,(a0)
rts
__m68k_end:
With that, the vblank does happen, the counter is advanced and the pads read (although nobody but gens likes the 6-button controller code yet).