Advice to fix some issues in Loopynes

Discuss emulation of the Nintendo Entertainment System and Famicom.
theelf
Posts: 5
Joined: Fri Feb 16, 2024 4:00 am

Advice to fix some issues in Loopynes

Post by theelf »

Hi everyone, first, hello! This is my first post here, gretings!

I’m writing because I need some help with the Loppynes emulator . I’m fixing some stuff and little problems that I didn’t like or that didn’t work right for me

I’m a fan of the Famicom, but I never really got interested in it technically… until today!!

The three main problems were the real scanlines mode, because in 256x240 the original emulator use a 100+ Hz mode and my 14" CRT was going crazy. Luckily I fixed it and set it to like 90 Hz, which works fine even on my old 1992 VGA. Second, original emu have no vsync, i fixed it. The third problem was the NOISE sound that was very distorted, I also fixed that, adding a filter

I have some questions, but I want to start with one: the game The Flintstones: The Rescue of Dino & Hoppy (one of my favorites games). When the character jumps, it makes this annoying noise. I checked and it’s channel 1, but I don’t know exactly what it could be. It’s just the jump sound, any idea?

I add the binary i compile with the 3 fix if someone want to test and try the Flintstones bug
NES.zip
As I find more little things I want to fix, I’ll be asking here if it’s ok. Thanks a lot everyone!

Code: Select all

more conservative refresh rate for scanlines, 

original 
t256x240lines dd 00e3h,0c11h,5e00h,3f01h,4002h,8203h,4d04h,8005h
            dd 0706h,1107h,4009h,0f510h,0ef12h,2013h,0f215h,0516h

change to 
t256x240lines dd 00e3h,0c11h,5F00h,3F01h,4002h,8103h,4E04h,9605h
              dd 0806h,1107h,4009h,0F510h,0EF12h,2013h,0F215h,0516h


About bad NOISE sound  i add a  filter

ch59:                   ;(ch58 returns here)

 [b]       ; --- filtro anti-click ---
        mov ecx,[ch5level]        ; valor anterior
        sub edx,ecx
        sar edx,2                 ; suaviza (divide por 4)
        add edx,ecx
        ; --------------------------[/b]
        
        
        mov eax,edx
        sar eax,5
        add [mixbuff+edi*4],edx
        sub edx,eax
        inc edi
        cmp edi,MIXSIZE
        jb ch50

        mov [ch5level],edx
        mov [sregs+11h],bl
        ret
You do not have the required permissions to view the files attached to this post.
theelf
Posts: 5
Joined: Fri Feb 16, 2024 4:00 am

Re: Advice to fix some issues in Loopynes

Post by theelf »

Like i said in last post, I noticed that when the character jumps, Square 1 makes this annoying click, while other sounds like punches are fine.

What I did was add a tiny automatic fade at the end of the channel1 routine. It just smooths out the very short sounds, and poof—the click disappears.

Now jumps sound clean, volume stays good, and the game runs fine. Super simple tweak, but it makes a big difference. But other games, sound dissapear, like in Yo Noid

Ani idea guys?

Code: Select all

channel1: ; add ch1 (square) to mixer buffer
        mov eax,[ch1buffptr]
        xor edi,edi             ; edi = mixbuff ptr
        xor esi,esi             ; esi = ch*buffptr

        mov [ch1buff+eax*8+time],9999999
        mov eax,[ch1buff+esi*8+time]
        mov [ch1next],eax
        mov [ch1buffptr],edi

        mov edx,[ch1vol]
        mov eax,[ch1freq]
        mov ebp,[freqtbl+eax*4] ; ebp = freq

ch10:   ; port write
        add [ch1frac],MINOR
        sbb [ch1next],MAJOR
        jns ch12

        mov ebx,dword ptr [ch1buff+esi*8+port]
        mov al,[ch1buff+esi*8+data]
        and ebx,7
        call [ch1write+ebx*4]

        mov eax,[ch1buff+esi*8+time+8]
        inc esi
        add [ch1next],eax

