News:

11 March 2016 - Forum Rules

Main Menu

Bsnes problem

Started by yugisokubodai, January 12, 2018, 12:16:48 AM

Previous topic - Next topic

yugisokubodai

I'm coding a vwf text routine, everything is Ok until I run with emulators. Bsnes, is said to be the most accurate emulator, gives different result than the others (Snes9x, Zsnes, Snesgt).
I write the text to the screen every line and when it hit the end code.
Here's my routine:

  JSR init_bg3
LDY #$0000
TYX
STY {shift}
JSR pointer_write
REP #$20
LDA #$1000
STA {tileset_pos}
LDA #$2800
STA {tile_pro}
read_instant_text:
LDA [$40],y
AND #$00FF
CMP #$00F0
BCS control_code
JSR write_font_ptr
JSR draw_char
JSR get_width
INY
BRA read_instant_text
control_code:
CMP #$00FF
BNE pos_code
end_instant_text:
JSR write_tilemap
JSR dma_tileset
JSR dma_tilemap
RTL

pos_code:
CMP #$00FE
BNE line_code
INY
LDA [$40],y
STA {text_pos}
INY
INY
JMP read_instant_text

line_code:
JSR write_tilemap
JSR dma_tileset
JSR dma_tilemap

LDA {tileset_pos}
CLC
ADC #$0200
STA {tileset_pos}
STZ {shift}
LDA {tile_pro}
CLC
ADC #$0040
STA {tile_pro}
LDA {text_pos}
CLC
ADC #$0040
STA {text_pos}
JSR clear_char
INY
JMP read_instant_text


{test_pos} is where the tilemap (the text) appears on the screen.
Well, for the first line, verythings seem right.

<pos><$25><$02>
This is the first line<end>


The text_pos is 0225, this means the first text appears at 044A in Vram. Both Bsnes and other emulators give the same result.



But for the second line, Bsnes gives different result than the others.

<pos><$25><$02>
This is the first line<line>
This is the second line. <end>





The problem is the second line.

   LDA {text_pos}
   CLC
   ADC #$0040
   STA {text_pos}


I think this is right, and all emulators give result as my expectation. But you can see, Bsnes gives the diffrence.
Theorically, the second text is:

0225 + 40 = 0265. In Bsnes, the second line starts from $04D4, not $04CA as I expect and as other emulators.

Just not that, if I change the size of the second line, its position in Bsnes also changes too.
For example,

<pos><$25><$02>
This is the first line<line>
T<end>




Now, while the value of the second line written to $2116 (0265) is unchanged, the Vram address in Bsnes of it becomes 05CA, making the line is pushed downward further more.

Can anyone understand it?
All Bsnes versions I downloaded give the same result so It's hard to think Bsnes is wrong. But I can't see where I gone wrong.  :banghead: :banghead:
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

slidelljohn

What are the results if you use higan? Higan should be the most accurate snes emulator. Bsnes is the outdated version of higan.

Disch

This is a symptom of a larger problem...  there is exactly a 0% chance that this is an issue with the way the emus are running your code.  All emus are going to have the core 65816 emulation pretty much nailed -- if they didn't, games just flat out wouldn't run.

The only way something like this is going to differ between emus is if you are doing screen rendering when it's not safe to do so, and the effect you're seeing is due to slight timing differences between emus.

The question to ask here is when are you actually transferring the data to VRAM?  And are you sure the system is still in VBlank when you're doing so?

EDIT

From the code it looks like you are putting the VWF stuff inside the actual screen rendering, which is a terrible idea because VWF processing is going to take a lot of time.  You're probably running out of VBlank time.

Typically what you'd want to do is do this processing and put the stuff you're going to draw to RAM somewhere -- then when VBlank comes around just do a single quick DMA to get it all in VRAM at once.

yugisokubodai

Yes, I transfer to Vram during Vblank.
Unfortunatelly I can't run Higan.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Disch

I just edited my post before you replied -- I would like to draw your attention to that edit

yugisokubodai

#5
I've tested Higan and it gives the same result as Bsnes.
I think the vwf is not a problem, but the line break function.

The tilemap is transferred to Vram has small size ($80 bytes) so it's not the problem with Vblank timing.


January 12, 2018, 03:50:35 AM - (Auto Merged - Double Posts are not allowed before 7 days.)

Here I made a video for more clarity

https://www.youtube.com/watch?v=4q4crFQtNC4
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

STARWIN

I would examine a bsnes-plus tracelog if I were you. That I imagine would be enough, but it is possible to make a tracelog in something like geiger's and compare the logs too.

yugisokubodai

#7
Yes, I used Bsnes plus and all other versions.

The log of Bsnes is the same to Geiger, no difference.
What I don't understand is, the value #$0225 is written to $2116 in both Bsnes and Geiger, but Bsnes shows different position of text on the screen. The text also changes its position on Bsnes, too.

Here I made a video for more clarity

https://www.youtube.com/watch?v=4q4crFQtNC4

Comparing Bsnes and Geiger's logs, you can see they're the same.



兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

mziab

Something is probably clobbering the DMA you set up, maybe the NMI handler. I'd suggest stepping through the code in the bsnes debugger till you get to the 420b write, which starts the actual DMA and checking in the properties viewer whether the address is still set correctly at that point. If you have a NMI handler which does its own DMA, that's your most probable culprit.

yugisokubodai

Thank you Mziab  :D
Here's my Tilemap dma function

dma_tilemap:
LDX #$1801
STX $4300
LDX #$1190
STX $4302
LDA {buffer} //tile count
ASL
CLC
ADC #$0040
STA $4305
SEP #$20
LDA #$7E
STA $4304
LDX {text_pos}
STX $2116
JSR wait_vblank
LDA #$01
STA $420B
REP #$20
RTS


