# This is a simple example of Sarcasm's syntax.
#
# First, Sarcasm needs to know the layout of your Z80 system's memory.
#
# I use a system with 32K of EEPROM and 32K of SRAM.  This configuration
# can be specified as simply as this:

range rom $0000 $7FFF
range ram $8000 $FFFF

# However, you can specify as many memory ranges as you like, and so I usually
# use these lines instead:

range start $0000 $0037
range int   $0038 $0065
range nmi   $0066 $007F
range code  $0080 $3FFF
range data  $4000 $7FFF
range mem   $8000 $EFFF
range stack $F000 $FFFF

# Memory ranges have two advantages.  The more obvious advantage is that if I
# write code than will not fit in my memory spaces, I'll see an error message.
# The less obvious advantage is that I can randomly switch between these
# sections in my source code, placing memory variables near the code which
# uses them, which drastically improves readability.

# Anyway, to begin writing code, choose the memory range you want that code to
# exist in, switch to that memory range with the 'section' directive, and then
# write your code:

section start
  ld sp $0000
  jp .code.

# The above tells sarcasm to start assembling in the 'start' range.
# It then initalizes the stack pointer, then jumps to the beginning of
# the 'code' section.

# Now we will place some data in the 'data' section.

section data

# The 'bytes' and 'words' statements accept bytes and words respectively.

bytes $0 $01 $002 $0003 4 5 06 0007
words $100 $00302 1284 1798

# Both decimal and hexidecimal numbers are accepted, however, numbers with
# leading zeros are not octal as in other programming languages.  I've never
# in my life felt the need to type an octal number, as the only thing the
# number base has going for it is that it uses fewer than ten digits, and
# I'm just not that obsessed with the number ten, so I use hexidecimal.
# On the other hand, I use leading zeros all the time, as they are useful
# for formatting, and so leading zeros mean nothing in Sarcasm.

# The 'data' statement accepts four types of data, which can be intermixed
# The most common is text strings:

text_strings
data "This is a text string."
data 'This is also a string.'
data 'It isn't a problem if single quoted strings contain apostrophes.'
data ""This double-quoted strings contains a double-quoted string.""

# The trick with the last two examples is that a quotation mark isn't accepted
# as the end of the string unless it is followed by a comma, space, semicolon,
# hash symbol, or the end of the line.  In other words, if the only other way
# Sarcasm could look at it would be to view it as malformed data, then it makes
# a little more sense to just include it in the string and not bitch about it.

# data 'isn't

# You see, no one ever types data like that.  From the moment you see that 't'
# after the single quote, the only logical conclusion is that the string
# contiues and the real closing quotation mark comes later, and so that's how
# Sarcasm looks at it.  If there is another single quote later on, everything
# works out just fine, and if there isn't, then you see an error message about
# an unterminated string.

# The second data type Sarcasm accepts is the byte string.

data !DEAD !BEEF !DECADE !12345678

# That's basically shorthand for this:

bytes $DE $AD $BE $EF $DE $CA $DE $12 $34 $56 $78

# Byte strings can contain any number of bytes, but the number of hexadecimal
# digits must be a multiple of two, two digits for each byte.  The bytes are
# placed into memory in the order they are typed, which is more "big-endian"
# as opposed to the "little-endian" ordering you would get if you tried to
# save time by typing words instead of bytes.

# The remaining two data types the 'data' statement accepts are bytes and
# words.  Each must contain either two or four hexadecimal digits, so that
# Sarcasm knows if they are a byte or a word.  One and three digits aren't
# allowed, in a sort of a "don't you know this isn't the 'bytes' or 'words'
# statement" sort of way.  What can I say?  The 'data' statement is my
# invention and this is how I want it to work.

data $01 $0203 "Four" $0506 !070809

# That results in the same data as this:

bytes $01 $03 $02 $46 $6F $75 $66 $06 $05 $07 $08 $09

# ...or what you might type in old-school assemblers...

# db $01
# dw $0203
# db "Four"
# dw $0506
# db $05, $06, $07

# In other words, the 'data' statement has a lot of rules, but it's damn nice.

# Basic addition and subtraction is possible:

words 1 + 2, 3 + 4 - 5, 6 + -1 - -7, text_strings + $10, .code. - 2

# Note that Sarcasm's 'commas optional' feature applies here as well.

words 1 + 2 3 + 4 - 5 6 + -1 - -7 text_strings + $10 .code. - 2

# Obviously you might want to include commas for readibility, but be warned
# that Sarcasm treats them as spaces, so if you type this...