ch12:   test [on],00001b
        jz ch16

        mov eax,[ch1timerspeed]
        add [ch1timermod],eax
        jnc ch15
        and [on],not 00001b

ch15:   add [ch1pos],ebp
        jnc ch11

        mov bl,[sregs+00h]
        test bl,00010000b
        jnz ch151
        mov ebx,[ch1decayvol]
ch151:  and ebx,15
        add edx,[squarevols+ebx*4]

ch11:   add [ch1neg],ebp
        jnc ch13

        mov bl,[sregs+00h]
        test bl,00010000b
        jnz ch111
        mov ebx,[ch1decayvol]
ch111:  and ebx,15
        sub edx,[squarevols+ebx*4]

ch13:   mov ebx,[ch1decayspeed]
        add [ch1decaymod],ebx
        sbb [ch1decayvol],0
        jnc ch133
        inc [ch1decayvol]
        test [sregs+00h],00100000b
        jz ch133
        mov [ch1decayvol],15

ch133:  mov eax,[ch1sweepspeed]
        add [ch1sweepmod],eax
        jnc ch16

        mov eax,[ch1freq]
        mov cl,[ch1sweepshift]
        shr eax,cl
        test [sregs+01h],00001000b
        jz ch131
        not eax
ch131:  add eax,[ch1freq]
        cmp eax,800h
        jb ch132
        xor eax,eax
ch132:  mov [ch1freq],eax
        mov ebp,[freqtbl+eax*4]

;------------------------------------------------------------
; Fade automático para sonidos cortos (elimina click)
ch16:
        cmp [ch1decayvol],0
        je ch16_end

        mov eax,[ch1decayvol]
        cmp eax,4            ; si muy bajo, reducir 1 unidad
        jb ch16_fade1
        sar eax,1            ; reduce a la mitad suavemente
        mov [ch1decayvol],eax
        jmp ch16_end

ch16_fade1:
        dec [ch1decayvol]

ch16_end:
;------------------------------------------------------------

        mov eax,edx
        sar eax,5
        add [mixbuff+edi*4],edx
        sub edx,eax
        inc edi
        cmp edi,MIXSIZE
        jb ch10

        mov [ch1vol],edx
        ret
theelf
Posts: 5
Joined: Fri Feb 16, 2024 4:00 am

Re: Advice to fix some issues in Loopynes

Post by theelf »

Hi! nobody? thanks
User avatar
TakuikaNinja
Posts: 427
Joined: Mon Jan 09, 2023 6:42 pm
Location: New Zealand

Re: Advice to fix some issues in Loopynes

Post by TakuikaNinja »

Reasons you may not be getting help for this:
  • This is an emulator which runs on DOS environments. Most people run emulators on desktop OSes (Windows, Mac, Linux, etc.). Homebrew developers have little interest in supporting old emulators. If you're modding this emulator to play NES games on vintage (PC) hardware you own, you might as well invest in an original NES/FC console and a flashcart.
  • This emulator is written in x86 assembly. Most PC developers these days write in high-level languages, the bare minimum being C. Even embedded development in assembly tends to go for ARM or other RISC architectures. Most NES/FC homebrew developers write in 6502 assembly, which is vastly simpler compared to x86. There's no guarantee that said developers are also interested in PC software development, either.
What I'm trying to get at is similar to this venn diagram:
VennDiagram.png
The overlap between people interested in modifying an old emulator and people who can code in x86 assembly is minuscule. Good luck.
You do not have the required permissions to view the files attached to this post.
theelf
Posts: 5
Joined: Fri Feb 16, 2024 4:00 am

Re: Advice to fix some issues in Loopynes

Post by theelf »

Hi, thanks for reply, i dont need much x86 asm help, but famicom/nes tech advice. I can develop in asm, but my knowledge of nes is limited, and i believe this is correct place for nes info

For example, im writting a mapper 69 for loopynes, i can load batman return joker until intro, but hangs before load a level, i read mapper69 data tech but i cant really understand how it works veryt well, then i write code without all the info

Here my mapper 69

