Updated 64TASS Client Files

This commit is contained in:
Peter Weingartner 2024-09-14 12:08:21 -04:00
parent 0b0124d883
commit ef473f74ac
33 changed files with 1448 additions and 2585 deletions

30
client-64tass/README.md Normal file
View file

@ -0,0 +1,30 @@
# Foenix Toolbox Function Bindings for the 64TASS Assembler
This folder contains the assembly (*.s) files needed to call into the Foenix Toolbox using 64TASS assembly.
## Foenix Toolbox Assembly ABI
Foenix Toolbox functions are called using the Calypsi "simplecall" calling convention.
1. The first parameter is passed using the accumulator for 8 and 16 bit quantities, and the X register and accumulator for 24 and 32 bit quantities (with the X register holding the most significant bits).
2. Additional parameters are passed on the stack, pushed so that the left-most parameter is at the top of the stack before the call.
3. The return value is passed in the accumulator for 8 and 16 bit values or the X register and accumulator for 24 and 32 bit values.
4. The caller is responsible for removing the parameters from the stack (if any) after the call returns.
5. The Foenix Toolbox will preserve the caller's direct page and data bank registers at the start of the call and restore them just before returning to the caller.
6. All functions are accessed using long calls (`JSL`).
## Files
The files that are included as part of the client bindings are:
* `toolbox.s`: the main include file. This file includes `bindings.s` automatically and also defines the `alloc` and `free` macros that can be used to help manage the stack. NOTE: the `free` macro uses the first two bytes in the caller's direct page as scratch storage to preserve the return value from the function while cleaning up the stack.
* `types.s`: this include file defines some structures to match the data structures used by some of the Toolbox functions.
* `bindings.s`: this include file defines all the function labels as well as labels that may be used to treat the parameters as locations in memory, rather than as values on the stack. This may simplify coding in some cases.
* `genbindings.py`: this Python script is used to generate the `bindings.s` file in the case that Toolbox functions are removed, altered, or added. It uses the files in the Calypsi bindings folder as the source for what functions are present. The general user of the 64TASS client files will probably never use this script.
* `hello.s`: A simple "Hello, world" example. It also demonstrates using the program header for programs to run from RAM, flash, or the cartridge.

867
client-64tass/bindings.s Normal file
View file

