It is currently Tue Nov 21, 2017 7:05 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 12 posts ] 
Author Message
PostPosted: Fri May 02, 2014 6:11 pm 
Offline
User avatar

Joined: Mon Nov 06, 2006 9:34 am
Posts: 164
Location: Potsdam, Germany
Hey folks,

I got fed up with having to write header files and ca65's limitations when working with scopes so I created this little tool.
This is what it allows you to do:

File: Module.z
Code:
.segment "CODE"
func1:

.proc func2
   var1: .reszp 1
.endproc

.macro someMacro arg1, arg2
.endmacro

File: main.z
Code:
.use Module

main:
   jsr Module.func1
   
   lda #0
   sta Module.func2.var
   jsr Module.func2
   
   Module.someMacro 1, 2

Code:
> lazy65 Module
> lazy65 main

This will generate ca65-compatible header and source files that you can integrate into your build process. However, a generic build script (lazymake) is also included which can take care of everything for you.
Python 2 is required.

==============
DOWNLOAD
lazy65 V0.1.4 (current) (May 13, 2015)
lazy65 V0.1.3 (May 18, 2014)
lazy65 V0.1.2 (May 11, 2014)
lazy65 V0.1.1 (May 3, 2014)
lazy65 V0.1.0
==============

Planned features
    - python macros (.pymacro)
    - automatic generation of linker config files for common mappers
    - maybe a couple of extra commands that make life easier

The tool is still in a somewhat early stage and currently identifies and replaces symbols in a rather lazy way which may result in cryptic error messages, I'm hoping to fix that in a later version. If you decide to give it a try, please let me know if you encounter any problems. There may be unresolved bugs with certain ca65 commands (.struct?) that need fixing.


Last edited by miau on Thu May 21, 2015 9:26 am, edited 10 times in total.

Top
 Profile  
 
PostPosted: Fri May 02, 2014 7:23 pm 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
I did a kind of hacky thing with macros to scope macros that are a part of a header interface:
viewtopic.php?p=112437#p112437

Not sure if I will keep it, but the idea isn't too messy and it does work, with the only downside being you can't access a variable constant, as in:
myscope::foo .set 1
Since it will be interpreted as a macro call. Also, if there is an error in a macro call you'll get a couple of extra error messages as the errors trace through the macro calls. (You may need higher verbosity setting to see this.)


Top
 Profile  
 
PostPosted: Sat May 03, 2014 4:30 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
Seems cool.

I don't know if I'm in the minority here, but when I installed Python on Windows, it didn't by default associate .py files to run with Python. So just typing "lazymake.py" doesn't work here (I have .py associated with a text editor).

One way to fix that could be to provide lazy65.cmd and lazymake.cmd (for Windows) and lazy65 and lazymake shell scripts (for *nix) in the base directory. Then a simple "lazy65" or "lazymake" could be used to invoke the scripts.

lazy65.cmd and lazymake.cmd could look like this:
Code:
@echo off
python %~dpn0.py %*

Not sure what the *nix counterparts would be. Also need to change LAZY65 in lazymake.py from lazy65.py to lazy65. I think I may have missed some other place where it tries to run lazy65.py, because when I run lazymake, lazy65.py opens in my text editor. :)

Aaaand, not sure if I just messed something up with my changes, but when I run lazymake, it occasionally picks a different compilation order and fails to compile the "basic" example.

Here's a run that failed (didn't compile Graphics before main):
Code:
C:\Users\f\Downloads\lazy65-0.1.0\examples\basic>lazymake
lazy65 -s "src" -o "obj" Global
lazy65 -s "src" -o "obj" Module
lazy65 -s "src" -o "obj" Graphics.Sprite
lazy65 -s "src" -o "obj" Graphics.Tile
lazy65 -s "src" -o "obj" main
Traceback (most recent call last):
  File "C:\Users\f\Downloads\lazy65-0.1.0\lazy65.py", line 92, in <module>
    main()
  File "C:\Users\f\Downloads\lazy65-0.1.0\lazy65.py", line 80, in main
    lines = parser.parse() #2nd pass
  File "C:\Users\f\Downloads\lazy65-0.1.0\src\tempy.py", line 46, in parse
    self.lineCallback()
  File "C:\Users\f\Downloads\lazy65-0.1.0\lazy65.py", line 20, in lineCallback
    asm.parse()
  File "C:\Users\f\Downloads\lazy65-0.1.0\src\Assembler.py", line 185, in parse
    self.command(tok.text)
  File "C:\Users\f\Downloads\lazy65-0.1.0\src\Assembler.py", line 385, in command
    self.importModule(moduleName, scopeName, True, True)
  File "C:\Users\f\Downloads\lazy65-0.1.0\src\Assembler.py", line 115, in importModule
    self.importSingleModule(moduleName, scopeName, generateIncludes)
  File "C:\Users\f\Downloads\lazy65-0.1.0\src\Assembler.py", line 85, in importS
ingleModule
    with open(symfile,'rb') as f:
IOError: [Errno 2] No such file or directory: 'obj/Graphics.sym'
lazymake.py: Error 1

