;*--------------------------------------------------------------------------- ; :Modul. GravityHD.asm ; :Contents. Gravity slave ; :Author. JOTD ; :Original. ; :Version. ; :History. ; ; :Requires. 68000 or higher ; :Copyright. Public Domain ; :Language. 68000 Assembler ; :Translator. Barfly V2.9 ; :To Do. ;---------------------------------------------------------------------------* INCDIR Include: INCDIR osemu: INCLUDE whdload.i INCLUDE whdmacros.i IFD BARFLY OUTPUT "Gravity.Slave" IFND DEBUG BOPT O+ ;enable optimizing BOPT OG+ ;enable optimizing BOPT ODd- ;disable mul optimizing BOPT ODe- ;disable mul optimizing ENDC BOPT w4- ;disable 64k warnings BOPT wo- ;disable optimizer warnings SUPER ENDC ;============================================================================ IFD DEBUG CHIPMEMSIZE = $FF000 FASTMEMSIZE = $0000 ELSE CHIPMEMSIZE = $80000 FASTMEMSIZE = $40000 ENDC NUMDRIVES = 1 WPDRIVES = %1111 DISKSONBOOT ;HDINIT ;HRTMON ;MEMFREE = $100 ;NEEDFPU ;SETPATCH BOOTBLOCK ;============================================================================ slv_Version = 16 slv_Flags = WHDLF_NoError|WHDLF_Examine|WHDLF_EmulDivZero|WHDLF_EmulTrap slv_keyexit = $5D ; num '*' INCLUDE kick13.s ;============================================================================ IFND .passchk DOSCMD "WDate >T:date" .passchk ENDC DECL_VERSION:MACRO dc.b "2.1" IFD BARFLY dc.b " " INCBIN "T:date" ENDC ENDM dc.b "$","VER: slave " DECL_VERSION dc.b $A,$D,0 slv_name dc.b "Gravity" IFD DEBUG dc.b " (DEBUG MODE)" ENDC dc.b 0 slv_copy dc.b "1989 Imageworks",0 slv_info dc.b "adapted & fixed by CFou! & JOTD",10,10 dc.b "Set CUSTOM1=1 to disable stars background",10,10 dc.b "Version " DECL_VERSION dc.b 0 slv_CurrentDir dc.b 0 EVEN ;============================================================================ _bootblock: movem.l a0-a2/a6/d0-d1,-(A7) ;get tags lea (tags,pc),a0 move.l _resload(pc),a2 jsr (resload_Control,a2) move.l custom1(pc),d0 beq.b .skip ;eat some memory to prevent stars to be displayed move.l #$10000,d0 move.l #MEMF_CHIP,d1 move.l $4.W,a6 jsr _LVOAllocMem(a6) .skip movem.l (a7)+,a0-a2/a6/d0-d1 jsr ($C,a4) movem.l a0-a2/a6/d0-d1,-(A7) move.l a0,a1 lea pl_boot(pc),a0 move.l _resload(pc),a2 jsr resload_Patch(a2) movem.l (a7)+,a0-a2/a6/d0-d1 moveq.l #0,D0 rts _quit PEA TDREASON_OK MOVE.L _resload(PC),-(A7) add.l #resload_Abort,(a7) rts pl_boot PL_START PL_PS $A564-$A498,check_copylock ; Rixa: remove this PL_P $B98E-$A498,end_disk_read ; Rixa: needs change to $148E PL_END end_disk_read movem.l (a7)+,d1-d7/a0-a6 ; stolen ; patch if executable found movem.l d0-d1/a0-a2,-(a7) move.l d2,a0 ; start of loaded file move.w (a0)+,d0 cmp.w #$601A,d0 ; all code chunks start by BRA +$18 bne.b .out move.l _resload(pc),a2 move.l d2,a1 move.l (a0)+,d0 ; length/signature cmp.l #$BAE,d0 beq.b .st_replay cmp.l #$375A,d0 beq.b .code_part_2 cmp.l #$1100C,d0 ; Rixa: Needs change to $11044 beq.b .loader cmp.l #$5D80,d0 beq.b .in_game_1 cmp.l #$4B1C,d0 beq.b .in_game_2 cmp.l #$1240,d0 beq.b .in_game_3 cmp.l #$C80,d0 beq.b .in_game_4 cmp.l #$5CC,d0 beq.b .in_game_5 bsr _flushcache ;; ILLEGAL ; unknown program .out movem.l (a7)+,d0-d1/a0-a2 tst.l d0 rts .patch jsr resload_Patch(a2) bra.b .out ; around $8Cxxx .in_game_5 .in_game_4 .in_game_3 .in_game_2 .in_game_1 bsr _flushcache bra.b .out .loader pea add_a0(pc) move.l (a7)+,$80.W pea trap_1(pc) move.l (a7)+,$84.W pea trap_2(pc) move.l (a7)+,$88.W pea trap_3(pc) move.l (a7)+,$8C.W pea trap_4(pc) move.l (a7)+,$90.W patch $100,emulate_sub_d7_to_d4 move.l attnflags(pc),d0 btst #AFB_68010,d0 beq.b .68000 ; JOTD: don't do it on 68000 because it would crash badly lea pl_loader(pc),a0 bra.b .patch .68000 lea pl_loader_68000(pc),a0 bra.b .patch .st_replay pea smc_bra_replay(pc) move.l (a7)+,$94.W lea pl_replay(pc),a0 bra.b .patch .code_part_2 lea pl_code_2(pc),a0 bra.b .patch pl_replay PL_START PL_PS $309EC-$300B6,fix_dbf_replay PL_L $3067C-$300B6,$4E714E71 PL_W $3085E-$300B6,$4E45 PL_END ; 68010+ only pl_loader PL_START ; stack-leak error PL_PS $174DA-$C558,fix_stackframe_error ; Rixa: needs change to $AFBA PL_I $17520 ; RTE return: does not happen ; Rixa: needs change to $17558? PL_NEXT pl_loader_68000 pl_loader_68000 PL_START ; SMC fix PL_W $1B5F4-$C558,$4E40 ; TRAP #0 to simulate SMC ; Rixa: needs change to $F0D4 PL_W $1B694-$C558,$4E40 ; TRAP #0 to simulate SMC ; Rixa: needs change to $F174 PL_PS $1B896-$C558,smc_link ; Rixa: needs change to $F376 PL_W $18E72-$C558,$4E44 ; Rixa: needs change to $C952 PL_W $18EC2-$C558,$4E44 ; Rixa: needs change to $C9A2 PL_W $18F82-$C558,$4E44 ; Rixa: needs change to $CA62 PL_W $1902C-$C558,$4E44 ; Rixa: needs change to $CB0C PL_W $19A24-$C558,$4E44 ; Rixa: needs change to $D504 PL_L $1933E-$C558,$4EB80100 ; Rixa: needs change to $CE1E ; copylock check (already disabled BTW) ; if wrong copylock, clicking on the ; buttons during the game has no effect! PL_L $11CB4-$C558,$4E714E71 ; Rixa: needs to be removed ; 24-bit access fault problem ; game loads a an address register then masks it ; with $FFFFFF sometimes causing 24 bit error ; (but sometimes it is useful) PL_PS $0E480-$C558,fix_24_bit_d1 PL_PS $0FB42-$C558,fix_24_bit_d0 PL_PS $0FB8E-$C558,fix_24_bit_d0 PL_PS $0FBE4-$C558,fix_24_bit_d0 PL_PS $15E6C-$C558,fix_24_bit_d0 ; Rixa: needs change to $0994C PL_PS $1860C-$C558,fix_24_bit_d0 ; Rixa: needs change to $0C0EC PL_PS $1CB64-$C558,fix_24_bit_d0 ; Rixa: needs change to $10644 PL_PS $1CE04-$C558,fix_24_bit_d0 ; Rixa: needs change to $108E4 PL_END pl_code_2 PL_START PL_W $62A54-$6009A,$4E42 ; TRAP #2 to simulate SMC PL_W $629CC-$6009A,$4E41 ; TRAP #1 to simulate SMC PL_W $62228-$6009A,$4E44 PL_W $628D8-$6009A,$4E44 PL_PS $62A04-$6009A,emulate_sub_d2_d3 ; BRA emulation PL_W $600BA-$6009A,$4E43 PL_W $600BE-$6009A,$4E43 PL_W $600C2-$6009A,$4E43 PL_W $600C6-$6009A,$4E43 PL_W $600CA-$6009A,$4E43 PL_W $600CE-$6009A,$4E43 PL_W $600D2-$6009A,$4E43 PL_END ; the routine in the trap #15 handler is really stoopid: ; it pops SR & return address from supervisor state (SSP) and restores ; it in user state (USP). ; There is not really an immediate stackframe error since the game uses RTR ; instruction, which does not have stackframe check/pop (not like RTE) ; ; BUT the problem is that SSP state is reached using TRAP, and on 68020+ one more ; word is added (stackframe). So SSP value decreases at each call, and ends up ; trashing the code in the title screen, or later. ; ; this is really a vicious bug fix_stackframe_error ; first, store return address move.l a0,-(a7) lea .return_address(pc),a0 move.l 4(a7),(a0) move.l (a7)+,a0 addq.l #4,a7 ; pop the stack to simulate a JMP below MOVE (A7)+,-(A0) ;174DA: 311F ; pop/save SR/CCR from SSP MOVE.L (A7)+,-(A0) ;174DC: 211F ; pop/save return address from SSP addq.l #2,a7 ; fix remove stackframe if 68020+ MOVE.L A0,-(A7) ;174DE: 2F08 ; return to program move.l .return_address(pc),-(a7) rts .return_address: dc.l 0 smc_bra_replay movem.l a0,-(a7) move.l 6(a7),a0 ; return address cmp.l #$4E714E71,(a0) movem.l (a7)+,a0 bne.b .jsr ; was BRA: branch RTE .jsr ; tricky: first, recover from the RTE movem.l A0/A1,-(A7) move.l 10(A7),A0 ; return PC lea .return_address(pc),a1 move.l a0,(a1) ; save return address for later on lea .jsr_address(pc),a1 move.l (a0),(a1) ; save jsr address for later on lea .recov(pc),a1 move.l a1,10(a7) ; change return PC movem.l (A7)+,A0/A1 rte .recov ; now we're in user mode: first push return address move.l .return_address(pc),-(a7) addq.l #4,(a7) ; skip JSR operand ; then push JSR operand move.l .jsr_address(pc),-(a7) ; go rts .return_address dc.l 0 .jsr_address dc.l 0 emulate_sub_d2_d3 move d1,d3 asr #5,d2 asr #5,d3 movem.l d0/a0,-(a7) move.l 8(a7),a0 ; return address sub.w (2,A0),d2 sub.w (6,A0),d3 movem.l (a7)+,d0/a0 rts emulate_sub_d7_to_d4 move 6(a0),d7 ; original movem.l d0/a0,-(a7) move.l 8(a7),a0 ; return address sub.w ($2,A0),d7 sub.w ($12,A0),d6 sub.w ($20,A0),d5 sub.w ($2E,A0),d4 movem.l (a7)+,d0/a0 rts fix_dbf_replay move.w #12,d0 .bd_loop1 move.w d0,-(a7) move.b $dff006,d0 ; VPOS .bd_loop2 cmp.b $dff006,d0 beq.s .bd_loop2 move.w (a7)+,d0 dbf d0,.bd_loop1 addq.l #4,(a7) rts add_a0 move.l a1,-(a7) move.l 6(a7),a1 ; return address add.w (a1),a0 ; simulate lea x(a0),a0 (x depends because of smc grrrr) move.l (a7)+,a1 add.l #2,2(a7) ; skip lea opcode rte ; < D0: link offset smc_link movem.l d0/a0/a1,-(a7) lea return_address(pc),a0 move.l 12(a7),a1 add.l #10,a1 ; -> leads to adda d0,a6, just after the LINK instruction move.l a1,(a0)+ ext.l d0 move.l d0,(a0) ; writes required LINK parameter to link_value movem.l (a7)+,d0/a0/a1 addq.l #4,a7 ; pops up the stack because we're going to LINK ; LINK emulation move.l a6,-(a7) move.l a7,a6 add.l link_value(pc),a7 ; goto next move.l return_address(pc),-(a7) rts ; do not separate return_address from link_value variables! return_address dc.l 0 link_value dc.l 0 DEF_FIX_24_BIT:MACRO fix_24_bit_d\1: move.l d7,-(a7) move.l d\1,d7 rol.l #8,d7 tst.b d7 beq.b .out cmp.b _expmem(pc),d7 beq.b .out ; not 0 and not expmem MSB: clear it clr.b d7 ror.l #8,d7 move.l d7,d\1 .out move.l (a7)+,d7 rts ENDM DEF_FIX_24_BIT 0 DEF_FIX_24_BIT 1 trap_1 movem.l d0/a1,-(a7) move.l 10(a7),a1 ; return address add.w (a1),a3 ; simulate lea x(a0),a0 (x depends because of smc grrrr) add.w 4(a1),a4 ; simulate lea x(a0),a0 (x depends because of smc grrrr) move.w 8(a1),d0 add.w d0,60(a6) ; simulate addi to 60(a6) move.w (14,a1),d0 add.w d0,62(a6) movem.l (a7)+,d0/a1 add.l #2+4+6+6,2(a7) ; skip opcodes rte ; lea a5, add d0, add d1 trap_2 move.l a1,-(a7) move.l 6(a7),a1 ; return address add.w (a1),a5 ; simulate lea x(a5),a5 (x depends because of smc grrrr) add.w (4,a1),d0 ; simulate addi to d0 add.w (8,a1),d1 ; simulate addi to d1 move.l (a7)+,a1 add.l #2+4+4,2(a7) ; skip opcodes rte ; sub #x,d0, sub #x,d1 trap_4 move.l a1,-(a7) move.l 6(a7),a1 ; return address sub.w (a1),d0 ; simulate subi to d0 sub.w (4,a1),d1 ; simulate subi to d1 move.l (a7)+,a1 add.l #2+4,2(a7) ; skip opcodes rte ; BRA emulation trap_3 movem.l d0/A0,-(A7) move.l 10(A7),A0 ; return address moveq #0,d0 move.w (a0),d0 add.l d0,10(A7) ; RTE -> BRA address movem.l (A7)+,D0/A0 rte check_copylock move.l (a7),a0 ; A568 move.l -80(a0),a0 ; lea $A51A cmp.w #$4AFC,$E(a0) bne.b .nocopylock moveq #0,d0 ; original ;;; move.l #$DD17A129,d0 ; no disk in drive (also one of copylock checksum) rts ; move.l #$90006,$6198 ; move.l #$b6c00000,$619C .nocopylock jmp (a0) tags dc.l WHDLTAG_ATTNFLAGS_GET attnflags dc.l 0 dc.l WHDLTAG_CUSTOM1_GET custom1 dc.l 0 dc.l 0 ;============================================================================ END