Code: Select all

.486p
.model flat
.code

PRG_BANKS equ 32

include empty.h
include kb.h
include file.h
include 6502.h
include ppu.h
include data.h
include equates.h
include debug.h
include memory.h
include map00.h

public mapperinit69
public hook69
public write0, write1, write2, write3

; --------------------------------------------------------------------------
; Mapper69 data layout
; --------------------------------------------------------------------------
latch0      equ mapperdata+0       ; CHR latch low (0..255)
latch1      equ mapperdata+1       ; CHR latch high (0..255)
irq_enable  equ mapperdata+2       ; byte
irq_counter equ mapperdata+3       ; word (2 bytes)
reg_prg0    equ mapperdata+64      ; PRG bank $8000
reg_prg1    equ mapperdata+65      ; PRG bank $A000
reg_prg2    equ mapperdata+66      ; PRG bank $C000
mirroring   equ mapperdata+68
total_prg   equ mapperdata+69      ; ultimo banco PRG
cmd_byte    equ mapperdata+70      ; command byte
write_toggle equ mapperdata+71     ; reservado

; --------------------------------------------------------------------------
mapperinit69:
; --------------------------------------------------------------------------
    ; Inicializa PRG banks
    mov byte ptr [reg_prg0], 0
    mov byte ptr [reg_prg1], 1
    mov byte ptr [reg_prg2], 2
    mov byte ptr [total_prg], (PRG_BANKS-1)

    ; Inicializa IRQ
    mov byte ptr [irq_enable], 0
    mov word ptr [irq_counter], 0

    ; Latches neutros (no FD/FE) ?¿
    mov [latch0], 0
    mov [latch1], 0

    ; Mirroring horizontal por defecto
    mov byte ptr [mirroring], 0

    ; Byte command inicial
    mov byte ptr [cmd_byte], 0

    ; Setup write handlers
    mov [write_tbl+4*4], offset write0 ; $8000-$9FFF -> command byte
    mov [write_tbl+5*4], offset write1 ; $A000-$BFFF -> param
    mov [write_tbl+6*4], offset write2 ; $C000-$DFFF -> param
    mov [write_tbl+7*4], offset write3 ; $E000-$FFFF -> param

    ; Map initial PRG banks
    call romswitch69

    ; Scanline hook
    mov [scanlinehook], offset hook69

    ret

; --------------------------------------------------------------------------
; PRG bank switching
; --------------------------------------------------------------------------
romswitch69:
    mov al, [reg_prg0]
    call map89
    mov al, [reg_prg1]
    call mapAB
    mov al, [reg_prg2]
    call mapCD
    mov al, [total_prg]
    call mapEF
    ret

; --------------------------------------------------------------------------
; CHR latch update 
; --------------------------------------------------------------------------
chrswap:
    push eax
    push edi

    ; Latch0 -> bloques 0..3
    mov al, [latch0]
    movzx eax, al
    shl eax, 12        ; << 12 = bank * 0x1000 (4KB pages)  <-- ¿?
    and eax, [chrmask]
    add eax, [chr_ptr]
    mov [chr_map+0], eax
    add eax,1000h
    mov [chr_map+4], eax
    add eax,1000h
    mov [chr_map+8], eax
    add eax,1000h
    mov [chr_map+12], eax

    ; Latch1 -> bloques 4..7
    mov al, [latch1]
    movzx eax, al
    shl eax, 12        ; << 12 tambien aca?¿
    and eax, [chrmask]
    add eax, [chr_ptr]
    mov [chr_map+16], eax
    add eax,1000h
    mov [chr_map+20], eax
    add eax,1000h
    mov [chr_map+24], eax
    add eax,1000h
    mov [chr_map+28], eax

    call newchrmap

    pop edi
    pop eax
    ret

