MaxCoderz

for your 1 bit pleasure!

All times are UTC




Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject:
PostPosted: Fri 05 Oct, 2007 9:44 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
King Harold wrote:
What would happen if you tried to name something "macro"?
The logic is this: if an argument is only one token long (eg "x", "value" or "macro") it is implicitly treated as a "value" argument. If the argument is two tokens long ("value x", "macro value", "macro macro") then the name is the second token and the type is the first token (and can either be "value" or "macro").


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 08 Oct, 2007 10:17 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
I've added a number of bits and pieces; list file exporter plugins, number encoders, data structures and indexing.

For the second half of that statement, here's a real example:

Code:
ComplexNumber: .data ticomplex -234.5, +0.25 ; -234.5+0.25i

/*

This outputs the data:

   8C 82 23 45 00 00 00 00 00
   0C 7F 25 00 00 00 00 00 00

To copy the components to OP1 and OP2 you could
do something like this:

   ld hl,ComplexNumber[1]
   rst rMov9ToOP1
   bcall(_OP1toOP2)
   
   ld hl,ComplexNumber[0]
   rst rMov9ToOP1

*/
Labels now have types associated with them, which gives them a size and so means that you can use an index (inside []) to access element addresses individually.

You can define new structures at runtime with .struct:
Code:
.struct Vector3
   byte X,
   byte Y,
   byte Z

.struct Plane
   Vector3 Normal,
   byte Offset

.struct Edge
   Vector3[2] Ends

.varloc 0, 1024
.var Edge SomeEdge

    ld (SomeEdge[0].X),a

.var Plane SomePlane

    ld a,(SomePlane.Normal.X)


(I've also added a .var directive).


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 08 Oct, 2007 2:03 pm 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
This is so totally insane... I love it! :)

Quote:
if an argument is only one token long (eg "x", "value" or "macro") it is implicitly treated as a "value" argument. If the argument is two tokens long ("value x", "macro value", "macro macro") then the name is the second token and the type is the first token (and can either be "value" or "macro").

Is this really necessary? Can't it "detect" what it is you want? Because usually you'll want the macro style replace with something textual (label, string) and the value with something numeric or a known variable.

This is some seriously extreme preprocessing for a z80 assembler :) I just know people are going to write the most horrific things with this, as well as the most brilliant (and unreadable) things.

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 08 Oct, 2007 2:21 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Timendus wrote:
Is this really necessary? Can't it "detect" what it is you want? Because usually you'll want the macro style replace with something textual (label, string) and the value with something numeric or a known variable.
I don't really like attempting to guess what the user wants. Take the factorial example;

Code:
#function f(n)
   .if n == 0
      f = 1
   .else
      f = n * f(n - 1)
   .endif
#endfunction

val = 10
.echoln f(val)
In that instance you'd really want val to be evaluated and passed as the number "10", even though you're passing in a label. Of course you could force it with f(val+0), but then things start getting messy. :)

I agree that if you pass a string constant ("") it should default to passing-by-macro, so good idea. :)

Quote:
This is some seriously extreme preprocessing for a z80 assembler :)
I'm trying to make it as flexible as possible before a release so that people can write useful extra directives and functions for the assembler. The examples are designed to be very silly and over the top to stress-test the parser and preprocessor. :)

Edit: I should also mention that thus far I haven't implemented the old Brass-style macros (eg .define ld_a({0}) xor a). I don't know how useful they would be, maybe something for the "legacy" plugin collection I'm arranging (see also: .equ).


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue 09 Oct, 2007 10:11 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Hm, next "problem" I need some community guidance on.

The output as generated by the compiler is a large array of OutputData structure, which contains the page number, program counter and array of bytes output at that address (array of bytes thanks to output modifiers - unsquished programs have two bytes of output data per byte written by the compiler).

Now, currently, I sort by page then by program counter then write sequentially, which is clearly "wrong" (think of .relocated blocks).

My current idea is to maintain two variables - program counter and "output counter". The output counter increments with the program counter and is set by directives like .org, but if you write to the $ directly ($ = xyz) or use a directive like .relocate only $ gets modified. This way when sorted things end up (hopefully) in the right order.

Any thoughts?

Bear in mind that "holes" in the source code (ie, non-consecutive output addresses) can be present; in a raw file they'd be ignored, in a hex file each data record has an address anyway (so that's OK). Maybe I need a "padded raw" output writer that pads the data so it sits neatly on pages, and have a page definition directive?

