Skip to content
shaw02 edited this page Sep 8, 2019 · 7 revisions

Developer's Guide

This libraly is made for cc65.
This document are witten for cc65.

Coding guide

User source code SHOULD include the following code.
In these include file, there is the prototype declaration for control function and structure define of this library.

For C language

#include	"nsd.h"

For Assembly language

	.include	"nsd.inc"

Linking guide

User SHOULD link the nsd.lib as object libraly to your project with the ld65.exe.

Reference

Using segment

This libraly is used the following segment.

  • "CODE" for main program.
  • "RDATA" for const dat.
  • "BSS" for control works on RAM. (Not on Zeropage)
  • "ZEROPAGE" for control works on Zeropage.

As abobe, this library is using the ZEROPAGE area.
Therefore, when assemble .s file with the ca65.exe and when compile .c file with the cl65.exe, user MUST set the option -t none.
Moreover, when link the object files with the ld65.exe, user MUST set the option -C with the Configuration files that reserved ZEROPAGE for nsd.lib.

And you SHOULD refer the documents Defining a Custom cc65 Target.

Using label

In the label with extern define, this label names are started with _nsd_. (First _ is for the calling conversion of C language.)
If C language, these label names start with nsd_.

Functions

Calling conversion

The calling conversion of nsd.lib is __fastcall__ of cc65.

Return value Name Contents
void nsd_init Initraize the driver.
void nsd_set_dpcm Set the dpcm information.
void nsd_main Driver main routine. Please call by one V-blank.
void nsd_main_bgm Driver main routine(BGM). Please call by one V-blank
void nsd_main_se Driver main routine(SE). Please call by one V-blank.
void nsd_play_bgm Start the BGM.
void nsd_stop_bgm Stop the BGM.
void nsd_play_se Start the SE.
void nsd_stop_se Stop the BGM.
void nsd_pause_bgm Pause the BGM.
void nsd_resume_bgm Resume the BGM.
void nsd_save Save the control work.
void nsd_load Load the control work.

Note: If you want to use nes.lib in cc65.

nes.lib in cc65 is using the any zeropage area with the absolute addressing.
However, this area does not reserve with the inner configuration files for NES in linker ld65.exe.
Therefore, you SHOULD refer the library source code of nes.lib, and document of cc65.


MML compiler nsc.exe

MML compiler can convert to the aasembly source code for ca65.exe.

About the label and segment name

You can include the command to define label and segment name for assembly with the following command to the MML file:

  • #label command defines the starting name for the label.
    If you do not declaration, MML compiler will name "_nsd_".
    The MML compiler adds the following string and number to this starting name:
    • "DPCM" for the delta pcm information struct (nsd_dpcm).
    • "BGM" for the BGM data.
    • "SE" for the SE data.
  • #segment command defines the name for the segment of the song data.
    If you do not declaration, MML compiler will name "RODATA".
  • #segmentPCM command defines the name for the segment of Delta PCM data.
    If you do not declaration, MML compiler will name "PCMDATA".

Thers label will be declared extern.
Therefore, your source code can access this song data.


Samples

testmus.mml

#title  "Test"
#Label  "_Test_"        //'_' is need for calling conversion of C langage.
#bgm    1

#offsetPCM  $C000       //Address of Delta PCM. This is the same address as Configuration file setting of ld65.exe

DPCM{
    b1,     "../dmc/bd.dmc",14,0,64
    c2,     "../dmc/bd.dmc",15,0,64
    d2,     "../dmc/sd.dmc",15,0,64
    e2,     "../dmc/sd.dmc",14,0,64
    f+2,    "../dmc/hhc.dmc",15,0,64
    a+2,    "../dmc/hho.dmc",15,0,64
    c+3,    "../dmc/cymbal.dmc",15,0,64

    f2,     "../dmc/tom.dmc",10,0,64
    g2,     "../dmc/tom.dmc",11,0,64
    a2,     "../dmc/tom.dmc",12,0,64
    b2,     "../dmc/tom.dmc",13,0,64
    c3,     "../dmc/tom.dmc",14,0,64
    d3,     "../dmc/tom.dmc",15,0,64
}
			
Envelop( 0){15  L   12  R   10  8   7   6   D0  5   D1  4   D2  3   D3  L   2   }
Envelop(100){   0   D36 L   1   2   3   2   1   0   -1  -2  -3  -2  -1  }
Envelop(300){   3   2   L   0	}

Sub(0){ l4o4u8. E@300   Em100   Ev0 cdefgab > c1,2. }

