One of the problems when converting Gravitar to run on Space Duel hardware is the button input circuitry differences. Gravitar expects to read two addresses $8000 and $8800 where all 8 bits correspond to a button input. Space Duel reads 8 addresses from $900 to $907 but only bits 6 and 7 correspond to buttons.
When converting Gravitar I wrote some code that would read the Space Duel addresses and construct an 8 bit value that mapped the Space Duel buttons to the Gravitar pattern.
I then searched the Gravitar code to look for any reads of address $7800, $8000 and $8800 and replaced the read instructions with a jump to subroutine pointed at my conversion code. There were only a handful of reads found and it was fairly quick to replace, so it appeared to work OK.
But one part of the game code did not work correctly which was the test mode. In test mode both Gravitar and Space Duel use a similar screen where there are a few rows of binary digits shown as 0's or 1's. Pressing a button changes the 0 to a 1 and there's a short beep sound to confirm the button press.
My converted Gravitar code did beep correctly but would not change the 0 to a 1 on screen, which was a puzzle.
I've tried to find the part of code responsible for some time but not had much success until now. After a fair bit of MAME debugger breakpoints and tracing back the test mode screen draw for 0's and 1's I finally found the part that does the test mode.
The basic reason it was not working is that instead of a simple read of the addresses $7800, $8000 or $8800 that the rest of the game code uses, the test code sets up a 16 bit pointer in RAM and uses that with the 6502 Indirect Indexed addressing mode to read from the input addresses. It then reads the three addresses from a short loop and then prints out the state of each bit using 0's and 1's on the screen.
The routine starts at $EC41 for Gravitar Rev 3. The first part of the routine reads from POKEY registers on both POKEY chips to get two bytes that represent the two 8 way DIP switches on the PCB that are connected to the POKEY pot ports. This part was already working as I'd done a simple search and replace on any reads and writes to the POKEY addresses and moved them to the Space Duel addresses.
EC41 loc_EC41:
EC41 LDX #0Fh ; Button test 0/1 display
EC43 STX byte_22
EC45 STA POKEY_1+0Bh ; POKEY 1 POTGO
EC48 NOP
EC49 LDA POKEY_1+8 ; Read POKEY 1 POT register
EC4C STA byte_24 ; Store POT bits in RAM temp
EC4E STA POKEY_0+0Bh ; POKEY 0 POTGO
EC51 NOP
EC52 LDA POKEY_0+8 ; Read POKEY 0 POT register
Then the test code enters a loop of 16 counts starting at $EC55 to print a 0 or 1 for each of those two bytes.
EC55 loc_EC55:
EC55 PHA ; Test POKEY DIP switches x 16
EC56 AND #1
EC58 CLC
EC59 JSR sub_DE54 ; Test 0/1 buttons
EC5C LSR byte_24
EC5E PLA
EC5F ROR A
EC60 DEC byte_22
EC62 BPL loc_EC55 ; Test POKEY DIP switches x 16
After exiting the loop it moves the vector beam to a new screen position ready for the next line of 0's and 1's.
EC64 LDA #0D0h
EC66 LDY #0
EC68 LDX #0F8h ; Move to next line for text draw position
EC6A JSR sub_E48A ; Insert draw/move vector to new position
Next a loop count of 8 is set up and a 16 bit pointer at $38/39 is initialised to $7800. This was the culprit causing the problem!
EC71 LDA #78h ; Upper byte of address points to $7800 (Coin/test inputs)
EC73 STA byte_39
EC75 loc_EC75:
EC75 LDA #7
EC77 STA byte_3A ; Loop count
EC79 LDA #0
EC7B STA byte_38 ; Low byte off address pointer
EC7D TAY ; Clear Y index too
EC7E LDA (byte_38),Y ; Read input port starting at $7800
EC80 EOR #0FFh ; Invert button bits
EC82 AND #7Fh ; Mask top bit 7 (ignore top bit for each address)
After printing each of the 8 bits read in...
EC84 loc_EC84:
EC84 PHA
EC85 AND #1 ; Get button state bit
EC87 CLC
EC88 JSR sub_DE54 ; Insert 0/1 for button test
EC8B PLA
EC8C ROR A ; Shift for next button state bit
EC8D INY
EC8E DEC byte_3A
EC90 BPL loc_EC84
...the code moves the vector beam to the next line position...
EC92 LDA #0D0h
EC94 LDY #0
EC96 LDX #0F8h ; Move to next line for text draw position
EC98 JSR sub_E48A ; Insert draw/move vector to new position
...then adds $800 to the pointer at $38/39 and tests to see if it's hit $9000. If it has it exits the routine, else it loops to draw the next 8 characters.
EC9B LDA byte_39
EC9D CLC
EC9E ADC #8 ; Add $800 to pointer to read $7800, 8000 and 8800 in sequence
ECA0 STA byte_39
ECA2 CMP #90h ; Loop test stops at $9000
ECA4 BCC loc_EC75
ECA6 RTS
The initialising of the pointer is what I was missing in my conversion, as it's hardcoded in the LDA #78 at $EC71. Once I spotted that I realised that was why it doesn't work properly. Interestingly the sound beep feedback when you press a button in test mode is done in another part of code that does read the $7800/8000/8800 addresses directly and had already been converted properly.
Next job is to work out how to convert this code to work on the Space Duel hardware. I'm hoping Black Widow uses the same code and will be now easy to find.