Super NES EMULATOR SE dev question

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Super NES EMULATOR SE dev question
by on (#194296)
Hello,

I own a SUPER NES EMULATOR SE with Assembler, Linker and Debugger.

I modified a public code for assemble and link it. After assemble it without error, I found 2 issues when run it:

First : $4212 register never return $01 but $?2. How is possible to return 2 value when only bit 0, 6 an 7 can be set?

Second : When I CMP with $02 value in VBlank, only the first two conditions works (Red and Yellow BEQ) but not all others.

Please, look at the screenshot attachment. I can provide the ISX file is needed. Thanks for your help!

Here is the main file code :

Code:
; bgcolor
; Press the A, B, X and Y buttons to change the background color.

   file head.s
   file reg.s
   file set.s
   file val.s
   file init.s

bank0 group 0

   org $8000

Reset:

   Reset

Main:

    ; Set accumulator register to 8-bit
    sep #$20

    ; Set color 0 of palette 0 to white
    stz CGADD
    lda #$FF
    sta CGDATA
    lda #$7F
    sta CGDATA

    ; Enable the screen at full brightness
    lda #$0F
    sta INIDISP

    ; Enable VBlank and the joypad
    lda #(NMITIMEN_NMI_ENABLE | NMITIMEN_JOY_ENABLE)
    sta NMITIMEN

    ; Keep waiting for interrupts
w00 wai
    jmp w00

VBlank:
    ; Wait until the joypad input can be read
    lda #HVBJOY_JOYREADY
w01 and HVBJOY
    cmp #HVBJOY_JOYREADY
    bne w01

    ; Prepare to change color 0 of palette 0
    stz CGADD

    ; Reset accumulator register to 16-bit
    rep #$20
   
    on16a
   
    ; Jump to label Yellow if the A and Y buttons were pressed
    lda #(JOY_RED + JOY_GREEN)
    and JOY1
    cmp #(JOY_RED + JOY_GREEN)
    beq Yellow

    ; Jump to label Red if the A button was pressed
    lda #JOY_RED
    and JOY1
    cmp #JOY_RED
    beq Red

    ; Jump to label Yellow if the B button was pressed
    lda #JOY_YELLOW
    and JOY1
    cmp #JOY_YELLOW
    beq Yellow

    ; Jump to label Blue if the X button was pressed
    lda #JOY_BLUE
    and JOY1
    cmp #JOY_BLUE
    beq Blue

    ; Jump to label Green if the Y button was pressed
    lda #JOY_GREEN
    and JOY1
    cmp #JOY_GREEN
    beq Green

    lda #RDNMI
   
    off16a

    rti

Red:
    ; Set accumulator register back to 8-bit
    sep #$20
   
    ; Set color 0 of palette 0 to red
    lda #%00011111
    sta CGDATA
    lda #%00000000
    sta CGDATA

    rti

Green:
    ; Set accumulator register back to 8-bit
    sep #$20

    ; Set color 0 of palette 0 to green
    lda #%11100000
    sta CGDATA
    lda #%00000011
    sta CGDATA

    rti

Blue:
    ; Set accumulator register back to 8-bit
    sep #$20

    ; Set color 0 of palette 0 to blue
    lda #%00000000
    sta CGDATA
    lda #%01111100
    sta CGDATA

    rti

Yellow:
    ; Set accumulator register back to 8-bit
    sep #$20

    ; Set color 0 of palette 0 to yellow
    lda #%11111111
    sta CGDATA
    lda #%00000011
    sta CGDATA

    rti

EmptyHandler:

    rti
   
    end
Re: Super NES EMULATOR SE dev question
by on (#194302)
Can you post the rom ? Might be easier to analyze ...

Also great to see that some owner of the SE devkit are really using it ! <3
Re: Super NES EMULATOR SE dev question
by on (#194304)
Thank you for answer.

Pseudo Instruction ON16A/ON16OFF notified the assembler that the effective data range is being processed in 16 bits.

I've attached the source and ISX files. Don't know if ISX is readed by other emulator however.

ISX is the output file from ISLK (linker) and include symbol value and data area definition table for debugger.
Re: Super NES EMULATOR SE dev question
by on (#194308)
Is there a way to ouput something else than .isx format ?
Re: Super NES EMULATOR SE dev question
by on (#194314)
I found an ISX to ROM converter and apply to ISX file but ROM doesn't seem to work on my Everdrive flash card.

http://www.inetmie.or.jp/~koh/inside/koh-tool.htm

I attached the converted rom, I hope it could help.
Re: Super NES EMULATOR SE dev question
by on (#194321)
in your code you have :

Quote:
VBlank:
; Wait until the joypad input can be read
lda #HVBJOY_JOYREADY
w01 and HVBJOY
cmp #HVBJOY_JOYREADY
bne w01

Could you try to change that to :
Quote:
VBlank:
; Wait until the joypad input can be read
lda HVBJOY
w01 and #HVBJOY_JOYREADY
cmp #HVBJOY_JOYREADY
bne w01

and change
Quote:
HVBJOY_JOYREADY def $82

to
Quote:
HVBJOY_JOYREADY def $81

wich is the right value.

I really suspect that the "and $4212" is not the correct way to check for value.
Re: Super NES EMULATOR SE dev question
by on (#194325)
Thank you for your help.

The initial HVBJOY_JOYREADY value was $01 but as you can see on screenshot, my $4212 register always return $?2 values ($C2, $82, $02, etc ...).

After making the change for check the value code, I got the same issue (only the two first colors (yellow and red) are display when I push joypad buttons, others don't work)

When I change the $81 value too for HVBJOY_JOYREADY, nothing is happend when I push joypad buttons.
Re: Super NES EMULATOR SE dev question
by on (#194328)
Hang on, you have the software for the Emulator SE? Last I heard, people haven't been able to find that anywhere; is there a chance you could upload it somewhere?
Re: Super NES EMULATOR SE dev question
by on (#194329)
Peperocket wrote:
The initial HVBJOY_JOYREADY value was $01 but as you can see on screenshot, my $4212 register always return $?2 values ($C2, $82, $02, etc ...).
Odds are good that the middle five bits are not explicitly driven, and that "2" is set because the last byte on the data bus was the $42. (And the other four bits are low for the same reason)

So, while you're ≈right that you should mask the result you loaded, that should look like "and #$c1" to get rid of the bits that aren't explicitly driven.

Actually, really, you should mask and compare only the bits that you care about. You don't care about hsync/vsync in this case, so why are you keeping them at all? Use the BIT instruction.
Re: Super NES EMULATOR SE dev question
by on (#194330)
Nicole wrote:
Last I heard, people haven't been able to find that anywhere


Maybe they don't know the VUE Debugger software (Virtual Boy) hold SHVC/SNES abilities.

You can find here : http://www.planetvb.com/modules/hardware/?type=vue

Use the japanese VUE Developement Software version for Intelligent System SHVC Debugger and US version for SNES Emulator SE.

I can provide the Assembler/Linker/Debugger english version manual if needed.
Re: Super NES EMULATOR SE dev question
by on (#194331)
Also, warning, from my own experience:

vblank NMI has enough time to start executing code before autoread starts, so you can't just wait for vblank, then wait for autoread to end.
Re: Super NES EMULATOR SE dev question
by on (#194341)
Hello,

Thank you for your answer. I don't really understood what you mean when you're talking about "VBlank has enought time to start executing code before autoread start" because only thing I need to do in VBlank is reading joypad register and I can do only at the autoread start.

Do you think my VBlank handler is not reliable?
Re: Super NES EMULATOR SE dev question
by on (#194351)
What they mean is, autoreading doesn't start until a little bit after vblank, so HVBJOY can show up as "ready" from the previous frame before it becomes "not ready". It's better to wait for it to not be ready, and then wait for it to be ready, to make sure you don't end up reading it before autoreading happens.
Re: Super NES EMULATOR SE dev question
by on (#194362)
Exactly.

Per anomie's documentation, there's 32-97 pixels after NMI before [$4212]&1 reads as 0. That's 128-388 master cycles, 13-64 instruction cycles, or enough time after the NMI starts for 1-20 instructions to execute.

So ... make sure you do something else in your NMI before you check HVBJOY. Doesn't have to be much. If you're not using an NMI (as I wasn't), wait for autoread to start and finish, instead of waiting for Vblank to start.
Re: Super NES EMULATOR SE dev question
by on (#194515)
Hello,

Thank you all for explanation. I have re-written the Joypad routine and NMI's one but at this time, the program is a little bit buggy since the left direction doesn't show anything and the right one show blue screen (it must be yellow). I don't really understand ... Could you help me please?

Code:
; ***********************************************************
; *** Bgcolor 20170428 V0.1                        ***       
; *** Press the U, D, L, R buttons to change the          ***
; *** background color.                               ***
; ***********************************************************

   file head.s
   file reg.s
   file set.s
   file val.s
   file init.s

bank0 group 0

   org $8000

Reset:
   Reset

Main:
    ; Set accumulator register to 8-bit
    sep #$20

    ; Set color 0 of palette 0 to white
    stz CGADD
    lda #$FF
    sta CGDATA
    lda #$7F
    sta CGDATA

    ; Enable the screen at full brightness
    lda #$0F
    sta INIDISP

    ; Enable VBlank and the joypad
    lda #(NMITIMEN_NMI_ENABLE | NMITIMEN_JOY_ENABLE)
    sta NMITIMEN

   
; ***********************************************************
; ***  Main Code                                 ***       
; ***                                          ***
; ***                                            ***
; ***********************************************************
                 
MainLoop:
   wai
   
   lda JoypadLo               ; Put pad register copied in Direct Page into Accumulator
   
   ; Prepare to change color 0 of palette 0
    stz CGADD
   
Up:
   bit #JOYH_UP               
   beq Down                  
   
    ; Set color 0 of palette 0 to red
    lda #%00011111
    sta CGDATA
    lda #%00000000
    sta CGDATA
   
Down:
   bit #JOYH_DOWN               
   beq Left                  
   
    ; Set color 0 of palette 0 to green
    lda #%11100000
    sta CGDATA
    lda #%00000011
    sta CGDATA

Left:
   bit JOYH_LEFT               
   beq Right                  

    ; Set color 0 of palette 0 to blue
    lda #%00000000
    sta CGDATA
    lda #%01111100
    sta CGDATA

Right:
   bit JOYH_RIGHT               
   beq TerminateControl   

    ; Set color 0 of palette 0 to yellow
    lda #%11111111
    sta CGDATA
    lda #%00000011
    sta CGDATA

TerminateControl:    
   bra MainLoop               

   
; ***********************************************************
; *** NMI Interrupt                              ***
; ***                                            ***
; ***********************************************************

NMI:
    php
   pha
   phx
   
w00:
   lda HVBJOY                  ; status register, bit 0 joypad ready?
   and #$00         
   bne w00
   
w01:
   lda HVBJOY                  ; status register, bit 0 joypad ready?
   and #$01         
   bne w01

   lda JOY1H                   ; on stock le registre $4219 (status register) dans A (bystudlr)     
   sta JoypadLo               ; pour le copier en page 0
   
   lda #RDNMI                  ; clear NMI flag
   
   plx
   pla
   plp
   
   rti

EmptyHandler:
    rti
   
    end


Re: Super NES EMULATOR SE dev question
by on (#194529)
You forgot a # before JOYH_LEFT and JOYH_RIGHT.
Re: Super NES EMULATOR SE dev question
by on (#194535)
Well seen !!! Thank you very much Nicole, It's working without problem now!

Thank you ALL for the help!

I attached the source and the binary files for those interested by.
Re: Super NES EMULATOR SE dev question
by on (#194572)
Peperocket wrote:
I attached the source and the binary files for those interested by.

Nice, It's great to see another person try their hand at programming a Super Nintendo.


I've tried running your ROM on my PAL SNES and it only showed a white screen.
Tracing the code through bsnes-plus I discovered your NMI routine is broken. The two and NMITIMEN_JOY_ENABLE lines should be and #NMITIMEN_JOY_ENABLE. The code worked on your system because memory address $000001 had bits 7, 6 or 0 set. If all those bits were clear then NMI would never end.



Besides that bug, I have the following observations about your code. I apologise in advance for my tone, but I believe these sort of issues should be caught early.

1) Your storing and retrieving JOYH from JoypadLo, not JoypadHi.

2) The mainloop is setting CGRAM colour 1 to Blue when down is pressed.

3) You should remove the # from the following line:
Code:
    lda #RDNMI

4) Your register push/pop code for NMI is incomplete. It only works because your used an 8 bit accumulator and never touched bits 8-15 of A in the program.

The following code correctly saves the CPU state, resets DB/DP to 0, and restores the CPU state for an Interrupt Service Routine. We do not need to push/pop the P register, as the 65816 will push P to the stack when an interrupt is triggered.
Code:
NMI:
; save CPU state
    rep     #$30
on16i
on16a
    pha
    phx
    phy
    phd
    phb

; set DB to 0
    phk
    plb

; set DP to 0
    lda   #0
    tcd


; set a/x size
; code goes here


; restore CPU state
    rep     #$30
on16i
on16a
    plb
    pld
    ply
    plx
    pla

    rti



Peperocket wrote:
$4212 register never return $01 but $?2. How is possible to return 2 value when only bit 0, 6 an 7 can be set?

Only bits 0, 6, 7 of register $4212 are set/cleared, the unmaped bits will contain the previous value of the data bus. See https://wiki.superfamicom.org/snes/show/Open+Bus for more details


---
EDIT: Removed clear decimal flag code from NMI ISR. The 65816 clears the decimal flag when an interrupt is triggered.
Re: Super NES EMULATOR SE dev question
by on (#194580)
Hello,

Thank you for your answer.

Quote:
Tracing the code through bsnes-plus I discovered your NMI routine is broken. The two and NMITIMEN_JOY_ENABLE lines should be and #NMITIMEN_JOY_ENABLE. The code worked on your system because memory address $000001 had bits 7, 6 or 0 set. If all those bits were clear then NMI would never end.


What a stupid error!

Quote:
1) Your storing and retrieving JOYH from JoypadLo, not JoypadHi.

2) The mainloop is setting CGRAM colour 1 to Blue when down is pressed.

3) You should remove the # from the following line:
Code:
lda #RDNMI


You right. I don't understand the second point however. Could you explain?

Quote:
4) Your register push/pop code for NMI is incomplete. It only works because your used an 8 bit accumulator and never touched bits 8-15 of A in the program.

The following code correctly saves the CPU state, resets DB/DP to 0, and restores the CPU state for an Interrupt Service Routine. We do not need to push/pop the P register, as the 65816 will push P to the stack when an interrupt is triggered.
Code:
NMI:
; save CPU state
rep #$30
on16i
on16a
pha
phx
phy
phd
phb

; set DB to 0
phk
plb

; set DP to 0
lda #0
tcd


; set a/x size
; code goes here


; restore CPU state
rep #$30
on16i
on16a
plb
pld
ply
plx
pla

rti


Great, thank you! What is the assembler/linker you use? If you use Intelligent System stuff, how do you generate a usable snes rom because I would like put my works on a flash card because I only output ISX files from Linker?

Quote:
Only bits 0, 6, 7 of register $4212 are set/cleared, the unmaped bits will contain the previous value of the data bus. See https://wiki.superfamicom.org/snes/show/Open+Bus for more details


Ohhh ... I understand now ...

Quote:
EDIT: Removed clear decimal flag code from NMI ISR. The 65816 clears the decimal flag when an interrupt is triggered.


Right, I read this yesterday.
Re: Super NES EMULATOR SE dev question
by on (#194594)
Peperocket wrote:
I don't understand the second point however. Could you explain?
When down is pressed it loads green into CGDATA (at color 0) and the Accumulator is set to 3. The Accumulator (3) is then bit tested with JOYH_LEFT (2), which always passes, so blue is also loaded into CGDATA (at colour 1).

To fix this you need to add an exit branch to each direction test after setting CGDATA. To demonstrate:
Code:
Up:
    bit #JOYH_UP                                    ; on compare bit a bit avec haut
    beq Down                                                ; si non egal, passe au prochain boutton
   
    ; Set color 0 of palette 0 to red
    lda #%00011111
    sta CGDATA
    lda #%00000000
    sta CGDATA

    bra EndJoypadTest

Down:
; ...
; Add `bra EndJoypadTest` to Down and Left tests
; ...

NotRight:
EndJoypadTest:


Peperocket wrote:
Great, thank you! What is the assembler/linker you use?
No problem. I've used both ca65/ld65 and byuu's bass assembler for my SNESdev projects.

Peperocket wrote:
If you use Intelligent System stuff, how do you generate a usable snes rom because I would like put my works on a flash card because I only output ISX files from Linker?
I just used iscv.exe to convert PROG.ISX to PROG.ROM, renamed PROG.ROM to PROG.SFC and it worked fine on my Quickdev16. I don't see why it shouldn't work on a flash cart.
Re: Super NES EMULATOR SE dev question
by on (#194615)
Thank you for these clear explanation. I tried to convert once again ISX file to ROM/SFC but it always fail running on my SD2SNES.

I attached the updated code and ISX/ROM files. Could you confirm it works on your QUICKDEV?
Re: Super NES EMULATOR SE dev question
by on (#194622)
Your ROM file does seem fine, though the header claims the ROM is 256 KB when it's actually 32 KB, and the checksums haven't been set.

My guess is that the ROM size is the problem, and it should be zero-padded out to 256 KB. I don't own a SD2SNES, but at least on the Super EverDrive, I've had problems with ROMs that were too small in the past.

Correct checksums would also be nice, but I can't imagine it's the problem here. So many ROM hacks and homebrew games don't bother, so I doubt the SD2SNES would check them, and the SNES itself doesn't care about the header at all besides the vectors.
Re: Super NES EMULATOR SE dev question
by on (#194623)
HEAD.S specifies Mode 21 (HiROM) but the ROM is only half a bank in size and expects to be loaded from $8000. Try changing
Code:
      db      MODE_21                                         ; D5 - map mode

to
Code:
      db      MODE_20                                         ; D5 - map mode

in HEAD.S.

Edit: still doesn't work, it gets stuck at the white screen... I shall take a closer look.
Re: Super NES EMULATOR SE dev question
by on (#194632)
Peperocket wrote:
I attached the updated code and ISX/ROM files. Could you confirm it works on your QUICKDEV?
The updated PROG.ROM works perfectly on my Quickdev16.


ikari_01 wrote:
HEAD.S specifies Mode 21 (HiROM) but the ROM is only half a bank in size and expects to be loaded from $8000....

I looked at the SD2SNES source code and discovered that SD2SNES uses the map mode byte from the ROM Header to determine which memory map to use.

I did not notice the incorrect header because bsnes/higan/snes9x uses the location of the header in the ROM file to determine the memory map.
Re: Super NES EMULATOR SE dev question
by on (#194635)
True, I only fall back to the header location if the header data is found to be unusable (invalid map mode byte). I guess I could add in another little plausibility check to match the map byte against the header location.
Re: Super NES EMULATOR SE dev question
by on (#194657)
Hello all!

After changing header adress to $7FB0 and mode 20, rom works on my sd2snes.

I don't understand why mode 21 doesn't work however ...
Re: Super NES EMULATOR SE dev question
by on (#196898)
I've been trying to setup the tool chain for SNES programming, and I'd love the manuals in English! (Also a manual for VUCC would be nice, if possible...)
Re: Super NES EMULATOR SE dev question
by on (#197084)
Hello,

Because Nintendo legal issue, I don't know if I can attached the manual here.

Is it possible?
Re: Super NES EMULATOR SE dev question
by on (#197115)
Peperocket wrote:
Hello,

Because Nintendo legal issue, I don't know if I can attached the manual here.

Is it possible?


I honestly don't know myself. All I know, is that Nintendo doesn't seem to have bothered about all the other VUE Debugger floppies that have been released in the past.

If you feel uncomfortable about this, I completely understand!
Re: Super NES EMULATOR SE dev question
by on (#197124)
At least, in the past, there was one takedown request for the SNES dev manuals, and Koitsu has been justifiably jumpy ever since.

If that's what you're talking about. They're really east to search google for.
Re: Super NES EMULATOR SE dev question
by on (#197127)
Peperocket wrote:
I can provide the Assembler/Linker/Debugger english version manual if needed.


Is what I was interested in, since, as far as I know, there are only Japanese manuals out there but, like I said, if Peperocket is uncomfortable about this, I wouldn't want to pressure them into anything. I could just write my own compiler/assembler/linker in the worst case.

I'm just really interested in the historical background of these old pieces of software, and I believe that preservation is very important. (The fact that there are still no copies of the SNES dev software on the internet I incredibly sad to me)
Re: Super NES EMULATOR SE dev question
by on (#197183)
Sure, we are talking about Intelligent System assembler/linker/debugger manual not the common snes one.

It's very usefull if you want to code with it.

I send you a MP for a link.
Re: Super NES EMULATOR SE dev question
by on (#197185)
If someone need something I've, please contact me.

I'm still looking for all Graphics and Sound software for Emulator SE/ IS Character or IS Sound.

For information, ISAS and ISLK works with Super FX and SPC700 code, just put the good ISSND or ISSFX pseudo instruction in it.