BGM(0){
    TR1 v12         S0
    TR2 v8  r-8.    S0
    TR5 o2 l16  [2  c8f+f+  d8f+f+  c8f+f+  d8f+f+  ]   `c+1
}

test.c

#define	__NES__

#include    <nes.h>
#include    <conio.h>
#include    "..\..\include\nsd.h"

//Music Data
extern  const   char        Test_BGM0[];        // '_' is not needed because this is C language.
extern  const   nsd_dpcm    Test_DPCMinfo[];    // '_' is not needed because this is C language.

//Main routine
void	main()
{

    nsd_init();                     // Initraize the driver.
    nsd_set_dpcm(Test_DPCMinfo);    // Set the dpcm information.

    nsd_play_bgm(Test_BGM0);        // Start music.

    while(1){
        waitvblank();
        nsd_main();                 // Call by one V-Blank (As an alternative, call it with an NMI routine.)
    }

}

config.cfg

MEMORY {
    # INES Cartridge Header
    HEADER:   start = $0,    size = $10,   file = %O ,fill = yes;
    # PRG-ROM (32kByte)
    ROM0:     start = $8000, size = $4000, file = %O ,fill = yes, define = yes;
    ROM1:     start = $C000, size = $3ff4, file = %O ,fill = yes, define = yes;
    ROMV:     start = $fff6, size = $c,    file = %O, fill = yes;
    # CHR-ROM ( 8kByte)
    ROM2:     start = $0000, size = $2000, file = %O, fill = yes;
    # RAM     ( 2kByte)
    ZP:       start = $02,   size = $60,   type = rw,             define = yes;
    SRAM:     start = $0500, size = $0300,                        define = yes;
    RAM:      start = $6000, size = $2000,                        define = yes;
}

SEGMENTS {
    HEADER:   load = HEADER,          type = ro;
    STARTUP:  load = ROM0,            type = ro,  define = yes;
    LOWCODE:  load = ROM0,            type = ro,                optional = yes;
    INIT:     load = ROM0,            type = ro,  define = yes, optional = yes;
    CODE:     load = ROM0,            type = ro,  define = yes;
    RODATA:   load = ROM0,            type = ro,  define = yes;
    DATA:     load = ROM0, run = RAM, type = rw,  define = yes;
    PCMDATA:  load = ROM1,            type = ro,  define = yes;
    VECTORS:  load = ROMV,            type = rw;
    CHARS:    load = ROM2,            type = rw;
    ZEROPAGE: load = ZP,              type = zp;
    BSS:      load = RAM,             type = bss, define = yes;
    HEAP:     load = RAM,             type = bss,               optional = yes;
}

FEATURES {
    CONDES: segment = INIT,
        type = constructor,
        label = __CONSTRUCTOR_TABLE__,
        count = __CONSTRUCTOR_COUNT__;
    CONDES: segment = RODATA,
        type = destructor,
        label = __DESTRUCTOR_TABLE__,
        count = __DESTRUCTOR_COUNT__;
    CONDES: type = interruptor,
        segment = RODATA,
        label = __INTERRUPTOR_TABLE__,
        count = __INTERRUPTOR_COUNT__;
}

SYMBOLS {
	# 3 pages stack
#   __STACKSIZE__ = $0300;                          for cc65 version 2.13.3
    __STACKSIZE__: type = weak, value = $0300;      for cc65 version 2.14

make.bat

cl65 -t none -Oi -Os -Or -c -o test.o test.c
nsc -a testmus.mml
ca65 -t none testmus.s
ld65 -C config.cfg -v -o test.nes test.o testmus.o nsd.lib nes.lib
  • Home
  • Developer's Guide
  • Function reference
  • Structure reference
  • MML command reference
    • Setting command
    • Define Envelope pattern (E(){})
    • Define Patch pattern (P(){})
    • Define Delta PCM (DPCM{})
    • Define FDS carrer wave (FDSC(){})
    • Define FDS modulator wave (FDSM(){})
    • Define VRC7 voice (VRC7(){})
    • Define N16x voice (N163(){})
    • Define Sequence (BGM(){},SE(){},Sub(){})
      • Notes (a,b,c,d,e,f,g)
      • Rest (r,w)
      • Key shift (k)
      • Length (l)
      • Octave (o)
      • Quantize (q)
      • Sweep (s)
      • Tempo (t)
      • Volume (v)
      • Memory witer (y)
      • VRC7 register write (yV)
      • Detune (D,D%)
      • Envelop (E@,Ev,Em,En)
      • Pseudo echo (EC)
      • Pseudo echo buff control
      • SN5b Envelop Frequency (F)
      • Key signature (K{})
      • Scale (scale())
      • Jump (j)
      • Loop (L)
      • n16x channnel number (NC)
      • Portamento (P)
      • Portamento2 ({})
      • Relase control (Rm,R@,Rv)
      • Sub routine call (S)
      • SE call (SE)
      • Track (TR)
      • Call macro ($)
      • Define local macro ($$)
      • Set Instruments (@)
      • Set Patch (@P)
      • Set VRC7 user instruments (@V)
      • Set FDS carrer waveform (@FC)
      • Set FDS modulator wafevorm (@FM)
      • Set FDS modulator frequency (@FF)
      • Set FDS master volume (@FV)
      • Load n16x wafe vorm (@N)
      • Load n16x wafe vorm (@NL)
      • Set n16x sample length (@NS)
      • Relative volume ((,))
      • Relative octave (<,>,",')
      • Repeat type A ([,:,])
      • Repeat type B (|:,\,:|)
      • Tie (^)
      • Transpose (_,__)
Clone this wiki locally