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
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
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.
Is there a way to ouput something else than .isx format ?
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.htmI attached the converted rom, I hope it could help.
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.
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.
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?
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.
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=vueUse 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.
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.
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?
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.
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.
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
You forgot a # before JOYH_LEFT and JOYH_RIGHT.
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.
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.
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.
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.
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?
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.
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.
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.
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.
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 ...
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...)
Hello,
Because Nintendo legal issue, I don't know if I can attached the manual here.
Is it possible?
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!
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.
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)
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.
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.