Jump to content
IGNORED

VGM Compression Tool


Tursi

Recommended Posts

last problem I'm having is:

 

I call the stplay from my main program loop but in order to get the playback timing to work and it to sound as it should I need to call a delay(1) (1 cycle? I think)

 

this corrects the music and it plays with no distortion. the sprites animate and the bg is proper. however it completely disables joystick or keypad input so I can't move or even start the game.

 

a kind of work around is to make a for..I loop to waste some time instead of using delay(1) but this distorts the music. the joystick input works this way though.

 

now if I put a delay(1) without stplay() it doesn't effect the joystick input.

 

I'm not sure what is going on.

Excellent, congrats!

It doesn't matter if it's called from the NMI itself, it's only the timing that matters. :)

Link to comment
Share on other sites

I can't help you with that, since I don't use your library, but like the previous issues, there's no reason I can think of why my playback library would affect the joystick, especially with timing (it doesn't do any kind of background/delayed processing). As my demo shows, the joystick works fine normally.

 

Is there a reason you're not just basing your timing on the NMI?

Link to comment
Share on other sites

The nmi might be disable, which is why the controller isn't working. I have delay(1) in my game loop, which acts like vsync. Only time I disable NMI is when I'm writing a lot of data to the VRAM. After writing is finished I enable the nmi.

I usually have my loop formed like this,

initialization of variable
enable_nmi();
while(game==0){
updatesprite here

small video update stuff here

controls here

game logic and entering new data to sprite table here
delay(1);

}

 

without delay() in the game loop, the game is not running at 60(over that) and not in sync with the video chip which will cause issue.

Edited by Kiwi
Link to comment
Share on other sites

yeah when I put stplay inside the nmi routine the timing is correct but distorted. that's why I was trying it outside of it. I'm going to try what kiwi suggested about only disabling nmi only during large vram writes. I currently have it used during any sprite updates which might be overkill.

overuse of disabling nmi may be causing the distortion. i'll post an update after i try a few things.

 

1 positive thing I managed to do today also was convert a midi file into a vgm and then into a packed file and it worked and sounded as expected with the player library.

 

Anyways this seems like the last hurdle

 

 

I can't help you with that, since I don't use your library, but like the previous issues, there's no reason I can think of why my playback library would affect the joystick, especially with timing (it doesn't do any kind of background/delayed processing). As my demo shows, the joystick works fine normally.

 

Is there a reason you're not just basing your timing on the NMI?

 

The nmi might be disable, which is why the controller isn't working. I have delay(1) in my game loop, which acts like vsync. Only time I disable NMI is when I'm writing a lot of data to the VRAM. After writing is finished I enable the nmi.

I usually have my loop formed like this,

initialization of variable
enable_nmi();
while(game==0){
updatesprite here

small video update stuff here

controls here

game logic and entering new data to sprite table here
delay(1);

}

 

without delay() in the game loop, the game is not running at 60(over that) and not in sync with the video chip which will cause issue.

Link to comment
Share on other sites

Nope didn't work,

 

I removed all disable nmi from the project except for major writes to the vram (tables loading mostly) . Got a little graphic corruption but not much . I'll track down which part later.

 

I Put the stplay only in the nmi routine. Now the timing is correct throughout the game, the joystick works but the sound is muted or distorted exactly as in the example I showed earlier.

http://www.eriscreations.com/downloads/test2.zip

 

My work around has been to call the stplay from outside the nmi routine followed immediately by a delay(1) and disable the nmi while I do this . Sound is then correct but the joystick stops working even when nmi is re-enabled and the joystick input routines are not within a disable/enable. nmi.

 

I don't want to bug you. I'm just posting my update / thoughts as I'm working on it. It's got to be something minor . I'll figure it out it's just a funny/frustrating problem.

Link to comment
Share on other sites

The example you showed earlier - I'm quite sure something else was writing to the sound chip. I'll ask, is something in the library you are using turning on the BIOS music player or something like that? Another player running during the NMI would explain why you have better luck running mine outside of the NMI.

 

the fact that the joystick works or doesn't based on your NMI usage suggests there is some kind of magic going on in the library. :) It would be good to understand what it's doing.

Link to comment
Share on other sites

  • 5 months later...

Sound effects are made the same way - you have to create them in VGM format and run them through the compressor. To the playback engine, the only difference between a sound effect and music is a sound effect will mute the music on any channels it uses.

 

I did sort of cheat for my example, I just took the sound effects from the Antarctic Adventure VGM archive, but that is all there is to it.

 

The only tool I've ever used for creating VGMs (except for converters) is MOD2PSG2, which is much like a MOD tracker. It's good for editing and although it has its own format, it can export VGM.

 

http://www.smspower.org/Music/Mod2PSG2

 

HTH!

Link to comment
Share on other sites

  • 6 months later...

