disk-utilities icon indicating copy to clipboard operation
disk-utilities copied to clipboard

Copy Protection: Dogs Of War

Open nicodex opened this issue 2 years ago • 7 comments

Dogs Of War T00.1 looks like unformatted, but is part of the copy protection. I think the game waits for the index (by reading CIAICR FLG) and than reads 14200 words. Later the game scans the raw MFM data for the bit pattern 0100010001010100. It's OK if the bit sequence is not found at all - or, if found, a second match has to be at least 6700 words away. If the copy protection check fails ($023A(A5=0).l <= 0), the player joystick data is filled with random values (you cannot control your movement).

Is there already a way to describe something like this in the formats file, or do we have to implement another sector format for this?

0039E4: clr.w   $01E4(A5)
0039E8: clr.w   $01E6(A5)
0039EC: bsr.w   dow_dsk_motor_on
0039F0: bsr.w   dow_seek_track0
0039F4: move.l  #20000,D7
0039FA: bsr.w   dow_wait_cycles_d7
0039FE: bclr.b  CIAB_DSKSIDE,(_ciab.ciaprb).l
003A06: bsr.w   dow_wait_icrflg
003A0A: move.w  #INTF_DSKBLK,(_custom.intreq).l
003A12: move.l  #$0006154C,(_custom.dskpt).l
003A1C: move.w  #~ADKF_SETCLR,(_custom.adkcon).l
003A24: move.w  #ADKF_SETCLR|ADKF_FAST,(_custom.adkcon).l
003A2C: move.w  #DMAF_SETCLR|DMAF_MASTER|DMAF_DISK,(_custom.dmacon).l
003A34: move.w  #DSKDMAOFF,(_custom.dsklen).l
003A3C: move.w  #$8000|14200,(_custom.dsklen).l
003A44: move.w  #$8000|14200,(_custom.dsklen).l
003A4C: bra.w   dow_wait_dskblk
004C5A: lea     ($0004F54C).l,A0
004C60: move.l  #14200,D3
004C66: adda.l  #$00012000,A0
004C6C: move.l  (A0),D0
004C6E: addq.l  #2,A0
004C70: moveq   #16-1,D2
004C72: move.l  D0,D1
004C74: swap    D1
004C76: cmp.w   #%0100010001010100,D1
004C7A: beq.b   004C88
004C7C: lsl.l   #1,D0
004C7E: dbf     D2,004C72
004C82: dbf     D3,004C6C
004C86: bra.b   004CA6
004C88: clr.l   D5
004C8A: move.l  (A0),D0
004C8C: addq.l  #2,A0
004C8E: moveq   #16-1,D2
004C90: move.l  D0,D1
004C92: swap    D1
004C94: cmp.w   #%0100010001010100,D1
004C98: beq.b   004CAC
004C9A: lsl.l   #1,D0
004C9C: dbf     D2,004C90
004CA0: addq.l  #1,D5
004CA2: dbf     D3,004C8A
004CA6: st      $023A(A5)
004CAA: rts
004CAC: subi.l  #6700,D5
004CB2: move.l  D5,$023A(A5)
004CB6: rts

ps: I recommend to test this game on a plain 68000, it often uses instruction loops for 'timed' waiting (also for disk reading - you might have to umount and insert your image again to continue).

nicodex avatar May 28 '22 20:05 nicodex

You'll need a new format, as you must see the 4454 pattern. If you don't you end up at 4CA6 and set the longword there negative. 6700*16 == 107200 bitcells. So you need a 110000-bit longtrack with 4454 appearing once. The rest could be all AAAA... which isn't a faithful repro of the original track but will pass the protection check. If you want to be more faithful then most of the track needs to be written MFM all zeroes. But the AAAA pattern is surely more deterministic and safer.

keirf avatar May 28 '22 21:05 keirf

You'll need a new format, as you must see the 4454 pattern

OK, thank you. My hope was that it could be somehow possible to create a valid standard track format without this pattern (as far as I know, the st <ea> instruction is similar to move.b $FF,<ea> (byte-sized) and the check is long-sized signed - so the pattern could be missing).

Most of the time I'm just reading code to answer questions, but it seems I have to get used to on-disk formats and the encodings. I'll start with getting used to the capsimage library to actually dump the original MFM data...

nicodex avatar May 29 '22 07:05 nicodex

Regarding the ST.b instruction, remember 68000 is big endian. So this instruction does also make the longword negative!

What do you have for dumping disks? I can send you a greaseweazle if you like; you can email me your details.

keirf avatar May 29 '22 08:05 keirf