; --------------------------------------------------------------------------
; Scanline IRQ hook (mejorada)
; --------------------------------------------------------------------------
hook69:
    test [ctrl1], CR1_BG+CR1_OBJ   ; si PPU desactivado, no tocar nada
    jz h69_end
    cmp [scanline],239
    ja h69_end

    ; Solo procesar IRQ si esta habilitado
    cmp byte ptr [irq_enable], 0
    je h69_end

    ; decrement counter
    mov ax, word ptr [irq_counter]
    dec ax
    mov word ptr [irq_counter], ax
    jnz h69_end

    ; disparar IRQ si llego a 0
    or [int_flags], IRQ

h69_end:
    ret

; --------------------------------------------------------------------------
; Execute command
; --------------------------------------------------------------------------
do_command69:
    push eax
    push ebx
    mov bl, [cmd_byte]

    cmp bl, 8
    jb .is_chr_command

    ; PRG / mirroring / IRQ commands
    cmp bl, 9
    je .cmd_9_prg8000
    cmp bl, 0Ah
    je .cmd_A_prgA000
    cmp bl, 0Bh
    je .cmd_B_prgC000
    cmp bl, 0Ch
    je .cmd_C_mirroring
    cmp bl, 0Dh
    je .cmd_D_irqcontrol
    cmp bl, 0Eh
    je .cmd_E_irq_low
    cmp bl, 0Fh
    je .cmd_F_irq_high
    jmp .done

.is_chr_command:
    cmp bl, 4
    jb .set_latch0
    mov [latch1], al
    jmp .done_unpush
.set_latch0:
    mov [latch0], al

.done_unpush:
    call chrswap
.done:
    pop ebx
    pop eax
    ret

; --------------------------------------------------------------------------
; Writes
; --------------------------------------------------------------------------
write0:
    and al,0Fh
    mov [cmd_byte], al
    ret
write1:
    call do_command69
    ret
write2:
    call do_command69
    ret
write3:
    call do_command69
    ret

; --------------------------------------------------------------------------
; PRG commands
; --------------------------------------------------------------------------
.cmd_9_prg8000:
    mov [reg_prg0], al
    call romswitch69
    jmp .done

.cmd_A_prgA000:
    mov [reg_prg1], al
    call romswitch69
    jmp .done

.cmd_B_prgC000:
    mov [reg_prg2], al
    call romswitch69
    jmp .done

.cmd_C_mirroring:
    and al,03h
    mov [mirroring], al
    jmp .done

.cmd_D_irqcontrol:
    mov [irq_enable], al
    jmp .done

.cmd_E_irq_low:
    movzx eax, al
    mov bx, word ptr [irq_counter]
    and bx, 0FF00h
    or bx, ax
    mov word ptr [irq_counter], bx
    jmp .done

.cmd_F_irq_high:
    movzx eax, al
    shl eax, 8
    mov bx, word ptr [irq_counter]
    and bx, 0FFh
    or bx, ax
    mov word ptr [irq_counter], bx
    jmp .done

end
User avatar
Dwedit
Posts: 5257
Joined: Fri Nov 19, 2004 7:35 pm

Re: Advice to fix some issues in Loopynes

Post by Dwedit »

I never really looked that hard at the loopynes source code before, but the code style looks just like pocketnes.

(Which of course should not be a surprise as they were both made by Loopy)
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
User avatar
dink
Posts: 247
Joined: Sun Jan 12, 2020 8:42 pm

Re: Advice to fix some issues in Loopynes

Post by dink »

Hi,
The only thing that worked for me, for getting rid of clicks in the pulse(square) channels is:
on writes to 4003 and 4007:
if the square is enabled, restart the pulse phase for that channel

hope this helps!

best regards,
- dink
theelf
Posts: 5
Joined: Fri Feb 16, 2024 4:00 am

Re: Advice to fix some issues in Loopynes

Post by theelf »

Thanks fr reply, Dwedit i will check pocketnes source, i did not have any idea was same author, maybe i can get some ideas, even if different platform

dink thanks, im doing diffrerent test to restart the pulse phase on writes to 4003 and 4007 to check if is what i need


Anyways, i have contra and flindstones with good sound now, even if are just hacks for now, loopynes is a very good emulator, just need some
small fixes, im pretty close

thanks