aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile10
-rw-r--r--src/casm.c117
-rw-r--r--src/example/Makefile5
-rw-r--r--src/example/snes.asm127
-rw-r--r--src/output.c8
-rw-r--r--src/output.h1
-rw-r--r--src/snesout.c295
-rw-r--r--src/snesout.h56
8 files changed, 575 insertions, 44 deletions
diff --git a/src/Makefile b/src/Makefile
index 4f7ec33..af7befa 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -45,7 +45,8 @@ SOURCE = casm.c \
specout.c \
t64out.c \
zx81out.c \
- gbout.c
+ gbout.c \
+ snesout.c
OBJECTS = casm.o \
expr.o \
@@ -68,7 +69,8 @@ OBJECTS = casm.o \
specout.o \
t64out.o \
zx81out.o \
- gbout.o
+ gbout.o \
+ snesout.o
$(TARGET): $(OBJECTS)
$(CC) $(CLAGS) -o $(TARGET) $(OBJECTS)
@@ -83,7 +85,7 @@ clean:
alias.o: alias.c global.h basetype.h util.h state.h alias.h
casm.o: casm.c global.h basetype.h util.h state.h expr.h label.h macro.h \
cmd.h parse.h codepage.h stack.h listing.h alias.h output.h rawout.h \
- specout.h t64out.h zx81out.h gbout.h z80.h 6502.h gbcpu.h
+ specout.h t64out.h zx81out.h gbout.h z80.h 6502.h gbcpu.h 65c816.h
codepage.o: codepage.c global.h basetype.h util.h state.h codepage.h \
parse.h cmd.h
expr.o: expr.c global.h basetype.h util.h state.h expr.h label.h
@@ -103,6 +105,8 @@ parse.o: parse.c global.h basetype.h util.h state.h codepage.h parse.h \
cmd.h
rawout.o: rawout.c global.h basetype.h util.h state.h rawout.h parse.h \
cmd.h
+snesout.o: snesout.c global.h basetype.h util.h state.h expr.h codepage.h \
+ parse.h cmd.h snesout.h
specout.o: specout.c global.h basetype.h util.h state.h specout.h parse.h \
cmd.h
stack.o: stack.c global.h basetype.h util.h state.h stack.h
diff --git a/src/casm.c b/src/casm.c
index 2643a02..fb50532 100644
--- a/src/casm.c
+++ b/src/casm.c
@@ -86,6 +86,16 @@ typedef struct
} CPU;
+/* Defines a static value table handler
+*/
+typedef struct
+{
+ const ValueTable *table;
+ CommandStatus (*handler)(int o, int ac, char *av[],
+ int q[], char *e, size_t es);
+} ValTableHandler;
+
+
/* ---------------------------------------- GLOBALS
*/
static const CPU cpu_table[]=
@@ -123,6 +133,10 @@ static const CPU cpu_table[]=
static const CPU *cpu = cpu_table;
+static ValTableHandler *valtable_handler;
+static int valtable_count;
+
+
/* ---------------------------------------- PROTOS
*/
static void CheckLimits(void);
@@ -133,6 +147,45 @@ static void RunPass(const char *name, FILE *, int depth);
static void ProduceOutput(void);
+/* ---------------------------------------- STATIC VALUE TABLE HANDLING
+*/
+static void PushValTableHandler(const ValueTable *t,
+ CommandStatus (*h)(int o, int ac, char *av[],
+ int q[], char *e, size_t es))
+{
+ if (t)
+ {
+ valtable_handler = Realloc(valtable_handler,
+ (sizeof *valtable_handler) *
+ (++valtable_count));
+
+ valtable_handler[valtable_count - 1].table = t;
+ valtable_handler[valtable_count - 1].handler = h;
+ }
+}
+
+
+static CommandStatus CheckValTableHandlers(const char *opt, int ac,
+ char *args[], int q[],
+ char *err, size_t errsize)
+{
+ const ValueTable *entry;
+ int f;
+
+ for(f = 0; f < valtable_count; f++)
+ {
+ if ((entry = ParseTable(opt, valtable_handler[f].table)))
+ {
+ return valtable_handler[f].handler
+ (entry->value, ac, args, q, err, errsize);
+ }
+ }
+
+ return CMD_NOT_KNOWN;
+}
+
+
+
/* ---------------------------------------- INTERNAL COMMAND HANDLING
*/
@@ -384,6 +437,7 @@ static CommandStatus OPTION(const char *label, int argc, char *argv[],
char **args;
int ac;
char *opt;
+ CommandStatus status = CMD_NOT_KNOWN;
if (*argv[1] == '+' || *argv[1] == '-')
{
@@ -412,51 +466,25 @@ static CommandStatus OPTION(const char *label, int argc, char *argv[],
opt = argv[1];
}
- /* TODO: There should be someway to make this better
- */
- if ((entry = ParseTable(opt, ListOptions())))
- {
- return ListSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, MacroOptions())))
- {
- return MacroSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, CodepageOptions())))
- {
- return CodepageSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, OutputOptions())))
- {
- return OutputSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, RawOutputOptions())))
- {
- return RawOutputSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, SpecTAPOutputOptions())))
- {
- return SpecTAPOutputSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, T64OutputOptions())))
- {
- return T64OutputSetOption(entry->value, ac, args, q, err, errsize);
- }
- else if ((entry = ParseTable(opt, ZX81OutputOptions())))
+ status = CheckValTableHandlers(opt, ac, args, q, err, errsize);
+
+ if (status == CMD_NOT_KNOWN)
{
- return ZX81OutputSetOption(entry->value, ac, args, q, err, errsize);
+ if ((entry = ParseTable(opt, cpu->options())))
+ {
+ status = cpu->set_option(entry->value, ac, args, q, err, errsize);
+ }
}
- else if ((entry = ParseTable(opt, GBOutputOptions())))
+
+ if (status == CMD_NOT_KNOWN)
{
- return GBOutputSetOption(entry->value, ac, args, q, err, errsize);
+ snprintf(err, errsize, "%s: unknown option %s", argv[0], opt);
+ return CMD_FAILED;
}
- else if ((entry = ParseTable(opt, cpu->options())))
+ else
{
- return cpu->set_option(entry->value, ac, args, q, err, errsize);
+ return status;
}
-
- snprintf(err, errsize, "%s: unknown option %s", argv[0], opt);
- return CMD_FAILED;
}
@@ -576,6 +604,17 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
+ PushValTableHandler(ListOptions(), ListSetOption);
+ PushValTableHandler(MacroOptions(), MacroSetOption);
+ PushValTableHandler(CodepageOptions(), CodepageSetOption);
+ PushValTableHandler(OutputOptions(), OutputSetOption);
+ PushValTableHandler(RawOutputOptions(), RawOutputSetOption);
+ PushValTableHandler(SpecTAPOutputOptions(), SpecTAPOutputSetOption);
+ PushValTableHandler(T64OutputOptions(), T64OutputSetOption);
+ PushValTableHandler(ZX81OutputOptions(), ZX81OutputSetOption);
+ PushValTableHandler(GBOutputOptions(), GBOutputSetOption);
+ PushValTableHandler(SNESOutputOptions(), SNESOutputSetOption);
+
ClearState();
SetPC(0);
diff --git a/src/example/Makefile b/src/example/Makefile
index f83d006..3c57e50 100644
--- a/src/example/Makefile
+++ b/src/example/Makefile
@@ -20,7 +20,7 @@
# Makefile for examples
#
-ALL = spectrum.tap c64.t64 zx81.p gb.gb vcs.bin
+ALL = spectrum.tap c64.t64 zx81.p gb.gb vcs.bin snes.sfc
CASM = ../casm
all: $(ALL) $(CASM)
@@ -45,5 +45,8 @@ gb.gb: gb.asm $(CASM)
vcs.bin: vcs.asm $(CASM)
$(CASM) vcs.asm
+snes.sfc: snes.asm $(CASM)
+ $(CASM) snes.asm
+
clean:
rm -f $(ALL)
diff --git a/src/example/snes.asm b/src/example/snes.asm
new file mode 100644
index 0000000..bea3235
--- /dev/null
+++ b/src/example/snes.asm
@@ -0,0 +1,127 @@
+ processor 65c816
+
+ option output-file,snes.sfc
+ option output-format,snes
+
+ option snes-irq,vbl,handler
+ option snes-irq,irq,handler
+
+ ; Initialise SNES
+ ;
+ org $8000
+
+ sei
+ clc
+ xce
+ ldx #$1fff
+ txs
+
+ sep #$30 ; X,Y,A are 8 bit numbers
+ lda #$8F ; screen off, full brightness
+ sta $2100 ; brightness + screen enable register
+ stz $2101 ; Sprite register (size + address in VRAM)
+ stz $2102 ; Sprite registers (address of sprite memory [OAM])
+ stz $2103 ; "" ""
+ stz $2105 ; Mode 0, = Graphic mode register
+ stz $2106 ; noplanes, no mosaic, = Mosaic register
+ stz $2107 ; Plane 0 map VRAM location
+ stz $2108 ; Plane 1 map VRAM location
+ stz $2109 ; Plane 2 map VRAM location
+ stz $210A ; Plane 3 map VRAM location
+ stz $210B ; Plane 0+1 Tile data location
+ stz $210C ; Plane 2+3 Tile data location
+ stz $210D ; Plane 0 scroll x (first 8 bits)
+ stz $210D ; Plane 0 scroll x (last 3 bits) #$0 - #$07ff
+ lda #$FF ; The top pixel drawn on the screen isn't the top one in the tilemap, it's the one above that.
+ sta $210E ; Plane 0 scroll y (first 8 bits)
+ sta $2110 ; Plane 1 scroll y (first 8 bits)
+ sta $2112 ; Plane 2 scroll y (first 8 bits)
+ sta $2114 ; Plane 3 scroll y (first 8 bits)
+ lda #$07 ; Since this could get quite annoying, it's better to edit the scrolling registers to fix this.
+ sta $210E ; Plane 0 scroll y (last 3 bits) #$0 - #$07ff
+ sta $2110 ; Plane 1 scroll y (last 3 bits) #$0 - #$07ff
+ sta $2112 ; Plane 2 scroll y (last 3 bits) #$0 - #$07ff
+ sta $2114 ; Plane 3 scroll y (last 3 bits) #$0 - #$07ff
+ stz $210F ; Plane 1 scroll x (first 8 bits)
+ stz $210F ; Plane 1 scroll x (last 3 bits) #$0 - #$07ff
+ stz $2111 ; Plane 2 scroll x (first 8 bits)
+ stz $2111 ; Plane 2 scroll x (last 3 bits) #$0 - #$07ff
+ stz $2113 ; Plane 3 scroll x (first 8 bits)
+ stz $2113 ; Plane 3 scroll x (last 3 bits) #$0 - #$07ff
+ lda #$80 ; increase VRAM address after writing to $2119
+ sta $2115 ; VRAM address increment register
+ stz $2116 ; VRAM address low
+ stz $2117 ; VRAM address high
+ stz $211A ; Initial Mode 7 setting register
+ stz $211B ; Mode 7 matrix parameter A register (low)
+ lda #$01
+ sta $211B ; Mode 7 matrix parameter A register (high)
+ stz $211C ; Mode 7 matrix parameter B register (low)
+ stz $211C ; Mode 7 matrix parameter B register (high)
+ stz $211D ; Mode 7 matrix parameter C register (low)
+ stz $211D ; Mode 7 matrix parameter C register (high)
+ stz $211E ; Mode 7 matrix parameter D register (low)
+ sta $211E ; Mode 7 matrix parameter D register (high)
+ stz $211F ; Mode 7 center position X register (low)
+ stz $211F ; Mode 7 center position X register (high)
+ stz $2120 ; Mode 7 center position Y register (low)
+ stz $2120 ; Mode 7 center position Y register (high)
+ stz $2121 ; Color number register ($0-ff)
+ stz $2123 ; BG1 & BG2 Window mask setting register
+ stz $2124 ; BG3 & BG4 Window mask setting register
+ stz $2125 ; OBJ & Color Window mask setting register
+ stz $2126 ; Window 1 left position register
+ stz $2127 ; Window 2 left position register
+ stz $2128 ; Window 3 left position register
+ stz $2129 ; Window 4 left position register
+ stz $212A ; BG1, BG2, BG3, BG4 Window Logic register
+ stz $212B ; OBJ, Color Window Logic Register (or,and,xor,xnor)
+ sta $212C ; Main Screen designation (planes, sprites enable)
+ stz $212D ; Sub Screen designation
+ stz $212E ; Window mask for Main Screen
+ stz $212F ; Window mask for Sub Screen
+ lda #$30
+ sta $2130 ; Color addition & screen addition init setting
+ stz $2131 ; Add/Sub sub designation for screen, sprite, color
+ lda #$E0
+ sta $2132 ; color data for addition/subtraction
+ stz $2133 ; Screen setting (interlace x,y/enable SFX data)
+ stz $4200 ; Enable V-blank, interrupt, Joypad register
+ lda #$FF
+ sta $4201 ; Programmable I/O port
+ stz $4202 ; Multiplicand A
+ stz $4203 ; Multiplier B
+ stz $4204 ; Multiplier C
+ stz $4205 ; Multiplicand C
+ stz $4206 ; Divisor B
+ stz $4207 ; Horizontal Count Timer
+ stz $4208 ; Horizontal Count Timer MSB (most significant bit)
+ stz $4209 ; Vertical Count Timer
+ stz $420A ; Vertical Count Timer MSB
+ stz $420B ; General DMA enable (bits 0-7)
+ stz $420C ; Horizontal DMA (HDMA) enable (bits 0-7)
+ stz $420D ; Access cycle designation (slow/fast rom)
+
+ cli ; Enable interrupts
+
+ ; Set the background color to green.
+ sep #$20 ; Set the A register to 8-bit.
+ lda #%10000000 ; Force VBlank by turning off the screen.
+ sta $2100
+ lda #%11100000 ; Load the low byte of the green color.
+ sta $2122
+ lda #%00000000 ; Load the high byte of the green color.
+ sta $2122
+ lda #%00001111 ; End VBlank, setting brightness to 15 (100%).
+ sta $2100
+
+ ; Loop forever.
+Forever:
+ jmp Forever
+
+
+; IRQ vectors
+;
+
+handler:
+ rti
diff --git a/src/output.c b/src/output.c
index 7d42565..71eb786 100644
--- a/src/output.c
+++ b/src/output.c
@@ -52,7 +52,8 @@ typedef enum
TAP,
T64,
ZX81,
- GAMEBOY
+ GAMEBOY,
+ SNES
} Format;
static char output[4096] = "output";
@@ -67,6 +68,7 @@ static ValueTable format_table[] =
{"t64", T64},
{"zx81", ZX81},
{"gameboy", GAMEBOY},
+ {"snes", SNES},
{NULL}
};
@@ -148,6 +150,10 @@ int OutputCode(void)
return GBOutput(output, output_bank, bank, count,
error, sizeof error);
+ case SNES:
+ return SNESOutput(output, output_bank, bank, count,
+ error, sizeof error);
+
default:
break;
}
diff --git a/src/output.h b/src/output.h
index 1069fed..b894e88 100644
--- a/src/output.h
+++ b/src/output.h
@@ -36,6 +36,7 @@
#include "t64out.h"
#include "zx81out.h"
#include "gbout.h"
+#include "snesout.h"
/* ---------------------------------------- INTERFACES
*/
diff --git a/src/snesout.c b/src/snesout.c
new file mode 100644
index 0000000..1612a6b
--- /dev/null
+++ b/src/snesout.c
@@ -0,0 +1,295 @@
+/*
+
+ casm - Simple, portable assembler
+
+ Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ -------------------------------------------------------------------------
+
+ SNES ROM output handler.
+
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "global.h"
+#include "expr.h"
+#include "codepage.h"
+#include "snesout.h"
+
+
+/* ---------------------------------------- MACROS & TYPES
+*/
+
+enum option_t
+{
+ OPT_ROM_TYPE,
+ OPT_IRQ,
+ OPT_NAME,
+ OPT_START,
+ OPT_RAM_SIZE,
+ OPT_ROM_SIZE,
+};
+
+static const ValueTable option_set[] =
+{
+ {"snes-rom-type", OPT_ROM_TYPE},
+ {"snes-irq", OPT_IRQ},
+ {"snes-name", OPT_NAME},
+ {"snes-start", OPT_START},
+ {"snes-ram-size", OPT_RAM_SIZE},
+ {"snes-rom-size", OPT_ROM_SIZE},
+ {NULL}
+};
+
+typedef enum
+{
+ ROM_LOROM = 0x00,
+ ROM_HIROM = 0x01,
+ ROM_LOROM_FAST = 0x30 | ROM_LOROM,
+ ROM_HIROM_FAST = 0x30 | ROM_HIROM
+} ROM_Type;
+
+static ValueTable rom_table[] =
+{
+ {"lorom", ROM_LOROM},
+ {"hirom", ROM_HIROM},
+ {"lorom-fast", ROM_LOROM_FAST},
+ {"hirom-fast", ROM_HIROM_FAST},
+ {NULL}
+};
+
+typedef enum
+{
+ IRQ_VBLANK,
+ IRQ_IRQ
+} IRQ_Type;
+
+static ValueTable irq_table[] =
+{
+ {"vbl", IRQ_VBLANK},
+ {"irq", IRQ_IRQ},
+ {NULL}
+};
+
+
+static struct
+{
+ ROM_Type rom_type;
+ int irq_vector[2];
+ char name[22];
+ int start;
+ int ram_size;
+ int rom_size;
+} option =
+{
+ ROM_LOROM, {-1, -1}, "NONAME", 0x8000, 0, -1
+};
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+
+static int PokeB(Byte *mem, int addr, Byte b)
+{
+ mem[addr++] = b;
+ return (addr % 0x10000);
+}
+
+
+static int PokeW(Byte *mem, int addr, int w)
+{
+ addr = PokeB(mem, addr, w & 0xff);
+ return PokeB(mem, addr, (w & 0xff00) >> 8);
+}
+
+
+static int PokeS(Byte *mem, int addr, const char *str, int maxlen, char pad)
+{
+ while(*str && maxlen--)
+ {
+ addr = PokeB(mem, addr, CodeFromNative(CP_ASCII, *str++));
+ }
+
+ while(maxlen-- > 0)
+ {
+ addr = PokeB(mem, addr, CodeFromNative(CP_ASCII, pad));
+ }
+
+ return addr;
+}
+
+
+/* ---------------------------------------- INTERFACES
+*/
+const ValueTable *SNESOutputOptions(void)
+{
+ return option_set;
+}
+
+CommandStatus SNESOutputSetOption(int opt, int argc, char *argv[],
+ int quoted[], char *err, size_t errsize)
+{
+ const ValueTable *val;
+ int f;
+
+ CMD_ARGC_CHECK(1);
+
+ switch(opt)
+ {
+ case OPT_ROM_TYPE:
+ CMD_TABLE(argv[0], rom_table, val);
+ option.rom_type = val->value;
+ break;
+
+ case OPT_IRQ:
+ CMD_ARGC_CHECK(2);
+ CMD_TABLE(argv[0], irq_table, val);
+ CMD_EXPR(argv[1], f);
+ option.irq_vector[val->value] = f;
+ break;
+
+ case OPT_NAME:
+ CopyStr(option.name, argv[1], sizeof option.name);
+ break;
+
+ case OPT_START:
+ CMD_EXPR(argv[0], f);
+ option.start = f;
+ break;
+
+ case OPT_ROM_SIZE:
+ CMD_EXPR(argv[0], f);
+ option.rom_size = f;
+ break;
+
+ case OPT_RAM_SIZE:
+ CMD_EXPR(argv[0], f);
+ option.ram_size = f;
+ break;
+
+ default:
+ break;
+ }
+
+ return CMD_OK;
+
+}
+
+int SNESOutput(const char *filename, const char *filename_bank,
+ MemoryBank **bank, int count, char *error, size_t error_size)
+{
+ FILE *fp;
+ Byte *mem;
+ int base;
+ int len;
+ int f;
+
+ /* If the ROM type is LOROM then we assume each bank holds 32Kb. Otherwise
+ each bank is a full 64Kb.
+ */
+ if (option.rom_type == ROM_LOROM || option.rom_type == ROM_LOROM_FAST)
+ {
+ for(f = 0; f < count; f++)
+ {
+ if (bank[f]->min_address_used < 0x8000)
+ {
+ snprintf(error, error_size, "Bank %u uses memory below 0x8000",
+ bank[f]->number);
+ return FALSE;
+ }
+ }
+
+ base = 0x8000;
+ len = 0x8000;
+ }
+ else
+ {
+ base = 0;
+ len = 0x10000;
+ }
+
+ if (!(fp = fopen(filename, "wb")))
+ {
+ snprintf(error, error_size, "Failed to create %s", filename);
+ return FALSE;
+ }
+
+ /* Setup ROM header
+ */
+ mem = bank[0]->memory;
+
+ PokeS(mem, 0xffc0, option.name, 21, ' ');
+
+ PokeB(mem, 0xffd5, option.rom_type);
+
+ PokeW(mem, 0xfffc, option.start);
+
+ if (option.irq_vector[IRQ_VBLANK] != -1)
+ {
+ PokeW(mem, 0xffea, option.irq_vector[IRQ_VBLANK]);
+ PokeW(mem, 0xfffa, option.irq_vector[IRQ_VBLANK]);
+ }
+ else
+ {
+ fprintf(stderr, "WARNING: VBLANK IRQ not set\n");
+ }
+
+ if (option.irq_vector[IRQ_IRQ] != -1)
+ {
+ PokeW(mem, 0xffee, option.irq_vector[IRQ_IRQ]);
+ PokeW(mem, 0xfffe, option.irq_vector[IRQ_IRQ]);
+ }
+
+ /* TODO: What goes in 0xffd6 - ROM type? */
+
+ if (option.rom_size == -1)
+ {
+ if (option.rom_type == ROM_LOROM || option.rom_type == ROM_LOROM_FAST)
+ {
+ PokeB(mem, 0xffd7, count * 32);
+ }
+ else
+ {
+ PokeB(mem, 0xffd7, count * 64);
+ }
+ }
+ else
+ {
+ PokeB(mem, 0xffd7, option.rom_size);
+ }
+
+ PokeB(mem, 0xffd8, option.ram_size);
+
+ /* TODO: Need checksums? */
+
+ /* Output ROM contents
+ */
+ for(f = 0; f < count; f++)
+ {
+ fwrite(bank[f]->memory + base, len, 1, fp);
+ }
+
+ fclose(fp);
+
+ return TRUE;
+}
+
+
+/*
+vim: ai sw=4 ts=8 expandtab
+*/
diff --git a/src/snesout.h b/src/snesout.h
new file mode 100644
index 0000000..ecc4c9e
--- /dev/null
+++ b/src/snesout.h
@@ -0,0 +1,56 @@
+/*
+
+ casm - Simple, portable assembler
+
+ Copyright (C) 2003-2015 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ -------------------------------------------------------------------------
+
+ Gameboy ROM output
+
+*/
+
+#ifndef CASM_SNESOUT_H
+#define CASM_SNESOUT_H
+
+#include "parse.h"
+#include "state.h"
+#include "cmd.h"
+
+/* ---------------------------------------- INTERFACES
+*/
+
+
+/* SNES Output options
+*/
+const ValueTable *SNESOutputOptions(void);
+
+CommandStatus SNESOutputSetOption(int opt, int argc, char *argv[],
+ int quoted[], char *error,
+ size_t error_size);
+
+
+/* SNES ROM output of assembly. Returns TRUE if OK, FALSE for failure.
+*/
+int SNESOutput(const char *filename, const char *filename_bank,
+ MemoryBank **bank, int count,
+ char *error, size_t error_size);
+
+#endif
+
+/*
+vim: ai sw=4 ts=8 expandtab
+*/