And here's a one that succeeded (I did lazymake clean inbetween):
Code:
C:\Users\f\Downloads\lazy65-0.1.0\examples\basic>lazymake
lazy65 -s "src" -o "obj" Global
lazy65 -s "src" -o "obj" Module
lazy65 -s "src" -o "obj" Graphics.Sprite
lazy65 -s "src" -o "obj" Graphics.Tile
lazy65 -s "src" -o "obj" Graphics
lazy65 -s "src" -o "obj" main
ca65 "obj/Global.s" -o "obj/Global.o"
ca65 "obj/main.s" -o "obj/main.o"
ca65 "obj/Module.s" -o "obj/Module.o"
ca65 "obj/Graphics/Sprite.s" -o "obj/Graphics/Sprite.o"
ca65 "obj/Graphics/Tile.s" -o "obj/Graphics/Tile.o"
ca65 "obj/Graphics.s" -o "obj/Graphics.o"
ld65 -o "basic.nes" -C linker.cfg "obj/Global.o" "obj/main.o" "obj/Module.o" "ob
j/Graphics/Sprite.o" "obj/Graphics/Tile.o" "obj/Graphics.o"
basic.nes: Build complete

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Sat May 03, 2014 1:49 pm 
Offline
User avatar

Joined: Mon Nov 06, 2006 9:34 am
Posts: 164
Location: Potsdam, Germany
Movax12 wrote:
I did a kind of hacky thing with macros to scope macros that are a part of a header interface:
viewtopic.php?p=112437#p112437

Oh, I never checked that topic again. Interesting. A bit of nasty boilerplate code, but still, it goes to show how powerful ca65 really is.

thefox wrote:
lazy65.cmd and lazymake.cmd could look like this...

Thanks, added them!

thefox wrote:
Aaaand, not sure if I just messed something up with my changes, but when I run lazymake, it occasionally picks a different compilation order and fails to compile the "basic" example.

It was most likely a race condition with the multi-threaded compilation going on. Anyway, thanks for your feedback, I added dependency file generation and based the build system around it which will hopefully eliminate these errors.

Updated download link in first post.


Top
 Profile  
 
PostPosted: Sat May 03, 2014 2:12 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
Trivial error on line 85 in Assembler.py:
Code:
C:\Users\f\Downloads\lazy65-011\examples\basic>lazymake
lazy65 --sym-only -s "src" -o "obj" Module
Traceback (most recent call last):
  File "C:\Users\f\Downloads\lazy65-011\lazy65.py", line 8, in <module>
    from src.Assembler import Assembler
  File "C:\Users\f\Downloads\lazy65-011\src\Assembler.py", line 85
    raise tempy.Error('Could not create symbol file for module '+moduleName+')
                                                                             ^
SyntaxError: EOL while scanning string literal
lazymake.py: Error 1


And if you want to add *nix support, this "npm" shell script from node.js may be a good template to base "lazy65" and "lazymake" on:
Code:
#!/bin/sh

basedir=`dirname "$0"`

case `uname` in
    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac

if [ -x "$basedir/node.exe" ]; then
  "$basedir/node.exe" "$basedir/node_modules/npm/bin/npm-cli.js" "$@"
else
  node "$basedir/node_modules/npm/bin/npm-cli.js" "$@"
fi

EDIT: In hindsight, I'm not sure if this script is the same one that ships with the *nix installations of node.js.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Last edited by thefox on Mon May 05, 2014 2:29 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Sat May 03, 2014 2:40 pm 
Offline
User avatar

Joined: Mon Nov 06, 2006 9:34 am
Posts: 164
Location: Potsdam, Germany
Woops, fixed.
Cool. I am going to look into that.


Top
 Profile  
 
PostPosted: Sat May 03, 2014 3:48 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6447
Location: UK (temporarily)
*nix support should just involve having the right #! line in the original python script... and preferably not having ".py" in the command name, which is probably best solved with symlinks.


Top
 Profile  
 
PostPosted: Sat May 03, 2014 4:27 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
lidnariq wrote:
*nix support should just involve having the right #! line in the original python script... and preferably not having ".py" in the command name, which is probably best solved with symlinks.

How do you plan to put a symlink in a zip file?

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Sat May 03, 2014 4:59 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6447
Location: UK (temporarily)
Zip doesn't preserve the executable bit either, so it already requires finessing: zip is poorly suited to unixy things. The options are "accept having .py at your command line", "use a different compressor" (tgz, 7z, rar), or "rename the files to not end with .py"


Top
 Profile  
 
PostPosted: Sat May 03, 2014 5:54 pm 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2981
Location: Tampere, Finland
lidnariq wrote:
Zip doesn't preserve the executable bit either

True.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Sun May 11, 2014 9:21 am 
Offline
User avatar

Joined: Mon Nov 06, 2006 9:34 am
Posts: 164
Location: Potsdam, Germany
Updated. Fixed a couple of bugs and added the custom commands .reszp and .resbss.

This:
Code:
.proc func
    .segment "ZEROPAGE"
        localvar: .res 1
    .segment "CODE"
    rts
.endproc

can now be written like this:
Code:
.proc func
    localvar: .reszp 1
    rts
.endproc

.reszp and .resbss use the ca65 commands .pushseg and .popseg when translated so the segment you are in will be automatically restored.

I also got rid of the .py extensions so now the tools can be called the same way in both Windows and Linux (by just typing "lazy65" or "lazymake").


Top
 Profile  
 
PostPosted: Sun May 11, 2014 12:15 pm 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
I like the res command. I did that too (macros):

Code:
 ; Example of declaring variables using .struct syntax.
        resZP { \
                foo     .byte ,     \
                bar     .word ,     \
                test    .addr 6     \
        }
 
        resBSS { myVar  .byte, yourVar  .addr 4 }
        resBSS  baz     .byte


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group