### Little doc for HuC
the PC Engine C compiler

previous home : utopia.consolemul.com
home : www.zeograd.com
www.magickit.com/mkit

In this documentation, you'll find how to use this compiler, how to interface it with your own asm routine and such. If you want to see anything added there or just want some explanation, tell me. I'll try my best to make it clearer.

## What's new ?

- From 3.20 to 3.21 (Denki version)
  - Bug fix when #incchr filename invalid
- From 3.11 to 3.20 (Nuku Nuku version)
  - Substantial speed and size optimization improvements
  - Enhanced tile functionality to include easier use of multiple palettes and either 8x8 or 16x16 tiles
  - Added functionality to create a specify a "special" CDROM overlay for use when a SCD game/demo is run on plain CDROM hardware
  - Fixed screen positioning between CDROM and HuCard to match
  - New clock_xx functions for measuring time
  - PSG player is started, and will be available soon
  - Several bug fixes
- From 3.10 to 3.11 (Ayeka version)
  - Much improved display on real console
  - New horizontal resolution (512 pixels width)
  - Color correction
  - Bug fixed in put_number with 3 arguments
  - Line drawing function
- From 3.04 to 3.10 (Washu version)
  - CD overlays !!. Stacks your programs into a single cd image and share variable and stuff like this.
- From 3.03 to 3.04 (Miz version)
  - Some font fixes
  - Ability to change the font base address (with #asmdef FONT_VADDR $1000 e.g.)
  - Fixes in assembler output concerning segment usage
  - Lots of bug fixes (in cd generation, or bm_rawwrite function e.g.)
  - Removed obsolete grp_* functions
  - Added several memory access functions
  - Added pixel plotting functions
  - Improved randomness
  - Childish "let's give 'codenames' to release" idea implemented (blame zeo!)
- From 3.02 to 3.03
  - Better output to segment listing
  - Improved document mostly concerning BRAM related functions
  - Bunch of new BRAM functions (complete list in whats.new)
  - Some new functions to handle string (complete list in whats.new)
- From 3.01 to 3.02
  - Substantial changes in bank management in the library banks; removed 2 unused banks, and merged code into a shared bank with font data
  - For SCD programs, the machine is checked at bootup, and issues an error message if the runtime machine is not SCD-capable
  - Fixed 'Segment Usage' display output significantly
  - Improved default font slightly, and added a new font - italics (but access to thie new font has not yet tested)
  - cd_fade() function now fixed
  - cd_playtrk() now fixed to convert data to BCD for BIOS call
  - New CDrom functions(though simple to write) features :
    - ac_exists() detects Arcade Card (but HuC does not yet use it)
    - ad_reset() resets ADPCM sound generator
    - cd_unpause() continues playing CD track
    - cd_playmsf(start m, s, f, end m, s, f, mode) plays CD audio like cd_playtrk() but with minute/second/frame indexing
    - cd_numtrk() returns number of tracks on CD
    - cd_trktype(track) returns type of track on CD (audio/data)
- From 3.0 to 3.01
  - joytrg() function have been fixed in the cd version
  - joyold() and joybuf() have been added and allow deeper reading of joypad
  - Fixed some minor init bugs in the mouse driver
  - Improved stability of cd games (while we hadn't detected problems, there were a little design flaw when calling interruptions)
  - CDrom library appears which some tasty (though simple to write) features :
    - cd_reset() which stops cd player and motor
    - cd_pause() which pauses the cd track playing
    - cd_playtrk(start,end,mode) which plays from track start until end (non-inclusive) in a certain mode
    - cd_getver() which returns the version of the cd system used
    - cd_fade(mode) which fades out the pcm and adpcm music
- From 1.5 to 3.0
  - This release, like the previous release, had Dave Shadoff as the main programmer for all areas of changes. But it was mostly integrating code that David Michel had previously written (similar to backup RAM support in previous version).
  - The main new feature is CDROM/SCD support, to create programs which can boot from CDROM. (Isn't that enough ? ;-) )
  - Synchronization between HuC and MagicKit version numbering. 3.0 was the next major number after MagicKit's previous version (2.51).
  - Miscellaneous bugfixes
- From 1.4.2 to 1.5
  - Backup ram support (to save/load game data).
  - Mouse and 6 button joypads support.
  - Preliminary sound support.
  - Improved libc in term of speed (while the code takes a bit more space).
  - Several function added (disable_scroll, srandom, bounded random generation).
  - Extended font for text output.
  - Improved randomness in random functions.
  - Compiler sources are now 100% ansi and compile without a warning on modern compilers (i.e. made after 83 ^^)
  - The base code is now in CVS form for better team programming.
- From 1.4 to 1.4.2
  - As you may have seen, the official magic kit homepage have opened on www.magicengine.com/mkit/index.html. Since the magickit and HuC are extremely close, you'll find there extremely valuables stuff (doc, games and much more)
  - A few bugs have been fixed
  - Offset can now be added to far pointers. Offset are those name/pointer created when including tiles or sprites and such. This feature enables you to write such a piece of code :
    `#include(tiles, "tiles.pcx", 1, 16);
    load_vram(0x1400, tiles + (1 << 6), 64);
    ` This way, you'll be able to easily create multi pattern sprite (for animated moves, e.g.)
  - All included data through #INC and #DEF directives can be accessed as const array too. #INCBIN directive creates a char array while others create int arrays.
    After having wrote
    `#INCBIN(level1, "level1.fmp");`
    It's exactly as if you had wrote
    `const char level1[] = { <stuff inside level1.fmp> };`
  - fmp ?
    did you see fmp ?
    what's that ?
    Well, it's a feature of magic kit 2.51 (on which HuC 1.4.2 relies and thus also benefits this). fmp is a format from mappy, a map editor. Now, you can make maps using this tool and then add them natively into HuC with the #INCBIN directive.
  - Some functions have been added to the libC, `get_tile(x,y)` to return the index of the tile at position x,y in the current map (for sprite/tile collision checking, isn't it, gravis ?). `get_map_width()` and `get_map_height()` which work on the current map.
  - HUGE maps are supported! 16384x16384 tiles (which is 262144x262144 pixels) is what I call huge :-) Well, all maps functions are still limited to 256x256 maps but we can now gather all of them using a special array and a special function, scan_map_table() . This function returns the map at the requested position.
    Here's an example :

        #incbin(level1, "level1.fmp") /* 256x256 */
                #incbin(level2, "level2.fmp") /* 256x256 */
                #incbin(level3, "level3.fmp") /* 256x256 */
                #incbin(level4, "level4.fmp") /* 256x256 */

                const int big_map[] = {
                /* width & height of all the maps
                 * put together
                 */
                  512, 512,

                /* the following lines declare all
                 * the small maps, one line per map :
                 *
                 * the two first values are the top/left
                 * coordinates of the small map inside
                 * the big map, the two followings values
                 * are bottom/right coordinates (inclusive),
                 * and the two last values are the map
                 * address in ROM
                 */

                  0,   0, 255, 255, bank(level1), level1,
                256,   0, 511, 255, bank(level2), level2,
                  0, 256, 255, 511, bank(level3), level3,
                256, 256, 511, 511, bank(level4), level4,

                /* -1 closes the table */

                -1
                };

- From 1.3 to 1.4
  - Support of tiles and scrolling, check the scroll demo and the LibC reference to see how to implement this on your own roms.
  - Added plenty of other little functions, you can find them in the LibC reference too (Exists also in plain text version, in the doc/HuC subdir too)
  - As for sign support, we added it to integer BUT chars remain unsigned, we choosed this. So when declaring 'int', you'll have a 16 bits signed integer while using 'char', you'll have an unsigned 8 bits value. We plan to add full support of 'unsigned'/'signed' type modifier.
  - Compatibility is slightly broken since last versions, David Michel uses the fact we're not yet a lot to break compatibility to implement more robust basis.
    In order to adapt your code, you'll have to do the following :
    - put* functions in debug.c have been renamed to put_* (added underscore). By the way, thses functions are integrated in assembler so you won't have to include "debug.c" anymore.
    - put_number syntax has changed, it's now :
      `put_number(int num, char width, int vaddr);`
      'width' is the field width, the number will be right justified, and eventualy truncated, or spaces will be added if the field is larger than the number. If the number is negative a '-' is printed. Before, the VRAM was corresponding to the right, it's now more classic, it represent the left address.
    - It's not really useful for porting code but it's better to have it said somewhere : There's a function able to handle 16x16 tiles,
      `put_tile(int tile, int vaddr);`
      'tile' is not a bat value, it's a tile index. To use this function you first need to initialize the tiles with set_tile_data();
    - The size of the screen has been changed, a 256x224 screen is now opened (it was 256x240). This means that it's no more necessary to add $40 to VRAM address to write something at the top of the screen. But this also means that all the put_* functions will have to be patched. :) But idealy rather than subtracting $40 to every put_* call, you can use the new put_* syntax :
      `put_digit(char num, char x, char y);`
      All the put_* functions have now two syntaxes, one with a VRAM address, and one with screen coordinates. The latter is a little bit slower, but very handy.
    - `spr_x()` and `spr_y()` has been changed, the syntax is always the same, but the coordinate system is different. Now 0 corresponds to the top of the screen. To make a sprite disappear behind the top border you must use negative value. This way, a char is enough to handle the position (note that chars are unsigned and can handle until coordinate 256 [while screen is 256x224])
  - Corrected argument order in #inc* statements, I wrongly inverted the two last couple or argument in former from of each #inc* statements.
- From 1.2 to 1.3
  - secret ^^, well in fact, I hadn't understood/don't remember why we choose to skip 1.3
- From 1.1 to 1.2
  - This version is marked by the return of David Michel as coder and David Shadoff as cool ideas generator.
  - The first feature you'll notice is the arrival of a GREAT optimiser. Your proggy will run up to 2 or 3 times faster and somewhat smaller.
  - Another thing is that the assembler under HuC have evolved a lot. Since it now support an auto filling of bank, you don't have to worry anymore about mapping stuff and the resulting rom will be optimaly filled (thus smaller). Thank to this, you don't need anymore the `newbank` pseudo instruction.
  - Addition of constant variables (syntax is const int x[4] = {0, 1, 2, 3} )
  - Correction of some bugs when using static variables
  - The switch/case instruction have been implemented even if not optimised yet.
  - Interface between asm and C have changed, in this doc, some parts have been said outdated but let because it's still useful to know how it was implemented before.
  - On error, line and file where problem were is displayed in an "easy to parse" way.
  - Some little things I must have forgotten.
- From 1.0 to 1.1
  - Modulo operator debugged (it's was twice my fault, writing the modulo code and writing memory mangement in Hu-Go!, I was writing to ROM in fact)
  - Some operators have been rewritten ( ==, !=, <, >, <=, >=). They are now faster and smaller (sometimes up to 66% shorter) in the libc
  - Optimisation have been tackled (but not yet working)
  - Produced variable reservation code is smaller if you put all your declarations on one line
  - Lots of pseudo instructions have been added to add easy support for multi bank rom and sprite handling (assembler were needed until then)
  - Added transparent support for inter bank function calls
  - Some libc functions have been improved for more security ( X << 0 was egal to 0 before)
  - More examples have been included

## Known bugs

- No more known bugs... ^^

## C/asm interface

You'll find here some trick to understand how this compiler works. Before trying to write your own asm routine, read that first. Even if you don't intend to make asm, I think you should read it at least once, knowledge can't harm.

Whatever you write in a asm block (i.e. beginning by #asm and ended by #endasm) is directly passed to the assembler, without any modification from the C compiler. You can write this way your own assembler lib function (when speed is needed for example) but it's harder to write and support than C code, of course.

You must be aware that C function names are limited to 24 chars and when passed to assembler are preceded with a '_' char. That's why you can't have 2 functions with the same 24 first characters and need to add a _ when calling a function directly from an assembly block. (The part concerning the length of identifier is not as important as when this document was first wrote, it was then limited to 8)

Argument passage is done trough a special stack, not the internal stack of the pc engine (that is 256 bytes long only and must be saved whenever possible) but a stack situated in RAM, at the end of the RAM to be more precise. The head of this stack is pointed by the variable __stack ( 2 '_' characters before ).

Since the tail is fixed at the very end of the RAM ($4000), the head 'goes down' when you add an item in it. Here's the pseudo code for adding an item on it ("pushing" a value).

> __stack -= sizeof(var);
> *__ stack = var;

This is exactly what is done in assembler before calling a function, to set the value of the various arguments.

outdated : If you want to write your own assembler function with parameters, you must restore the value of __stack because it's the calling program that must 'clean' the stack and not the called sub routine (contrary to the pascal convention) . This is due to the C calling convention which allows variable number of arg for subroutines (which is not supported by HuC and is likely to be never supported).

Now, David Michel decided (for optimisation purpose) to use anew the pascal convention for passing arguments and passing the first argument in the A:X registers instead of using the stack. This means that the stack must be restored in the called function, no more in the calling one.

Once in the subroutine, argument are then situated 'above' the stack (i.e. *__stack, *(__stack+1), and so on.. ). As for the order, rightmost C declared arguments are found on the 'bottom' of the stack. A little example to understand better...

                                                 +------------+
    dummy(val,offset,x, reg_arg) __stack     ->  |//// x /////|
       char val;                                 +------------+
       int offset;               __stack + 1 ->  |\\\\\\\\\\\\|
       char x;                                   +-- offset --+
       int reg_arg;              __stack + 2 ->  |\\\\\\\\\\\\|
                                                 +------------+
                                 __stack + 3 ->  |/// val ////|
                                                 +------------+
                                                 |            |

You may even consider the following pseudo code is executed to set the value of the argument using the stack :

      reg_arg = value of reg X + 256 * value of reg A;
      x = *__stack;
      offset = (*(__stack + 1) + 256 * (*(__stack + 2))
      val = *(__stack + 3)

## Sprite handling

Sprites are handled trough a table of 64 items, one for each sprite, each entry being 8 bytes long.

We are reusing the method of the magic kit, that's to say that we keep a local copy of this table in RAM on which we work and then we copy this local table to the real one (located in the video ram) each frame. This method allows faster manipulation (RAM is easier to access than video memory).

This local SATB (Sprite Attribute TaBle) is initialized by `satb_init()`, future call to this function will just clear it.

You can change every attribute of each sprite, individually. There are 4 attributes (using 16 bits each, which make this 64 sprites long table using 512 bytes). 2 are for the position (x,y), one for the pattern and the last one contains various flags...

When you want to change anything in a sprite, the method is the following : first, you must tell the system what is the sprite you want to deal with `spr_set(no)` where `no` is the number of the sprite (in 0-63).

Once done, you have a few functions you can use to modify the sprite you've chosen. `spr_x(x_coord)` and `spr_y(y_coord)` respectively change the position of the sprite on screen.

`spr_pri(priority)` allows to set the priority of the sprite, that's to say behind or in front of tiles. Priority of 0 makes it behind the tiles map and 1 draw them front of them.

`spr_pal(pal_number)` changes the palette for this sprite. There are 16 palettes of 16 colors for sprites. You can change the palette using `set_sprpal(palette)`, supposing you have a palette defined somewhere else with the `incpal` or `defpal` statement we'll also talk about.

Last function to control flags is the more generic `spr_ctrl(ctrl_mask, ctrl_value)` function. It controls the mirror flags (you can flip a sprite, either horizontally or vertically) and size flags (sprites can be 16x16, 32x16, 16x32, 32x32, 16x64 or 32x64). To use this, you must provide as the mask, the one corresponding to the flag you want to change or both (combining them with a logical 'or' i.e. | ) and on value, well, the value. There's a bunch of #define statements in the file `huc.h` which make it easy to use. A few examples, to draw the 13th sprite horizontally flipped, write :

`spr_set(13);
spr_ctrl(FLIP_MAS, FLIP_X);`

As for drawing a sprite flipped both horizontally and vertically, while setting the size to 32x64, simply put :

`spr_ctrl(FLIP_MAS | SIZE_MAS, FLIP_X | FLIP_Y | SZ_32x64);`

The last function to handle sprite is the `spr_pattern(pattern_address)` function. It's used to change the pattern of a sprite, i.e. the real shape of it. This 16 bits address is the place in the video memory where resides the pattern. The address is in word, not in bytes, which allows to access the whole 0x20000 bytes of video. You must not forget to load this pattern from the rom with another asm piece of code. First, you must define the pattern in a data bank including pieces of pcx files (or even creating yours with hexa numbers), then loading these datas in the video memory using the `load_sprite` statement. The `load_sprite` function takes the label of the data first, then the address in the video ram where it should be situated, THIS IS THE VERY SAME PARAMETER THAT SHOULD BE USED IN THE `SPR_PATTERN` FUNCTION, and finally the number of sprite that should be loaded. This number is in 32x64 big sprites. So loading 8 16x16 sprites requires only the value 1 here...

Finally, you shouldn't forget to update the true satb with the local one using the function `satb_update()`, which should be also accompanied by a `vsync(1)` call in order to let the user see the changes.

## PSEUDO INSTRUCTIONS

This part describes all the instructions which are not real C statements. They are HuC built in instructions and are processed at the compilation time, they are not call to library function for example (although they often produce calls to library functions). Since they're specific to HuC, they deal with all which is pc engine specific such as banking, sprites and tiles...

Outdated :

- `newbank` : This instruction must be used at top level only (that's to say outside any function, at the same 'level' than `main` function for example). Its goal is to provide an easy way to take advantage of pc engine banking ability (in fact, to use more than 8 kilobytes of memory :). You can use it of 4 different ways :
  1. `newbank();
     ` Without argument, all that follow this instruction is placed in the next free bank, and code which will be in will be designed to be placed at a compiler chosen position (If you want to know more, you can check a brief summary of the pc engine hardware). This is the most used form. It's typical use is when you get an assembler error such as `"Out of range, bank offset > 0x1FFF"`. This means you have filled a bank (which is 0x2000 bytes long, that's to say 8192 bytes). In order to solve this you have to 'break' your code. Indeed, currently, since `newbank` can only occur at top level, you can't have a function the flow of which goes from one bank to another. Each function must reside in one bank. It's then up to you to put the 'overflowing' code into a newer bank including the `newbank` instruction before it. From this moment, you still have another 0x2000 bytes of data for your use (in the limit of 128 banks, which still represent 1 megabyte). I fear this point is relatively unprecise but we'll try our best to improve it.
  2. `newbank(bank_number);`
     You can specify the number of the bank you want to 'tackle'. This number must be in 0-127 range. Usually you shouldn't have to deal with this form of `newbank`. Only people who see what's its use should use it :)
  3. `newbank(offset_value);`
     This version of newbank must be used in certain situation by non pc engine expert coders. It's used to tell the compiler we want a new bank but designed to be placed in a certain position (here again, check the brief summary of the pc engine hardware if you want to learn more). When you want to import any kind of graphical data (such as palettes, sprites patterns, tiles and such), you must declare this bank with `newbank(0x4000);` because we've decided it would make things much more easier to have all data mapped at 0x4000. This version is recognized from the previous because the argument is a multiple of 0x2000 and is greater than 128.
  4. `newbank(bank_number, offset_value);`
     Here is a combination of the two later forms and its use is pretty rare.
- `incpal` : This top level instruction allows to include a palette coming from a .pcx file. It's basically a wrapper for the magic kit equivalent instruction. It exists in 3 flavors :
  1. #`incpal(identifier_name, "filename");`
     Creates a series of palette identified by `identifier_name` coming from the file called `filename`. It extracts 16 palettes from the 0th to the 15th.
  2. #`incpal(identifier_name, "filename", start_pal);`
     Extract only from palette `start_pal` to the 15th
  3. #`incpal(identifier_name, "filename", start_pal, number_pal);`
     Extract `number_pal` palettes from palette `start_pal`.
- `incspr` : This instruction includes data for sprite patterns from a .pcx file.
  1. #`incspr(identifier_name, "filename");`
     Extract all possible 16x16 sprites from the file called `filename`.
  2. #`incspr(identifier_name, "filename", col, row);`
     Extract only `row` rows and `col` columns of 16x16 sprites from the file.
  3. # `incspr(identifier_name, "filename", begin_x, begin_y, col, row);`
     Extract `row` rows and `col` columns of 16x16 sprites starting at position (`begin_x`, `begin_y)`

- `incchr` : This instruction includes data for character patterns from a .pcx file.
  1. #`incchr(identifier_name, "filename");`
     Extract all possible 8x8 tiles from the file called `filename`.
  2. #`incchr(identifier_name, "filename", col, row);`
     Extract only `row` rows and `col` columns of 8x8 tiles from the file.
  3. #`incchr(identifier_name, "filename", begin_x, begin_y, col, row);`
     Extract `row` rows and `col` columns of 8x8 tiles starting at position (`begin_x`, `begin_y)
     `
- `incchr_ex` : This instruction includes data for character patterns from a series of .pcx files, and sets up for the "new style" of 8x8 scroll-tiling.
  1. #`incchr(identifier_name, "filename_1", begin_x, begin_y, col, row, pal_idx1, \
     "filename_2", begin_x, begin_y, col, rox, pal_idx2, \
     "filename_n", begin_x, begin_y, col, rox, pal_idxn );`
     Extract `row` rows and `col` columns of 8x8 tiles starting at position (`begin_x`, `begin_y`), and using the stated pal_idx from filename_1 (etc.), assembling them as a single list of tiles in memory, available for use in the map and scrolling functions
- `inctile` : This instruction includes data for tile patterns from a .pcx file.
  1. #`inctile(identifier_name, "filename");`
     Extract all possible 16x16 tiles from the file called `filename`.
  2. #`inctile(identifier_name, "filename", col, row);`
     Extract only `row` rows and `col` columns of 16x16 tiles from the file.
  3. #`inctile(identifier_name, "filename", begin_x, begin_y, col, row);`
     Extract `row` rows and `col` columns of 16x16 tiles starting at position (`begin_x`, `begin_y)
     `
- `inctile_ex` : This instruction includes data for character patterns from a series of .pcx files, and sets up for the "new style" of 16x16 scroll-tiling.
  1. #`inctile(identifier_name, "filename_1", begin_x, begin_y, col, row, pal_idx1, \
     "filename_2", begin_x, begin_y, col, rox, pal_idx2, \
     "filename_n", begin_x, begin_y, col, rox, pal_idxn );`
     Extract `row` rows and `col` columns of 16x16 tiles starting at position (`begin_x`, `begin_y`), and using the stated pal_idx from filename_1 (etc.), assembling them as a single list of tiles in memory, available for use in the map and scrolling functions
- `incbat` : This is a special instruction that include a kind of map used to recreate a background picture in conjunction with inclusion of tiles pattern. We've set another pseudo instruction that does that but it's not completely flexible (see load_background).
  1. #`incbat(identifier_name, "filename", pcx_offset);`
     Extract the map for displaying the whole pcx containing in the file `filename`. `pcx_offset` is the position in the video ram where will be stored the pattern to draw the picture. I advise you to let 0x1000 for this argument, if you want to use the load_background instruction for now.
  2. #`incbat(identifier_name, "filename", pcx_offset, col, row)`
     Extract only `col` columns and `row` rows from the file.
  3. #`incbat(identifier_name, "filename", pcx_offset, begin_x, begin_y, col, row);`
     Extract only `col` columns and `row` rows starting at position (`begin_x`, `begin_y`)
- `defpal` : This instruction allows you to define a palette data in your code. Instead of referencing it from a picture, you will simply tell the RGB components for each color of the palette.

  > `#defpal(identifier_name, <color component> * 16);`
  > You are not obliged to define all 16 colors of a palette. As for the components, they are easy to use if you use the hexa decimal notation in which only the 3 last digits are used and represent (from left to right) red, green and blue. The maximum for each component is 7, thus a perfect while is 0x777, while a purple is something like 0x607...

- `defspr` : With this one, you'll define your own sprites using also inline data, not coming from a picture.

  > `#defspr(identifier_name, vram_address, default_palette, <8 pixels data> * 32);`
  > The `vram_address` is a value in the range 0-0x10000 which tell the assembler where you want to see these data in the video ram. Don't forget that before using a sprite and such, you'll have to load data into video ram before the real use. In fact, this argument just tells a preference and its value doesn't oblige you to respect this. This is also true for the `default_palette` (there are 16 palettes for sprites). As for the data, I recommand you to use the hexadecimal notation, in which each 32 bits number easily represent 8 pixels using a digits for each. I bet a little example will make this appear clearer. To declare 8 pixels beginning by 3 pixels of color 5, then 2 of color 10 and finishing by color 1, you'll use the number 0x555AA111. Since we're defining 16x16 sprites, we need two of these numbers to define a line and thus we'll have 32 arguments to define the whole sprite pattern.

- `defchr` : basically, you should have guessed what this one is for :) (I'm also pretty tired to make documentation ***yawn*** )

  > `#defchr(identifier_name, vram_address, default_palette, <8 pixels data> * 8);`
  > See `defspr` for most information. I just want to confirm that you also have 16 palettes for tiles data (which makes a total of 32 differents palettes). And since a tile is only 8x8, you have only one hexa number per line and 8 of these numbers. You can have a look at the debug.c file which has the font used for printing defined this way (notice how the `vram_address` is useless :)

- `set_sprpal` : We're arriving to pseudo functions built to be used inside functions, as the same place you would write down statements, function calls, declarations and such... This function change a palette using data included or defined.

  > `set_sprpal(first_palette, palette_name [, number_palette ] );`
  > `first_palette` is the number of the palette to alter (in the range 0-15) while `palette_name` is an identifier to a palette to load or to the first palette you want to load (in this case, you should have included or defined all your palettes without any other actions between them). The last argument is optionnal and assumed to be 1 is missing. It's the number of palette you'll load from the rom into the hardware.

- `set_bgpal` : This one is exactly the same as the previous one expected that it will alter one of the 16 tile palettes.
- `load_sprites` : This function is just a wrapper for a magic kit macro but it's pretty important. It's the function that permit to load sprite from the rom to the video ram. Don't forget it only become useful there. Once in the video ram, you'll be able to use it in the spr_pattern function (see sprite handling).

  > `load_sprites(vram_address, data_name, number_sprites);`
  > `vram_address` is the address in the video ram where you want to transfert your sprites. This is this value that you need to pass to the `spr_pattern` function. `data_name` is an identifier of the sprites you want to copy and `number_sprites` is the amount of sprites to transfert. Be careful however that the unit of transfert data is in 32x64 sprites. This mean that for transfering 4 16x16 sprites, putting 1 for `number_sprites` is enough.

- `load_background` : contrary to what you could think about, this function isn't the tiles equivalent of `load_sprites`. It used to load a whole background picture using tiles. I consider this function as unperfect, it still requires some improvements, some flexibility but as it is, it works :)

  > `load_background(data_name, palette_name, bat_name, width, height);`
  > `data_name` is the identifier of the first tile that compose the picture. As it is currently, it must be beginning a bank; you can't have some data between the last `newbank(0x4000)` statement and the label you're referencing. The `palette_name` identifier must refer to the whole palette which have been extracted from the picture. It is HIGHLY recommended to convert your picture to 16 colors only before including them because if you know that each 8x8 tile must use only 16 colors consecutive, you'll quickly understand that it's not so easy to have more than 16 colors on a whole picture. `bat_name` is the identifier of the BAT which is in fact the way to use tiles to compose anew the original picture. Finally `width` and `height` are self explicite ^^, the only thing I could add is that the unit is the tile, that's to say a 8x8 piece of graphic. The best to see how this function works is to check sources of Pong.

## BRIEF SUMMARY OF THE PC ENGINE HARDWARE

The goal of this documentation is not to explain how does the pc engine works but since it's quite near of the machine architecture, I fell obliged to talk a bit about it to fully understand the utility of HuC. For a complete pc engine documentation, don't worry, we're also working on it. Until it's complete, you would like to check the one done my J.C. Restemeyer and on which ours will be based.

Concerning the memory management, you must be aware that the pc engine owns a very little addressable memory, 64 kB. In order to access the whole 1MB which can be present on a HuCard (plus some more special part of memory), there're a system of banking which allow you to access some part of the HuCard at a given moment. The 64 kb is divided in 8 pieces of 8 kb each. Each one of these piece is controlled by a special register indicating the "mapping" that's to say the bank we are accessing trough the memory range controlled by this register. For example, let's say you're setting MMR (Memory Management Unit I think) number 4 to the value 30. Since MMR4 controls 0x8000-0xA000 memory range, you'll be able to read the 15th byte of bank 30 at 0x800F and the last byte of bank 30 at position 0x9FFF.

Normal banks are numbered from 0-127, above these, you can find special banks. The bank numbered 0xFF is the Input/Output bank. When you read or write in memory where this bank is mapped, you won't read or write in some memory but rather access some hardware ports. For example, writing at position 0 of this bank will change the current video register (forget about its use, it's an example), sound stuff is at offset 0x800, cdrom stuff at 0x1800 and such... It's the way the program can communicate with the hardware. Bank 0xF8 is the ram for the coregraphx (there may be more for supergraphx). Whenever available the backup RAM is located at bank 0xF7.

There's also something I didn't explain. In order to make it more easy to handle all of this, we generally "schedule" a bank to be placed at a certain place (such as 0x4000 or 0xC000 and such). We way, we can use absolute jumps and such, we are not limited to relative addressing. Whatever, you must be aware that each bank is prepared for a certain position, not forgetting that some MMR are reserved. Indeed, it's not compulsory but most of roms, not to say absolutely all, uses a certain scheme. MMR0 (controlling 0x0000-0x2000) is mapped to the I/O bank for controlling the hardware. MMR1 (controlling 0x2000-0x4000) is mapped to the RAM bank. MMR7 (the last one) is mapped to bank 0. This one should always be mapped since interruption vectors are taken from the very end of the RAM (and thus in this bank), this bank generally contain general purpose functions (BIOS) and it's the only one which is mapped by default when booting anew. So code at the beginning of this bank will be the 'boot' code.

Outdated : As for easing creation of ROM from HuC, we've also decided to use 0x4000-0x6000 for data such as sprites, tiles. If you've read everything, you'll notice we still have 0x6000-0xDFFF for our purposes. Code can be placed in any of these and when telling HuC to use a new bank, it will try to feed all this bank so that you won't have overlapping function calls. About function calls, we're still working on it but we already have a working solution.

- Calling a function in the same bank as the caller : nothing easier, a simple instruction in assembler is able to call a sub routine which is currently in memory. We're sure it's mapped since it's the same bank of the calling function, which insure us that it's in memory.
- Calling a function in another bank as the caller, AND the called function bank is scheduled to be mapped at another place than the calling function bank : In this case, we can safely map the new bank since it won't overwrite the calling function bank. Once mapped, we can use the assembler instruction to call a subroutine.
- Calling a function in another bank as the caller, BUT the called function bank is scheduled to be mapped at the SAME place than the calling function bank : Here, this is trickier and there are a current working way of doing as well as another approach from David Michel. The current approach put a few values on the pc engine stack and then call a special function in the bank 0 (which is always mapped, don't forget). This little function will map the new bank, make a call to the new function then restore the old mapping. The other approach would be to store a fake function in the bank 0 that would always map the new bank and restore the mapping. Each version got advantages and backdraws. As for now, I've kept the one which work and is implemented even if it will changes. Whatever the solution it will be transparent for the user.

All of this to show you that a good spreading of the code will make things faster and smaller...

Thanks to the new magic kit used, the assembler is able to map automaticaly data and code. This means that you don't use to specify any "newbank" statement since the assembler will spread code and data in various banks and will take care of mapping stuff before using it. As far as I remember the code only uses one bank and another one will only be used to contain a wraper for each function that maps correctly a bank before calling a function. Two banks are used for startup code (hucard and cd one). One will contain data (such as sprites, tiles and such) and another one for constant data (as the string constant in C programs). Remain the two classical first MMR filled with the hardware access bank and the RAM one.

As you can see, everything is used now and transparently for us, C coders :)