I fixed the parser so indexers and field accessors work properly, so "ld a,(Var[2].Plane[3].Normal.X)" now compiles if you wanted something like that. I also fixed right-associative operators (order of precence is from right-to-left, rather than left-to-right, like x = y = 1).


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Tue 09 Oct, 2007 10:27 am 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
Sounds like it should work, but I'm not really up to speed with all that... So don't take my advice :)

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Wed 10 Oct, 2007 10:15 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Well, it "seems" to work. :) I created a rawpages plugin that outputs the defined pages in their index order, writing X bytes per page where X is the defined size of the page.

As an example, Sega recommend the following SMS memory map for megabit cartridges. There are three "windows" that can be swapped in of 16KB each; they recommend that you use a fixed 32KB in the lower two windows and vary the third window's 16KB page (the final 16KB memory is mapped to RAM).

So, in Brass code;

Code:
.defpage 0, $0000, kb(32)

; Page numbers are offset by one so that I can take the page
; of a label (:label) and output that to $FFFF directly to switch
; to the correct page.
.for p is 1 to 6
    .defpage p + 1, $8000, kb(16)
.loop

.page 0 ; Implicitly sets $ and output counter = 0
    xor a
    ld ($FFFC),a ; RAM control.

    ld ($FFFD),a ; Page 0 = 0
    inc a
    ld ($FFFE),a ; Page 1 = 1
    inc a
    ld ($FFFF),a ; Page 2 = 2

.page 2 ; Implicitly sets $ and output counter = $8000

    ; ...


(KB is a silly function that returns 1024xvalue).

I'm making some parts of the core plugin collection extendable; for example, the SMS requires certain data to be written into the ROM (checksum, TMR SEGA header and so on) as well as SDSC tags (author, description and so on). Thus, a "smsrom" plugin writes the stuff then can hijack the "rawpages" plugin to perform the actual writing to disk.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu 11 Oct, 2007 11:28 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
The help viewer can now export all of the documentation into a single website (including a contents frame). I'll make it zip up the output files so that it can be easily distributed/downloaded.

I've uploaded a copy here if you want to observe some of the documentation as it grows. :)

Brass 3 Plugin Documentation


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Fri 12 Oct, 2007 12:30 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
I wrote some output writer plugins for TI development; ti8x, ti83, ti82, ti85, ti86, ti73.

To take advantage of the better page support, each page is output as a different program variable.

Code:
/* The following would create a group file
containing two programs, PRGMA and PRGMB. */

.page 1
.tivariablename "PRGMA"

.org $9D93
    ret

.page 2
.tivariablename "PRGMB"

.org $9D93
    ret

/* Naturally, you need to be using a TI program
output writing plugin for this to work. */


I have also promoted ":" to an operator in its own right (eg :y is seen as ":" and "y" rather than ":y") which makes macro replacement much easier.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat 13 Oct, 2007 10:18 pm 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
To be entirely honest, I understand only about half the things you say, but what I understand of it sounds great :)

benryves wrote:

Why does that look so much better than my documentation? :mrgreen:
I think I'm going to steal parts of it from you ;)

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Sat 13 Oct, 2007 10:39 pm 
Offline
Extreme Poster
User avatar

Joined: Thu 17 May, 2007 4:49 pm
Posts: 395
Location: $4080
Don't forget to release a "Hello World!" program! :D
(I never got the 'old' brass to properly compile a asm program, I kept using devpac8x for doing .bin->.8xp) :oops:

anyway, wouldn't it it better to make an .endpage directive?

benryves wrote:
I have also promoted ":" to an operator in its own right (eg :y is seen as ":" and "y" rather than ":y") which makes macro replacement much easier.
that's a good idea ;)

What happens when u use .page n when you haven't yet defined that page?

And just to be sure, what output does this generate:
Code:
  x=20
.for t is 0 to x
  .db t
  x=x-1
  t=t*2
.loop


EDIT:
is this valid?
Code:
.module x
  y=255
.endmodule
.module x
  z=y