Note the JSR wait_vblank. If I disable it, the 2nd text is in the position it should be. If the wait vblank is enabled, the said problem occurs.

Look inside the log:

808bb5 bit #$80           
808bb7 beq $8bb2     ---> Wait for vblank
808bb2 lda $4210     
808bb5 bit #$80             
808bb7 beq $8bb2     [808bb2] A:0042 X:0265 Y:001f S:1ff4 D:0000 DB:80 nvMxdIZc

***NMI occurs***

00800f phx                    A:0042 X:0265 Y:001f nvMxdIZc V:225 H: 22 F:37
008010 phy                    A:0042 X:0265 Y:001f S:1fee D:0000 DB:80
008011 pha                    A:0042 X:0265 Y:001f S:1fec D:0000 DB:80
008012 phb                    A:0042 X:0265 Y:001f S:1feb D:0000 DB:80
008013 php                    A:0042 X:0265 Y:001f S:1fea D:0000 DB:80
008014 ldx $1e       [00001e] A:0042 X:0265 Y:001f S:1fe9 D:0000 DB:80
008016 jsr ($8121,x) [008123] A:0042 X:0002 Y:001f S:1fe9 D:0000 DB:80
00812d nop                    A:0042 X:0002 Y:001f S:1fe7 D:0000 DB:80
00812e rts                    A:0042 X:0002 Y:001f S:1fe7 D:0000 DB:80
008019 plp                    A:0042 X:0002 Y:001f S:1fe9 D:0000 DB:80
00801a plb                    A:0042 X:0002 Y:001f S:1fea D:0000 DB:80
00801b pla                    A:0042 X:0002 Y:001f S:1feb D:0000 DB:80
00801c ply                    A:0042 X:0002 Y:001f S:1fec D:0000 DB:80
00801d plx                    A:0042 X:0002 Y:001f S:1fee D:0000 DB:80
00801e rti                    A:0042 X:0265 Y:001f S:1ff0 D:0000 DB:80

***RETURN FROM NMI***

808bb2 lda $4210     [804210] A:0042 X:0265 Y:001f S:1ff4 D:0000 DB:80
808bb5 bit #$80               A:00c2 X:0265 Y:001f S:1ff4 D:0000 DB:80
808bb7 beq $8bb2     [808bb2] A:00c2 X:0265 Y:001f S:1ff4 D:0000 DB:80
808bb9 plp                    A:00c2 X:0265 Y:001f S:1ff4 D:0000 DB:80
808bba pla                    A:00c2 X:0265 Y:001f S:1ff5 D:0000 DB:80
808bbb rts                    A:007e X:0265 Y:001f S:1ff6 D:0000 DB:80
808963 lda #$01               A:007e X:0265 Y:001f S:1ff8 D:0000 DB:80
808965 sta $420b     [80420b] A:0001 X:0265 Y:001f S:1ff8 D:0000 DB:80

You can see the Nmi has nothing to do with $2116 and all Register's values are preserved.
So I wonder why the Wait vblank routine hinders the DMA?
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

optiroc

If I'm not completely misremembering you can't safely write to any of the PPU registers outside of the blanking intervals (except INIDISP). It seems you're setting up the VRAM write registers "whenever", then wait for vblank and kick off the transfer.

But I took only a cursory look so my assessment could very well be completely off.

yugisokubodai

QuoteIf I'm not completely misremembering you can't safely write to any of the PPU registers outside of the blanking intervals (except INIDISP). It seems you're setting up the VRAM write registers "whenever", then wait for vblank and kick off the transfer.

You are right. I set the Dma "whenever" and kick off the transfer when Vblank occurs. I see it's the same as setting up the Dma inside the blank. Correct me if I'm wrong.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

mziab

I suggest moving your JSR wait_vblank to the start of dma_tilemap, i.e. doing all the register writes during vblank. If we were right about the culprit, this should resolve the issue.

yugisokubodai

Quote from: mziab on January 12, 2018, 05:27:46 AM
I suggest moving your JSR wait_vblank to the start of dma_tilemap, i.e. doing all the register writes during vblank. If we were right about the culprit, this should resolve the issue.

True. Solved. Thank you for your all comments.  :thumbsup:
I thought the Dma setup can be whenever and the kick off should be in Vblank. But this problem just proved that I was wrong.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

Squall_FF8

yugisokubodai did you fix it?

In general, Dish gave you an excellent advice, even if that is not the case here :beer:
Welcome to the FF5 Den: https://discord.gg/AUqDF85

yugisokubodai

I fixed it. It turns out that $2116 needed to be set up in blanking.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

slidelljohn

#16
Awesome advice everyone! Image how hard that would have been to figure out if we didn't have romhacking.net.

yugisokubodai:
I see you have it working now. Have you tried doing what Disch said in the edited part of reply#2? Seems like what Disch said wasn't what the exact issue was that you were having but it could possibly cause future problems if the code isn't fully optimized.

KingMike

Quote from: yugisokubodai on January 12, 2018, 08:20:45 PM
I fixed it. It turns out that $2116 needed to be set up in blanking.
Might be why games I've seen tended to either figure out and write the values during blanking and/or previously calculate the wanted values to RAM and then write the values from RAM to the DMA registers.
"My watch says 30 chickens" Google, 2018

yugisokubodai

Quote from: slidelljohn on January 13, 2018, 09:52:22 AM


yugisokubodai:
I see you have it working now. Have you tried doing what Disch said in the edited part of reply#2? Seems like what Disch said wasn't what the exact issue was that you were having but it could possibly cause future problems if the code isn't fully optimized.

Yes, what I did is exactly as Disch said. For the vwf processing, I do in in Ram and transfer during blanking.
兵法の勝ちを取りても
世の海を渡りかねたる
石の船かな

slidelljohn