3D Block (Hwang Shinwei)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
3D Block (Hwang Shinwei)
by on (#201038)
I am trying to figure out how to get this game working.

To initialize, it does 4 writes:
0x32 -> 0x4800
0x37 -> 0x4900
0x1 -> 0x4A00
0x18 -> 0x4E00

I'm not exactly sure what they do, but it looks like it's setting up some IRQ behaviour. The write of 0x1 might be setting up mirroring mode?
The game expects to split the screen using IRQs (more then one per frame)

Here is the IRQ:

Code:
====IRQ====
0201:  4C  JMP $CF02       A:10 X:00 Y:00 P:24 SP:FA Cy:1281871 nvTbdIzc
CF02:  85  STA $F7         A:10 X:00 Y:00 P:24 SP:FA Cy:1281874 nvTbdIzc
CF04:  EE  INC $01E4       A:10 X:00 Y:00 P:24 SP:FA Cy:1281877 nvTbdIzc
CF07:  AD  LDA $01E4       A:10 X:00 Y:00 P:24 SP:FA Cy:1281883 nvTbdIzc
CF0A:  29  AND #$01        A:03 X:00 Y:00 P:24 SP:FA Cy:1281887 nvTbdIzc
CF0C:  F0  BEQ $CF20       A:01 X:00 Y:00 P:24 SP:FA Cy:1281889 nvTbdIzc
CF0E:  A9  LDA #$24        A:01 X:00 Y:00 P:24 SP:FA Cy:1281891 nvTbdIzc
CF10:  8D  STA $2006       A:24 X:00 Y:00 P:24 SP:FA Cy:1281893 nvTbdIzc
CF13:  A9  LDA #$00        A:24 X:00 Y:00 P:24 SP:FA Cy:1281897 nvTbdIzc
CF15:  8D  STA $2006       A:00 X:00 Y:00 P:26 SP:FA Cy:1281899 nvTbdIZc
CF18:  A9  LDA #$83        A:00 X:00 Y:00 P:26 SP:FA Cy:1281903 nvTbdIZc
CF1A:  8D  STA $2000       A:83 X:00 Y:00 P:A4 SP:FA Cy:1281905 NvTbdIzc
CF1D:  4C  JMP $CF41       A:83 X:00 Y:00 P:A4 SP:FA Cy:1281909 NvTbdIzc
CF41:  EE  INC $02D1       A:83 X:00 Y:00 P:A4 SP:FA Cy:1281912 NvTbdIzc
CF44:  AD  LDA $02D1       A:83 X:00 Y:00 P:24 SP:FA Cy:1281918 nvTbdIzc
CF47:  C9  CMP #$5C        A:4F X:00 Y:00 P:24 SP:FA Cy:1281922 nvTbdIzc
CF49:  90  BCC $CF4F       A:4F X:00 Y:00 P:A4 SP:FA Cy:1281924 NvTbdIzc
CF4F:  A5  LDA $F7         A:4F X:00 Y:00 P:A4 SP:FA Cy:1281927 NvTbdIzc
CF51:  40  RTI             A:10 X:00 Y:00 P:24 SP:FA Cy:1281930 nvTbdIzc


The first problem I am having is that there doesn't seem to be anything to acknowledge the IRQ. Those branches in there don't lead to anything that would do so either.

Does anyone know of any other examples of IRQs being acknowledged in non-standard ways? Maybe that will point me in the right direction on how to approach emulating this ROM.
Re: 3D Blcok (Hwang Shinwei)
by on (#201043)
Which specific build are you trying to get to work?
The one in GoodNES3.14 ("3D Block (Unl).nes", crc32 1c4f2651 crc32(prg) cae5382d) seems fine?
Re: 3D Blcok (Hwang Shinwei)
by on (#201048)
3-D Block (Asia) (Unl) (Hwang Shinwei).nes

CRC32: 5E8764F8

EDIT: Another thing I noticed is that possibly the 32k of rom is swappable 16k banks. one interrupt vector I noticed in the swapped bank set up is A800, and following through that code I get to a JMP ($53A6)

But, I have no idea what is supposed to be read from the EXP addresses. Maybe we are missing some information about this ROM that the dump doesnt provide.
Re: 3D Block (Hwang Shinwei)
by on (#201114)
(edit: remove copypasta) GoodNES3.14 has a '3D Block (Unl) [a1][!].nes' that matches the CRC that you provided. It's marked as mapper 219, but it clearly doesn't comply with our notes as to what mapper 219 should be.

Comparing a1! to ! , there are a few minor differences causing some blocks of code to move around, but the substantial difference is the insertion of an extra 4 KiB of ... something? that would be mapped at $E600.

What's really odd about that is that it implies that the plain NROM build has the same (but vestigial) IRQ handler sitting around.

Due to the similarities betweeen a1! and !, I'm not convinced there's any bankswitching here...
Re: 3D Block (Hwang Shinwei)
by on (#201131)
Well, the main problem is that I don't see any way to control the IRQ's and have no way to interpret what the writes to $4x00 are doing.

Without bank switching, I checked the startup routines for both ROMs and they are indeeed pretty similar, but the Hwang Shinwei ROM clears the interrupt flag right before drawing the intro screen, and if the same IRQs are active there that need to be active in the games screen, the result is just a mess.

Maybe this isn't tractable without the original cart to decrypt what is supposed to be happening.
Re: 3D Block (Hwang Shinwei)
by on (#201132)
Looking a bit more closely, the game seems to switch between 4 different IRQ vectors, using a table at $CD80. One of these four IRQ handlers is just this tiny thing:
Code:
IRQvecs_4E8C
        $CE8C  E6 11:       inc $11
        $CE8E  EA:          nop
        $CE8F  EA:          nop
        $CE90  EA:          nop
        $CE91  48:          pha
        $CE92  68:          pla
        $CE93  48:          pha
        $CE94  68:          pla
        $CE95  40:          rti

(total IRQ duration: 7+3+5+2+2+2+3+4+3+4+6 = 41cy)

It's pretty clear that there's no acknowledgement here.

So ... there's only really two guesses I have for how it could possibly work:
1- it drives /IRQ low for N clocks every M clocks (where clocks maybe is PPUA13, PPUA12, PPU/RD, M2, &c)
2- it detects some bus activity during the IRQ vectoring process and uses that to acknowledge the IRQ.

The string of nops and two pairs of pha/pla implies #1.
Re: 3D Block (Hwang Shinwei)
by on (#201136)
"Magic Jewelry 2" writes to 4A00 and 4C00 as well. It's possible that 3D Block (1989) uses the same PCB, and if so, should be put under Mapper 216 as well.

Edit:
Alyosha_TAS wrote:
and if the same IRQs are active there that need to be active in the games screen, the result is just a mess.
During the title screen, BG and Sprites are fetched both from $0000, while they are fetched from different pattern tables during the actual gameplay. That means that IRQs will not occur on the title screen if the IRQ is clocked by A12 change.
Re: 3D Block (Hwang Shinwei)
by on (#201137)
No implementation on mapper 216 I check has any IRQ behaviour associated with it, so if it is really mapper 216 then mapper 216 is underspecified. But it does seem reasonable for them to be the same (they have the same music at least.)

@lidnariq: thanks for the analysis, I tried implementing a mmc3 style IRQ that only asserts for a set number of cycles, and the IRQ behaviour is starting to look correct (it doesn't fire on the title screen because it doesn't use PPU a12.) So maybe we are on the right track here and just need to narrow down what it is measuring and how it is counting.
Re: 3D Block (Hwang Shinwei)
by on (#201139)
No matter how I implement IRQs, the blocks don't seem to actually fall. Either they only fall if the IRQs occur at exactly the right time, or something else is missing.
Re: 3D Block (Hwang Shinwei)
by on (#201141)
NewRisingSun wrote:
No matter how I implement IRQs, the blocks don't seem to actually fall. Either they only fall if the IRQs occur at exactly the right time, or something else is missing.


Were you able to at least get the screen and blocks to look correct?

I think there might be some bank switching going on somehow (swapping top and bottom 16k banks) but my only evidence of this is that there appears to be an IRQ vector at $3FFE (on the cart) and the code at the pointed to location appears to be a proper IRQ location (it promptly stores A,X,Y at the start of execution.)

I'm not sure what would trigger the bank swap though.
Re: 3D Block (Hwang Shinwei)
by on (#201142)
Quote:
I think there might be some bank switching going on somehow (swapping top and bottom 16k banks) but my only evidence of this is that there appears to be an IRQ vector at $3FFE (on the cart)
That doesn't look like a vector to me at all, as it occurs within a contiguous section of code that also crosses the 16k boundary. I don't think there are 16k swappable banks.
Re: 3D Block (Hwang Shinwei)
by on (#201143)
... Um? At $3FFE in PRG I see the bytes $0 $a8, and in its surrounding bytes that feels more like a chunk of code than a pointer.... are we talking about the same ROM after all?

I agree that I see code starting at PRG $6800, but it looks like a replacement NMI (it writes to $4014)
Re: 3D Block (Hwang Shinwei)
by on (#201144)
lidnariq wrote:
... Um? At $3FFE in PRG I see the bytes $0 $a8, and in its surrounding bytes that feels more like a chunk of code than a pointer.... are we talking about the same ROM after all?

I agree that I see code starting at PRG $6800, but it looks like a replacement NMI (it writes to $4014)


Yeah that's the block of code I mean, maybe it's just coincidence then.
Either way, maybe we need some way to access this code?

EDIT: Oh wait, it does run it, ok nevermind me.

EDIT2: It looks like the write to $4900 is the IRQ reload counter, setting it to 0x37 *2 + 1 gives exactly the right split in the screen.
Re: 3D Block (Hwang Shinwei)
by on (#222579)
The 3D Block PCB is also used by the original version of "Block Force" (called "Square Force" in GoodNES). It uses a PIC16C54 microcontroller with an embedded ROM and takes CPU A4-A14 plus M2 as an input, and provides /IRQ as an output. In other words, it watches the CPU address bus, counts M2 cycles, and fires an IRQ when it feels like it. CPU D0-D7 are not connected to the microcontroller. The microcontroller has a protection feature which prevents the embedded ROM from being read out by an EPROM programmer.

Images provided by MLX.
Re: 3D Block (Hwang Shinwei)
by on (#222580)
PIC16C54 pinout
Code:
PIC.01 - 27C.05
PIC.02 - 27C.06
PIC.03 - NC
PIC.04 - 4.7kΩ
PIC.05 - GND
PIC.06 - 27C.02
PIC.07 - 27C.03
PIC.08 - CPU A10
PIC.09 - 27C.23
PIC.10 - 27C.24
PIC.11 - 27C.25
PIC.12 - 27C.26
PIC.13 - 27C.27
PIC.14 - +5V
PIC.15 - NC
PIC.16 - M2
PIC.17 - /IRQ (pin 15)
PIC.18 - 27C.04
Re: 3D Block (Hwang Shinwei)
by on (#222656)
A very partial emulation that runs Block Force. Using the Square Force ROM from GoodNES, setting it to mapper #355 (and CHR-RAM to 8 KiB), and making sure that CPU->RAM Initialization is set to 00 in the emulator, should run the game. The initial high score (which is 006502 on the unprotected multicart-extracted version) is very sensitive to IRQ timing and therefore probably displayed incorrectly.

Right now, I am just firing an IRQ 13760 M2 cycles after any write to addresses 00D7 or 00E8. Emulating 3D Block will not be possible with such fakery and will definitely require dumping the microcontroller ROM, because that one will actually contain some gameplay code without which the blocks will never fall.
Re: 3D Block (Hwang Shinwei)
by on (#222661)
What I personally find weird is that the PIC here is running directly off the same 1.8MHz clock that the CPU is, but the PIC has a ÷4 prescaler on the CPU, so it's actually running at ≈450KIpS.

The 12 I/O lines on the PIC are connected to CPUA[4...14] and /IRQ; so theoretically the PIC could choose to assert /IRQ based on that portion of the address, possibly requiring specific addresses in sequence. But it's not paying attention to the R/W line, so whatever's going on can't be related to direction.

This very old model of PIC doesn't have (internal) interrupts, and the only thing it could be doing is polling the address lines; to check for specific addresses will take 8 Tcy (32 6502 cycles) with some code that looks something like
Code:
a:
movlw 0x55
xorwf PORTB, w
btfss STATUS, Z
goto a
movlw 0xA
xorwf PORTA, w
btfss STATUS, Z
goto a

although I'm certain there's a little more cleverness possible.

Due to using the same clock as the CPU, we know that the PIC can only check its inputs (the address bus) exactly every 4th cycle. But at the same time, there's nothing to keep the PIC synchronized, so I don't think there's reason to think that the code inside is only checking 6502 CPU cycles n where n≡1(mod 4)


I know I'd read some article in the past about defeating the code protect using a die photograph to find the location that the CP bit is and erase it...

Apparently the PIC16C54 follow-up PIC – the PIC16C84 – is vulnerable to a variety of relatively inexpensive deprotection attacks. https://www.cl.cam.ac.uk/~sps32/mcu_lock.html

There's also more invasive solutions: http://caps0ff.blogspot.com/2018/05/mos ... 16c57.html
Re: 3D Block (Hwang Shinwei)
by on (#223951)
I read the PIC's contents from MLX's cartridge:
Re: 3D Block (Hwang Shinwei)
by on (#223952)
Cool! Was it not protected after all, or did you manage to disable/evade the protection?
Re: 3D Block (Hwang Shinwei)
by on (#223953)
I did not do anything.
Re: 3D Block (Hwang Shinwei)
by on (#223955)
Data sheet wrote:
In code protected parts, specifically PIC16C54/C54A/CR54/C55/C56/C57 devices, the contents of the program memory cannot be read out in a way that the program code can be reconstructed. A location when read out will read as: 0000 0000 xxxx where xxxx is the XOR of the three nibbles. For example, if the memory location contains 0xC04 (movlw 4), after code protection the output will be 0x008.

That seems to describe the data in PIC.BIN rather well, so it is protected after all, and the data you have read is not the actual data.
Re: 3D Block (Hwang Shinwei)
by on (#223959)
Ok, I will brute force the chip with logic values soon.
Re: 3D Block (Hwang Shinwei)
by on (#223972)
NewRisingSun wrote:
That seems to describe the data in PIC.BIN rather well, so it is protected after all, and the data you have read is not the actual data.
Heh, I was going to say those bytes didn't look like actual code.

It does let us see that there's only 151 words of code in it, at least.

edit: on the unlikely chance this is helpful, I'd made a table of the 12-bit PIC instruction set sorted by instruction encoding:
Code:
00X-03X 000000dfffff movw*
    000 000000000000 nop
    002 000000000010 option
    003 000000000011 sleep
    004 000000000100 clrwdt
005-009 00000000ffff tris
010-017 000000010fff movlb
    01E 000000011110 return
    01F 000000011111 retfie
02X-03X 0000001fffff movwf
04X-07X 000001dfffff clr*
    040 000001000000 clrw
06X-07X 0000011fffff clrf
08X-0BX 000010dfffff subwf
0CX-0FX 000011dfffff decf
10X-13X 000100dfffff iorwf
14X-17X 000101dfffff andwf
18X-1BX 000110dfffff Xorwf
1CX-1FX 000111dfffff addwf
20X-23X 001000dfffff movf
24X-27X 001001dfffff comf
28X-2BX 001010dfffff incf
2CX-2FX 001011dfffff decfsz
30X-33X 001100dfffff rrf
34X-37X 001101dfffff rlf
38X-3BX 001110dfffff swapf
3CX-3FX 001111dfffff incfsz
    4XX 0100bbbfffff bcf
    5xx 0101bbbfffff bsf
    6xx 0110bbbfffff btfsc
    7xx 0111bbbfffff btfss
    8xx 1000xxxxxxxx retlw
    9xx 1001xxxxxxxx call
Axx-Bxx 101xxxxxxxxx goto
    Cxx 1100xxxxxxxx movlw
    Dxx 1101xxxxxxxx iorlw
    Exx 1110xxxxxxxx andlw
    Fxx 1111xxxxxxxx xorlw
Re: 3D Block (Hwang Shinwei)
by on (#224051)
Out of curiosity, would the mentionned version of 3D-Block (CRC 5E8764F8) work on this PCB (did they leave compatibily code in the PIC?).
Re: 3D Block (Hwang Shinwei)
by on (#224080)
That is unknown at this time. Since both games' PRG-ROMs are already dumped however, one could reprogram the EPROM on the Block Force PCB with 3D Block's PRG-ROM data and see if it works --- if it doesn't, one can always reprogram it with the original Block Force PRG-ROM data.
Re: 3D Block (Hwang Shinwei)
by on (#224198)
I found a trivial way to get the contents of a 16C54 out: http://www.piclist.com/techref/microchip/crackpic.htm

In short, you can read the XORed ROM contents, re-program the ROM with all FF0h, read the XORed ROM contents, re-program the ROM with all F00h, read the ROM contents, and then combine the three dumps together.

It does require a some extra effort to program an already-programmed PIC.
Re: 3D Block (Hwang Shinwei)
by on (#224208)
Not to mention that if something goes wrong, the PIC data will likely be lost, so the original cartridge owner should consent to the attempt first.
Re: 3D Block (Hwang Shinwei)
by on (#224210)
If that's the only way to go, I'd like the person to try their hands with another 16C54, serving as a guinea pig.

I'm not interested in digging for years to find another copy.
Re: 3D Block (Hwang Shinwei)
by on (#224213)
Seems like a good approach.
Re: 3D Block (Hwang Shinwei)
by on (#224219)
(I do prefer that one attempt of feeding it with addresses and see how it reacts is done before going that way too).
Re: 3D Block (Hwang Shinwei)
by on (#226559)
I have been able to deduce for 3D Block how the main game code communicates with the PIC, and what data is being sent and returned.

As we know, the game can only communicate with the PIC through the upper twelve bits of the CPU address bus. The game does this by calling wait loop procedures that are spaced 16 bytes apart. In the case of 3D Block, there is one wait loop procedure each at E180, E190... E1F0. The PIC sees address E18x for several cycles and concludes that its function 0 is to be executed; it sees address E1Fx and concludes that its function 7 is to be executed --- you get the idea. Both the functions and the addresses that trigger them are game-specific; 3D Block's are incompatible to Block Force's. 3D Block's PIC functions are:
  • Function 0: Main game screen split --- raise one IRQ about 12,400 M2 cycles later.
  • Function 1: Clear internal 32-bit register and prepare for further data --- raise one IRQ immediately to acknowledge.
  • Function 2: Start raising IRQs timed such that a counter in the main game, increased on every IRQ being generated, reaches 247, no lower, no higher. (I don't know the exact timing values, only the result that must be reached in the main game.)
  • Function 3: Send a 1 bit to the PIC. Raise one IRQ immediately to acknowledge.
  • Function 4: Level introduction screen split --- raise several IRQs about 2,175-or-so cycles apart. I don't know the exact duration or how many; I'm basing this on the fact that the pattern table is switched after the IRQ handler has been called six times, and the pattern switch still needs to be about mid-screen for the playfield to not look wong.
  • Function 5: Send a 0 bit to the PIC. Raise one IRQ immediately to acknowledge.
  • Function 6: Receive a result byte from the PIC. The number of IRQs generated resembles the result byte value and can be 0 if no IRQ is generated.
  • Function 7: Reset the IRQ generation counter for subfunction 2.
Functions 7 and 2 are used on the title screen to set the byte at $02D1 to its proper value of $F7. Wrong value, and the blocks that have fallen to the ground already will be displayed incorrectly.
Functions 1, 3 and 5 are used in-game whenever the wire-frame pieces are being redrawn. The main game packs most of its game state into four bytes and sends them to the PIC. After receiving 32 bits, the PIC apparently starts processing them.
Function 6 is called four times to receive four result bytes. Basically, based on the current game state that was sent before, the PIC spits out the next position of the current piece. That is why not emulating the PIC causes the pieces to never move. Mercifully, the proper game logic can be deduced from the later 1990 release of the game.
Functions 0 and 4 are only cosmetic and cause pattern table switches and X position updates in the case of 4.

Block Force has sixteen functions from FE00 to FEF0, again spaced in 16-byte distances:
  • Function 12: status bar during game play. Raise one IRQ after about 25,000 M2 cycles.
  • Function 15: something at bootup. I just raise one IRQ after 6,000 M2 cycles.
  • Functions 9 and 11: unknown, but raising one IRQ immediately minimizes the pauses.
Wait procedure 0 immediately jumps to wait procedure 8, 1 to 9, and so on. Apparently, this version of the PIC program will not execute the same function twice, so functions 0-7 seem to be dummy functions to enable executing functions 8-15 multiple times in a row.

This is all preliminary, because I have not tested the games at length. Block Force is supposed to display an initial high score of 006502, which it does not with the above description. But it's playable with the status bar.

Try a current build of NintendulatorNRS if you want, and be sure to set your unmodified ROM images to NES 2.0 Mapper 355. Credit to krzysiobal for pointing out the 16-bytes-spaced wait loops that signal a function request to the PIC, and credit to me for determining what the subfunctions that have been identified do.

This does not remove the need to have both games' PIC prgoram to be dumped.
Re: 3D Block (Hwang Shinwei)
by on (#226572)
NewRisingSun wrote:
Wait procedure 0 immediately jumps to wait procedure 8, 1 to 9, and so on. Apparently, this version of the PIC program will not execute the same function twice, so functions 0-7 seem to be dummy functions to enable executing functions 8-15 multiple times in a row.
I bet that's for better synchronization. An iteration through the tightest possible poll loop takes 3 PIC instruction cycles, or 12 M2. To check for a specific value requires more instructions—loading the value, XORing it, check the flag, repeat—but just polling for a single pin's rising edge is tighter:

Somewhere in Block Force's PIC there's assuredly going to be a pair of instructions:
Code:
btfss PORTB, 1 ;  0x726 → when enciphered should read back as 3
goto $-2 ; encoding unknown; no relative address instructions in 12-bit PIC


CPU A14 through CPU A7 are available on the PIC's 8-bit wide "port B", while CPU A6 through A4 are are the 4-bit wide "port A". This means that the PIC can literally just use PORTA to select the requested function.

Since the poll loop in 3D Block will involve looking for the address $E180, that will be the byte 0xC3 inside the PIC. ((0xE180 >> 7) & 0xFF). It'll most likely show up as either movlw 0xC3 / xorwf PORTB, w (0xCC3 / 0x186 → 3 / F) or movf PORTB, w / xorlw 0xC3 (0x206 / 0xFC3 → 4 / 0) although they could have written the code in various other obfuscatory ways. not C3. E2. Bits are shuffled.
Re: 3D Block (Hwang Shinwei)
by on (#226584)
I have been able to gain a better understanding of Block Force's PIC functions.

As mentioned before (and as originally found out by Krzysiobal), function 0 is invoked by calling a wait loop at $FE00, function 15 at $FEF0, and so on. The wait loops at functions 0-7 directly jump to the wait loop of the respective function +8. The function is therefore invoked by a rising edge of CPU A7. This was not the case with 3D Block.
  • Function 0: Set PIC RAM address to 0.
  • Function 1: Increase PIC RAM address by 1.
  • Function 2: Set the byte at the current PIC RAM address to $00.
  • Function 3: Increase the byte at the current PIC RAM address.
  • Function 4: Generate an IRQ after about 25,000 M2 cycles. This function is used to time the status bar during gameplay.
  • Function 5: Replace the high score at RAM $1A-$1F with the current score at RAM $14-$19 if the current score is higher.
  • Function 6: Load the PIC latch with the byte at the current PIC RAM address.
  • Function 7: Decrease the PIC latch, and generate an IRQ if it has become zero after decreasing.
The PIC RAM has 32 bytes, and is initialized with zeros except for addresses $1A-$1F, which hold the high score, and which are initialized to 006502 ("02 00 05 06 00 00"). The game also writes the current game level to RAM $08, and $09 in two-player mode, but I have no idea why. I don't know whether the functions other than 4 and 7 generate an IRQ at all, to acknowledge the request; the game would ignore the IRQ if they do.

I have updated the NintendulatorNRS build linked to in my previous post.
Re: 3D Block (Hwang Shinwei)
by on (#226596)
NewRisingSun wrote:
The PIC RAM has 32 bytes, and is initialized with zeros except for addresses $1A-$1F, which hold the high score, and which are initialized to 006502 ("02 00 05 06 00 00"). The game also writes the current game level to RAM $08, and $09 in two-player mode, but I have no idea why. I don't know whether the functions other than 4 and 7 generate an IRQ at all, to acknowledge the request; the game would ignore the IRQ if they do.
Huh. That's probably directly manipulating the PIC's pointer register ("File Selection Register"). The PIC16C54 only has 25 bytes of RAM (addresses 7-0x1F), in 32 addressable locations. The other 7 addresses are so-called "Special Function Registers" and control things like indirect branching, the current pin i/o values, and a few other things.

Because of this, we should be able to read PCL ("Program Counter Low byte", address 2) to figure out where in the PIC's memory space function 6 is.
Re: 3D Block (Hwang Shinwei)
by on (#226663)
Do we have the enciphered dump of Block Force's PIC anywhere?
Re: 3D Block (Hwang Shinwei)
by on (#226666)
Right here as an attachment. Or maybe I am misunderstanding your request.
Re: 3D Block (Hwang Shinwei)
by on (#226667)
I thought that one was 3D block?
Re: 3D Block (Hwang Shinwei)
by on (#226668)
No, the PCB is from a Block Force cartridge. The PCB has just 3-D Block written on it, apparently because Block Force reuses that game's PCB, with different EPROM and PIC ROM content.
Re: 3D Block (Hwang Shinwei)
by on (#226682)
NewRisingSun wrote:
The PIC RAM has 32 bytes, and is initialized with zeros except for addresses $1A-$1F, which hold the high score, and which are initialized to 006502 ("02 00 05 06 00 00").
Does the 6502 tell the PIC to do this? Or does the PIC need to have done this on its own?Oh, it's the PIC.

I've been playing "jigsaw puzzle" with the dump, and am pretty certain of this small handful of instructions starting at word 3:
Code:
03 c movlw 0xFF
04 6 tris PORTB
05 e movlw 2
06 9 movwf 0x1A
07 c movlw 0
08 8 movwf 0x1B
09 9 movlw 5
0a f movwf 0x1C
0b a movlw 6
0c e movwf 0x1D
0d c movlw 0
0e d movwf 0x1E
0f c movlw 0
10 c movwf 0x1F


slightly lower confidence for the immediate next eight:
Code:
11 c  movlw 0xdd ; 0xDD corresponds to address 0xFE00
12 f  xorwf PORTB, w
13 0  btfss STATUS,Z ; wait until address bus matches
14 a  goto 0x11
15 c  movlw 0xdd
16 f  xorwf PORTB, w
17 1  btfsc STATUS,Z ; wait until address bus mismatch
18 e  goto 0x15


a hunch:
Code:
30 2 clrf FSR ; f'n 0
31 a incfsz 7,f
32 c incf FSR,f ; f'n 1
33 a incfsz 7,f
34 6 clrf INDF ; f'n 2
35 a incfsz 7,f
36 8 incf INDF,f ; f'n 3
37 a incfsz 7,f


There's also an interesting set of almost-repeats starting at word 4F:
AA61846
AB71146
A441946
A551046
A621E46
A713746
.... I wonder if that's the routine that copies over the score? I can't figure out why it takes 7 instructions per byte instead of 2, though.
Re: 3D Block (Hwang Shinwei)
by on (#226752)
NewRisingSun wrote:
Function 5: Replace the high score at RAM $1A-$1F with the current score at RAM $14-$19 if the current score is higher.
PIC RAM has 32 bytes, and is initialized with zeros except for addresses $1A-$1F, which hold the high score, and which are initialized to 006502 ("02 00 05 06 00 00"). The game also writes the current game level to RAM $08, and $09 in two-player mode
Have you seen it use memory addresses other than 8, 9, and 0x14-0x1F ?

Does krzysiobal have the ability to test the PIC's reactions to certain queries? I'm curious what the result is if one tries to read from PIC RAM addresses 0-7.

The repetitions starting at word 4F are probably the bit that compare the score at $1A-$1F with the score at $14-$19, something like this:
Code:
4f a
50 a  movf 0x19,w ; {a,b,4,5,6,7} ^ 3 = {9,8,7,6,5,4}
51 6  subwf 0x1f,w ; {6,7,4,5,2,3} ^ 9 = {f,e,d,c,b,a}
52 1  btfsc STATUS,Z
53 8  goto 0x57 (8,1,9,0,e) is +7 before enciphering
54 4  btfss STATUS,C
55 6  goto ?
Re: 3D Block (Hwang Shinwei)
by on (#226754)
lidnariq wrote:
Have you seen it use memory addresses other than 8, 9, and 0x14-0x1F ?
It uses addresses 0x10 and 0x11 to store values that are immediately returned, basically to test the PIC's function, because it deliberately goes on a code path to nowhere if the just-written value is not properly returned.
Re: 3D Block (Hwang Shinwei)
by on (#226784)
If the PIC only asserted /IRQ for one Tcy (four M2) would that pose a problem for the existing 2A03 code?

Hunch:
Code:
48 2   movf INDF, w ??? ; f'n 6????
49 5   movwf 7
4a a   goto 0x11 ???
4b b   decfsz 7,f ; f'n 7???
4c a   goto 0x11 ???
4d 1   bcf PORTA,0 ???
4e 0   bsf PORTA,0 ???
4f a   goto 0x11 ???
Re: 3D Block (Hwang Shinwei)
by on (#226785)
That would depend on what the 6502 CPU does when an IRQ is raised while an instruction is executing but lowered before that same instruction is finished --- is the IRQ lost? If so, then yes, it would be a problem, otherwise no.
Re: 3D Block (Hwang Shinwei)
by on (#226786)
Yeah, my understanding is that the 6502 will only dispatch an IRQ if /IRQ is asserted during the φ1 of the penultimate cycle of an instruction. (Right?)

The reason I ask is I see that "1 / 0" pattern in two places, which could mean "drive /IRQ low then drive /IRQ high" (bcf PORTA,0 / bsf PORTA,0) and no obvious other places where 1 and 0 are separated by other instructions. Which in turn means it would only be asserted for 4 M2, which makes it highly dependent on the exact code that's interrupted as to whether the 6502 would receive them correctly. (Hence asking)

The other possibility is that it's actually using the tris PORTA instruction to toggle the line between driven low and hiZ; tris PORTA will encipher to 5. There's only one place that could be, but it's not really all that plausible:

unlikely:
Code:
3c f movlw 0xde
3d 5 tris PORTA
3e e movlw 0xdf
3f 5 tris PORTA
Generally one doesn't put a random-feeling number like "0xd" in the don't care bits.
Re: 3D Block (Hwang Shinwei)
by on (#226787)
The 6502 code is extremely obfuscated. We're talking replacing a single STA by a mountain of indirect-indirect-indirectly-addressed transfers, which take 5 or 6 cycles each.

And when reading PIC RAM, the 6502 code cannot afford to miss the IRQ, because it works like this (greatly simplified):
Code:
   JSR   ReadPICValue
   ; (...)
   
   ; subroutine
ReadPICValue:
   JSR   PIC_LoadLatch   ; fn#6
   LDA   #0
   STA   value+0
   STA   value+1
loopy:
   JSR   PIC_DecLatch   ; fn#7
   CLC
   LDA   value+0
   ADC   #1
   STA   value+0
   LDA   value+1
   ADC   #0
   STA   value+1
   JMP   loopy
   ; no RTS!
   
IRQhandler:
   PLA
   PLA
   PLA
   RTS
   
Re: 3D Block (Hwang Shinwei)
by on (#226789)
How many M2 does it take between when it arrives at "loopy" and gets there again?
Re: 3D Block (Hwang Shinwei)
by on (#226808)
405, of which 126 are spent in the wait loop that requests function 7.