• Ninja Tap patch for Rock'N'Roller (MSX1)

    03/17/2023 at 04:33 0 comments

    After a suggestion from [gdx] from MRC I took a look at the Rock'N'Roller (MSX1) and started to work on a patch for Ninja/Shinobi Tap multi controller adapter.

    First step was to disassemble the game and figure out how the game deals with the controls. There are several calls to 3 of the BIOS routines that read the keyboard, the joysticks and the trigger buttons (from the joysticks) and decided that the best strategy was to emulate such BIOS routines and return correspondent values based on the buttons pressed on the controllers plugged in the multitap adapter.

    Next step was to figure out a position in RAM out of the game execution to place the patch code -> address 0xdf00 to 0xe300 seemed nice

    Following I have created the alternate routines:


    The alternate routines fall back to the original BIOS call when the Ninja/Shinobi tap is not detected (a flag is reset) . for instance...

        ld b,a                  ; save row number
        ld a,(ninjaDetectFlag)  ; test for ninja presence
        and a                   ;
        ld a,b                  ; restore row number
        jp z,0d5h ; (GTSTCK)    ; if not present continue with BIOS routine
        ; read and return STICK value

    Next step was to generate a list of addresses where the BIOS calls are called and write a quick and dirt and code to replace such calls with the alternate routines created. The +1 is the offset for the instruction code CD (call) at the addresses that call the bios routines.

    ; Patch Original game code 
        ld hl, ALT_SNSMAT  ; patch calls to 0141h (SNSMAT)
        ld (09648h+1),hl 
        ld (0966bh+1),hl 
        ld (09676h+1),hl 
        ld (09685h+1),hl 
        ld (09b7ch+1),hl 

    Then I have created a function that will be called in the game main loop to scan the joystick ports and detect the presence of a multitap adapter om port A. If an adapter is detected, a flag is marked and the four taps are read and converted as a mirror of a keyboard matrix and joystick directionals and triggers.

    	; check for presence of Tap
    	call CHECKTAPS ; c = 0  0  0  0  a1 a0 b1 b0
    	cpl            ;  c = 1  1  1  1 /a1 /a0 /b1 /b0
    	and 08h        ; isolate bit a1 ->  a = 0 0 0 0 /a1 0 0 0
    	ld (ninjaDetectFlag),a  ; /a1 should be 1 if a ninja or shinobi is detected
    	ret z
    ; scan taps
    ;   ld de,0fa7ah  ;  Tap connected to joy port 2
       ld de,0ba3ah  ;   Tap connected to joy port 1
       ld hl,ntapData
       call GETNIN ; read TAPS on port 1	
    ; process taps *************************************


    Button Mapping

    Tap 1 is mapped as :

    • Up, Down, Left, Right -> Ditto
    • Trigger A - Z
    • Trigger B - X
    • Select  - SEL
    • Start - Escape

    That was done to allow full access and control of Options menu from the game, but it is still possible to access and control the Optiosn menu using the MSX keyboard.

    Tap 2 is mapped as the QSCS (Q, S, Control, Shift) controls

    Tap 3 is mapped as Joystick 1

    Tap 4 is mapped as Joystick 2

    To be continued...

  • Keyboard Controller with Joystick for MSX (2)

    11/26/2022 at 21:33 0 comments

    Added a second diode to enhance the detection

    And drafted some driver code that provides scan and decode that takes 98 bytes plus 5 RAM addresses.

    ; Scan Atari keyboard and single button joystick using 
    ; and adapter with 74LS139
    ; PSG IO addresses
    ; DetectKB2600 - Detect Atari controller keyboard
    ; Input: 
    ;       register A: 0=Connector 1, >0=Connector 2.
    ; Ouptut:
    ;       Z -> keyboard detected
    ;      NZ -> keyboard adapter not detected
      call ScanKB2600
      ld de,KBROWS
      ld c,0
      ld a,(de)
      and 00010000b ; isolate bit 4
      or c
      ld c,a
      inc de
    djnz Detct0
      cp 01000000b
    ; ScanKB2600 - Scan Atari controller keyboard 
    ; Inputs: 
    ;        register A: 0=Connector 1, >0=Connector 2.
    ; Ouptuts   :          bit  7  6  5  4  3  2  1  0
    ;           KBROWS     ->   1  1  1  0  #  9  6  3
    ;           KBROWS + 1 ->   1  1  1  1  0  8  5  2
    ;           KBROWS + 2 ->   1  1  1  0  *  7  4  1
    ;(JOYTBITS) KBROWS + 3 ->   1  1  1  TA RG LF DW UP
       ; set zero flag according to port option
       and a
       ; Save PSG Context
       ld a,15
       out (PSGAD),a
       in a,(PSGRD)
       ld (SAVPSG),a
       ld hl, KBROWS
       ; Select Joystick port accordingly
       jr NZ, ScanCon2
       and 10101101b  ; clear bit 6 -> Joysel -> joy port 0, 4:PULSE and 1:TRIGGER B
    ;  a = pins 8,7 low  (row 0)
       ld b,a  ; a = pin 8=0, pin 7=0 (row 0)
       set 4,b ; b = pin 8=1, pin 7=0 (row 1)
       ld c,b  ;
       set 1,c ; c = pin 8=1, pin 7=1 (row 2)
       ld d,a  ; a = pin 8=0, pin 7=0 (row 0)
       set 1,d ; b = pin 8=0, pin 7=1 (Joystick)
       jr ScanRow0
       and 10010111b  ; clear bit 5:PULSE and 3:TRIGGER B
       set 6,a        ; Set bit 6 -> Joysel -> joy port 1
       ld b,a  ; a = pin 8=0, pin 7=0 (row 0)
       set 5,b ; b = pin 8=1, pin 7=0 (row 1)
       ld c,b  ;
       set 3,c ; c = pin 8=1, pin 7=1 (row 2)
       ld d,a  ; a = pin 8=0, pin 7=0 (row 0)
       set 3,d ; b = pin 8=0, pin 7=1 (Joystick)
       ld e,a
       call SaveRow
       ld e,b
       call SaveRow
       ld e,c
       call SaveRow
       ld e,d
       call SaveRow
       ld e,(hl) ; hl now points to SAVPSG
       di             ; disable interrupts
       ld a,15
       out (PSGAD),a
       ld a, e
       out (PSGWR),a  ; update register 15
       ld a,14
       out (PSGAD),a  ; select register 14
       in a,(PSGRD)   ; read keys hhhh*741
       or 11110000b   ; mask unused bits
       ld (HL),a      ; save keyboard state
       inc hl
     ; Variables
    ; keyboard rows HHHL#963, HHHH0852, HHHL*741
     KBROWS:  DS 3
     JOYBITS: DS 1
    ;   PSG register 15 save state during execution, destroyed buttons at the end
    ; must be contiguous to Joybits
     SAVPSG: DS 1 

  • Keyboard Controller with Joystick for MSX

    11/19/2022 at 10:49 0 comments

    I have built the Atari 2600 controller keyboard DIY to develop an adapter and write a driver for MSX. The adapter aimed for simplicity but it does not provide any detection feature, requiring the user to without an action, either pressing a key or move the joystick to any direction, depending upon the peripheral connected on the joystick port.

    If I give up the simplicity and add an Integrated Circuit and a bunch of diodes it is possible, though, to build an adapter that can support both the keyboard controller and a single button joystick, connected at the same time, using basically the same driver. And there's more: the joystick can still be read by Basic.

    here's the circuit:

    The rows of the keyboard connected at X2 are selected by the pins PULSE (8) and TRIGGER_B(7) (which is bidirectional). The default state of these pins are PULSE->0 and TRIGGER_B->1 which selects the common line of the joystick, thus allowing the single button joystick connected to X3 to be read using BASIC.

    Detection is possible by Selecting the third keyboard ROW, then diode D5 will bring down the level on the TRIGGER_A line. The other keyboard rows will keep this line high.