did you get the music to work in sdcc while also using the cvlib and getput libraries or did you use another method? I tried again last week but something is still interfering when I use those libraries.

Hi Tursi,

I have a question. It is OK for music, i understood how to manage it.

But I have problem with effects, how can we create them (i saw your packed.h file in your example but don't know how you created it).

Link to comment
Share on other sites

Yes I did,

I modified Daniel's crtcv.s file and shipped it with each project that need this player instead than in the library.

Here is the source code I used for UWOL, it works fine but I think I will update it for 50/60Hz management. The currrent checking is not OK, only adapt for coleco bios music.

You can remove the frequency checking, it is useless.

As you can see, the only thing I did is to removed calls to Coleco BIOS music to avoid problems.

; crt0.s for Colecovision cart

	.module crt0

    ;; external sound table setting routine
	.globl set_snd_table

	;; global from this code
	.globl  _buffer32
	.globl _no_nmi
	.globl _vdp_status
	.globl _nmi_flag
	.globl _joypad_1
	.globl _keypad_1
	.globl _joypad_2
	.globl _keypad_2
	.globl snd_areas
	
	.globl _vid_freq
	.globl _vid_frsw
	
	;; global from C code
	.globl _main
	.globl _nmi

  .globl _update_music
  

	.globl l__INITIALIZER
	.globl s__INITIALIZER
	.globl s__INITIALIZED

	;; Ordering of segments for the linker - copied from sdcc crt0.s
	.area _HOME
	.area _CODE
	.area _INITIALIZER
	.area _GSINIT
	.area _GSFINAL
        
	.area _DATA
	.area _INITIALIZED
	.area _BSEG
	.area _BSS
	.area _HEAP

	;; TABLE OF VARIABLES (IN RAM)
	.area	_DATA
_buffer32::
	.ds	32 ; buffer space 32    [7000-701F]
snd_addr::
	.ds	11 ; sound addresses    [7020-702A]
snd_areas::
	.ds	61 ; 5 sound slots + NULL (00h) [702B-...]
_no_nmi::
	.ds    1
_vdp_status::
	.ds    1
_nmi_flag::
	.ds    1
_joypad_1::
	.ds    1
_keypad_1::
	.ds    1
_joypad_2::
	.ds    1
_keypad_2::
	.ds    1	
_vid_freq::
	.ds 1
_vid_frsw::
	.ds 1
	
	;; CARTRIDGE HEADER (IN ROM)
	.area _HEADER(ABS)
	.org 0x8000
	
	.db	0x55, 0xaa		; no default colecovision title screen => 55 AA
	.dw	0			; no copy of sprite table, etc.
	.dw	0			; all unused
	.dw	_buffer32		; work buffer
	.dw	0			; ??
	.dw	start_program	; start address for game coding
	.db	0xc9,0,0		; no RST 08 support
	.db	0xc9,0,0		; no RST 10 support
	.db	0xc9,0,0		; no RST 18 support
	.db	0xc9,0,0		; no RST 20 support
	.db	0xc9,0,0		; no RST 28 support
	.db	0xc9,0,0		; no RST 30 support
	.db	0xc9,0,0		; no RST 38 support  (spinner)
	jp	_nmi_asm

	;; CODE STARTS HERE WITH NMI
        .area _CODE
_nmi_asm:
	push	af
        ld	a,#1
        ld      (_nmi_flag),a           ; set NMI flag
	;;;
        call    0x1fdc                   ; get VDP status
        ld      (_vdp_status),a
	;;;
        ld      a,(_no_nmi)             ; check if nmi() should be
        or      a                       ;  called
        jp      nz,nmi_exit
        inc     a
        ld      (_no_nmi),a
        
        ld      a,(_vid_frsw) ; update flag for frequency
        inc	a
        ld		(_vid_frsw),a
                
        push    bc
        push    de
        push    hl
        push    ix
        push    iy
        ex      af,af'
        push    af
        exx
        push    bc
        push    de
        push    hl
        call    0x1f76                   ; update controllers
        ld      a,(0x73ee)
        and	#0x4f
        ld      (_joypad_1),a
        ld      a,(0x73ef)
        and	#0x4f
        ld      (_joypad_2),a
        ld      a,(0x73f0)
        and	#0x4f
        ld      (_keypad_1),a
        ld      a,(0x73f1)
        and	#0x4f
        ld      (_keypad_2),a
        call    decode_controllers
        call    _nmi                    ; call C function
        
        ld      a,(_vid_freq)           ; if 50Hz, setting redo music for bagman
        sub #0x32
        jr nz, $1101
        ld      a,(_vid_frsw)           ; only recall if 1 cycle per 3
        and		#0x03
        jr nz, $1101

$1101:
        pop     hl
        pop     de
        pop     bc
        exx
        pop     af
        ex      af,af'
        pop     iy
        pop     ix
        pop     hl
        pop     de
        pop     bc
        xor     a
        ld      (_no_nmi),a
nmi_exit:
        pop     af
        ret

keypad_table::
	.db    0xff,8,4,5,0xff,7,11,2,0xff,10,0,9,3,1,6,0xff

; joypads will be decoded as follows:
; bit
; 0     left
; 1     down
; 2     right
; 3     up
; 4     --------
; 5     --------
; 6     button 2
; 7     button 1
; keypads will hold key pressed (0-11), or 0xff
decode_controllers:
	ld      ix, #_joypad_1
	call    decode_controller
	inc     ix
	inc     ix
decode_controller:
	ld      a,0(ix)
	ld      b,a
	and     #0x40
	rlca
	ld      c,a
	ld      a,b
	and     #0x0f
	or      c
	ld      b,a
	ld      a,1(ix)
	ld      c,a
	and     #0x40
	or      b
	ld      0(ix),a
	ld      a,c
	cpl
	and    #0x0f
	ld      e,a
	ld      d,#0
	ld      hl,#keypad_table
	add     hl,de
	ld      a,(hl)
	ld      1(ix),a
	ret


start_program:
	im       1                      ; interrupt mode -> rst 38h
	di

	xor     a                       ; clear carry
	ld      bc,#0x3b8		; ram size left
	ld      hl,#0x7000		; starting from 7000
	ld      de,#0x7001
	ld      (hl),a
	ldir                            ; zero-fill bss

	call gsinit					; Initialize global variables.

	ld	h,#0 ; set dummy sound table
	call set_snd_table

	ld      hl,#0x0033                ; initialise random generator
	ld      (0x73c8),hl
                                    ; set screen mode 2 text
	call    0x1f85                   ; set default VDP regs 16K
	ld      de,#0x4000                ; clear VRAM
	xor     a
	ld      l,a
	ld      h,a
	call    0x1f82
	
	ld 		a, (0x0069)				; initialise video frequency
	ld      (_vid_freq),a
	
	; call main rountine
	jp      _main
	
	.area _GSINIT
gsinit::
	ld      bc, #l__INITIALIZER
	ld	a,b
	or	a,c
	jr	z, gsinit_next
	ld      de, #s__INITIALIZED
        ld      hl, #s__INITIALIZER

	ldir
gsinit_next:


	.area _GSFINAL
	ret
	;

Edited by alekmaul
Link to comment
Share on other sites

Thanks. This worked. I was able to get the music working before but never with all the coleco libraries added. Now it works. Thanks.

 

Probably too late for my current project but If I ever make another game it'll be useful. I'll play with it some more.

  • Like 1
Link to comment
Share on other sites

Rasmus sent me an example of a tune that compressed poorly, and I found a couple more bugs thanks to it! So v102 was just posted (only the compression tool has changed):

 

Changed the default frequency lossy compression method to popularity (with scaling for musical notes). The decision of what the notes should become is still a little arbitrary, but it seems(?) to work. The old method is available with the argument -lossyslide

-There was a bug in the lossy slide code too that made it compare against the wrong values and be somewhat arbitrary in what it removed - fixed that.

-There was a bug in the user-defined noise tuning code so that when it needed to tune notes in channel three, it would leave the original note alone and tune it on the next frame instead.

-Improved the previous first-note hack to be a little more resilient, just in case

 

http://harmlesslion.com/software/vgmcomp

 

I noticed after uploading that the ColecoVision example folder still has the old playback code - pull the latest down from Github if you need it. If you aren't having problems, there's nothing there which is critical to update.

Link to comment
Share on other sites

  • 2 months later...

Are you adding the sound fx to the same compressed archive as the music?

 

Or a separate file for the music & the sound fx.

Sound effects are made the same way - you have to create them in VGM format and run them through the compressor. To the playback engine, the only difference between a sound effect and music is a sound effect will mute the music on any channels it uses.

I did sort of cheat for my example, I just took the sound effects from the Antarctic Adventure VGM archive, but that is all there is to it.

The only tool I've ever used for creating VGMs (except for converters) is MOD2PSG2, which is much like a MOD tracker. It's good for editing and although it has its own format, it can export VGM.

http://www.smspower.org/Music/Mod2PSG2

HTH!

Link to comment
Share on other sites

thanks, so I'll attempt to get the soundfx working using a separate archive. I got the music working great. I havn't even tried the sound fx til now so i'll look over the sample you provided.

 

 

You're intended to combine them into a single sound bank, but in practice it often makes only a few bytes of difference in the compression size, and no difference in playback.

Link to comment
Share on other sites

A problem with v102 was presented to me, and thanks to TheMole I was able to quickly find a memory corruption that occurred during compression of multiple VGMs into one archive. Please grab v103 to fix this:

 

• Fix corruption bug introduced in last version on multiple song banks
• made version number more prominent

 

http://harmlesslion.com/software/vgmcomp

Link to comment
Share on other sites

  • 4 months later...

Got this all working real good. Problem I have though is the video memory is becoming corrupted at times. I have 1 project identical except all player code is strip out and one with the player code. The stripped code version doesn't corrupt.

 

It's not the name table but the actual patterns & sometimes colour patterns

 

What do you think is the most likely problem. Not enough memory due to my program?

 

It seems to be random. I play long enough it happens and it's the whole screen. Reloading the name table only does not correct it so the actual tile patterns have been over written or displaced as the patterns still look correct individually and not looking like white noise.

 

 

A problem with v102 was presented to me, and thanks to TheMole I was able to quickly find a memory corruption that occurred during compression of multiple VGMs into one archive. Please grab v103 to fix this:

 

• Fix corruption bug introduced in last version on multiple song banks
• made version number more prominent

 

http://harmlesslion.com/software/vgmcomp

Link to comment
Share on other sites

Got this all working real good. Problem I have though is the video memory is becoming corrupted at times. I have 1 project identical except all player code is strip out and one with the player code. The stripped code version doesn't corrupt.

 

It's not the name table but the actual patterns & sometimes colour patterns

 

What do you think is the most likely problem. Not enough memory due to my program?

 

It seems to be random. I play long enough it happens and it's the whole screen. Reloading the name table only does not correct it so the actual tile patterns have been over written or displaced as the patterns still look correct individually and not looking like white noise.

Disable VDP interrupts while decompressing can help a lot ;)