Regarding the ST.b instruction, remember 68000 is big endian. So this instruction does also make the longword negative!

Mistake on my site, you are right :)

What do you have for dumping disks? I can send you a greaseweazle if you like; you can email me your details.

I'm just helping analyze/convert the mission data for an open source remake of the game. Since most of my original disks are modified or the bits faded, I'm using the IPF as a reference (I'm not interested in analyzing Suxxess' and others' ADF conversions, even if they include some fixes).

nicodex avatar May 29 '22 10:05 nicodex

You'll need a new format, as you must see the 4454 pattern. If you don't you end up at 4CA6 and set the longword there negative. 6700*16 == 107200 bitcells. So you need a 110000-bit longtrack with 4454 appearing once.

Seems like the existing protec_longtrack exactly implements this (even detecting/using the fill byte). With this config I converted it from IPF to HFE, and it works (besides the mentioned timing issues with the original track loader on my A500 with a 68010 on an external Gotek with a simple DF0/1-switch):

#
# This config is intended to be used with the config/format options of
# Keir Fraser's disk-analyse utility (build with CAPS/SPS IPF support),
# for more details browse to <https://github.com/keirf/disk-utilities>.
#
# Expamples:
#
#   # convert to HxC/FlashFloppy Emulator image
#   disk-analyse --format='Dogs of War' --config=./DogsOfWar-ipf.format \
#     --end-cyl=79 \
#     ./DogsOfWar.ipf ./DogsOfWar.hfe
#
#   # extract 'MAINGRAF.PRG' track data blocks
#   disk-analyse --format='Dogs of War' --config=./DogsOfWar-ipf.format \
#     --ss=1 --start-cyl=1 --end-cyl=15 \
#     ./DogsOfWar.ipf ./h1c01-15.img
#
"Dogs of War"
    0 amigados
    1 protec_longtrack
    2-76/2 ibm_pc_dd_10sec
    3-77/2 ibm_pc_dd_10sec
    78-83 amigados
    84-158/2 ibm_pc_dd_10sec
    85-159/2 ibm_pc_dd_10sec
    * ignore

BTW, the --end-cyl=79 did not what I expected and the HFE still has more than 80 tracks/side :)

However, in the long term someone/me would have to write a special format handler for T79.0 (highscore). The game's track writer does not fill the ID fields and CRCs correctly, and even writes too few words if my math is correct :)

#
# Index field: 50/146 words
#                                       # GAP 4A (0/80 0x4E)
#                                       # SYNC 1 (0/12 0x00)
#                                       # IAM    (0/3 0xC2*, 0xFC)
mfm_bytes(0x4E, 50)                     # GAP 1  (50 0x4E)
# (10*614/9*654 words)
for(i = 0; i < 10; ++i) {
  # ID field: 44/44 words
  mfm_bytes(0x00, 12)                   # SYNC 2 (12 0x00)
  0x44894489,0x4489,mfm_bytes(0xFE, 1)  # IDAM   (3 0xA1*, 0xFE)
  mfm_bytes(0x00, 6)                    # C, H, S, B, CRC
  mfm_bytes(0x4E, 22)                   # GAP 2  (22 0x4E)
  # DATA field: 570/610 words
  mfm_bytes(0x00, 12)                   # SYNC 3 (12 0x00)
  0x44894489,0x4489,mfm_bytes(0xFB, 1)  # DAM    (3 0xA1*, 0xFB)
  for(j = 0; j < 512; ++j) {
    mfm_byte(data[j])                   # DATA   (512 words)
  }
  # 6144 words written - last 4 DATA words, CRC, and GAP 3 missing
  mfm_bytes(0x01, 2)                    # CRC
  mfm_bytes(0x4E, 40)                   # GAP 3  (40/80 0x4E)
}

If you want to have a look at the code and have Ghidra installed, there is an 'openDOW' with anonymous read-only access at ghidra.nicode.net

nicodex avatar May 30 '22 19:05 nicodex

Maybe the protection code at least is protec. It rings a bell actually.

I've never used ghidra is it good?

And yes you'll need a new format for high scores.

keirf avatar May 30 '22 20:05 keirf

I've never used ghidra is it good?

There are still a lot of issues to solve/implement for easier/correct analysis - but it helps a lot to have an interactive tool with all the auromatic references. The more code to review the more effective you can answer questions with it (not intended/ready to re-source an app, even if this has already been done with custom plug-in). The nice thing, it's free and with a server you can work together on a project.

nicodex avatar May 30 '22 20:05 nicodex