.endmodule
;Now should x.y=x.z=255


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 15 Oct, 2007 10:00 am 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
driesguldolf wrote:
Don't forget to release a "Hello World!" program! :D
(I never got the 'old' brass to properly compile a asm program, I kept using devpac8x for doing .bin->.8xp) :oops:
Hm, putting .binarymode TI8X \ .variablename "PRGMNAME" should be enough to turn a .bin->.8xp.

Quote:
anyway, wouldn't it it better to make an .endpage directive?
I'm not sure what advantage that would have..?

Quote:
What happens when u use .page n when you haven't yet defined that page?
The page number will be set (:$ = <page>) and the output and program counters will be set to zero.

As for what will be output, it depends on the output writer. The raw writer will just spit out a binary of all pages, Intel HEX will also emit a correct object file, but the rawpages directive requires that all pages be defined so it knows how to format each page. In the case of undefined pages it displays a warning that it found data on page X, but page X wasn't defined so it doesn't appear in the output.

Quote:
And just to be sure, what output does this generate:
Code:
  x=20
.for t is 0 to x
  .db t
  x=x-1
  t=t*2
.loop
0, 1, 3, 7, 15.

Quote:
EDIT:
is this valid?
Code:
.module x
  y=255 ; <-
.endmodule
.module x
  z=y
.endmodule
;Now should x.y=x.z=255
Yes. :) The logic is that the current module name is appended to all newly created labels (so, on the line y=255 it sees "y, hmm, don't know what that is, so I'll create a new label called "x.y").

As for label resolution, the compiler starts by searching the current module for a match; if none is found it moves up a module and searches again, moving up until it reaches the "global" label scope.

Timendus wrote:
Why does that look so much better than my documentation? :mrgreen:
I think I'm going to steal parts of it from you ;)
Probably because I got the MSDN team to design it for me. :pirate: (Sorry about the awful CSS/HTML, it was chucked together quickly).


---

The silly parser in Brass 1 would strip out all whitespace first of arguments (unless it was detected inside a string) and work on that.

A side-effect of that was that the following source would assemble:

Code:
 ld h l, 1 23 ; Assembles as ld hl,123


This could actually be quite useful in some instances where you, say, wanted to pass a register pair to a function like this:

Code:
.deflong some_function(regh, regl)
   inc regh regl
.enddeflong

some_function(h,l)


Brass 3 has a much stricter (and more complex) parser, so the above simply wouldn't work. This results in a missing feature, which we can't have..!

I'm trying to avoid writing parser hacks. Another parser hack in Brass 1 was the replacement of [%var%] with the environment variable "var". As a compatibility hack I wrote a plugin that registers a bunch of macros to replace "[%var%]" with the contents of var (as [%var%] is five tokens - [, %, var, %, and ] - I can only replace the single token "[%var%]") but this doesn't help in the situations where you need to pass in a numeric value. To get around this I cobbled together an eval() function that evaluates whatever is in the argument and returns a numeric value. Thus;

Code:
; Brass 1 code:
.db "[%project_name%]"       ; debug_name is a string.
DebugLevel = [%debug_level%] ; debug_level is a number.

; Brass 3 code:
.db "[%project_name%]"               ; no change required :)
DebugLevel = eval("[%debug_level%]") ; evaluate to convert string->number.


How does this help with the above regh/regl feature? Well, why not beat around the bush and make labels capable of handling string values or numbers? Proper string handling helps in a lot of places, after all. Thus;

Code:
.function some_function(regh, regl)
   eval("inc " + regh + regl)
.endfunction

some_function("h", "l")


Some of the operators have been modified to change their behaviour if either of the arguments are passed as strings. + or & will concatenate strings if either operand is a string (as will their assignment versions += and &=); = assigns strings; ==/!=/>/>=/</<= compare string values. If either value is passed as a string then the string operator takes over; you can force conversion to a number by multiplying by 1 (returns the current encoding version) or by using eval() (parses as a number). Thus;

Code:
x = "1"
y = x       ; y = string "1".
y = x + 0   ; y = string "10".
y = x * 1   ; y = number 49 (ASCII '1').
y = eval(x) ; y = number 1.


To complement the new string support are a bunch of string manipulation functions.

Code:
.function rev(s)
    rev = ""
    .for i = 1, i <= strlength(s), ++i
        rev += strsub(s, -i, 1)
    .loop
.endfunction

; Displays "Hello!"
.echoln rev("!olleH")


I've also thrown together some Brass 1 compatible directives - from the simple .asc (just registers a macro that replaces .asc with .db) to a string encoder that mimics the behaviour of .asciimap.

