Any PGM Conversion info out there?

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Last night I popped in Nine Dragons just to verify normal carts were fine. I booted, then went into settings and did a system reset. I powered down, took out Nine Dragons and booted Espgaluda which then loaded normally. I then swapped to Ketsui and had garbled graphics again. Repeated the reset procedure with Nine Dragons, and then Ketsui loaded fine. If I reset with one of the conversion carts, a subsequent conversion won’t boot, but if I do a system reset after having booted Nine Dragons, all seems fine. I did this five times last night, and considered it a win for the evening. I’d still like to try a different PGM board with these at some point, but for now I have a quirky way of getting them to load.
    • I forgot to post this:

      Python Source Code

      1. import struct
      2. with open ("DOJDUAL.bin", "rb") as f:
      3. src = bytearray (f.read())
      4. kovsh_tab = [
      5. 0xe7, 0x06, 0xa3, 0x70, 0xf2, 0x58, 0xe6, 0x59, 0xe4, 0xcf, 0xc2, 0x79, 0x1d, 0xe3, 0x71, 0x0e,
      6. 0xb6, 0x90, 0x9a, 0x2a, 0x8c, 0x41, 0xf7, 0x82, 0x9b, 0xef, 0x99, 0x0c, 0xfa, 0x2f, 0xf1, 0xfe,
      7. 0x8f, 0x70, 0xf4, 0xc1, 0xb5, 0x3d, 0x7c, 0x60, 0x4c, 0x09, 0xf4, 0x2e, 0x7c, 0x87, 0x63, 0x5f,
      8. 0xce, 0x99, 0x84, 0x95, 0x06, 0x9a, 0x20, 0x23, 0x5a, 0xb9, 0x52, 0x95, 0x48, 0x2c, 0x84, 0x60,
      9. 0x69, 0xe3, 0x93, 0x49, 0xb9, 0xd6, 0xbb, 0xd6, 0x9e, 0xdc, 0x96, 0x12, 0xfa, 0x60, 0xda, 0x5f,
      10. 0x55, 0x5d, 0x5b, 0x20, 0x07, 0x1e, 0x97, 0x42, 0x77, 0xea, 0x1d, 0xe0, 0x70, 0xfb, 0x6a, 0x00,
      11. 0x77, 0x9a, 0xef, 0x1b, 0xe0, 0xf9, 0x0d, 0xc1, 0x2e, 0x2f, 0xef, 0x25, 0x29, 0xe5, 0xd8, 0x2c,
      12. 0xaf, 0x01, 0xd9, 0x6c, 0x31, 0xce, 0x5c, 0xea, 0xab, 0x1c, 0x92, 0x16, 0x61, 0xbc, 0xe4, 0x7c,
      13. 0x5a, 0x76, 0xe9, 0x92, 0x39, 0x5b, 0x97, 0x60, 0xea, 0x57, 0x83, 0x9c, 0x92, 0x29, 0xa7, 0x12,
      14. 0xa9, 0x71, 0x7a, 0xf9, 0x07, 0x68, 0xa7, 0x45, 0x88, 0x10, 0x81, 0x12, 0x2c, 0x67, 0x4d, 0x55,
      15. 0x33, 0xf0, 0xfa, 0xd7, 0x1d, 0x4d, 0x0e, 0x63, 0x03, 0x34, 0x65, 0xe2, 0x76, 0x0f, 0x98, 0xa9,
      16. 0x5f, 0x9a, 0xd3, 0xca, 0xdd, 0xc1, 0x5b, 0x3d, 0x4d, 0xf8, 0x40, 0x08, 0xdc, 0x05, 0x38, 0x00,
      17. 0xcb, 0x24, 0x02, 0xff, 0x39, 0xe2, 0x9e, 0x04, 0x9a, 0x08, 0x63, 0xc8, 0x2b, 0x5a, 0x34, 0x06,
      18. 0x62, 0xc1, 0xbb, 0x8a, 0xd0, 0x54, 0x4c, 0x43, 0x21, 0x4e, 0x4c, 0x99, 0x80, 0xc2, 0x3d, 0xce,
      19. 0x2a, 0x7b, 0x09, 0x62, 0x1a, 0x91, 0x9b, 0xc3, 0x41, 0x24, 0xa0, 0xfd, 0xb5, 0x67, 0x93, 0x07,
      20. 0xa7, 0xb8, 0x85, 0x8a, 0xa1, 0x1e, 0x4f, 0xb6, 0x75, 0x38, 0x65, 0x8a, 0xf9, 0x7c, 0x00, 0xa0,
      21. ]
      22. rom_size = len(src)
      23. for i in range(rom_size//2):
      24. x, = struct.unpack_from("<H", src, i * 2)
      25. if ((i & 0x040080) != 0x000080): x ^= 0x0001
      26. if((i & 0x004008) == 0x004008 and (i & 0x180000) != 0x000000): x ^= 0x0002
      27. if ((i & 0x000030) == 0x000010): x ^= 0x0004
      28. if ((i & 0x000242) != 0x000042): x ^= 0x0008
      29. if ((i & 0x008100) == 0x008000): x ^= 0x0010
      30. if ((i & 0x002004) != 0x000004): x ^= 0x0020
      31. if ((i & 0x011800) != 0x010000): x ^= 0x0040
      32. if ((i & 0x000820) == 0x000820): x ^= 0x0080
      33. x ^= kovsh_tab[i & 0xff] << 8
      34. struct.pack_into("<H", src, i * 2, x)
      35. with open("DDPDOJ_P1.bin", "wb") as f:
      36. f.write(src)
      Display All
      This is the decryption code from Mame for KOVSH. This will take the version of DoDonPachi that is used for KOVSH boards, and makes it usable in boards where the ASIC doesn't decrypt the ROM.
      You'll need Python 3.x and run it in a directory with DOJDUAL.BIN to produce DDPDOJ_P1.BIN.

      DoDonPachi uses the default boot address, so should run without the modifications to the PAL you need for Ketsui or Espgaluda.

      (Obviously now someone needs to link the encryption/decryption tool I missed ...)
    • Darksoft wrote:

      We're still talking arcade, right? :thumbsup:
      We are! :D
      Looking for:
      - OutRun boardset even untested or not working
      - Sega Super Scaler hardware (Out Run, Model X, Model Y), even with faulty PCM chip



      01010011 01000101 01000011 01010010 01000101 01010100 00100000 01001101 01000101 01001110 01010101 00100000 01000111 01010101 01011001
    • Scarletspeedstr wrote:

      Last night I popped in Nine Dragons just to verify normal carts were fine. I booted, then went into settings and did a system reset. I powered down, took out Nine Dragons and booted Espgaluda which then loaded normally. I then swapped to Ketsui and had garbled graphics again. Repeated the reset procedure with Nine Dragons, and then Ketsui loaded fine. If I reset with one of the conversion carts, a subsequent conversion won’t boot, but if I do a system reset after having booted Nine Dragons, all seems fine. I did this five times last night, and considered it a win for the evening. I’d still like to try a different PGM board with these at some point, but for now I have a quirky way of getting them to load.
      Check your PGM board to see if the main chip has been reworked or replaced. On one of my boards the main QFP chip had been shoddily replaced and when I tapped my finger on the cart, the glitching would come and go.
    • oneleaf86 wrote:

      If anyone is still having issues getting the dual version of DDP to function properly I have a possible solution for you.

      Turn DIP 8 off and load black or white label. Once the high score table has been displayed, power off and turn dip 8 back on.

      Tried this on 3 different PGM boards and worked every time.
      Isn't the real problem that the white label doesn't initialise backup RAM properly?
      To me a patch is required.
      Looking for:
      - OutRun boardset even untested or not working
      - Sega Super Scaler hardware (Out Run, Model X, Model Y), even with faulty PCM chip



      01010011 01000101 01000011 01010010 01000101 01010100 00100000 01001101 01000101 01001110 01010101 00100000 01000111 01010101 01011001
    • This is the code I used to generate the PAL equations for KOV2:

      Source Code

      1. from qm import QM
      2. # produce a pld-compatible equation from the miniterms
      3. def get_equation(minterms, variables):
      4. if isinstance(minterms,str):
      5. return "'b'%s" % minterms
      6. def parentheses(glue, array):
      7. if len(array) > 1:
      8. return ''.join(['(',glue.join(array),')'])
      9. else:
      10. return glue.join(array)
      11. or_terms = []
      12. for minterm in minterms:
      13. and_terms = []
      14. for j in range(len(variables)):
      15. if minterm[0] & 1<<j:
      16. and_terms.append(variables[j])
      17. elif not minterm[1] & 1<<j:
      18. and_terms.append('!%s' % variables[j])
      19. or_terms.append(parentheses(' & ', and_terms))
      20. return ' # '.join(or_terms)
      21. def generatePal(a, b, csvName, pldName, siName, pins, desc):
      22. pinIn = [11,10,9,8,7,6,5,4,3,2,1,13]
      23. pinOut = [23,22,21,20,19,18,17,16,15,14]
      24. # generate simple csv table
      25. with open(csvName, "wt") as f:
      26. f.write ("%s\n" % ",".join([pins[x] for x in pinIn]+[pins[x] for x in pinOut]))
      27. for i in range(len(a)):
      28. s = []
      29. for j in range(12):
      30. if i & (1<<j):
      31. s += ["1"]
      32. else:
      33. s += ["0"]
      34. x = a[i] | ((b[i] & 0xc0) << 2)
      35. for j in range(10):
      36. if x & (1<<j):
      37. s += ["1"]
      38. else:
      39. s += ["0"]
      40. f.write ("%s\n" % ",".join(s))
      41. # generate test vector
      42. with open(siName, "wt") as f:
      43. for key, value in desc.items():
      44. f.write("%s %s;\n" % (key, value))
      45. f.write("\nORDER: %s;\n" % ",".join([pins[x] for x in pinIn]+[pins[x] for x in pinOut]))
      46. f.write("\nVECTORS:\n")
      47. for i in range(len(a)):
      48. s = []
      49. for j in range(12):
      50. if i & (1<<j):
      51. s += ["1"]
      52. else:
      53. s += ["0"]
      54. x = a[i] | ((b[i] & 0xc0) << 2)
      55. for j in range(10):
      56. if x & (1<<j):
      57. s += ["H"]
      58. else:
      59. s += ["L"]
      60. f.write ("%s\n" % "".join(s))
      61. # generate pld file
      62. with open(pldName, "wt") as f:
      63. for key, value in desc.items():
      64. f.write("%s %s;\n" % (key, value))
      65. f.write("\n/* Inputs */\n")
      66. for x in pinIn:
      67. f.write("Pin %i = %s;\n" % (x, pins[x]))
      68. f.write("\n/* Outputs */\n")
      69. for x in pinOut:
      70. f.write("Pin %i = %s;\n" % (x, pins[x]))
      71. f.write("\n/* Logic */\n")
      72. qm = QM([pins[x] for x in pinIn])
      73. for i in range(len(pinOut)):
      74. ones = []
      75. for j in range(len(a)):
      76. x = a[j] | ((b[j] & 0xc0) << 2)
      77. if ((x >> i) & 1) != 0:
      78. ones.append(j)
      79. print ("solve %s" % pins[pinOut[i]])
      80. f.flush()
      81. f.write("%s = %s;\n" % (pins[pinOut[i]], get_equation(qm.solve(ones,[])[1], qm.variables)))
      82. # common description
      83. desc = {
      84. "PartNo": "PAL_CE",
      85. "Date": "27/01/2019",
      86. "Revision": "01",
      87. "Designer": "Fluffy",
      88. "Company": "None",
      89. "Assembly": "None",
      90. "Location": "None",
      91. "Device": "g22v10"
      92. }
      93. # Generate FI_U14
      94. pins = {
      95. 1:"U14_1",
      96. 2:"TA18",
      97. 3:"TA19",
      98. 4:"TA20",
      99. 5:"TA21",
      100. 6:"TA22",
      101. 7:"U14_7",
      102. 8:"U14_8",
      103. 9:"U14_9",
      104. 10:"U14_10",
      105. 11:"U14_11",
      106. 23:"U14_23",
      107. 22:"U14_22",
      108. 21:"TO_U15",
      109. 20:"U14_20",
      110. 19:"TA21_I",
      111. 18:"TA20_I",
      112. 17:"TA19_I",
      113. 16:"TA18_I",
      114. 15:"T_ROM_OE",
      115. 14:"INT_T_ROM_OE",
      116. 13:"U14_13"
      117. }
      118. desc["Name"] = "PGM_FI_U14"
      119. with open("FI_U14_A.bin", "rb") as f:
      120. a = f.read()
      121. with open("FI_U14_B.bin", "rb") as f:
      122. b = f.read()
      123. generatePal(a, b, "fi_u14.csv", "fi_u14.pld", "fi_u14.si", pins, desc)
      124. # Generate FI_U15
      125. pins = {
      126. 1:"AS",
      127. 2:"PA16",
      128. 3:"PA23",
      129. 4:"PA22",
      130. 5:"PA21",
      131. 6:"PA20",
      132. 7:"FROM_U14",
      133. 8:"FROM_U17_1",
      134. 9:"U15_9",
      135. 10:"U15_10",
      136. 11:"U15_11",
      137. 23:"INT_P_ROM_OE",
      138. 22:"P_ROM_OE",
      139. 21:"PA21_I",
      140. 20:"PA20_I",
      141. 19:"TO_U10_1",
      142. 18:"TO_U9_15",
      143. 17:"U15_17",
      144. 16:"U15_16",
      145. 15:"M68K_LATCH_ENABLE",
      146. 14:"SRAM_ENABLE",
      147. 13:"U15_13"
      148. }
      149. desc["Name"] = "PGM_FI_U15"
      150. with open("FI_U15_A.bin", "rb") as f:
      151. a = f.read()
      152. with open("FI_U15_B.bin", "rb") as f:
      153. b = f.read()
      154. generatePal(a, b, "fi_u15.csv", "fi_u15.pld", "fi_u15.si", pins, desc)
      Display All
      It was just slapped together for those two PALs, so doesn't have a proper user interface. It depends on github.com/prekageo/optistate to convert what is essentially a truth table into PLD equations.

      This is for 22V10, so it combines the output of two passes. The input is essentially a PAL read like a ROM, i.e. the address lines go through all values from 0 to the end of the ROM, and the values are whatever the PAL returned for that input. At that time I only had a G540, which seems to only support 8-bit ROMs. With a Top3000 you could treat this as a 16-bit ROM and read all 10 output values in one go.

      It doesn't detect high impedance outputs, though that could probably be done by comparing two passes with pull-up and pull-down resistors. It doesn't detect registers, or outputs configured for input, either, so you should have rough idea what the PAL does, and look at what they pins are connected to in the circuit.
    • I was looking through the PCB scans and noticed this one:
      gc8tech.com/wp-content/uploads/2019/03/HC2_BOTTOM_1.jpg

      This uses an off-the-shelf Lattice CPLD:
      uk.farnell.com/lattice-semicon…spmach-100tqfp/dp/2252885
      and an ARM cpu:
      uk.farnell.com/nxp/lpc2132fbd6…dmi-60mhz-lqfp/dp/1727702

      Later games (like Demon Front) apparently run a significant amount of the game logic on the cartridge, so this may be interesting for people developing multi carts.

      gc8tech.com/uncategorized/pgm-hacked-cart-2-pcbs/
    • oneleaf86 wrote:

      No idea what's functionally wrong the rom, just a work around in the short term for people having issues getting it running.
      Just a wild guess though, it seems to me it's the high score table that's causing the errors, if you turn off the high score save hack on DIP 8 it seems to work perfectly.
      I didn't test this by credit feeding, but it's likely the stage 4 freeze/crash bug that got reported earlier is still in this one.
      It's not related to the protection ASIC though, so possibly this could fix it. Way too busy with work and that damned addictive Apex Legends game still. (100 Kills now and my first win in the pocket ;).)
      If you want to support me, sign up for Dropbox by using db.tt/05qkhkFLVC. This gets you and me an extra 500MB for hosting roms, or other arcade related files :)