` loads the assembly code for controlling ROB
1 POKE &H7700,&H2C,&H02,&H20,&H10,&HFB,&HAD,&H32,&H00,&H29,&H7F,&H8D,&H00,&H20,&HA0,&H08,&HA2,&H00,&H98,&HE0,&H05,&HD0,&H03,&HAD,&HD0,&H77,&H4A,&HA8,&HA9,&H3F,&H8D,&HD1,&H77,&H90,&H05,&HA9,&H2A,&H8D,&HD1,&H77,&HA9
2 POKE &H7728,&H80,&H2C,&H02,&H20,&HF0,&HF9,&HE0,&H0D,&HF0,&H26,&HAD,&H02,&H20,&HA9,&H3F,&H8D,&H06,&H20,&HA9,&H04,&H8D,&H06,&H20,&HAD,&HD1,&H77,&H8D,&H07,&H20,&HAD,&H02,&H20,&HA9,&H3F,&H8D,&H06,&H20,&HA9,&H04,&H8D
3 POKE &H7750,&H06,&H20,&H8D,&H01,&H20,&HE8,&HD0,&HB9,&HAD,&H33,&H00,&H8D,&H01,&H20,&H2C,&H05,&H20,&HAD,&H9D,&H00,&H8D,&H05,&H20,&HAD,&H69,&H00,&H8D,&H05,&H20,&HAD,&H32,&H00,&H09,&H80,&H8D,&H00,&H20,&H60
` prints out a simple menu
10 PRINT "H=LEFT"
12 PRINT "J=DOWN"
14 PRINT "K=UP"
16 PRINT "L=RIGHT"
17 PRINT
18 PRINT "M=DOWN 2"
20 PRINT "I=UP 2"
21 PRINT
22 PRINT "A=OPEN"
24 PRINT "S=CLOSE"
25 PRINT
26 PRINT "W=BLINK"
28 PRINT "Q=INIT"
` checks for user input
100 S$=INKEY$
120 IF(ASC(S$)=0) GOTO 100
123 RESTORE 3000
125 FOR I=1 TO 10
130 READ X$
140 READ R
150 IF (X$=S$) GOSUB 2000
160 NEXT
200 GOTO 100
` when called, will set the pattern for ROB and call the assembly routine
2000 POKE &H77D0,R
2010 CALL &H7700
2080 RETURN
` pairs of keyboard keys and ROB patterns
3000 DATA H,&H5D,J,&H75,K,&H5F,L,&H57,I,&HDD,M,&HDF,A,&H77,S,&H7D,Q,&HD5,W,&HD7
;;;;;;;;;;;;;;
.rsset $77D0
robPattern .rs 1 ; the pattern to flash to ROB (after preamble)
robPalette .rs 1 ; the color to flash to ROB next
FAMBASIC_PPUCTRL = $32 ; where Family Basic 2.1 stores its PPU ctrl
; (it will always OR this with #$80 to keep NMI on)
FAMBASIC_PPUMASK = $33 ; where Family Basic 2.1 stores its PPU mask
FAMBASIC_SCROLLX = $9D ; where Family Basic 2.1 stores its X position for PPUSCROLL
FAMBASIC_SCROLLY = $69 ; where Family Basic 2.1 stores its Y position for PPUSCROLL
;;;;;;;;;;;;;;;
.org $E700
vblankwait3: ; Second wait for vblank, PPU is ready after this
BIT $2002
BPL vblankwait3
LoadROBPattern:
LDA FAMBASIC_PPUCTRL ; load the PPUCTRL used by Family Basic
AND #$7F ; AND with %01111111 to disable NMI
STA $2000 ; disable NMI
LDY #$08 ; load preamble (%00001000)
LDX #$00 ; rest step counter
NextROBBit:
TYA ; get the preamble/action into the Y register
CPX #$05 ; is this the beginning of the action byte?
BNE DoNextROBBit
LDA robPattern ; beginning of action byte, load it up
DoNextROBBit:
LSR A ; push the next ROB bit into the carry flag
TAY ; store the preamble/action state into the Y register
LDA #$3F ; assume black
STA robPalette
BCC FlashROBBit ; if black, go flash it
LDA #$2A ; otherwise load green and go flash it
STA robPalette
;
; Will load a palette byte (robPalette) into unused palette location
; $3F04. Will then point the VRAM address to $3F04 and disable
; sprite/bg rendering. On real hardware and accurate emulators, this
; robPalette value at $3F04 will be used to fill the background.
;
FlashROBBit:
LDA #$80
BIT $2002
BEQ FlashROBBit
CPX #$0D ; all bits loaded?
BEQ DoneFlashing
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$3F
STA $2006 ; write the high byte of $3F04 address
LDA #$04
STA $2006 ; write the low byte of $3F04 address
LDA robPalette ;load palette byte
STA $2007 ;write to PPU
LDA $2002 ; read PPU status to reset the high/low latch
LDA #$3F
STA $2006 ; write the high byte of $3F04 address
LDA #$04
STA $2006 ; write the low byte of $3F04 address
STA $2001 ; disable bg/sprite rendering while VRAM address is pointing
; at the robPalette byte
INX ; increment the step counter
BNE NextROBBit ; attempt to go do the next one
DoneFlashing:
LDA FAMBASIC_PPUMASK ; otherwise, restore the original PPU mask
STA $2001
BIT $2005 ; read PPUSTATUS to reset the addres latch
LDA FAMBASIC_SCROLLX ; load X position
STA $2005 ; store X position
LDA FAMBASIC_SCROLLY ; load Y position
STA $2005 ; store Y position
LDA FAMBASIC_PPUCTRL ; load the PPUCTRL used by Family Basic
ORA #$80 ; ORA with %10000000 to enable NMI
STA $2000 ; enable NMI
RTS ; and get out of here
10 PRINT "H=LEFT"
12 PRINT "J=DOWN"
14 PRINT "K=UP"
16 PRINT "L=RIGHT"
17 PRINT
18 PRINT "M=DOWN 2"
20 PRINT "I=UP 2"
21 PRINT
22 PRINT "A=OPEN"
24 PRINT "S=CLOSE"
25 PRINT
26 PRINT "W=BLINK"
28 PRINT "Q=INIT"
100 S$=INKEY$
120 IF(ASC(S$)=0) GOTO 100
123 RESTORE 3000
125 FOR I=1 TO 10
130 READ X$
140 READ R
150 IF (X$=S$) GOSUB 2000
160 NEXT
200 GOTO 100
2000 FOR I=1 TO 13
2010 X=R MOD 2
2020 R=R/2
2030 Y=&H3F
2040 IF (X) Y=&H2A
2050 PALETB 0,Y,Y,Y,Y
2060 NEXT
2070 PALETB 0,&HF,&H30,&H21,&H2
2080 RETURN
3000 DATA H,&HBA8,J,&HEA8,K,&HBE8,L,&HAE8,I,&H1BA8,M,&H1BE8,A,&HEE8,S,&HFA8,Q,&H1AA8,W,&H1AE8
Quote from: nerdynebraskan on July 17, 2013, 03:22:09 am
As someone who does not and will never have Family Basic, my question is: will this ever lead to a homebrew ROB game made available on a repro cart? And if so, when can I throw money at you to get one? In any event, it's super cool to see ROB getting some attention almost 30 years later.
Quote from: nerdynebraskan on July 17, 2013, 03:22:09 am
will this ever lead to a homebrew ROB game made available on a repro cart?
Quote from: P on July 21, 2014, 05:53:40 am
UglyJoe I noticed that Robot Block and Gyro uses the test command a bit differently ... Maybe it's doing this by keep sending the command over and over? I don't know.
Quote from: P on July 21, 2014, 05:53:40 am
Anyway, I made a working ROM that uses UglyJoe's routine that works on a real Famicom (I've tested it on the Everdrive at least). Only problem is that ROB doesn't respond 100% of the time and there's also something weird with the controller reading because my external controller doesn't work properly.
Quote from: UglyJoe on July 21, 2014, 06:16:33 amYes I'm sure it turns on permanently (like when you finished the test in Block/Gyro).Quote from: P on July 21, 2014, 05:53:40 am
UglyJoe I noticed that Robot Block and Gyro uses the test command a bit differently ... Maybe it's doing this by keep sending the command over and over? I don't know.
I'm pretty sure the game repeats the test pattern over and over again in order to get ROB to blink the LED. I don't know what it does to make the LED stay on. Are you sure the test command isn't just a toggle for the LED (turns it on the first time it reads, then off the second time, then on the third time, etc)?
Quote from: UglyJoe on July 21, 2014, 06:16:33 amQuote from: P on July 21, 2014, 05:53:40 am
Anyway, I made a working ROM that uses UglyJoe's routine that works on a real Famicom (I've tested it on the Everdrive at least). Only problem is that ROB doesn't respond 100% of the time and there's also something weird with the controller reading because my external controller doesn't work properly.
I'll try and check it out soon. I can't test the external controller thing since I don't have a FC flashcart, though. Did you add additional logic to read in the controller input from external controllers (bit 1 on $4016 and bit 1 on $4017)?
Quote from: P on March 23, 2020, 02:59:37 amLong story short, ROB's firmware has been dumped, deassembled and analysed.
Quote from: P on March 23, 2020, 02:59:37 amTo do that, you need to repeat a blinking pattern like so: GREEN,BLACK,GREEN,BLACK,GREEN,BLACK... forever