503 lines
9.0 KiB
Markdown
503 lines
9.0 KiB
Markdown
## 0x80 Play Beep
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 0
|
|
|
|
Vars used:
|
|
|
|
Byte_0493
|
|
|
|
Play's an audible beep on the Square 1 channel.
|
|
|
|
## 0x81 Halt
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 0
|
|
|
|
Vars used:
|
|
N/A
|
|
|
|
Infinite loop that does not return.
|
|
|
|
## 0x82 Tape NMI Shenanigans
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 0
|
|
|
|
Vars:
|
|
|
|
Byte_E0_TapeCtrl_Cache
|
|
Byte_EE
|
|
Byte_F2
|
|
|
|
Byte_0740
|
|
Byte_07EF
|
|
Byte_07F3
|
|
|
|
JSRs:
|
|
|
|
L2706_SetupNMI_ED00_LongJump
|
|
L2721_TurnOnNMI_LongJump
|
|
L2724_TurnOffNMI_LongJump
|
|
L2742
|
|
|
|
|
|
## 0x83 Tape Wait
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 0
|
|
|
|
Vars:
|
|
|
|
Byte_0740
|
|
|
|
JMPs to `L1329_WaitOn_EE`
|
|
|
|
## 0x84 Jump
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 1 Word
|
|
|
|
Vars:
|
|
|
|
Code_Pointer
|
|
Argument_A
|
|
|
|
Updates the script pointer to the inline address and continues script execution
|
|
from the new address.
|
|
|
|
## 0x85 Call
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 1 Word
|
|
|
|
Vars:
|
|
|
|
Code_Pointer
|
|
Argument_A
|
|
Stack_Pointer
|
|
|
|
Pushes return address to the stack and performs a Jump to the inline script
|
|
address.
|
|
|
|
## 0x86 Return
|
|
|
|
Stack Arguments: 0 (1 Word, implied)
|
|
Inline Arguments: 0
|
|
|
|
Vars:
|
|
|
|
Stack_Pointer
|
|
Code_Pointer
|
|
|
|
Remove a script address from the stack and update the `Code_Pointer` to it
|
|
before continuing execution.
|
|
|
|
## 0x87 Loop
|
|
|
|
Stack Arguments: 0 (4 implied)
|
|
Inline Arguments: 0
|
|
|
|
Args manually pulled from stack:
|
|
|
|
- Limit
|
|
- Increment
|
|
- LoopVar
|
|
- LoopEntry
|
|
|
|
ArgA `Stack_Pointer-6`
|
|
ArgB `(ArgD)`
|
|
ArgC `Stack_Pointer-2`
|
|
ArgD `Stack_Pointer-4`
|
|
ArgE `ArgA+1`
|
|
|
|
Vars:
|
|
|
|
Argument_A
|
|
Argument_B
|
|
Argument_C
|
|
Argument_D
|
|
Argument_E
|
|
Stack_Pointer
|
|
|
|
JSRs:
|
|
|
|
Handler_CB_Sum
|
|
Handler_C7_LessThan
|
|
|
|
JMPs to `L49CD_LessThan`
|
|
|
|
## 0x88 Play Sound
|
|
|
|
Stack Arguments: 32 bytes (string copied to `$0700`)
|
|
Inline Arguments: 0
|
|
|
|
Plays a short SFX defined by a string.
|
|
|
|
Vars:
|
|
|
|
Pointer_A0
|
|
Pointer_A2
|
|
|
|
Byte_0494
|
|
Byte_0495
|
|
Byte_0496
|
|
Byte_0497
|
|
Byte_0498
|
|
Byte_0499
|
|
Byte_04AC_AudioState
|
|
Byte_04AD
|
|
|
|
Vars inside `L5C18_CopyPtrA0PtrA2`:
|
|
|
|
Byte_0490_PtrA0Len
|
|
|
|
Vars inside `L5A6F_DecodeAudioString_EntryPoint`:
|
|
|
|
Pointer_A2
|
|
Byte_04AC_AudioState
|
|
|
|
Word_049A+0 (current channel ID)
|
|
Word_049A+1 (current channel mask)
|
|
|
|
Byte_0497 Byte_0498 Byte_0499
|
|
enable byte for each channel. RTS if != 1 on entry
|
|
written to with value of Byte_04B3
|
|
|
|
Byte_0494 Byte_0495 Byte_0496
|
|
Pointer_A2 low for channel. looks like it's updated after reading a
|
|
string.
|
|
|
|
Byte_049F Added to note lookup index; used with O stuff?
|
|
Byte_04B1 octave? value from Table_04A6
|
|
Byte_04B2 T value
|
|
Byte_04B3 = Byte_04B1 * Byte_04B2
|
|
|
|
Table_049C Y#
|
|
Table_04A0 V##
|
|
Table_04A3 M#
|
|
Table_04A6 ?? note related. octave? value after letter
|
|
Table_04A9 O#
|
|
Table_04AE T#
|
|
|
|
Table_B391 G??
|
|
|
|
JSRs:
|
|
|
|
L5C08_DataLen_A0
|
|
L5C18_CopyPtrA0PtrA2
|
|
L5CC5_LongDelay
|
|
L5A6F_DecodeAudioString_EntryPoint
|
|
L5A8F_DecodeAudioString (if audio is turned on)
|
|
L5C42 (for weird chars?)
|
|
|
|
Hard-coded addresses:
|
|
|
|
$0700 (Pointer_A0)
|
|
$0420 (Pointer_A2)
|
|
$0441 (Pointer_A2)
|
|
$0462 (Pointer_A2)
|
|
|
|
Copies data currently at `$0700` to three locations (`$0420`, `$0441`, `$0462`)
|
|
|
|
### String format
|
|
|
|
Three channels are encoded in this string, separated by a colon (`:`). The
|
|
string consists of letter and number pairs. The order of the individual pairs
|
|
in the overal string don't seem to matter.
|
|
|
|
M# Loop & Constant volume
|
|
number is 0 or 1.
|
|
|
|
V## Volume
|
|
number between 0 and 15, inclusive
|
|
|
|
Y# Duty
|
|
number between 0 and 3, inclusive
|
|
|
|
T# ?? $4001/$4006?
|
|
number between 1 and 9, inclusive (verify this)
|
|
|
|
O# Note related (timer low/high stuff)
|
|
number between 1 and 6, inclusive
|
|
|
|
A#-G# Notes and octaves?
|
|
number between 0 and 10, inclusive
|
|
|
|
## 0x89
|
|
|
|
Stack Arguments: 3
|
|
Inline Arguments: 0
|
|
|
|
## 0x8A Pop String to Address
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 1 Word
|
|
|
|
Removes 32 bytes from the stack and writes them starting to the inline address.
|
|
|
|
## 0x8B
|
|
|
|
## 0x97
|
|
|
|
Arguments: 2
|
|
|
|
ArgA
|
|
ArgB
|
|
|
|
Vars:
|
|
|
|
Byte_0740
|
|
Byte_44FE
|
|
Byte_4598 = Argument_B+0
|
|
Byte_44FD
|
|
|
|
Argument_A
|
|
Array_44FB+2 ($44FD)
|
|
|
|
JSRs:
|
|
|
|
L5592_CheckForZero
|
|
|
|
Conditionally sets up NMI stuff depending on byte $0740
|
|
If ArgA >= 3, setup some more stuff
|
|
|
|
## 0xA9
|
|
|
|
Arguments: 1
|
|
|
|
ArgA
|
|
|
|
Some sort of nametable restore operation?
|
|
|
|
Writes smaller updates to the nametable for animation purposes.
|
|
|
|
## 0x9D Something Tape (draw screen?)
|
|
|
|
Arguments: 2
|
|
|
|
ArgA -> X
|
|
AgrB
|
|
|
|
Vars:
|
|
|
|
Byte_44FE
|
|
Array_44F8, X
|
|
Array_44CF, X
|
|
Array_457A, X
|
|
|
|
If ArgB != 0
|
|
|
|
ldx ArgA
|
|
|
|
lda #1
|
|
sta Array_44F8, X
|
|
sta Array_44CF, X
|
|
|
|
lda #0
|
|
Array_457A, X
|
|
|
|
else, check for zero from $44F9 through $44FC.
|
|
if non-zero, store #1 into `Byte_FF4E` and return.
|
|
else:
|
|
|
|
ldx ArgA
|
|
lda #1
|
|
sta Array_44F8, X
|
|
lda #0
|
|
sta Byte_44F8
|
|
|
|
Then wait for `Array_44F8, X` to become zero. We're waiting for the IRQ to
|
|
finish writing data from the tape to RAM.
|
|
|
|
After this, jump into opcode `0x9E` after the argument parsing to draw a
|
|
screen.
|
|
|
|
## 0x9E Draw And Show Screen
|
|
|
|
Arguments: 2
|
|
|
|
ArgA
|
|
ArgB
|
|
|
|
If ArgB == 0, clear out a bunch of arguments and call `Handler_DD`. Clears
|
|
`Byte_44FE` afterwards and returns.
|
|
|
|
If ArgB != 0, make sure data has been loaded off the tape and is ready to draw.
|
|
This is done by checking `Word_FF49, X` for a value of 1. If 1, increment it
|
|
and store it in `Byte_44FE` before returning. Continue otherwise.
|
|
|
|
### Drawing
|
|
|
|
lda #0
|
|
sta Byte_0750
|
|
sta Byte_4579
|
|
sta Byte_457A ("Array_457A")
|
|
|
|
lda ArgA
|
|
sta Byte_4C
|
|
|
|
|
|
### Data layout
|
|
|
|
Data in RAM, starting at CPU address $5000
|
|
|
|
$5000 Word offset to palette data. Added to #$5004.
|
|
$5002 Word
|
|
$5004 Byte loop counter apparently?? adds #6 to #$5004 this many times in a
|
|
pointer. additional header data?
|
|
|
|
// generic image header data
|
|
$5005 Byte Width (data row len (tile data len))
|
|
$5006 Byte Height (row count (title count))
|
|
Data length = Width*Height (stored in Word_61 and Word_6AFE)
|
|
|
|
$5007 Word data length? offset offset to attr data?
|
|
|
|
$5008 Byte X/Y coords
|
|
$5009 Byte X/Y coords
|
|
|
|
|
|
$500B Data start
|
|
|
|
## 0xBB Push String / Push Data
|
|
|
|
Stack Arguments: 0
|
|
Inline Arguments: 32 bytes max (NULL terminated)
|
|
|
|
Push a NULL terminated string to the stack. This opperation will increment the
|
|
stack pointer by 32 bytes, always. Even if more than 32 bytes are pushed to
|
|
the stack. The code pointer is properly incremented, so long as there is a
|
|
NULL byte within 255 bytes of the start of data.
|
|
|
|
## 0xC1 Jump Switch
|
|
|
|
Stack Arguments: 1
|
|
Inline Arguments: 3+
|
|
|
|
ArgA
|
|
|
|
## 0xC5 Equal
|
|
|
|
If ArgA == ArgB
|
|
push 1 to stack
|
|
If ArgA != ArgB
|
|
push 0 to stack
|
|
|
|
## 0xC6 Not Equal
|
|
|
|
Stack Arguments: 2
|
|
Stack Result: 1
|
|
|
|
If ArgA != ArgB
|
|
push 1 to stack
|
|
If ArgA == ArgB
|
|
push 0 to stack
|
|
|
|
## 0xC7 Less Than
|
|
|
|
If ArgA < ArgB
|
|
push 1 to stack
|
|
If ArgA >= ArgB
|
|
push 0 to stack
|
|
|
|
## 0xC8 Less Than or Equal
|
|
|
|
If ArgA <= ArgB
|
|
push 1 to stack
|
|
If ArgA > ArgB
|
|
push 0 to stack
|
|
|
|
## 0xC9 Greater Than
|
|
|
|
If ArgA > ArgB
|
|
push 1 to stack
|
|
If ArgA <= ArgB
|
|
push 0 to stack
|
|
|
|
## 0xCA Greater Than or Equal To
|
|
|
|
If ArgA >= ArgB
|
|
push 1 to stack
|
|
If ArgA < ArgB
|
|
push 0 to stack
|
|
|
|
## 0xCB Add
|
|
|
|
ArgA = ArgA + ArgB
|
|
|
|
## 0xCC Subtract
|
|
|
|
ArgA = ArgA - ArgB
|
|
|
|
## 0xCD Multiply
|
|
|
|
ArgA-ArgB = ArgA * ArgB
|
|
|
|
## 0xCE Signed Divide
|
|
|
|
ArgA = ArgA / ArgB
|
|
|
|
## 0xCF Negate
|
|
|
|
ArgA = 0 - ArgA
|
|
|
|
## 0xD1 Controller Stuff
|
|
|
|
Stack Arguments: 2
|
|
Inline Arguments: 0
|
|
|
|
Vars:
|
|
|
|
Argument_C+0 = Argument_A+0
|
|
Argument_A = Word_B1 + Argument_B
|
|
Argument_B
|
|
|
|
|
|
# 0xD4 Set Cursor Location
|
|
|
|
Stack Arguments: 3
|
|
|
|
Some sort of setup for 0xFE Draw Rom Character.
|
|
|
|
Byte_0606 = ArgA
|
|
Byte_0604 = ArgB
|
|
Byte_0605 = ArgC
|
|
|
|
## 0xE0 Modulo
|
|
|
|
ArgA = ArgA % ArgB
|
|
|
|
# 0xE7 Draw Metasprite
|
|
|
|
Stack Arguments: 7
|
|
|
|
ArgA sprite ID? (read as byte, but high is used as temp) Some sort of list size or count (header count?)
|
|
This is used as a table lookup into a metasprite pointer table at $6980
|
|
ArgB (byte) X Coord
|
|
ArgC (byte) Y Coord
|
|
ArgD (byte?) Palette override. If positive, bottom two bits are used directly for palette index.
|
|
ArgE (byte) switch of some sort. sets X to $00 if zero, $20 if not zero
|
|
ArgF (byte) Sprite flip. Uses two middle bits of value (`%0001_1000`)
|
|
ArgG (byte) Extra args on HW stack??
|
|
|
|
Header data for metasprites. This location is pointed to by a table at $6980.
|
|
|
|
Width
|
|
Height
|
|
Count
|
|
Palette??
|
|
|
|
There is a table at $0140 that keeps track of sprite allocations. Each byte
|
|
corresponds to a hardware sprite and the value corresponds to a metasprite that
|
|
that hardware sprite is a part of.
|
|
|
|
# 0xFE Draw Rom Character
|
|
|
|
Stack Arguments: 4
|
|
Inline Arguments: 1 Word
|
|
|
|
Observed drawing a 1bpp kanji character taken from the SBX ROM charset.
|
|
Inline word seems to be an ID or index for the character to draw.
|
|
|