Link to comment
Share on other sites

I think you're doing too much in a single frame. Spunky's Super Car can sometime corrupt the score tileset graphics due to many put_frame objects on one screens while running over a grave even the nmi is disabled during these drawing those objects.

 

I would call the sound compression routine right after delay(1), so you have a fresh cycles. After that, graphical routines. What's left over like math and stuff can be safely interrupted by the NMI.

You can use the rainbow technique that the TI99 users used to see how much CPU your routines are taking up. Like

while(game==1){

paper(0);

delay(1);

paper(15);

sound decompression();

paper(14);

graphicstuff;

paper(13);

mathystuff;

}

Edited by Kiwi
Link to comment
Share on other sites

Kiwi and Nanochess have the same instinct that I do. The VGM player can take a lot of CPU time if the song is reasonably complex, IIRC the docs note as high as 30%. That's of the entire CPU, not vblank time, so don't play on the interrupt. Do your VDP work before you do anything else on the interrupt - then just set a flag to play music outside of it.

 

It's more expensive than I'd like, but work has me too tied up to do much free coding... I hope to do an optimization pass or rewrite of the player this summer.

  • Like 1
Link to comment
Share on other sites

ok, i do havethe nmi disabled for most all vdp but i can double check.

 

the stplay call is in the nmi and it is controlled by a flag to prevent bank switching from killing it.

 