@ -0,0 +1,867 @@
;
; extern SYSTEMCALL void sys_exit(short result);
;
; result goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_exit = $000000
;
; extern SYSTEMCALL void sys_int_enable_all();
;
; 0 bytes needed for the stack parameters
;
sys_int_enable_all = $ffe004
;
; extern SYSTEMCALL void sys_int_disable_all();
;
; 0 bytes needed for the stack parameters
;
sys_int_disable_all = $ffe008
;
; extern SYSTEMCALL void sys_int_disable(unsigned short n);
;
; n goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_int_disable = $ffe00c
;
; extern SYSTEMCALL void sys_int_enable(unsigned short n);
;
; n goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_int_enable = $ffe010
;
; extern SYSTEMCALL p_int_handler sys_int_register(unsigned short n, p_int_handler handler);
;
; n goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_int_register = $ffe014
int_register .namespace
.virtual 1,s
handler .dword ? ; pointer to the interrupt handler to register
.endv
;
; extern SYSTEMCALL short sys_int_pending(unsigned short n);
;
; n goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_int_pending = $ffe018
;
; extern SYSTEMCALL void sys_get_info(p_sys_info info);
;
; info goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_get_info = $ffe01c
;
; extern SYSTEMCALL void sys_int_clear(unsigned short n);
;
; n goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_int_clear = $ffe020
;
; extern SYSTEMCALL short sys_chan_read_b(short channel);
;
; channel goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_chan_read_b = $ffe024
;
; extern SYSTEMCALL short sys_chan_read(short channel, unsigned char * buffer, short size);
;
; channel goes in A[15..0]
;
; 6 bytes needed for the stack parameters
;
sys_chan_read = $ffe028
chan_read .namespace
.virtual 1,s
buffer .dword ? ; the buffer into which to copy the channel data
size .word ? ; the size of the buffer.
.endv
;
; extern SYSTEMCALL short sys_chan_readline(short channel, unsigned char * buffer, short size);
;
; channel goes in A[15..0]
;
; 6 bytes needed for the stack parameters
;
sys_chan_readline = $ffe02c
chan_readline .namespace
.virtual 1,s
buffer .dword ? ; the buffer into which to copy the channel data
size .word ? ; the size of the buffer
.endv
;
; extern SYSTEMCALL short sys_chan_write_b(short channel, uint8_t b);
;
; channel goes in A[15..0]
;
; 1 bytes needed for the stack parameters
;
sys_chan_write_b = $ffe030
chan_write_b .namespace
.virtual 1,s
b .byte ? ; the byte to write
.endv
;
; extern SYSTEMCALL short sys_chan_write(short channel, const uint8_t * buffer, short size);
;
; channel goes in A[15..0]
;
; 6 bytes needed for the stack parameters
;
sys_chan_write = $ffe034
chan_write .namespace
.virtual 1,s
buffer .dword ? ;
size .word ? ;
.endv
;
; extern SYSTEMCALL short sys_chan_status(short channel);
;
; channel goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_chan_status = $ffe038
;
; extern SYSTEMCALL short sys_chan_flush(short channel);
;
; channel goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_chan_flush = $ffe03c
;
; extern SYSTEMCALL short sys_chan_seek(short channel, long position, short base);
;
; channel goes in A[15..0]
;
; 6 bytes needed for the stack parameters
;
sys_chan_seek = $ffe040
chan_seek .namespace
.virtual 1,s
position .dword ? ; the position of the cursor
base .word ? ; whether the position is absolute or relative to the current position
.endv
;
; extern SYSTEMCALL short sys_chan_ioctrl(short channel, short command, uint8_t * buffer, short size);
;
; channel goes in A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_chan_ioctrl = $ffe044
chan_ioctrl .namespace
.virtual 1,s
command .word ? ; the number of the command to send
buffer .dword ? ; pointer to bytes of additional data for the command
size .word ? ; the size of the buffer
.endv
;
; extern SYSTEMCALL short sys_chan_open(short dev, const char * path, short mode);
;
; dev goes in A[15..0]
;
; 6 bytes needed for the stack parameters
;
sys_chan_open = $ffe048
chan_open .namespace
.virtual 1,s
path .dword ? ; a "path" describing how the device is to be open
mode .word ? ; s the device to be read, written, both? (0x01 = READ flag, 0x02 = WRITE flag, 0x03 = READ and WRITE)
.endv
;
; extern SYSTEMCALL short sys_chan_close(short chan);
;
; chan goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_chan_close = $ffe04c
;
; extern SYSTEMCALL short sys_chan_swap(short channel1, short channel2);
;
; channel1 goes in A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_chan_swap = $ffe050
chan_swap .namespace
.virtual 1,s
channel2 .word ? ; the ID of the other channel
.endv
;
; extern SYSTEMCALL short sys_chan_device(short channel);
;
; channel goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_chan_device = $ffe054
;
; extern SYSTEMCALL void sys_text_setsizes(short chan);
;
; chan goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_text_setsizes = $000000
;
; extern SYSTEMCALL short sys_bdev_register(p_dev_block device);
;
; device goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_bdev_register = $ffe05c
;
; extern SYSTEMCALL short sys_bdev_read(short dev, long lba, uint8_t * buffer, short size);
;
; dev goes in A[15..0]
;
; 10 bytes needed for the stack parameters
;
sys_bdev_read = $ffe060
bdev_read .namespace
.virtual 1,s
lba .dword ? ; the logical block address of the block to read
buffer .dword ? ; the buffer into which to copy the block data
size .word ? ; the size of the buffer.
.endv
;
; extern SYSTEMCALL short sys_bdev_write(short dev, long lba, const uint8_t * buffer, short size);
;
; dev goes in A[15..0]
;
; 10 bytes needed for the stack parameters
;
sys_bdev_write = $ffe064
bdev_write .namespace
.virtual 1,s
lba .dword ? ; the logical block address of the block to write
buffer .dword ? ; the buffer containing the data to write
size .word ? ; the size of the buffer.
.endv
;
; extern SYSTEMCALL short sys_bdev_status(short dev);
;
; dev goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_bdev_status = $ffe068
;
; extern SYSTEMCALL short sys_bdev_flush(short dev);
;
; dev goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_bdev_flush = $ffe06c
;
; extern SYSTEMCALL short sys_bdev_ioctrl(short dev, short command, uint8_t * buffer, short size);
;
; dev goes in A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_bdev_ioctrl = $ffe070
bdev_ioctrl .namespace
.virtual 1,s
command .word ? ; the number of the command to send
buffer .dword ? ; pointer to bytes of additional data for the command
size .word ? ; the size of the buffer
.endv
;
; extern SYSTEMCALL short sys_fsys_open(const char * path, short mode);
;
; path goes in X[15..0]:A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_fsys_open = $ffe074
fsys_open .namespace
.virtual 1,s
mode .word ? ; the mode (e.g. r/w/create)
.endv
;
; extern SYSTEMCALL short sys_fsys_close(short fd);
;
; fd goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_close = $ffe078
;
; extern SYSTEMCALL short sys_fsys_opendir(const char * path);
;
; path goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_opendir = $ffe07c
;
; extern SYSTEMCALL short sys_fsys_close(short fd);
;
; fd goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_close = $000000
;
; extern SYSTEMCALL short sys_fsys_opendir(const char * path);
;
; path goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_opendir = $000000
;
; extern SYSTEMCALL short sys_fsys_closedir(short dir);
;
; dir goes in A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_closedir = $ffe080
;
; extern SYSTEMCALL short sys_fsys_readdir(short dir, p_file_info file);
;
; dir goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_readdir = $ffe084
fsys_readdir .namespace
.virtual 1,s
file .dword ? ; pointer to the t_file_info structure to fill out.
.endv
;
; extern SYSTEMCALL short sys_fsys_findfirst(const char * path, const char * pattern, p_file_info file);
;
; path goes in X[15..0]:A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_fsys_findfirst = $ffe088
fsys_findfirst .namespace
.virtual 1,s
pattern .dword ? ; the file name pattern to search for
file .dword ? ; pointer to the t_file_info structure to fill out
.endv
;
; extern SYSTEMCALL short sys_fsys_findnext(short dir, p_file_info file);
;
; dir goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_findnext = $ffe08c
fsys_findnext .namespace
.virtual 1,s
file .dword ? ; pointer to the t_file_info structure to fill out
.endv
;
; extern SYSTEMCALL short sys_fsys_get_label(const char * path, char * label);
;
; path goes in X[15..0]:A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_get_label = $ffe090
fsys_get_label .namespace
.virtual 1,s
label .dword ? ; buffer that will hold the label... should be at least 35 bytes
.endv
;
; extern SYSTEMCALL short sys_fsys_set_label(short drive, const char * label);
;
; drive goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_set_label = $ffe094
fsys_set_label .namespace
.virtual 1,s
label .dword ? ; buffer that holds the label
.endv
;
; extern SYSTEMCALL short sys_fsys_mkdir(const char * path);
;
; path goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_mkdir = $ffe098
;
; extern SYSTEMCALL short sys_fsys_delete(const char * path);
;
; path goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_delete = $ffe09c
;
; extern SYSTEMCALL short sys_fsys_rename(const char * old_path, const char * new_path);
;
; old_path goes in X[15..0]:A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_rename = $ffe0a0
fsys_rename .namespace
.virtual 1,s
new_path .dword ? ; the new path for the file
.endv
;
; extern SYSTEMCALL short sys_fsys_set_cwd(const char * path);
;
; path goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_fsys_set_cwd = $ffe0a4
;
; extern SYSTEMCALL short sys_fsys_get_cwd(char * path, short size);
;
; path goes in X[15..0]:A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_fsys_get_cwd = $ffe0a8
fsys_get_cwd .namespace
.virtual 1,s
size .word ? ; the size of the buffer in bytes
.endv
;
; extern SYSTEMCALL short sys_fsys_load(const char * path, uint32_t destination, uint32_t * start);
;
; path goes in X[15..0]:A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_fsys_load = $ffe0ac
fsys_load .namespace
.virtual 1,s
destination .dword ? ; the destination address (0 for use file's address)
start .dword ? ; pointer to the long variable to fill with the starting address
.endv
;
; extern SYSTEMCALL short sys_fsys_register_loader(const char * extension, p_file_loader loader);
;
; extension goes in X[15..0]:A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_register_loader = $ffe0b0
fsys_register_loader.namespace
.virtual 1,s
loader .dword ? ; pointer to the file load routine to add
.endv
;
; extern SYSTEMCALL short sys_fsys_stat(const char * path, p_file_info file);
;
; path goes in X[15..0]:A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_fsys_stat = $ffe0b4
fsys_stat .namespace
.virtual 1,s
file .dword ? ; pointer to a file info record to fill in, if the file is found.
.endv
;
; extern SYSTEMCALL uint32_t sys_mem_get_ramtop();
;
; 0 bytes needed for the stack parameters
;
sys_mem_get_ramtop = $ffe0b8
;
; extern SYSTEMCALL uint32_t sys_mem_reserve(uint32_t bytes);
;
; bytes goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_mem_reserve = $ffe0bc
;
; extern SYSTEMCALL uint32_t sys_time_jiffies();
;
; 0 bytes needed for the stack parameters
;
sys_time_jiffies = $ffe0c0
;
; extern SYSTEMCALL void sys_rtc_set_time(p_time time);
;
; time goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_rtc_set_time = $ffe0c4
;
; extern SYSTEMCALL void sys_rtc_get_time(p_time time);
;
; time goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_rtc_get_time = $ffe0c8
;
; extern SYSTEMCALL uint16_t sys_kbd_scancode();
;
; 0 bytes needed for the stack parameters
;
sys_kbd_scancode = $ffe0cc
;
; extern SYSTEMCALL short sys_kbd_layout(const char * tables);
;
; tables goes in X[15..0]:A[15..0]
;
; 0 bytes needed for the stack parameters
;
sys_kbd_layout = $ffe0d4
;
; extern SYSTEMCALL short sys_proc_run(const char * path, int argc, char * argv[]);
;
; path goes in X[15..0]:A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_proc_run = $ffe0d8
proc_run .namespace
.virtual 1,s
argc .dword ? ; the number of arguments passed
argv .dword ? ; the array of string arguments
.endv
;
; extern SYSTEMCALL short sys_txt_set_mode(short screen, short mode);
;
; screen goes in A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_txt_set_mode = $ffe0e0
txt_set_mode .namespace
.virtual 1,s
mode .word ? ; a bitfield of desired display mode options
.endv
;
; extern SYSTEMCALL void sys_txt_set_xy(short screen, short x, short y);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_set_xy = $ffe0e8
txt_set_xy .namespace
.virtual 1,s
x .word ? ; the column for the cursor
y .word ? ; the row for the cursor
.endv
;
; extern SYSTEMCALL void sys_txt_get_xy(short screen, p_point position);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_get_xy = $ffe0ec
txt_get_xy .namespace
.virtual 1,s
position .dword ? ; pointer to a t_point record to fill out
.endv
;
; extern SYSTEMCALL short sys_txt_get_region(short screen, p_rect region);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_get_region = $ffe0f0
txt_get_region .namespace
.virtual 1,s
region .dword ? ; pointer to a t_rect describing the rectangular region (using character cells for size and size)
.endv
;
; extern SYSTEMCALL short sys_txt_set_region(short screen, p_rect region);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_set_region = $ffe0f4
txt_set_region .namespace
.virtual 1,s
region .dword ? ; pointer to a t_rect describing the rectangular region (using character cells for size and size)
.endv
;
; extern SYSTEMCALL void sys_txt_set_color(short screen, unsigned char foreground, unsigned char background);
;
; screen goes in A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_txt_set_color = $ffe0f8
txt_set_color .namespace
.virtual 1,s
foreground .byte ? ; the Text LUT index of the new current foreground color (0 - 15)
background .byte ? ; the Text LUT index of the new current background color (0 - 15)
.endv
;
; extern SYSTEMCALL void sys_txt_get_color(short screen, unsigned char * foreground, unsigned char * background);
;
; screen goes in A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_txt_get_color = $ffe0fc
txt_get_color .namespace
.virtual 1,s
foreground .dword ? ; the Text LUT index of the new current foreground color (0 - 15)
background .dword ? ; the Text LUT index of the new current background color (0 - 15)
.endv
;
; extern SYSTEMCALL void sys_txt_set_cursor_visible(short screen, short is_visible);
;
; screen goes in A[15..0]
;
; 2 bytes needed for the stack parameters
;
sys_txt_set_cursor_visible = $ffe100
txt_set_cursor_visible.namespace
.virtual 1,s
is_visible .word ? ; TRUE if the cursor should be visible, FALSE (0) otherwise
.endv
;
; extern SYSTEMCALL short sys_txt_set_font(short screen, short width, short height, unsigned char * data);
;
; screen goes in A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_txt_set_font = $ffe104
txt_set_font .namespace
.virtual 1,s
width .word ? ; width of a character in pixels
height .word ? ; of a character in pixels
data .dword ? ; pointer to the raw font data to be loaded
.endv
;
; extern SYSTEMCALL void sys_txt_get_sizes(short screen, p_extent text_size, p_extent pixel_size);
;
; screen goes in A[15..0]
;
; 8 bytes needed for the stack parameters
;
sys_txt_get_sizes = $ffe108
txt_get_sizes .namespace
.virtual 1,s
text_size .dword ? ; the size of the screen in visible characters (may be null)
pixel_size .dword ? ; the size of the screen in pixels (may be null)
.endv
;
; extern SYSTEMCALL void sys_txt_set_border(short screen, short width, short height);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_set_border = $ffe10c
txt_set_border .namespace
.virtual 1,s
width .word ? ; the horizontal size of one side of the border (0 - 32 pixels)
height .word ? ; the vertical size of one side of the border (0 - 32 pixels)
.endv
;
; extern SYSTEMCALL void sys_txt_set_border_color(short screen, unsigned char red, unsigned char green, unsigned char blue);
;
; screen goes in A[15..0]
;
; 3 bytes needed for the stack parameters
;
sys_txt_set_border_color = $ffe110
txt_set_border_color.namespace
.virtual 1,s
red .byte ? ; the red component of the color (0 - 255)
green .byte ? ; the green component of the color (0 - 255)
blue .byte ? ; the blue component of the color (0 - 255)
.endv
;
; extern SYSTEMCALL void sys_txt_put(short screen, char c);
;
; screen goes in A[15..0]
;
; 1 bytes needed for the stack parameters
;
sys_txt_put = $ffe114
txt_put .namespace
.virtual 1,s
c .byte ? ; the character to print
.endv
;
; extern SYSTEMCALL void sys_txt_print(short screen, const char * message);
;
; screen goes in A[15..0]
;
; 4 bytes needed for the stack parameters
;
sys_txt_print = $ffe118
txt_print .namespace
.virtual 1,s
message .dword ? ; the ASCII Z string to print
.endv

View file

@ -1,33 +0,0 @@
###
### Generate client bindings for the Toolbox (64TASS version)
###
# with open("toolbox_bindings.s", "w") as output:
table_entry_size = 4
table_address = 0xffe000
syscalls = {}
with open("..\src\C256\syscalls.txt", "r") as input:
for line in input:
# Remove comments
index = line.find("#")
if index == 0:
line = ""
elif index > 0:
line = line[index - 1:]
line = line.strip()
if line != "":
name = "sys_{}".format(line)
syscalls[name] = table_address
table_address += table_entry_size
with open("bindings.s", "w") as output:
output.write(";;;\n;;; Bindings for the Foenix Toolbox public calls\n;;;\n\n")
for name in syscalls.keys():
address = syscalls[name]
output.write("{0} = ${1:06X}\n".format(name, address))

View file

@ -0,0 +1,282 @@
#
# Create the 64tass parameters structures for the Toolbox functions
#
import re
import sys
class FunctionParameter:
def __init__(self):
self._name = "UNKNOWN"
self._position = 0
self._type = ""
self._description = ""
def set_name(self, name):
if name.endswith("[]"):
name = name[0:-2]
self._name = name
def name(self):
return self._name
def set_position(self, position):
self._position = position
def position(self):
return self._position
def set_type(self, type):
self._type = type
def type(self):
return self._type
def set_description(self, description):
self._description = description
def description(self):
return self._description
def print(self):
"""Print a simple version of a parameter"""
print("\tName: {0}, Type: {1}, Comment: {2}".format(self._name, self._type, self._description))
def size(self):
"""Return the size of the parameter in bytes."""
if self.type() == "char" or self.type() == "unsigned char" or self.type() == "uint8_t":
return 1
elif self.type() == "short" or self.type() == "unsigned short" or self.type() == "uint16_t":
return 2
else:
return 4
def emit_asm(self, output):
"""Emit the assembly reference for the parameter."""
size = self.size()
if size == 1:
output.write("{0:<16}.byte ? ; {1}\n".format(self.name(), self.description()))
elif size == 2:
output.write("{0:<16}.word ? ; {1}\n".format(self.name(), self.description()))
else:
output.write("{0:<16}.dword ? ; {1}\n".format(self.name(), self.description()))
def emit_accumulator(self, output):
size = self.size()
if size == 1:
output.write("; {0} goes in A[7..0]\n".format(self.name()))
elif size == 2:
output.write("; {0} goes in A[15..0]\n".format(self.name()))
else:
output.write("; {0} goes in X[15..0]:A[15..0]\n".format(self.name()))
class Function:
def __init__(self):
self._name = "UNKNOWN"
self._brief = ""
self._description = ""
self._type = "void"
self._parameters = []
self._address = 0
self._prototype = ""
def set_name(self, name):
self._name = name
def name(self):
return self._name
def set_prototype(self, prototype):
self._prototype = prototype
def prototype(self):
return self._prototype
def set_brief(self, brief):
self._brief = brief
def brief(self):
return self._brief
def set_description(self, description):
self._description = description
def description(self):
return self._description
def set_type(self, type):
self._type = type
def type(self):
return self._type
def set_address(self, address):
self._address = address
def address(self):
return self._address
def add_parameter(self, param_name, param_type):
"""Add a parameter to the function."""
param = FunctionParameter()
param.set_name(param_name)
param.set_type(param_type)
param.set_position(len(self._parameters))
self._parameters.append(param)
def parameters(self):
return self._parameters
def stack_size(self):
"""Return the number of bytes needed on the stack for the parameters"""
size = 0
if len(self.parameters()) > 1:
for parameter in self.parameters()[1:]:
size = size + parameter.size()
return size
def add_param_comment(self, param_name, param_comment):
"""Add a comment to a parameter"""
for param in self._parameters:
if param._name == param_name:
param.set_description(param_comment)
break
def print(self):
"""Print out a simple description of the function"""
print("Name: {0}, Type: {1}".format(self._name, self._type))
print(self._description)
for parameter in self._parameters:
parameter.print()
print()
def emit_asm(self, output):
"""Emit the assembly reference for the function."""
output.write("\n;\n; {0}\n".format(self.prototype()))
if len(self.parameters()) > 0:
first = self.parameters()[0]
output.write("; \n")
first.emit_accumulator(output)
output.write(";\n")
output.write("; {0} bytes needed for the stack parameters\n;\n".format(self.stack_size()))
output.write("{0} = ${1:06x}\n\n".format(self.name(), self.address()))
if len(self.parameters()) > 1:
m = re.match("sys_(\w+)", self.name())
if m:
short_name = m.group(1)
else:
short_name = self.name()
stack_parameters = self.parameters()[1:]
output.write("{0:<16}.namespace\n".format(short_name))
output.write(" .virtual 1,s\n")
for parameter in stack_parameters:
parameter.emit_asm(output)
output.write(" .endv\n")
comments = []
functions = []
def process_comment(line):
"""Deal with a comment line while we're in the middle of a block comment."""
index = line.index("*")
if index > -1:
comment_line = line[index+1:].strip()
else:
comment_line = line.strip()
if comment_line != "":
comments.append(comment_line)
def process_definition(type, name, parameters, comments, prototype):
"""Deal with a function prototype."""
func = Function()
func.set_name(name)
func.set_type(type)
func.set_prototype(prototype)
is_in_func_comments = True
for param in func_parameters:
m1 = re.match("^\s*(.*)\s(\S+)\s*$", param)
if m1:
param_type = m1.group(1).strip()
param_name = m1.group(2).strip()
func.add_parameter(param_name, param_type)
for comment in comments:
m2 = re.match("@param\s(\w+)\s+(.*)$", comment)
if m2:
param_name = m2.group(1).strip()
param_comment = m2.group(2).strip()
func.add_param_comment(param_name, param_comment)
else:
func._description = func._description + comment
functions.append(func)
#
# Read in the C header file with the extern prototypes and parse all the function names,
# return values, and parameters
#
with open(sys.argv[1], "r") as input:
is_in_comment = False
for line in input.readlines():
line = line.strip()
if line.startswith("/**"):
is_in_comments = True
comments = []
elif line.endswith("*/"):
is_in_comments = False
if is_in_comments and line.startswith("*"):
process_comment(line)
else:
m = re.match("extern\s+SYSTEMCALL\s+(\w+)\s+(\w+)\((.*)\)", line)
if m:
func_type = m.group(1)
func_name = m.group(2)
func_parameters = str.split(m.group(3), ",")
process_definition(func_type, func_name, func_parameters, comments, line)
#
# Read in the Caylpsi Toolbox jumptable assembly file and extract the addresses
#
with open(sys.argv[2], "r") as addresses:
for line in addresses.readlines():
m = re.match("^(\w+):\s+.equlab\s+0x([0-9a-fA-F]+)", line)
if m:
func_name = m.group(1).strip()
func_address = int(m.group(2), 16)
for func in functions:
if func.name() == func_name:
func.set_address(func_address)
break
#
# Create the bindings file with the relevant information
#
with open("bindings.s", "w") as bindings:
for func in functions:
func.emit_asm(bindings)

View file

@ -4,9 +4,20 @@
.cpu "65816"
.include "macros.s"
.include "toolbox.s"
.include "tb_params.s"
setdbr .macro ; Set the B (Data bank) register
pea #((\1) * 256) + (\1)
plb
plb
.databank \1
.endm
setaxl .macro
rep #$30 ; set A&X long
.al
.xl
.endm
* = $10000

View file

@ -1,68 +0,0 @@
; Set 8-bit accumulator
setaxs .macro
SEP #$30 ; set A&X short
.as
.xs
.endm
; Set 16-bit accumulator
setaxl .macro
REP #$30 ; set A&X long
.al
.xl
.endm
; Set 8-bit accumulator
setas .macro
SEP #$20 ; set A short
.as
.endm
; Set 16-bit accumulator
setal .macro
REP #$20 ; set A long
.al
.endm
; Set 8 bit index registers
setxs .macro
SEP #$10 ; set X short
.xs
.endm
; Set 16-bit index registers
setxl .macro
REP #$10 ; set X long
.xl
.endm
; Set the direct page.
; Note: This uses the accumulator and leaves A set to 16 bits.
setdp .macro
PEA #\1 ; set DP to page 0
PLD
.dpage \1
.endm
setdbr .macro ; Set the B (Data bank) register
PEA #((\1) * 256) + (\1)
PLB
PLB
.databank \1
.endm
TRACE .macro message
; PHA
; PHX
; PHY
; PEA #`txt_message
; PEA #<>txt_message
; JSL ITRACE
; BRA continue
; txt_message .null 13,\message
; continue PLY
; PLX
; PLA
.endm

View file

@ -1,124 +0,0 @@
;
; Allocate a number of bytes onto the stack for parameters
;
alloc .macro count
.switch \count
.case 0
.case 2
pea #0 ; 5
.case 4
pea #0 ; 10
pea #0
.case 6
pea #0 ; 15
pea #0
pea #0
.default
sta #0,d
tsc
sec
sbc #\count
tcs
lda #0,d
.endswitch
.endm
;
; Remove a number of bytes from the stack (previously alloc'ed)
;
free .macro count
.switch \count
.case 0
.case 2
ply ; 5
.case 4
ply ; 10
ply
.case 6
ply ; 15
ply
ply
.default
sta #0,d ; 4
tsc ; 2
clc ; 2
adc #\count ; 3
tcs ; 2
lda #0,d ; 4 (17 total)
.endswitch
.endm
tb .namespace
int_register .namespace
.virtual #1,s
handler: .dword ?
.endv
.endn
;
; Channel Parameters
;
chan_read .namespace
.virtual #1,s
size: .word ?
buffer .dword ?
.endv
.endn
chan_readline .namespace
.virtual #1,s
size .word ?
buffer .dword ?
.endv
.endn
chan_write_b .namespace
.virtual #1,s
b: .byte ?
.endv
.endn
chan_write .namespace
.virtual #1,s
buffer .dword ?
size .word ?
.endv
.endn
chan_seek .namespace
.virtual #1,s
base .word ?
position .dword ?
.endv
.endn
chan_ioctrl .namespace
.virtual #1,s
size .word ?
buffer .dword ?
command .word ?
.endv
.endn
chan_open .namespace
.virtual #1,s
mode .word ?
path .dword ?
.endv
.endn
chan_swap .namespace
.virtual #1,s
channel2 .word ?
.endv
.endn
.endn

View file

@ -1,59 +1,69 @@
;;;
;;; Bindings for the Foenix Toolbox public calls
;;; Definitions to connect a 64TASS assembly program to the Foenix Toolbox
;;;
sys_proc_exit = $FFE000
sys_chan_read_b = $FFE004
sys_chan_read = $FFE008
sys_chan_readline = $FFE00C
sys_chan_write_b = $FFE010
sys_chan_write = $FFE014
sys_chan_status = $FFE018
sys_chan_flush = $FFE01C
sys_chan_seek = $FFE020
sys_chan_ioctrl = $FFE024
sys_chan_open = $FFE028
sys_chan_close = $FFE02C
sys_chan_swap = $FFE030
sys_chan_device = $FFE034
sys_bdev_register = $FFE038
sys_bdev_read = $FFE03C
sys_bdev_write = $FFE040
sys_bdev_status = $FFE044
sys_bdev_flush = $FFE048
sys_bdev_ioctrl = $FFE04C
sys_fsys_open = $FFE050
sys_fsys_close = $FFE054
sys_fsys_opendir = $FFE058
sys_fsys_closedir = $FFE05C
sys_fsys_readdir = $FFE060
sys_fsys_findfirst = $FFE064
sys_fsys_findnext = $FFE068
sys_fsys_mkdir = $FFE06C
sys_fsys_delete = $FFE070
sys_fsys_rename = $FFE074
sys_fsys_set_cwd = $FFE078
sys_fsys_get_cwd = $FFE07C
sys_fsys_load = $FFE080
sys_fsys_register_loader = $FFE084
sys_fsys_stat = $FFE088
sys_mem_get_ramtop = $FFE08C
sys_mem_reserve = $FFE090
sys_err_message = $FFE094
sys_proc_run = $FFE098
sys_txt_get_capabilities = $FFE09C
sys_txt_set_mode = $FFE0A0
sys_txt_setsizes = $FFE0A4
sys_txt_set_xy = $FFE0A8
sys_txt_get_xy = $FFE0AC
sys_txt_get_region = $FFE0B0
sys_txt_set_region = $FFE0B4
sys_txt_set_color = $FFE0B8
sys_txt_get_color = $FFE0BC
sys_txt_set_cursor_visible = $FFE0C0
sys_txt_set_font = $FFE0C4
sys_txt_get_sizes = $FFE0C8
sys_txt_set_border = $FFE0CC
sys_txt_set_border_color = $FFE0D0
sys_txt_put = $FFE0D4
sys_txt_print = $FFE0D8
.include "bindings.s"
;
; Allocate space on the stack for parameters (count = number of bytes)
;
; Affects: A
;
alloc .macro count
.switch \count
.case 2
pea #0
.case 4
pea #0
pea #0
.case 6
pea #0
pea #0
pea #0
.default
sta #0,d
tsc
sec
sbc #(\count)
tcs
lda #0,d
.endswitch
.endm
;
; Remove space from the stack previously used for parameters (count = number of bytes)
;
; Affects: Y, #0,D, #1,D
;
free .macro count
.switch \count
.case 2
ply
.case 4
ply
ply
.case 6
ply
ply
ply
.default
sta #0,d
tsc
clc
adc #(\count)
tcs
lda #0,d
.endswitch
.endm

100
client-64tass/types.s Normal file
View file

@ -0,0 +1,100 @@
;;;
;;; Types used by the Foenix Toolbox functions
;;;
tb .namespace
;
; An extent or size of a rectangular area
;
s_extent .struct
width .word ? ; The width of the region
height .word ? ; The height of the region
.ends
;
; A point on a plane
;
s_point .struct
x .word ? ; The column of the point
y .word ? ; The row of the point
.ends
;
; A rectangle on the screen
;
s_rect .struct
origin .dstruct s_point ; The upper-left corner of the rectangle
size .dstruct s_extent ; The size of the rectangle
.ends
;
; A color (BGR)
;
s_color3 .struct
blue .byte ?
green .byte ?
red .byte ?
.ends
;
; A color entry for a color lookup table (BGRA)
;
s_color4 .struct
blue .byte ?
green .byte ?
red .byte ?
alpha .byte ?
.ends
;
; Type to describe the current time
;
s_time .struct
year .word ?
month .word ?
day .word ?
hour .word ?
minute .word ?
second .word ?
is_pm .word ?
is_24hours .word ?
.ends
;
; A description of a screen's capabilities
;
s_txt_capabilities .struct
number .word ? ; The unique ID of the screen
supported_modes .word ? ; The display modes supported on this screen
font_size_count .word ? ; The number of supported font sizes
font_sizes .dword ? ; Pointer to a list of t_extent listing all supported font sizes
resolution_count .word ? ; The number of supported display resolutions
resolutions .dword ? ; Pointer to a list of t_extent listing all supported display resolutions (in pixels)
.ends
;
; Structure to describe the hardware
;
s_sys_info .struct
mcp_version .word ? ; Current version of the MCP kernel
mcp_rev .word ? ; Current revision, or sub-version of the MCP kernel
mcp_build .word ? ; Current vuild # of the MCP kernel
model .word ? ; Code to say what model of machine this is
sub_model .word ? ; 0x00 = PB, 0x01 = LB, 0x02 = CUBE
model_name .dword ? ; Human readable name of the model of the computer
cpu .word ? ; Code to say which CPU is running
cpu_name .dword ? ; Human readable name for the CPU
cpu_clock_khz .dword ? ; Speed of the CPU clock in KHz
fpga_date .dword ? ; YYYYMMDD
fpga_model .word ? ; FPGA model number
fpga_version .word ? ; FPGA version
fpga_subver .word ? ; FPGA sub-version
system_ram_size .dword ? ; The number of bytes of system RAM on the board
has_floppy .byte ? ; TRUE if the board has a floppy drive installed
has_hard_drive .byte ? ; TRUE if the board has a PATA device installed
has_expansion_card .byte ? ; TRUE if an expansion card is installed on the device
has_ethernet .byte ? ; TRUE if an ethernet port is present
screens .word ? ; How many screens are on this computer
.endn

View file

@ -3,6 +3,14 @@
;;;
.public sys_proc_exit
.public sys_int_enable_all
.public sys_int_disable_all
.public sys_int_disable
.public sys_int_enable
.public sys_int_register
.public sys_int_pending
.public sys_get_info
.public sys_int_clear
.public sys_chan_read_b
.public sys_chan_read
.public sys_chan_readline
@ -16,6 +24,7 @@
.public sys_chan_close
.public sys_chan_swap
.public sys_chan_device
.public sys_chan_register
.public sys_bdev_register
.public sys_bdev_read
.public sys_bdev_write
@ -29,6 +38,8 @@
.public sys_fsys_readdir
.public sys_fsys_findfirst
.public sys_fsys_findnext
.public sys_fsys_get_label
.public sys_fsys_set_label
.public sys_fsys_mkdir
.public sys_fsys_delete
.public sys_fsys_rename
@ -39,7 +50,12 @@
.public sys_fsys_stat
.public sys_mem_get_ramtop
.public sys_mem_reserve
.public sys_time_jiffies
.public sys_rtc_set_time
.public sys_rtc_get_time
.public sys_kbd_scancode
.public sys_err_message
.public sys_kbd_layout
.public sys_proc_run
.public sys_txt_get_capabilities
.public sys_txt_set_mode
@ -59,57 +75,73 @@
.public sys_txt_print
sys_proc_exit: .equlab 0xFFE000
sys_chan_read_b: .equlab 0xFFE004
sys_chan_read: .equlab 0xFFE008
sys_chan_readline: .equlab 0xFFE00C
sys_chan_write_b: .equlab 0xFFE010
sys_chan_write: .equlab 0xFFE014
sys_chan_status: .equlab 0xFFE018
sys_chan_flush: .equlab 0xFFE01C
sys_chan_seek: .equlab 0xFFE020
sys_chan_ioctrl: .equlab 0xFFE024
sys_chan_open: .equlab 0xFFE028
sys_chan_close: .equlab 0xFFE02C
sys_chan_swap: .equlab 0xFFE030
sys_chan_device: .equlab 0xFFE034
sys_bdev_register: .equlab 0xFFE038
sys_bdev_read: .equlab 0xFFE03C
sys_bdev_write: .equlab 0xFFE040
sys_bdev_status: .equlab 0xFFE044
sys_bdev_flush: .equlab 0xFFE048
sys_bdev_ioctrl: .equlab 0xFFE04C
sys_fsys_open: .equlab 0xFFE050
sys_fsys_close: .equlab 0xFFE054
sys_fsys_opendir: .equlab 0xFFE058
sys_fsys_closedir: .equlab 0xFFE05C
sys_fsys_readdir: .equlab 0xFFE060
sys_fsys_findfirst: .equlab 0xFFE064
sys_fsys_findnext: .equlab 0xFFE068
sys_fsys_mkdir: .equlab 0xFFE06C
sys_fsys_delete: .equlab 0xFFE070
sys_fsys_rename: .equlab 0xFFE074
sys_fsys_set_cwd: .equlab 0xFFE078
sys_fsys_get_cwd: .equlab 0xFFE07C
sys_fsys_load: .equlab 0xFFE080
sys_fsys_register_loader: .equlab 0xFFE084
sys_fsys_stat: .equlab 0xFFE088
sys_mem_get_ramtop: .equlab 0xFFE08C
sys_mem_reserve: .equlab 0xFFE090
sys_err_message: .equlab 0xFFE094
sys_proc_run: .equlab 0xFFE098
sys_txt_get_capabilities: .equlab 0xFFE09C
sys_txt_set_mode: .equlab 0xFFE0A0
sys_txt_setsizes: .equlab 0xFFE0A4
sys_txt_set_xy: .equlab 0xFFE0A8
sys_txt_get_xy: .equlab 0xFFE0AC
sys_txt_get_region: .equlab 0xFFE0B0
sys_txt_set_region: .equlab 0xFFE0B4
sys_txt_set_color: .equlab 0xFFE0B8
sys_txt_get_color: .equlab 0xFFE0BC
sys_txt_set_cursor_visible: .equlab 0xFFE0C0
sys_txt_set_font: .equlab 0xFFE0C4
sys_txt_get_sizes: .equlab 0xFFE0C8
sys_txt_set_border: .equlab 0xFFE0CC
sys_txt_set_border_color: .equlab 0xFFE0D0
sys_txt_put: .equlab 0xFFE0D4
sys_txt_print: .equlab 0xFFE0D8
sys_int_enable_all: .equlab 0xFFE004
sys_int_disable_all: .equlab 0xFFE008
sys_int_disable: .equlab 0xFFE00C
sys_int_enable: .equlab 0xFFE010
sys_int_register: .equlab 0xFFE014
sys_int_pending: .equlab 0xFFE018
sys_get_info: .equlab 0xFFE01C
sys_int_clear: .equlab 0xFFE020
sys_chan_read_b: .equlab 0xFFE024
sys_chan_read: .equlab 0xFFE028
sys_chan_readline: .equlab 0xFFE02C
sys_chan_write_b: .equlab 0xFFE030
sys_chan_write: .equlab 0xFFE034
sys_chan_status: .equlab 0xFFE038
sys_chan_flush: .equlab 0xFFE03C
sys_chan_seek: .equlab 0xFFE040
sys_chan_ioctrl: .equlab 0xFFE044
sys_chan_open: .equlab 0xFFE048
sys_chan_close: .equlab 0xFFE04C
sys_chan_swap: .equlab 0xFFE050
sys_chan_device: .equlab 0xFFE054
sys_chan_register: .equlab 0xFFE058
sys_bdev_register: .equlab 0xFFE05C
sys_bdev_read: .equlab 0xFFE060
sys_bdev_write: .equlab 0xFFE064
sys_bdev_status: .equlab 0xFFE068
sys_bdev_flush: .equlab 0xFFE06C
sys_bdev_ioctrl: .equlab 0xFFE070
sys_fsys_open: .equlab 0xFFE074
sys_fsys_close: .equlab 0xFFE078
sys_fsys_opendir: .equlab 0xFFE07C
sys_fsys_closedir: .equlab 0xFFE080
sys_fsys_readdir: .equlab 0xFFE084
sys_fsys_findfirst: .equlab 0xFFE088
sys_fsys_findnext: .equlab 0xFFE08C
sys_fsys_get_label: .equlab 0xFFE090
sys_fsys_set_label: .equlab 0xFFE094
sys_fsys_mkdir: .equlab 0xFFE098
sys_fsys_delete: .equlab 0xFFE09C
sys_fsys_rename: .equlab 0xFFE0A0
sys_fsys_set_cwd: .equlab 0xFFE0A4
sys_fsys_get_cwd: .equlab 0xFFE0A8
sys_fsys_load: .equlab 0xFFE0AC
sys_fsys_register_loader: .equlab 0xFFE0B0
sys_fsys_stat: .equlab 0xFFE0B4
sys_mem_get_ramtop: .equlab 0xFFE0B8
sys_mem_reserve: .equlab 0xFFE0BC
sys_time_jiffies: .equlab 0xFFE0C0
sys_rtc_set_time: .equlab 0xFFE0C4
sys_rtc_get_time: .equlab 0xFFE0C8
sys_kbd_scancode: .equlab 0xFFE0CC
sys_err_message: .equlab 0xFFE0D0
sys_kbd_layout: .equlab 0xFFE0D4
sys_proc_run: .equlab 0xFFE0D8
sys_txt_get_capabilities: .equlab 0xFFE0DC
sys_txt_set_mode: .equlab 0xFFE0E0
sys_txt_setsizes: .equlab 0xFFE0E4
sys_txt_set_xy: .equlab 0xFFE0E8
sys_txt_get_xy: .equlab 0xFFE0EC
sys_txt_get_region: .equlab 0xFFE0F0
sys_txt_set_region: .equlab 0xFFE0F4
sys_txt_set_color: .equlab 0xFFE0F8
sys_txt_get_color: .equlab 0xFFE0FC
sys_txt_set_cursor_visible: .equlab 0xFFE100
sys_txt_set_font: .equlab 0xFFE104
sys_txt_get_sizes: .equlab 0xFFE108
sys_txt_set_border: .equlab 0xFFE10C
sys_txt_set_border_color: .equlab 0xFFE110
sys_txt_put: .equlab 0xFFE114
sys_txt_print: .equlab 0xFFE118

View file

@ -9,7 +9,7 @@ table_entry_size = 4
table_address = 0xffe000
syscalls = {}
with open("..\src\C256\syscalls.txt", "r") as input:
with open("..\..\src\C256\syscalls.txt", "r") as input:
for line in input:
# Remove comments
index = line.find("#")
@ -35,4 +35,4 @@ with open("bindings.s", "w") as output:
for name in syscalls.keys():
address = syscalls[name]
output.write("{0}:\t.equlab\t0x{1:06X}\n".format(name, address))
output.write("{0:<30} .equlab 0x{1:06X}\n".format(name + ":", address))

View file

@ -733,7 +733,7 @@ extern SYSTEMCALL void sys_txt_put(short screen, char c);
* Print an ASCII Z string to the screen
*
* @param screen the number of the text device
* @param c the ASCII Z string to print
* @param message the ASCII Z string to print
*/
extern SYSTEMCALL void sys_txt_print(short screen, const char * message);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -1,62 +0,0 @@
#
# Create the 64tass parameters structures for the Toolbox functions
#
import re
class FunctionParameter:
def __init__(self):
self._name = "UNKNOWN"
self._position = 0
self._type = ""
self._description = ""
def set_name(self, name):
self._name = name
def set_position(self, position):
self._position = position
def set_type(self, type):
self._type = type
def set_description(self, description):
self._description = description
class Function:
def __init__(self):
self._name = "UNKNOWN"
self._brief = ""
self._description = ""
self._type = "void"
self._parameters = []
self._address = 0
def set_name(self, name):
self._name = name
def set_brief(self, brief):
self._brief = brief
def set_description(self, description):
self._description = description
def set_type(self, type):
self._type = type
with open("toolbox.h", "r") as input:
for line in input.readlines():
m = re.match("extern\s+SYSTEMCALL\s+(\w+)\s+(\w+)\((.*)\)", line)
if m:
func_type = m.group(1)
func_name = m.group(2)
func_parameters = str.split(m.group(3), ",")
print("Type: {0}, Name: {1}".format(func_type, func_name))
for param in func_parameters:
m2 = re.match("^\s*(.*)\s(\S+)\s*$", param)
if m2:
param_type = m2.group(1).strip()
param_name = m2.group(2).strip()
print("\tName: {0}, Type: {1}".format(param_name, param_type))