Latenite 1 compatibility is going to be fairly important. Brass 3 is quite different, but has been developed in such a way that for the most part it will integrate with Latenite 1 as well as Brass 1 currently does.

The current compilation process is to set a bunch of environment variables then invoke a compile command file (.cmd), which in turn runs Brass with a shedload of command-line arguments.

Brass 3 just takes one command-line argument - a project filename. Thus, the workaround is to do this;

  • Delete/move/rename existing Brass.exe in "Compile" directory.
  • Create a "Brass3" directory inside "Compile".
  • Copy new Brass.exe, plugins to Compile\Brass3
  • Copy CreateBrassProj.exe and CreateBrassProj.proj to Compile\Brass3.
  • Create Compile\Brass.cmd that invokes CreateBrassProj.exe and Brass.exe.

Code:
"%COMPILE_DIR%\Brass3\CreateBrassProj.exe" Latenite.brassproj %1 %2 %3 %4 %5 %6 %7 %8 %9
"%COMPILE_DIR%\Brass3\Brass.exe" Latenite.brassproj > Nul


CreateBrassProj is a combination of a Brass 3 project file and Brass 1 command-line argument processor. It loads its project file, parses the command-line arguments then spits out a new project file that causes Brass 3 to simulate most of what Brass 1 would have done (including loading list file generators to emit the Errors.xml and Debug.xml, which are part of the "Legacy.dll" plugin collection).

In brief; all you will hopefully have to do to get Brass 3 support in Latenite 1 is to copy a few files over and delete the old Brass.exe.

To further enhance compatibility, the Help viewer can output Latenite help files (.xml), resulting in highlighted Brass 3 directives and functions.

[url=http://benryves.com/bin/brass3/latenite.png]Image
Click for big.[/url]

For some more examples ("further reading"): eval(), year(), freadtext(), strtoken(), envvars, .asciimap, .clearpage.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 15 Oct, 2007 11:59 am 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
benryves wrote:
Timendus wrote:
Why does that look so much better than my documentation? :mrgreen:
I think I'm going to steal parts of it from you ;)
Probably because I got the MSDN team to design it for me. :pirate: (Sorry about the awful CSS/HTML, it was chucked together quickly).

*Steals* ;)
http://timendus.student.utwente.nl/~vera/asmdoc/
(See test.asm, others are pretty much empty)

The HTML/CSS really is a mess.. So I just copied some of the colors and a bit of css here and there, tried to make it look professional but not an exact copy. I'm not sure about the extendable tree. It's not necessary for now, and probably not worth my time to redo that at the moment. So maybe later.

It should have syntax highlighting though. Any ideas on how we could do that with XSL..? :mrgreen:

(Sorry for spamming in your topic, by the way ;) The string functions and Latenite integration look really cool, almost makes me regret not using Windows anymore :))

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 15 Oct, 2007 12:47 pm 
Offline
Maxcoderz Staff
User avatar

Joined: Thu 16 Dec, 2004 10:06 pm
Posts: 3064
Location: Croydon, England
Cool stuff, but renders very strangely in Opera 9. :|

Latenite 1 compatibility is just a temporary hack, ultimately I'd like to build a .NET-based IDE (Latenite 1 uses a lot of Win32 code). Hopefully Mono's WinForms will be up to the task. :)


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Mon 15 Oct, 2007 2:03 pm 
Offline
Calc King
User avatar

Joined: Sun 23 Jan, 2005 12:37 am
Posts: 1727
Location: Netherlands
benryves wrote:
Cool stuff, but renders very strangely in Opera 9. :|

That is weird... I'll look into it. Hadn't tested in Opera yet.
(Actually, I've only got Firefox here and I'm too lazy to install anything else when I've got my Grande Browser Compatibility Testsuite all set up at home ;))

Quote:
Latenite 1 compatibility is just a temporary hack, ultimately I'd like to build a .NET-based IDE (Latenite 1 uses a lot of Win32 code). Hopefully Mono's WinForms will be up to the task. :)

Whiiiiiiee :mrgreen:
Can't want to transparently wobble Latenite in my Beryl/Compiz! :mrgreen:

_________________
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 68 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


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:  
cron
Powered by phpBB ® Forum Software © phpBB Group | DVGFX2 by: Matt