perhaps calling less often and on a cycle that has less going on. i have my main game split into 10 cycles for spreading things out so i'll try that.

 

i had a manual sound call setup outside the nmi routine and that seemed more stable but music would slowdown if a lot of enemies were on the screen at the same time

Link to comment
Share on other sites

That suggests that your processing is taking more than one frame sometimes, meaning you need to be really careful what you do inside the NMI.

 

For my own coding I don't do anything except a sprite table copy in the NMI anymore, I just set a flag and process outside of it. That way if I run long all that happens is slowdown, no corruption.

Link to comment
Share on other sites

So do you mean? what would be the advantage of setting a flag inside the nmi? Wouldn't all other processes be waiting for the nmi to end anyways before continuing.

 

nmi()

{

flag=1;//disable stplay

updatesprites(0,16);

flag=0; enable stplay

}

That suggests that your processing is taking more than one frame sometimes, meaning you need to be really careful what you do inside the NMI.

For my own coding I don't do anything except a sprite table copy in the NMI anymore, I just set a flag and process outside of it. That way if I run long all that happens is slowdown, no corruption.

 

 

This is a good idea. I've split the cycle up using logic & a excel chart as too which cycle of 10 they happen on. But this would give better idea if one of these groupings was running too long.

 

 

I think you're doing too much in a single frame. Spunky's Super Car can sometime corrupt the score tileset graphics due to many put_frame objects on one screens while running over a grave even the nmi is disabled during these drawing those objects.

 

I would call the sound compression routine right after delay(1), so you have a fresh cycles. After that, graphical routines. What's left over like math and stuff can be safely interrupted by the NMI.

You can use the rainbow technique that the TI99 users used to see how much CPU your routines are taking up. Like

while(game==1){

paper(0);

delay(1);

paper(15);

sound decompression();

paper(14);

graphicstuff;

paper(13);

mathystuff;

}

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...