MESS OUT: Difference between revisions

From NeoGeo Development Wiki
Jump to navigation Jump to search
mNo edit summary
 
(9 intermediate revisions by 3 users not shown)
Line 1: Line 1:
=MESS_OUT ($C004CE): Generic VRAM output=
=MESS_OUT ($C004CE): Generic VRAM output=
[[File:Mess_out.png|frame|right]]


MESS_OUT executes the command buffer in the [[BIOSes|BIOS]]'s work RAM that starts at '''BIOS_MESS_BUFFER''' (constant $10FF00) and goes up to '''BIOS_MESS_POINT''' (longword variable $10FDBE). This can be used to display text messages, boxes... on the [[fix layer]] (is it used for sprites too ?).
MESS_OUT executes the command buffer in the [[System ROM]]'s work RAM that starts at '''BIOS_MESS_BUFFER''' (constant $10FF00) and goes up to '''BIOS_MESS_POINT''' (longword variable $10FDBE). This can be used to display text messages, boxes... on the [[fix layer]] (is it used for sprites too ?).


MESS_OUT is automatically called in the [[SYSTEM_INT1]] call. '''BIOS_MESS_BUSY''' ($10FDC2.b) can be used to prevent this (when setting up the command list, for example).
<s>MESS_OUT is automatically called in the [[SYSTEM_INT1]] call</s>. '''BIOS_MESS_BUSY''' ($10FDC2.b) can be used to prevent this (when setting up the command list, for example).


The command buffer can be made of commands directly, or pointers to lists in ROM or user RAM. To put commands directly into the buffer, a null pointer ($00.l) needs to be placed before the command list.
The command buffer can be made of commands directly, or pointers to lists in ROM or user RAM. To put commands directly into the buffer, a null pointer ($00.l) needs to be placed before the command list.
Line 9: Line 10:
Commands are always words.
Commands are always words.


==Command 0==
=Commands=
*1 word
==Command 0: End of command list==
End of actual command list.
1 word: $0000


==Command 1==
==Command 1: Set data format==
*2 words
2 words:
{{16BitRegister|0|6|Byte/Word|1|End code/Data size|1|$01|8}}
{{16BitRegister|0|6|Byte/Word|1|End code/Data size|1|$01|8}}


This command specifies if the data will be in bytes or words, and if the size is defined or if an end code has to be reached.
This command specifies if the data will be in bytes or words, and if the size is defined or if an end code has to be reached.


;If data is in bytes (bit 10 = 0):
;If data is in bytes (bit 9 = 0):
:The next word's upper byte will be the data's constant upper byte (since VRAM can only be written in words).
:The next word's upper byte will be the data's constant upper byte (since VRAM can only be written in words).
:If the data is limited by an end code (bit 9 = 0), the next word's lower byte will be the end code's value.
:If the data is limited by an end code (bit 8 = 0), the next word's lower byte will be the end code's value.
:If the data size is defined (bit 9 = 1), the next word's lower byte will be the size (so max length is $FF).
:If the data size is defined (bit 8 = 1), the next word's lower byte will be the size (so max length is $FF).


;If data is in words (bit 10 = 1):
;If data is in words (bit 9 = 1):
:If the data is limited by an end code (bit 9 = 0), the next word will be the end code's value.
:If the data is limited by an end code (bit 8 = 0), the next word will be the end code's value.
:If the data size is defined (bit 9 = 1), the next word will be the size (so max length is $FFFF).
:If the data size is defined (bit 8 = 1), the next word will be the size (so max length is $FFFF).


Examples:
Examples:
<pre>
<syntaxhighlight>
dc.w  $0001,$15FF  ;Data will be read in bytes, upper byte will always be $15, end code is $FF.
dc.w  $0001,$15FF  ;Data will be read in bytes, upper byte will always be $15, end code is $FF.
dc.w  $0101,$1520  ;Data will be read in bytes, upper byte will always be $15, data length is $20.
dc.w  $0101,$1520  ;Data will be read in bytes, upper byte will always be $15, data length is $20.
dc.w  $0201,$8000  ;Data will be read in words, end code is $8000.
dc.w  $0201,$8000  ;Data will be read in words, end code is $8000.
dc.w  $0301,$2044  ;Data will be read in words, data length is $2044.
dc.w  $0301,$2044  ;Data will be read in words, data length is $2044.
</pre>
</syntaxhighlight>


The format stays the same until command 1 is used again.
The format stays the same until command 1 is used again.


==Command 2==
==Command 2: Set auto-increment==
*1 word
*1 word
{{16BitRegister|Auto-inc value|8|$02|8}}
{{16BitRegister|Auto-inc value|8|$02|8}}


Sets the auto-increment value (written to '''VRAM_MOD''' ($3C0004)). Is the value sign-extended or not ?
Sets the auto-increment value (written to '''VRAM_MOD''' ($3C0004)). Is the value sign-extended or not ?
<pre>
<syntaxhighlight>
dc.w  $2002  ;Set auto-inc to $20
dc.w  $2002  ;Set auto-inc to $20
</pre>
</syntaxhighlight>


==Command 3==
==Command 3: Set VRAM address==
*2 words
*2 words
Sets the VRAM address written to '''VRAM_ADDR''' ($3C0000)) to the next word's value.
Sets the VRAM address written to '''VRAM_ADDR''' ($3C0000)) to the next word's value.
<pre>
<syntaxhighlight>
dc.w  $0003,$7201  ;Set VRAM address to $7201
dc.w  $0003,$7201  ;Set VRAM address to $7201
</pre>
</syntaxhighlight>


==Command 4==
==Command 4: Set data address==
*3 words
*3 words
Sets the output data address to the next longword. Actual writes to VRAM are done with this command.
Sets the output data address to the next longword. Actual writes to VRAM are done with this command.
<pre>
<syntaxhighlight>
dc.w  $0004
dc.w  $0004
dc.l  MESSAGE
dc.l  MESSAGE
</pre>
</syntaxhighlight>


==Command 5==
==Command 5: Add to current VRAM address==
*2 words
*2 words
Add the next word to the current VRAM address. (This is different from command 2). Useful to skip lines or spaces.
Add the next word to the current VRAM address. (This is different from command 2). Useful to skip lines or spaces.
<pre>
<syntaxhighlight>
dc.w  $0005,$001F  ;Add $1F to the current VRAM address
dc.w  $0005,$001F  ;Add $1F to the current VRAM address
</pre>
</syntaxhighlight>


==Command 6==
==Command 6: Resume data output==
*1 word
*1 word
Resume data output (instead of using command 4 again, keep going from the last address).
Resume data output (instead of using command 4 again, keep going from the last address).


==Command 7==
==Command 7: Directly define output data==
*at least 2 words
*at least 2 words
Directly define the data (instead of using command 4 to point to it). Don't forget the padding byte if the data ends on an odd address.
Directly define the data (instead of using command 4 to point to it). Don't forget the padding byte if the data ends on an odd address.
<pre>
<syntaxhighlight>
dc.w  $0007
dc.w  $0007
dc.b  $30,$31,$34,$45,$FF
dc.b  $30,$31,$34,$45,$FF
dc.b  $00    ;Pad byte
dc.b  $00    ;Pad byte
</pre>
</syntaxhighlight>


==Command 8==
==Command 8: Write text with 8x16 font==
*at least 2 words
*at least 2 words
{{16BitRegister|Upper data byte (fontset number)|8|$08|8}}
{{16BitRegister|Upper data byte (fontset number)|8|$08|8}}
Line 90: Line 91:
The auto-inc is automaticaly set to $20.
The auto-inc is automaticaly set to $20.


<pre>
<syntaxhighlight>
dc.w  $0108    ;Tileset 1
dc.w  $0108    ;Tileset 1
dc.b  $44,$51  ;Data
dc.b  $44,$51  ;Data
dc.b  $FF      ;End code
dc.b  $FF      ;End code
dc.b  $00      ;Pad byte
dc.b  $00      ;Pad byte
</pre>
</syntaxhighlight>
 
==Command 9: Write Japanese text==
Same as command 8 but for Japanese characters.
 
Upper-case ASCII (0x20-0x5F) and characters 0x80-0xFE are handled identically to command 8.<br />
Characters 0x00-0x19 are hiragana with diacritic marks.<br />
Characters 0x60-0x7A are katakana with diacritic marks.<br />


==Command 9==
The tiles used for this are all taken from page 0, irrespective of the selected fontset.<br />
Same as command 9 but for japanese characters.
0x00-0x1F map to 0x080-0x09F (upper) and 0x0C0-0x0DF (lower).<br />
0x60-0x7F map to 0x0A0-0x0BF (upper) and 0x0E0-0x0FF (lower).<br />


==Command A==
==Command A: Call sub list==
*3 words
*3 words
Call sub command list. The next longword is a pointer to another command list. Return has to be made using command B.
Call sub command list. The next longword is a pointer to another command list. Return has to be made using command B.
<pre>
<syntaxhighlight>
dc.w  $000A
dc.w  $000A
dc.l  SUBLIST
dc.l  SUBLIST
</pre>
</syntaxhighlight>
'''The call stack seems to be 5 addresses deep.''' Be sure to avoid nesting too many list calls.


==Command B==
==Command B: Return from sub list==
*1 word
*1 word
Return to calling command list.
Return to calling command list.


==Command C==
==Command C: Repeated data output==
*2 words
*2 words
Repeat output. The upper byte of the command is the number of times to output the next word.
Repeat output. The upper byte of the command is the number of times to output the next word.


<pre>
<syntaxhighlight>
dc.w  $090C,$0147  ;Outputs $0147 9 times
dc.w  $090C,$0147  ;Outputs $0147 9 times
</pre>
</syntaxhighlight>


==Command D==
==Command D: Repeat and increment output==
*2 words
*2 words


Repeat and increment output. The upper byte of the command is the number of times to output the next word. The lower byte of the data is incremented each time.
Repeat and increment output. The upper byte of the command is the number of times to output the next word. The lower byte of the data is incremented each time.
<pre>
<syntaxhighlight>
dc.w  $040D,$42FE  ;Outputs $42FE,$42FF,$4200,$4201
dc.w  $040D,$42FE  ;Outputs $42FE,$42FF,$4200,$4201
</pre>
</syntaxhighlight>


=Examples=
=Example code and command lists=
(Slightly modified code from SNK's doc, output gives the above screencap.)


<pre>
<syntaxhighlight>
bset.b  #0,BIOS_MESS_BUSY
bset.b  #0,BIOS_MESS_BUSY
movea.l BIOS_MESS_POINT,a0  ;Get current pointer in buffer
movea.l BIOS_MESS_POINT,a0  ;Get current pointer in buffer
move.l  #0,(a0)+      ;Direct commands
move.l  #0,(a0)+      ;Direct commands
move.w  #3,(a0)+      ;Set VRAM address to $7318
move.w  #3,(a0)+      ;Set VRAM address to $7318
move.w  #$7318,(a0)+
move.w  #$7318,(a0)+
move.w  #$0301,(a0)+  ;Words, size = 1
move.w  #$0301,(a0)+  ;Words, size = 1
move.w  #$0001,(a0)+
move.w  #$0001,(a0)+
move.w  #$0007,(a0)+  ;Output 7
move.w  #$0007,(a0)+  ;Output data
move.w  #0,(a0)+      ;End of this list
move.w  $100000,(a0)+
move.l  MESSAGE1,(a0)+ ;Pointer to list in ROM
move.w  #0,(a0)+      ;End of this list
move.l  a0,BIOS_MESS_POINT  ;Update pointer
move.l  #MESSAGE1,(a0)+ ;Pointer to list in ROM
bclr.b  #0,BIOS_MESS_BUSY  ;Ready to go
move.l  a0,BIOS_MESS_POINT  ;Update pointer
bclr.b  #0,BIOS_MESS_BUSY  ;Ready to go
rts


MESSAGE1:
MESSAGE1:
dc.w  $0001    ;Bytes, upper = $00, end code = $FF
  dc.w  $0001    ;Bytes, upper = $00, end code = $FF
dc.w  $00FF
  dc.w  $00FF
dc.w  $2002    ;Auto-inc = $20
  dc.w  $2002    ;Auto-inc = $20
dc.w  $0003    ;VRAM address = $7024
  dc.w  $0003    ;VRAM address = $7024
dc.w  $7024
  dc.w  $7024
dc.w  $0004    ;Write "MESSAGE1"
  dc.w  $0004    ;Write "MESSAGE1"
dc.l  MS1
  dc.l  MS1
dc.w  $0005    ;Next line
 
dc.w  $0001
  dc.w  $0005    ;Next line
dc.w  $0006    ;Resume, write "MESSAGE2"
  dc.w  $0001
dc.w  $0005    ;Next line
  dc.w  $0006    ;Resume, write "MESSAGE2"
dc.w  $0001
  dc.w  $0005    ;Next line
dc.w  $0007    ;Direct data output
  dc.w  $0001
dc.w 'MESSAGE3'
 
dc.b $FF      ;End code
  dc.w  $0007    ;Direct data output
dc.b $00      ;Pad byte
  dc.b "MESSAGE3"
  dc.w $FF00    ;End code and pad byte
 
  dc.w $0005    ;Next line
  dc.w  $0001


dc.w  $0005    ;Next line
  dc.w  $0108    ;8x16 write, fontset 1
dc.w  $0001
  dc.b "ABCDE",$FF
dc.w  $0108    ;8x16 write, fontset 1
  dc.w  $0005    ;Next line
dc.w 'ABCDE',$FF
  dc.w  $0001
dc.w  $0005    ;Next line
  dc.w  $0109    ;8x16 write, fontset 1
dc.w  $0001
  dc.b 0,1,2,3,4,$FF
dc.w  $0109    ;8x16 write, fontset 1
  dc.w  $0005    ;Next 2 lines
dc.w 0,1,2,3,4,$FF
  dc.w  $0002
dc.w  $000A    ;Sub list calls
  dc.w  $000A    ;Sub list calls
dc.l  SUB_MESS
  dc.l  SUB_MESS
dc.w  $000A
  dc.w  $000A
dc.l  SUB_MESS
  dc.l  SUB_MESS
dc.w  $000A
  dc.w  $000A
dc.l  SUB_MESS
  dc.l  SUB_MESS
dc.w  $0000
  dc.w  $0000


MS1:
MS1:
dc.b "MESSAGE1",$FF
  dc.b "MESSAGE 1",$FF
dc.b "MESSAGE2",$FF
  dc.b "MESSAGE 2",$FF


SUB_MESS:
SUB_MESS:
dc.w  $280C   ;Outputs $0020 $28 times
  dc.w  $090C   ;Outputs $0022 9 times
dc.w  $0020
  dc.w  $0022
dc.w  $100D   ;Outputs $0500 $10 times with inc
  dc.w  $070D   ;Outputs $0042 7 times with inc
dc.w  $0500
  dc.w  $0042
dc.w  $000B    ;Return
  dc.w  $0005    ;Next line
</pre>
  dc.w  $0001
  dc.w  $000B    ;Return
</syntaxhighlight>
 
[[Category:Code]]
[[Category:BIOS calls]]

Latest revision as of 02:03, 3 March 2021

MESS_OUT ($C004CE): Generic VRAM output

MESS_OUT executes the command buffer in the System ROM's work RAM that starts at BIOS_MESS_BUFFER (constant $10FF00) and goes up to BIOS_MESS_POINT (longword variable $10FDBE). This can be used to display text messages, boxes... on the fix layer (is it used for sprites too ?).

MESS_OUT is automatically called in the SYSTEM_INT1 call. BIOS_MESS_BUSY ($10FDC2.b) can be used to prevent this (when setting up the command list, for example).

The command buffer can be made of commands directly, or pointers to lists in ROM or user RAM. To put commands directly into the buffer, a null pointer ($00.l) needs to be placed before the command list.

Commands are always words.

Commands

Command 0: End of command list

1 word: $0000

Command 1: Set data format

2 words:

Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Def 0 Byte/WordEnd code/Data size$01

This command specifies if the data will be in bytes or words, and if the size is defined or if an end code has to be reached.

If data is in bytes (bit 9 = 0)
The next word's upper byte will be the data's constant upper byte (since VRAM can only be written in words).
If the data is limited by an end code (bit 8 = 0), the next word's lower byte will be the end code's value.
If the data size is defined (bit 8 = 1), the next word's lower byte will be the size (so max length is $FF).
If data is in words (bit 9 = 1)
If the data is limited by an end code (bit 8 = 0), the next word will be the end code's value.
If the data size is defined (bit 8 = 1), the next word will be the size (so max length is $FFFF).

Examples:

dc.w  $0001,$15FF  ;Data will be read in bytes, upper byte will always be $15, end code is $FF.
dc.w  $0101,$1520  ;Data will be read in bytes, upper byte will always be $15, data length is $20.
dc.w  $0201,$8000  ;Data will be read in words, end code is $8000.
dc.w  $0301,$2044  ;Data will be read in words, data length is $2044.

The format stays the same until command 1 is used again.

Command 2: Set auto-increment

  • 1 word
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Def Auto-inc value $02

Sets the auto-increment value (written to VRAM_MOD ($3C0004)). Is the value sign-extended or not ?

dc.w  $2002  ;Set auto-inc to $20

Command 3: Set VRAM address

  • 2 words

Sets the VRAM address written to VRAM_ADDR ($3C0000)) to the next word's value.

dc.w  $0003,$7201  ;Set VRAM address to $7201

Command 4: Set data address

  • 3 words

Sets the output data address to the next longword. Actual writes to VRAM are done with this command.

dc.w  $0004
dc.l  MESSAGE

Command 5: Add to current VRAM address

  • 2 words

Add the next word to the current VRAM address. (This is different from command 2). Useful to skip lines or spaces.

dc.w  $0005,$001F  ;Add $1F to the current VRAM address

Command 6: Resume data output

  • 1 word

Resume data output (instead of using command 4 again, keep going from the last address).

Command 7: Directly define output data

  • at least 2 words

Directly define the data (instead of using command 4 to point to it). Don't forget the padding byte if the data ends on an odd address.

dc.w  $0007
dc.b  $30,$31,$34,$45,$FF
dc.b  $00    ;Pad byte

Command 8: Write text with 8x16 font

  • at least 2 words
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Def Upper data byte (fontset number) $08

Writes with the 8*16 pixels fix font. The commands upper byte will be the data's constant upper byte. The next bytes are data, and the end code is $FF.

The auto-inc is automaticaly set to $20.

dc.w  $0108    ;Tileset 1
dc.b  $44,$51  ;Data
dc.b  $FF      ;End code
dc.b  $00      ;Pad byte

Command 9: Write Japanese text

Same as command 8 but for Japanese characters.

Upper-case ASCII (0x20-0x5F) and characters 0x80-0xFE are handled identically to command 8.
Characters 0x00-0x19 are hiragana with diacritic marks.
Characters 0x60-0x7A are katakana with diacritic marks.

The tiles used for this are all taken from page 0, irrespective of the selected fontset.
0x00-0x1F map to 0x080-0x09F (upper) and 0x0C0-0x0DF (lower).
0x60-0x7F map to 0x0A0-0x0BF (upper) and 0x0E0-0x0FF (lower).

Command A: Call sub list

  • 3 words

Call sub command list. The next longword is a pointer to another command list. Return has to be made using command B.

dc.w  $000A
dc.l  SUBLIST

The call stack seems to be 5 addresses deep. Be sure to avoid nesting too many list calls.

Command B: Return from sub list

  • 1 word

Return to calling command list.

Command C: Repeated data output

  • 2 words

Repeat output. The upper byte of the command is the number of times to output the next word.

dc.w  $090C,$0147  ;Outputs $0147 9 times

Command D: Repeat and increment output

  • 2 words

Repeat and increment output. The upper byte of the command is the number of times to output the next word. The lower byte of the data is incremented each time.

dc.w  $040D,$42FE  ;Outputs $42FE,$42FF,$4200,$4201

Example code and command lists

(Slightly modified code from SNK's doc, output gives the above screencap.)

 bset.b  #0,BIOS_MESS_BUSY
 movea.l BIOS_MESS_POINT,a0  ;Get current pointer in buffer
 move.l  #0,(a0)+       ;Direct commands
 move.w  #3,(a0)+       ;Set VRAM address to $7318
 move.w  #$7318,(a0)+
 move.w  #$0301,(a0)+   ;Words, size = 1
 move.w  #$0001,(a0)+
 move.w  #$0007,(a0)+   ;Output data
 move.w  $100000,(a0)+
 move.w  #0,(a0)+       ;End of this list
 move.l  #MESSAGE1,(a0)+ ;Pointer to list in ROM
 move.l  a0,BIOS_MESS_POINT  ;Update pointer
 bclr.b  #0,BIOS_MESS_BUSY   ;Ready to go
 rts

MESSAGE1:
  dc.w  $0001    ;Bytes, upper = $00, end code = $FF
  dc.w  $00FF
  dc.w  $2002    ;Auto-inc = $20
  dc.w  $0003    ;VRAM address = $7024
  dc.w  $7024
  dc.w  $0004    ;Write "MESSAGE1"
  dc.l  MS1

  dc.w  $0005    ;Next line
  dc.w  $0001
  dc.w  $0006    ;Resume, write "MESSAGE2"
  dc.w  $0005    ;Next line
  dc.w  $0001

  dc.w  $0007    ;Direct data output
  dc.b  "MESSAGE3"
  dc.w  $FF00    ;End code and pad byte

  dc.w  $0005    ;Next line
  dc.w  $0001

  dc.w  $0108    ;8x16 write, fontset 1
  dc.b  "ABCDE",$FF
  dc.w  $0005    ;Next line
  dc.w  $0001
  dc.w  $0109    ;8x16 write, fontset 1
  dc.b  0,1,2,3,4,$FF
  dc.w  $0005    ;Next 2 lines
  dc.w  $0002
  dc.w  $000A    ;Sub list calls
  dc.l  SUB_MESS
  dc.w  $000A
  dc.l  SUB_MESS
  dc.w  $000A
  dc.l  SUB_MESS
  dc.w  $0000

MS1:
  dc.b "MESSAGE 1",$FF
  dc.b "MESSAGE 2",$FF

SUB_MESS:
  dc.w  $090C    ;Outputs $0022 9 times
  dc.w  $0022
  dc.w  $070D    ;Outputs $0042 7 times with inc
  dc.w  $0042
  dc.w  $0005    ;Next line
  dc.w  $0001
  dc.w  $000B    ;Return