Mega Mouse Usage
Moderator: BigEvilCorporation
-
- Very interested
- Posts: 2984
- Joined: Fri Aug 17, 2007 9:33 pm
Re: Mega Mouse Usage
I see, you're trying to improve your emulator to get those weird games that didn't follow the rules to work by finding all the edge cases for incorrect usage. Those can be kinda fun to get working without breaking everything else.
Re: Mega Mouse Usage
Yes, that's pretty much it
Re: Mega Mouse Usage
Hi, sorry to bother, but i don't know where else to ask about Genesis assembler...
The Russian hacker "Ti" made an almost complete mouse patch for Dune, but lost interest.
It already works well except building placement has problems, sometimes it drifts a bit.
Could anyone else please take a quick look, perhaps (i hope) it's a quick fix?
I ask because there's a whole Russian Genesis Dune romhacking community out here.
And all these giant romhacks would benefit immensely from actual mouse support:
https://www.emu-land.net/forum/index.php?topic=16864
They even have 480x464 hacks of Dune, using a modded Mednafen, it's amazing:
The goal is to play those 480x464 hacks with the mouse.
Attached is the .asm patch i received from Ti, it's for: Dune - The Battle for Arrakis (USA).md CRC 4DEA40BA
Any thoughts or comments? Thanks & cheers
The Russian hacker "Ti" made an almost complete mouse patch for Dune, but lost interest.
It already works well except building placement has problems, sometimes it drifts a bit.
Could anyone else please take a quick look, perhaps (i hope) it's a quick fix?
I ask because there's a whole Russian Genesis Dune romhacking community out here.
And all these giant romhacks would benefit immensely from actual mouse support:
https://www.emu-land.net/forum/index.php?topic=16864
They even have 480x464 hacks of Dune, using a modded Mednafen, it's amazing:
The goal is to play those 480x464 hacks with the mouse.
Attached is the .asm patch i received from Ti, it's for: Dune - The Battle for Arrakis (USA).md CRC 4DEA40BA
Any thoughts or comments? Thanks & cheers
- Attachments
-
- dunemouse.rar
- (2.32 KiB) Downloaded 697 times
-
- Very interested
- Posts: 2984
- Joined: Fri Aug 17, 2007 9:33 pm
Re: Mega Mouse Usage
It drifts because it doesn't handle the sign bits for the mouse. It also doesn't check for overflow, but that's probably not an issue most of the time. Here's how it handles x and y
Note that all it does is simply use the raw x and y values from the mouse, sign extended to a word and divided by two. That may work some of the time, but isn't correct and will drift under the wrong conditions. The proper way to handle it is like this
Here we check for overflow, and then we properly sign extend the value using the sign bits. See how the extension is done? "mx |= mx ? 0xFF00 : 0xFFFF;" That prevents the drift you see in the game.
Code: Select all
move.w ($FFFFBF14).w,d1
move.b d0,d2
ext.w d2
asr.w #1,d2
sub.w d2,d1
cmpi.w #$D0,d1
ble.s *+6
move.w #$D0,d1
cmpi.w #$10,d1
bge.s *+6
move.w #$10,d1
move.w d1,($FFFFBF14).w
lsr.l #8,d0
move.w ($FFFFBF12).w,d1
move.b d0,d2
ext.w d2
asr.w #1,d2
add.w d2,d1
cmpi.w #$130,d1
ble.s *+6
move.w #$130,d1
cmpi.w #$10,d1
bge.s *+6
move.w #$10,d1
move.w d1,($FFFFBF12).w
Code: Select all
if (md[0] & 0x04)
mx = 256; /* x overflow */
else
mx = md[2]<<4 | md[3];
if (md[0] & 0x01)
mx |= mx ? 0xFF00 : 0xFFFF; /* x sign extend */
if (md[0] & 0x08)
my = 256; /* y overflow */
else
my = md[4]<<4 | md[5];
if (md[0] & 0x02)
my |= my ? 0xFF00 : 0xFFFF; /* y sign extend */
joyAxisX[port] += (s16)mx;
joyAxisY[port] += (s16)my;
Re: Mega Mouse Usage
If you're going as far as hacked emulators to use a resolution it wasn't designed for, is that really worth playing vs just running the PC version?
Re: Mega Mouse Usage
The drift issue would still happen without the hacked resolution (you can get the mouse to report a large enough motion to trigger the bug).
Sik is pronounced as "seek", not as "sick".
-
- Very interested
- Posts: 2984
- Joined: Fri Aug 17, 2007 9:33 pm
Re: Mega Mouse Usage
Just posting an update on the Dune mouse patch. Here's my current code to read the mouse. Of note, it assembles (using asmx) to 58 bytes smaller than the original code (400 bytes vs 458) and handles overflow and sign properly. Tested on my Model 2 Genesis + Model 2 CD + 32X with both a Japanese Sega Mouse and a US Mega Mouse, it's smooth as silk.
Note: I could pull the main loops for reading the header and packet out as a subroutine to make the code even smaller, but I wasn't trying to make the code as small as possible, just smaller than the original code despite the extra processing on the packet.
EDIT: Pulling the three-line handshake out as a subroutine reduces the size to 346 bytes. No noticeable impact on the game (I didn't expect any as the cost of the bsr/rts is minimal compared to the overall length of mouse handling).
EDIT 2: Note that while the code above halts the Z80, strictly speaking, it isn't necessary. There's a bug in the MD where under certain conditions, if you don't halt the Z80 while reading the IO area, the Z80 rom access cycle time becomes shortened until you reset the MD. With the original old, slow roms Sega and other devs used when the system first came out, you did need to halt the Z80. However, devs soon realized that higher speed roms could still meet the faster cycle time, so it didn't matter if the cycle time was shortened. As faster roms became cheaper, more and more games quit halting the Z80 while accessing IO. The code above only halts the Z80 because the original patch did, and I wanted to leave the patch alone as much as possible while fixing mouse handling.
Note: I could pull the main loops for reading the header and packet out as a subroutine to make the code even smaller, but I wasn't trying to make the code as small as possible, just smaller than the original code despite the extra processing on the packet.
Code: Select all
; ---------------------------------------------------------------------------
org $2460
mouse_read:
; halt z80
move.w #$100,($A11100).l
move.w #$100,($A11200).l
wait_z80:
btst #0,($A11100).l
bne.s wait_z80
movea.l #$A10005,a0
move.b #$60,6(a0) ; set port direction for TLH
nop
nop
move.b #$60,(a0) ; set port for TLH
nop
nop
wait_hs1:
btst #4,(a0)
beq.s wait_hs1
; get header
move.w #254,d1 ; # retries
moveq #1,d2 ; two bytes (four nibbles) in header
hdr_loop:
move.b (a0),d0
move.b #$20,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs2:
btst #4,(a0)
bne.s hdr_phase2
dbra d1,wait_hs2
bra.w mouse_err
hdr_phase2:
move.b (a0),d0
move.b #0,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs3:
btst #4,(a0)
beq.s hdr_chklp
dbra d1,wait_hs3
bra.w mouse_err
hdr_chklp:
dbra d2,hdr_loop
lsr.l #8,d0
; check header
cmpi.w #$0BFF,d0 ; check for mouse
bne.w mouse_err
; get mouse packet
moveq #2,d2 ; three bytes (six nibbles) in packet
pkt_loop:
move.b (a0),d0
move.b #$20,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs4:
btst #4,(a0)
bne.s pkt_phase2
dbra d1,wait_hs4
bra.w mouse_err
pkt_phase2:
move.b (a0),d0
move.b #0,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs5:
btst #4,(a0)
beq.s pkt_chklp
dbra d1,wait_hs5
bra.w mouse_err
pkt_chklp:
dbra d2,pkt_loop
lsr.l #8,d0
move.b #$60,(a0) ; TLH done
move.w #0,($A11100).l ; release z80
; process mouse packet
; d0 = YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
moveq #0,d2
move.b d0,d2
btst #23,d0 ; YO
beq.s chkys ; no overflow
move.w #$0100,d2
btst #21,d0 ; YS
beq.s calcy ; positive
neg.w d2
bra.s calcy
chkys:
btst #21,d0 ; YS
beq.s calcy ; positive
or.w #$FF00,d2 ; sign-extend Y
tst.b d2
bne.s calcy
seq d2 ; handle -0 case
calcy:
asr.w #1,d2
move.w ($FFFFBF14).w,d1 ; screen Y coord
sub.w d2,d1
cmpi.w #$D0,d1
ble.s *+6
move.w #$D0,d1
cmpi.w #$10,d1
bge.s *+6
move.w #$10,d1
move.w d1,($FFFFBF14).w ; update Y coord
lsr.w #8,d0
btst #22,d0 ; XO
beq.s chkxs ; no overflow
move.w #$0100,d0
btst #20,d0 ; XS
beq.s calcx ; positive
neg.w d0
bra.s calcx
chkxs:
btst #20,d0 ; XS
beq.s calcx ; positive
or.w #$FF00,d0 ; sign-extend X
tst.b d0
bne.s calcx
seq d0 ; handle -0 case
calcx:
asr.w #1,d0
move.w ($FFFFBF12).w,d1 ; screen X coord
add.w d0,d1
cmpi.w #$130,d1
ble.s *+6
move.w #$130,d1
cmpi.w #$10,d1
bge.s *+6
move.w #$10,d1
move.w d1,($FFFFBF12).w ; update X coord
clr.b d1
btst #16,d0 ; LMB
beq.s *+6
bset #6,d1
btst #17,d0 ; RMB
beq.s *+6
bset #4,d1
move.b d1,d0
move.b ($FFFFE41C).w,d1 ; save current button state
move.b d0,($FFFFE41C).w ; set current button state
eor.b d0,d1
move.b d1,($FFFFE41D).w ; change in button state
rts
; ---------------------------------------------------------------------------
mouse_err:
move.b #$60,(a0)
nop
nop
wait_err:
btst #4,(a0)
beq.s wait_err
moveq #-1,d0
move.w #0,($A11100).l ; release z80
rts
Code: Select all
; ---------------------------------------------------------------------------
org $2460
mouse_read:
; halt z80
move.w #$100,($A11100).l
move.w #$100,($A11200).l
wait_z80:
btst #0,($A11100).l
bne.s wait_z80
movea.l #$A10005,a0
move.b #$60,6(a0) ; set port direction for TLH
nop
nop
move.b #$60,(a0) ; set port for TLH
nop
nop
wait_hs0:
btst #4,(a0)
beq.s wait_hs0
move.w #254,d1 ; # retries
; get header
moveq #1,d2 ; two bytes (four nibbles) in header
bsr.w do_tlh
; check header
cmpi.w #$0BFF,d0 ; check for mouse
bne.w mouse_err
; get mouse packet
moveq #2,d2 ; three bytes (six nibbles) in packet
bsr.w do_tlh
move.b #$60,(a0) ; TLH done
move.w #0,($A11100).l ; release z80
; process mouse packet
; d0 = YO XO YS XS S M R L X7 X6 X5 X4 X3 X2 X1 X0 Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
btst #23,d0 ; YO
beq.s chkys ; no overflow
move.w #$0100,d2
btst #21,d0 ; YS
beq.s calcy ; positive
neg.w d2
bra.s calcy
chkys:
moveq #0,d2
move.b d0,d2
btst #21,d0 ; YS
beq.s calcy ; positive
or.w #$FF00,d2 ; sign-extend Y
tst.b d2
bne.s calcy
seq d2 ; handle -0 case
calcy:
asr.w #1,d2
move.w ($FFFFBF14).w,d1 ; screen Y coord
sub.w d2,d1
cmpi.w #$D0,d1
ble.s chkymin
move.w #$D0,d1
chkymin:
cmpi.w #$10,d1
bge.s updsy
move.w #$10,d1
updsy:
move.w d1,($FFFFBF14).w ; update Y coord
btst #22,d0 ; XO
beq.s chkxs ; no overflow
move.w #$0100,d0
btst #20,d0 ; XS
beq.s calcx ; positive
neg.w d0
bra.s calcx
chkxs:
lsr.w #8,d0
btst #20,d0 ; XS
beq.s calcx ; positive
or.w #$FF00,d0 ; sign-extend X
tst.b d0
bne.s calcx
seq d0 ; handle -0 case
calcx:
asr.w #1,d0
move.w ($FFFFBF12).w,d1 ; screen X coord
add.w d0,d1
cmpi.w #$130,d1
ble.s chkxmin
move.w #$130,d1
chkxmin:
cmpi.w #$10,d1
bge.s updsx
move.w #$10,d1
updsx:
move.w d1,($FFFFBF12).w ; update X coord
clr.b d1
btst #16,d0 ; LMB
beq.s chkrmb
bset #6,d1
chkrmb:
btst #17,d0 ; RMB
beq.s do_btns
bset #4,d1
do_btns:
move.b d1,d0
move.b ($FFFFE41C).w,d1 ; save current button state
move.b d0,($FFFFE41C).w ; set current button state
eor.b d0,d1
move.b d1,($FFFFE41D).w ; change in button state
rts
do_tlh:
move.b (a0),d0
move.b #$20,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs1:
btst #4,(a0)
bne.s pkt_phase2
dbra d1,wait_hs1
addq.l #4,sp ; pop return address
bra.s mouse_err
pkt_phase2:
move.b (a0),d0
move.b #0,(a0) ; next phase
lsl.b #4,d0
lsl.l #4,d0 ; save nibble
wait_hs2:
btst #4,(a0)
beq.s pkt_chklp
dbra d1,wait_hs2
addq.l #4,sp ; pop return address
bra.s mouse_err
pkt_chklp:
dbra d2,do_tlh
lsr.l #8,d0
rts
; ---------------------------------------------------------------------------
mouse_err:
move.b #$60,(a0) ; TLH done
move.w #0,($A11100).l ; release z80
moveq #-1,d0
rts
Re: Mega Mouse Usage
Big thanks again to Chilly Willy for fixing this & Russian hacker Ti_ for creating the initial Dune mouse patch!
Attached are .ips & .bps versions of the fixed patch, apply to the Dune USA rom with CRC 4dea40ba:
Attached are .ips & .bps versions of the fixed patch, apply to the Dune USA rom with CRC 4dea40ba:
- Attachments
-
- GenesisDuneMousePatch.rar
- (8.04 KiB) Downloaded 680 times
Re: Mega Mouse Usage
I would also like to point out a second way to play Dune (and few other Genesis games) with a mouse.
The Gens32 Surreal emulator (latest version from 2013) comes with a few internal mouse drivers!
Drivers for the following games, they are found in the "Tools\Mouse Drivers folder" subfolder:
Cannon Fodder (E) [!].gmd
Dune - The Building of a Dynasty (U) [!].gmd
General Chaos (UE) [!].gmd
LETHAL ENFORCERS.gmd
Lethal Enforcers II - Gun Fighters (UJ) [!].gmd
T2 - The Arcade Game.gmd
For this to work the rom & gmd must be named the same & be in the Gens32 Surreal root folder, example:
Gens32Surreal.exe
T2 - The Arcade Game.bin
T2 - The Arcade Game.gmd
Then just open the rom with Gens32Surreal.exe & press SHIFT + M to enable the mouse, that's it.
You should then see a white "mouse driver loaded" & "mouse enabled" text in the bottom left...
Download Gens32 Surreal here: Gens32_Surreal_V1.90Std.zip or 1.90-std.7z on github
Edit: This method works with unpatched standard roms
The Gens32 Surreal emulator (latest version from 2013) comes with a few internal mouse drivers!
Drivers for the following games, they are found in the "Tools\Mouse Drivers folder" subfolder:
Cannon Fodder (E) [!].gmd
Dune - The Building of a Dynasty (U) [!].gmd
General Chaos (UE) [!].gmd
LETHAL ENFORCERS.gmd
Lethal Enforcers II - Gun Fighters (UJ) [!].gmd
T2 - The Arcade Game.gmd
For this to work the rom & gmd must be named the same & be in the Gens32 Surreal root folder, example:
Gens32Surreal.exe
T2 - The Arcade Game.bin
T2 - The Arcade Game.gmd
Then just open the rom with Gens32Surreal.exe & press SHIFT + M to enable the mouse, that's it.
You should then see a white "mouse driver loaded" & "mouse enabled" text in the bottom left...
Download Gens32 Surreal here: Gens32_Surreal_V1.90Std.zip or 1.90-std.7z on github
Edit: This method works with unpatched standard roms