bytes 1 + 2, - 3, 4 -5

# ...Sarcasm will see this...

bytes 1 + 2  - 3  4 -5

# ...which is effectively this...

bytes 1 + 2 - 3, 4 - 5

# ...which isn't the same thing at all, the problem being the spacing around
# the numbers and symbols:

bytes 3 - 2 # This is obviously subtraction, one byte with value 1.
bytes 3- 2  # This is subtraction only because nothing else makes sense.
bytes 3 -2  # This is two independant bytes with values 3 and -2.
bytes 3-2   # With no spaces on either side, once again it must be subtraction.
bytes -1    # This is obviously a single byte, one byte with value -1.
bytes - 1   # This is nothing minus one.  It's subtraction, but it works out.

# Basically, just don't type things in silly ways and you'll be fine.
# About the only way you can really go wrong is to put spaces after hyphens
# which you intend to negate numbers, which I've never seen anyone do.

# The nice thing about memory ranges is that you can switch between them
# as much as you like:

section code
  ld hl message
  call print_text
section data
  message; data "Wow, this is sweet!" !00

section code
  ld hl [yes]
  call print_text
section data
  yes; data "Yes, it is!" !00

# The result is that the two text strings end up one right after the other
# in the 'data' section, and the two pieces of code end up one right after
# the other in the 'code' section.  This makes it possible to arrange your
# source code how you like it, irregardless of how it has to appear in Z80
# memroy, thereby making it easier to write and maintain since related items
# can be placed near eachother.

section code
  label; jp label

# Note that Sarcasm requires semicolons between labels and code that appears
# after them.  Most other assemblers do not.  In fact, most assemblers use
# semicolons to mark comments, whereas Sarcasm uses semicolons to seperate
# multiple instructions on a line:

section code
  print_text
    ld a [hl]; out $80
    cp $00; ret z
  jr print_text

# Assembly code is a lot easier to read when a small function doesn't span
# several pages, and so semicolons can be used to group instructions which
# work towards the same goal into a single line to improve readability.

# When you're all done, you need to tell Sarcasm what memory you want to
# write into which file, like this:

output "simple.rom" $0000 $7FFF

# This writes the first 32K into a file, which can then be burnt to a ROM chip.
# Note that the data written is what Sarcasm has assembled thus far, and so
# you will usually want this to be at the end of the file, unless you are
# assembling code for a system with multiple paged ROM chips and thus you
# need multiple different ROM files for the same range of memory.

# Now for the topic of namespaces and sub-labels:

namespace one

apple; data "apple in one"
peach; data "peach in one"

namespace two

apple; data "apple in two"
peach; data "peach in two"

# The identical lables are allowed because each is in a seperate namespace.

# When you use a label, the current namespace is used if one is not specified:

namespace one
  ld hl apple         # loads address of "apple in one"
  ld hl one.apple     # loads address of "apple in one"
  ld hl two.apple     # loads address of "apple in two"

# However, to complicate things further, there are also sub-labels:

namespace three
  apple
    .skin; data "apple.skin in three"
    .core; data "apple.core in three"
  pear
    .skin; data "pear.skin in three"
    .core; data "pear.core in three"

# Sub labels can only be accessed in short form until a new label is declared.

    ld hl .skin       # loads address of "pear.skin in three"
    ld hl .core       # loads address of "pear.core in three"

  orange
    .skin; data "orange.skin in three"

# Once you declare a new label, you need to specify sub-labels as such:

    ld hl apple.skin  # loads address of "apple.skin in three"

# ...or if you are in a different namespace...

namespace four

  ld hl three.apple.skin    # loads address of "apple.skin in three"

# So you might ask, what if you have this:

namespace xxx
  yyy; data "xxx.yyy"
    .zzz; data "xxx.yyy.zzz"

namespace whatever
  xxx; data "whatever.xxx"
    .yyy; data "whatever.xxx.yyy"

# ...and then you do something like this...

  ld hl xxx.yyy       # Is that 'yyy' in the 'xxx' namespace, or
                      # is it 'xxx.yyy' in the 'whatever' namespace?

# Well, the answer is that it is "whatever.xxx.yyy" so long as you are in the
# 'whatever' namespace, but if you are elsewhere, then it is "xxx.yyy"

# I think that covers everything, except for the "goto" statement:

goto $4000

# It just changes Sarcasm's "instruction pointer" or whatever you want to call
# it for the currently active section, in case you should want to overwrite
# code or to place certain code at a certain address.

