
 -*[ MAGIC ASM v1.1 ]*-
    ----------------

        Magic-ASM is an assembler for the HuC6280, the main CPU of
        the PC Engine console. This processor is based on the well
        known 6502 processor, if you are familiar with it, you will
        pass easily to the HuC6820, otherwise a good book on the
        6502 will give you all the bases.

        The assembler seems to be bug free, :) but... if you find
        something abnormal or if you have a nice idea for improving
        the program, feel free to contact me, my e-mail address is
        at the bottom of this file.


    History
    -------

        v0.1 : 12/Jun/97

               - modified an old 6502 assembler.
               - added support for most of the HuC6280 instructions.

        v0.2 : 18/Jun/97

               - added the .INCLUDE directive.
               - added a trap for divisions by zero.

        v0.3 : 26/Jun/97

               - corrected a bug with undefined symbols.
               - rewritten all the symbol routines and added local
                 symbols.
               - enhanced a bit the format of the listing file.

        v0.4 : 02/Jul/97

               - added all the missing instructions : BBRi, BBSi
                 TST, TII, TDD, TIN, TIA and TAI.
               - changed some error messages.
               - added two functions : HIGH, LOW.

        v1.0 : 06/Jul/97

               - rewritten the expression parser.
               - added support for PCX file.
               - added new functions PAGE and BANK. [thanks Dave!]
               - corrected lots of minor bugs.

        v1.1 : 15/Jul/97 [first release]

               - added macro support.
               - modified the ORG directive and removed the PAGE
                 directive.
               - corrected a few bugs (PCX and MACRO code).
               - added a small demo.


    Usage
    -----

        Usage is very simple, the assembler accept only one argument
        on the command line : the name of an asm file (the .ASM
        extension can be omitted). The assembler will create a
        complete listing file (.LST) if the LIST directive is used
        in the asm file, and a ROM file (.PCE) directly usuable by
        an emulator like VPCE or MagicEngine. The limit for the ROM
        file is 1MB.


    Instructions set
    ----------------

        +------+----------+-----------------------------+
        |      | NVTBDIZC | Description                 |
        +------+----------+-----------------------------+
        | ADC  | XX0---XX | Add with Carry              |
        | AND  | X-0---X- | Logical AND                 |
        | ASL  | X-0---XX | Arithmetic Shift left       |
        | BBRi | --0----- | Branch if Bit Reset         |
        | BBSi | --0----- | Branch if Bit Set           |
        | BCC  | --0----- | Branch if Carry Clear       |
        | BCS  | --0----- | Branch if Carry Set         |
        | BEQ  | --0----- | Branch if Equal             |
        | BIT  | XX0---X- | Bit Test                    |
        | BMI  | --0----- | Branch if Minus             |
        | BNE  | --0----- | Branch if Not Equal         |
        | BPL  | --0----- | Branch if Plus              |
        | BRA  | --0----- | Branch Always               |
        | BRK  | --0----- | Break                       |
        | BSR  | --0----- | Branch Sub Routine          |
        | BVC  | --0----- | Branch if Overflow Clear    |
        | BVS  | --0----- | Branch if Overflow Set      |
        | CLA  | --0----- | Clear A                     |
        | CLC  | --0----0 | Clear Carry flag            |
        | CLD  | --0-0--- | Clear Decimal flag          |
        | CLI  | --0--0-- | Clear Interrupt disable     |
        | CLV  | -00----- | Clear Overflow flag         |
        | CLX  | --0----- | Clear X                     |
        | CLY  | --0----- | Clear Y                     |
        | CMP  | X-0---XX | Compare A with source       |
        | CPX  | X-0---XX | Compare X with source       |
        | CPY  | X-0---XX | Compare Y with source       |
        | CSH  | --0----- | Clock Select High           |
        | CSL  | --0----- | Clock Select Low            |
        | DEC  | X-0---X- | Decrement                   |
        | DEX  | X-0---X- | Decrement X                 |
        | DEY  | X-0---X- | Decrement Y                 |
        | EOR  | X-0---X- | Logical Exclusive OR        |
        | INC  | X-0---X- | Increment                   |
        | INX  | X-0---X- | Increment X                 |
        | INY  | X-0---X- | Increment Y                 |
        | JMP  | --0----- | Jump                        |
        | JSR  | --0----- | Jump to Sub Routine         |
        | LDA  | X-0---X- | Load A                      |
        | LDX  | X-0---X- | Load X                      |
        | LDY  | X-0---X- | Load Y                      |
        | LSR  | 0-0---XX | Logical Shift Right         |
        | NOP  | --0----- | No Operation                |
        | OR   | X-0---X- | Logical inclusive OR        |
        | PHA  | --0----- | Push A                      |
        | PHP  | --0----- | Push P                      |
        | PHX  | --0----- | Push X                      |
        | PHY  | --0----- | Push Y                      |
        | PLA  | X-0---X- | Pull A                      |
        | PLP  | XXXXXXXX | Pull P                      |
        | PLX  | X-0---X- | Pull X                      |
        | PLY  | X-0---X- | Pull Y                      |
        | RMBi | --0----- | Reser Memory Bit            |
        | ROL  | X-0---XX | Rotate Left                 |
        | ROR  | X-0---XX | Rotate Right                |
        | RTI  | XXXXXXXX | Return from Interrupt       |
        | RTS  | --0----- | Return from Sub Routine     |
        | SAX  | --0----- | Swap A and X                |
        | SAY  | --0----- | Swap A and Y                |
        | SBC  | XX0---XX | Substract with Carry        |
        | SEC  | --0----1 | Set Carry flag              |
        | SED  | --0-1--- | Set Decimal flag            |
        | SEI  | --0--1-- | Set Interrupt disable       |
        | SET  | --1----- | Set T flag                  |
        | SMBi | --0----- | Set Memory Bit              |
        | ST0  | --0----- | Store HuC6270[0]            |
        | ST1  | --0----- | Store HuC6270[2]            |
        | ST2  | --0----- | Store HuC6270[3]            |
        | STA  | --0----- | Store A                     |
        | STX  | --0----- | Store X                     |
        | STY  | --0----- | Store Y                     |
        | STZ  | --0----- | Store Zero                  |
        | SXY  | --0----- | Swap X and Y                |
        | TAI  | --0----- | Transfert block             |
        | TAMi | --0----- | Transfert A to MPRi         |
        | TAX  | X-0---X- | Transfert A to X            |
        | TAY  | X-0---X- | Transfert A to Y            |
        | TDD  | --0----- | Transfert block             |
        | TIA  | --0----- | Transfert block             |
        | TII  | --0----- | Transfert block             |
        | TIN  | --0----- | Transfert block             |
        | TMAi | --0----- | Transfert MPRi to A         |
        | TRB  | XX0---X- | Test and Reset Bit          |
        | TSB  | XX0---X- | Test and Set Bit            |
        | TST  | XX0---X- | Test memory                 |
        | TSX  | X-0---X- | Transfert S to X            |
        | TXA  | X-0---X- | Transfert X to A            |
        | TXS  | --0----- | Transfert X to S            |
        | TYA  | X-0---X- | Transfert Y to A            |
        +------+----------+-----------------------------+


    Operand syntax
    --------------

        A        accumulator
        #i       immediate
        #i,<n    immediate and zero page              | 
        #i,<n,X  immediate and zero page indexed by X | TST
        #i,n     immediate and absolute               | 
        #i,n,X   immediate and absolute indexed by X  |
        <n       zero page
        <n,X     zero page indexed by X
        <n,Y     zero page indexed by Y
        <n,r     zero page and relative               | BBRi/BBSi
        [n]      indirect (*)
        [n,X]    indirect pre-indexed by X (*)
        [n],Y    indirect zero page post-indexed by Y
        r        relative                             | BRA/BSR/Bcc
        n        absolute
        n,X      absolute indexed by X
        n,Y      absolute indexed by Y
        n,n,n    source, destination, length          | TAI/TIA/TII/TIN/TDD

        (*) can be zero page or absolute


    Symbols
    -------

        Two types of symbol are supported, global symbols and local
        symbols. Local symbols are preceded by a dot '.' and are 
        valid only between two global symbols. A symbol can be 
        followed by a colon ':' but this is not necessary.


    Expressions
    -----------

        The assembler supports very complex expressions. You can
        use as many level of parenthesis as you want and spaces
        between operators and numbers are possible. For the
	priority, the same rules as C apply.

        Numbers can be written in four base : hexa ($), octal (&),
        binary (%) and decimal. Character values are also supported
        (ie. 'A') and all the usual operators are present :
        +, -, *, /, %, ^, &, |, ~, <<, >>.

        In an expression four predefined functions can be used too :

            HIGH(), return the high byte of a number.

            LOW(),  return the low byte.

            BANK(), return the bank index of a symbol. If no
                    symbol, or more than one, are given, the
                    function return an error.

            PAGE(), return the page index of a symbol.
                    See BANK for errors.


    Macros
    ------

        Up to nine parameters, \1 to \9, can be used in a macro call.
        There's also a special parameter \@ that returns a different
        number for each macro, it's used to make local symbols inside
        the macro :

            dummy   macro
                     lda   \1
                     bpl   .x\@
                     eor   #$FF
                     inc   A
                     sta   \1
            .x\@:
                    endm


    Directives
    ----------


        LIST,    tell the assembler that you want a complete listing
                 file. You can later stop temporarily the output with
                 the NOLIST directive and restart it with LIST.

        NOLIST,  stop the listing output.

        MLIST,   include the macros in the listing file.

        NOMLIST, stop expanding macros in the listing file.

        EQU,     assign a value to a symbol. The character '=' has
                 the same function too.

        BANK,    select a ROM bank (0-127) and reset the location
                 counter to the latest known position in this bank.

        ORG,     fix the location of the program counter. The thirteen
                 lower bits of the address inform the assembler about
                 the offset in the ROM bank and the third upper bits
                 represent the page index.

        DB,      data byte(s).

        DW,      data word(s).

        MACRO,   start a macro definition.

        ENDM,    end a macro definition.

        INCBIN,  include a binary file at the current location. If
                 the file is bigger than a ROM bank, as many successive
                 banks as necessary will be filled and the bank and
                 the location counter will be updated.

        INCLUDE, include a source file at the current location.
                 Up to 7 levels are possible.

        INCCHR,	 extract a part of a PCX file and convert it to
                 the graphic format used by background characters.
                 Three syntaxes are possible :

                 INCCHR "pic.pcx"

                     without additional parameters, the command
                     convert the whole PCX file.

                 INCCHR "pic.pcx",32,4

                     tell the assembler to convert only 4 rows
                     of 32 characters (a character size is 8x8).

                 INCCHR "pic.pcx",48,16,32,4

                     same as above but start extracting characters
                     from coordinate 48,16 (in pixels).

        INCSPR,	 same as INCCHR but for sprites, excepted that
                 the size of a sprite character is 16x16.

        INCPAL,	 extract the palette of a PCX file. If no extra
                 parameters are given all the 256 colors are loaded
                 and converted. The first parameter indicates from
                 what sub-palette to start (a sub-palette is a
                 block of 16 colors). The second parameter is the
                 number of sub-palette to extract, if omitted one
                 is used instead.


    HuC6280 banks mechanism
    -----------------------

        To access more than the usual 64KB, the HuC6280 uses a MMU
        that splits the address space in 8 pages of 8KB. For each
        page there's a 8bit register (MPRi) that contains the bank
        index for this page. There's two special instructions that
        access the MPRi registers :

            TAMi, transfer the content of the accumulator (A) to
                  the MPRi register.

            TMAi, transfert the MPRi register to the accumulator.

        Banks map :

            $00-$7F ROM
            $F7     battery backup RAM
            $F8     RAM
            $FF     I/O page

        There's a sort of standard for pages mapping. You are not
        obliged to respect it, but it's recommended if you want to
        share examples, libraries, etc...

            page 0 -> bank $FF
            page 1 -> bank $F8
            page 2 ->  |
            page 3 ->  | user
            page 4 ->  | definable
            page 5 ->  |
            page 6 ->  |
            page 7 -> bank $00

        NOTE : After a RESET all the pages are mapped to bank $00.


    PC Engine hardware registers map
    --------------------------------

        Details of the I/O page :

            $0000-$0003 HuC6270, Video Display Controller (VDC)
            $0400-$0407 AuC6260, Video Colour Encoder (VCE)
            $0800-$080F Programmable Sound Generator (PSG)
            $0C00-$0C01 Timer
            $1000       External port (gamepad)
            $1402       Interrupt disable register
            $1403       Interrupt request register

        NOTE : I know, this summary is very simple. :) For a
               detailled description of the PC Engine hardware
               check the homepage of VPCE's author : Jens Ch.
	       Restemeier, you won't be disappointed!
	       Jens has put all his knowledge on the PC Engine
               in a nice documentation. [Nice job Jens!]

            <http://www.geocities.com/SiliconValley/Way/3340/>

               Follow the 'projects' link.


    HuC6280 IRQ vectors
    -------------------

        $FFF6   IRQ2 (BRK)
        $FFF8   IRQ1
        $FFFA   TIMER
        $FFFC   NMI
        $FFFE   RESET


    Thanks to
    ---------

        - Jens Ch. Restemeier, for making this excellent documentation
            on the PC Engine hardware.

        - J. H. Van Ornum, for his old 6502 assembler (11/May/84).
            I used his sources as a base for the assembler.

        - DJ Delorie, for DJGPP.
            If you search for a fast, good and *free* C compiler,
            go to : <http://www.delorie.com/djgpp>

        - Charles Sandmann, for CWSDPMI.
            A pretty good DPMI server, needed by DJGPP.
            <ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2misc/csdpmi*.zip>

        and to you if you like this program! ;)


 ------------
 David Michel <dmichel@easynet.fr>

