This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

uc65, a Mid-Level Language Compiler READY FOR USE!

uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#114550)
Update

uc65 is now recommended for use! Please report any bugs, issues or feature requests to this thread or the project's issue tracker.

Status

Micro Code 65 is a mid-level language compiler targeting the cc65 tool chain with a focus on the NES target. The current release candidate of version 0.5 is feature complete and ready for testing for large-scale development. This release candidate is being tested through practical application prior to promotion for release.

The project's source code, documentation and road map can be found on the project site.

Attached to the thread is the latest binary distribution of the compiler along with Windows executables of the cc65 tool chain for your convenience. This package is also hosted on the project's page. The compiler should run on any platform supporting the Java Desktop profile. It has been confirmed to run correctly on 64-bit Linux and 32-bit Windows systems.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114590)
My comments:

Code:
; ROM statements tell the compiler what ROM bank to place ROM-able code and data
; into.
rom 0

; RAM statements tell the compiler what RAM bank to place variables into.
ram 1

What's the reason for not using cc65's built-in segmentation ability?

Code:
; Anything declared as extern can be imported from another file
extern byte somePig

I don't like the naming of "extern" here. In C it's used for the exact opposite purpose (importing), and I read the word as "external" in that context. I would rather use "export", but that maybe because I'm so used to ca65's use of that word.

Code:
; Subroutines can have parameters, but do not return values
sub doesNothing byte first byte second

Not really a fan of this format for defining the parameter list, I think the parameters should be separated by something at least (for readability). Or the separator (comma) could be optional, I'm sure some masochists prefer not having it...

Also why no return values? Maybe make it possible to define "in" and "out" parameters.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114593)
In C, "static" means don't export it, and no qualifier means export it.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114594)
Thank you for the feedback TheFox! The rom and ram statements are using segments under the hood. The default code generator used the names "BSSn" and "ROMn" for the respective banks. BSS0 is assumed to be in zero page. Do you have a suggestion for how I could handle this better? It's on the road map to improve this.

I agree on the extern keyword naming. I had intended to name it export and kept confusing myself ;)

As for subroutine parameter lists, we're getting into some forward-looking subjects. Let me run it down for you and see what you think.

Code:
; Declare an array
byte someArray,4

; Reference array members
someArray,0 = someArray,1 + someArray,2

; Call a subroutine
someSub someArray,0 otherParam


As you can see, using the comma for array dimensions means we can't use commas to separate subroutine parameters during a call. I chose this style of array dimensions to reduce the total amount of punctuation and shifts required. With the parser I have now though I'll know in advance if something is an array or not and could handle it that way, but it still looks kinda strange.

Thinking ahead to a few other features I want, maybe this would work better:
Code:
; Declare an array
word dataPointers[10]

; Define a subroutine
export sub doesSomething byte idx, byte offset
    ; Declare a pointer
    address dataAddress

    ; Reference an array
    dataAddress = dataPointers[idx]

    ; Pointer manipulation
    byte val1
    val1 = (dataAddress)
    val1 = (dataAddress),offset
    dataAddress += 1
    val1 = (dataAddress)

    ; Calling other subroutine
    otherSub val1, (dataAddress), dataAddress
end sub


As for not having return values from subroutines, this is part of the language's design as a finite state machine description, much like the early BASIC dialects.

I need to add functions to the road map. Early BASIC dialects allowed single-expression functions as a way to inline a computational expression in an abbreviated form. In uc65, a function will be a special case of subroutine which may only contain assignment and flow control statements and generates inline code.

In this way there are no automatic or "magic" storage or intermediate variables.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114595)
very awesome to see things getting started, great work! Looking forward to playing around with this, and future releases.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114597)
you could limit the return values to the a x y registers. if that is not enough for someone, they can return a pointer or set up a memory buffer somewere else.

or maybe I'm just thinking too low level.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114599)
While we all like return variables, it can be easy to get around not having them in your code by passing in the variable/pointer you want modified. Is it pass by reference or value? We're used to pass by value, and I'm guessing this is pass by reference for the global variables at least which makes this simpler.

Instead of this:
Code:
x = function (y, z)


Just adopt a subroutine style/midset that the first/last parameter is 'returned'.
Code:
function (y, z, x)


Are my presumptions correct?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114602)
Passing an address to a subroutine is one way of getting data back. Another is to use a global variable to store the computed result.

There's a key difference in mindset here though. Subroutines are for implementing behavior. Functions are for computing values in a convenient way. This is modeled after the early BASIC environments. This compiler is in many ways a compiled BASIC with a cleaned up syntax.

I value the community input! Thank you all very much.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114606)
qbradq wrote:
Thank you for the feedback TheFox! The rom and ram statements are using segments under the hood. The default code generator used the names "BSSn" and "ROMn" for the respective banks. BSS0 is assumed to be in zero page. Do you have a suggestion for how I could handle this better? It's on the road map to improve this.

Try syntax like this:
Code:
word dataPointers[10] in BSS0

export sub doesSomething byte idx, byte offset in CODE7
  ; etc.
end sub


Quote:
As for not having return values from subroutines, this is part of the language's design as a finite state machine description, much like the early BASIC dialects.

It's common practice at least in my 6502 programs for assembly language subroutines to act as functions, leaving results in C:A, X, and Y for the caller to pick up, as Movax12 suggested.

Quote:
Subroutines are for implementing behavior. Functions are for computing values in a convenient way.

At least in my calling conventions, subroutines can also return whether a behavior was performed or not (a "result code"), or the number of behaviors that were performed, or whether a behavior results in other behaviors that need to be performed.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114608)
The SUB function looks like how QuickBasic and FreeBasic does SUBs,

The same math functions are also featured in the compilers mentioned above!
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114609)
Any reason why you are writing your own parser backend from scratch? In my humble opinion that choice often leads to lots of headache fixing bugs in your parsing that could be better spent making the compiler itself :)

http://dinosaur.compilertools.net/
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114611)
I've used Lex and Yacc in the past. I wrote my first several compilers with them. Then I read the excellent article series Let's Build a Compiler by Jack Crenshaw. Although dated (with example code in Pascal) it's still the most effective way to write a compiler, in my opinion. Jack even addresses the question of "why not use a parser generator" in the series. That's just the way I prefer to do things now.

I guess I'm going to have to re-think the whole return value thing. Passing a return value through A works very well. Extending that to either the X/Y registers or the stack has a lot of problems though.

So I've researched ca65's .dbg statement and wrote it up here. If anyone knows what the "type" parameters are and what they mean I'd be very interested to know. Also, a clarification of the REGISTER storage type would be helpful.

I've finally finished the second quest of the Legend of Zelda! So I might start making quicker progress on this now :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114612)
The thing is, you really have no idea how to effectively use LEX and YACC until after you've attempted to reinvent the wheel, then you see how to use them.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114613)
qbradq wrote:
I guess I'm going to have to re-think the whole return value thing. Passing a return value through A works very well. Extending that to either the X/Y registers or the stack has a lot of problems though.


While restricting return values to a single byte is limiting, just having that small functionality alone is still pretty convenient/powerful. I'd say imposing that limit is a good way to provide functionality that parallels the hardware, especially since it seems to be working well on your end. Ignoring the mess of X/Y/stack, while it could have a use, it's not as straight forward or efficient so it's not a big loss IMO.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114623)
Dwedit wrote:
The thing is, you really have no idea how to effectively use LEX and YACC until after you've attempted to reinvent the wheel, then you see how to use them.


I have done both, and have better success with this method.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114624)
Dwedit wrote:
The thing is, you really have no idea how to effectively use LEX and YACC until after you've attempted to reinvent the wheel, then you see how to use them.


Those tools always looked like some strange dinosaurs to me. It is simpler to make a recursive descent parser, plus you don't need other tools than your favorite compiler in your favorite language.

Also, technically, any function not marked as "static" are extern, that is, you can always type "extern" / "static" in front of a function definition/declaration (but you should be consistent).
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114631)
Lex and Yacc aren't the only options, there's also pyparsing and other such libraries for Python. I used pyparsing once and it was pretty convenient.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114653)
Release 0.2 has been published with support for flow control statements (If/Else, While, Loop, Break, Continue and Return), conditional operator equals, ca65 debug info output and documentation (both a user's guide and full javadoc). Sources and binaries can be found in the same places.

Again this release has no practical application. Release 0.4 will be logic-complete and capable of initializing and interacting with the NES hardware. Releases 0.5 and 0.6 will add more expressiveness to the language.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114680)
qbradq wrote:
I've used Lex and Yacc in the past. I wrote my first several compilers with them. Then I read the excellent article series Let's Build a Compiler by Jack Crenshaw. Although dated (with example code in Pascal) it's still the most effective way to write a compiler, in my opinion. Jack even addresses the question of "why not use a parser generator" in the series. That's just the way I prefer to do things now.


I would suppose you are aware of this but just in case you or someone else isn't,
be sure to check out this article on writing a Pratt parser.

http://javascript.crockford.com/tdop/tdop.html
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114712)
It's looking really good so far! I'm just hoping we don't have to wait for you to beat the 3rd quest in Zelda before we can get the 3rd release, likewise for the fully functional 4th release. ;)

Quote:
The width of the assignment is the larger of the two parameters. If the width of the assignment is greater than the width of the target, a loss of precision warning is issued.

So how is the result truncated exactly? I'm used to loosing the MSBits/bytes, but loss of precision suggests the lower byte(s) are lost.

I'm also a little unsure of how I need to set things up to compile a project, but we're not exactly fully functional yet so it's not of much need other than playing around. So if the version 4 with the initialization example could come along with a brief instruction on how to setup and compile the project it'd be much appreciated. I'm looking forward to starting a simple project of my own using this once you've released v0.4 :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114732)
I've updated the user guide with a correct usage line. Here's an example of compiling, assembling and linking:

Code:
java -jar uc65.jar main.uc
ca65 main.uc.s
ld65 --config lib\memory.cfg main.uc.o


I'm also struggling to figure out how I'm going to make a test harness for this thing. A compiler without a good test suite isn't a good thing :)

I am making progress at a decent clip. I've front-loaded most of the challenging problems and it's paying off pretty well. I just finished the basic optimizer. I've only got arrays and subroutines left before release 0.3.

Thanks for all the encouragement!

Also, thank you for the link. I haven't studied Pratt parsers. I'll have to give this a read.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114738)
I'll give the compiling a try, thanks for updating that.

qbradq wrote:
I'm also struggling to figure out how I'm going to make a test harness for this thing. A compiler without a good test suite isn't a good thing :)


While I agree, I'd argue that we're not really used to a test suite. We compile via command line, then boot in a emu/hardware which gives us the test suite of our liking. A test harness for your compiler would be nice, but you might be able to get around it. Having a sensible assembly output that can be checked by the user if the suspect issues is sufficient for now. Do your testing, for those of us interested in your beta builds we can expect bugs/fixes being needed. To some degree beta testers can be your test harness for the compiler.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114740)
Ideally, a Lua script in an emulator could perform regression testing by resetting the machine, providing inputs, and checking the resulting RAM contents.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114741)
When you'll get the compiler to usable state, I think I could make a small test game project using it. Small game is normally like 1000-2000 lines of code in C, which is maybe not a great reliability test, but still some material to debug the compiler, catch regressions, and improve code generation.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114757)
infiniteneslives wrote:
Quote:
The width of the assignment is the larger of the two parameters. If the width of the assignment is greater than the width of the target, a loss of precision warning is issued.

So how is the result truncated exactly? I'm used to loosing the MSBits/bytes, but loss of precision suggests the lower byte(s) are lost.


I've updated the documentation to be explicit: In this case the arithmetic is limited to the n least-significant bytes of the variables, where n is the width of the target.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114791)
Shiru, I'd be honored for you to make a game with uc65 :) I'm hoping to be 100% ready with the compiler before the next NES Dev competition.

So I'm going to go ahead and implement full subroutine return values and expressions as subroutine parameters. The author will need to understand the overhead of a subroutine return. Interestingly, allowing expressions as subroutine parameters can improve efficiency in some cases.

I'll leave fastcall for later.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114867)
Well I've finished Super Metroid (for the first time actually) and finished off release 0.3 of uc65! Woot! Release-0.3 adds support for subroutine return values, subroutines in assignment statements, byte-level addressing of n-byte variables, arrays (uses interleaved data for fast access, maximum of 256 elements), a basic optimizer and addressing of hardware registers via the new "port" variable type.

I have also reworked the code generation for the main, frame and interrupt subroutines to include standard boilerplate code.

The documentation has been updated with the new features and the flow control statements I forgot to document last time :oops: As usual the first post has been updated and a binary distribution is linked to from the project page.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114892)
Yay! I made my first build! :) Well asm output anyways...

This is probably a no brainier for most, but for those that need a little more assistance getting java development kit up and running in the command prompt and all I found these (notably obsolete) instructions helpful: java and the windows cmd prompt

One small note, not sure if I'm doing something wrong, but my output assembly file still contains the .uc as part of the name. So the name is 'subroutines.uc' of file type .s Not sure if that's intentional or not, but I was expecting the .uc to not be part of the assembly file name.

I'm sure that I'm doing something wrong as I don't really know what I'm doing... But I figure I'll ask the stupid questions so others don't have to.

Code:
C:\Users\Paul\uc65-release-0.3>java -jar uc65.jar test\subroutines.uc
.\test\subroutines.uc:19 Warning - Possible loss of percision

C:\Users\Paul\uc65-release-0.3>cc65\ca65.exe test\subroutines.uc.s
test\subroutines.uc.s(133): Error: Symbol `bigSum___d' is undefined
test\subroutines.uc.s(131): Error: Symbol `bigSum___c' is undefined
test\subroutines.uc.s(129): Error: Symbol `bigSum___b' is undefined
test\subroutines.uc.s(127): Error: Symbol `bigSum___a' is undefined
test\subroutines.uc.s(96): Error: Symbol `sum__' is undefined
test\subroutines.uc.s(62): Error: Symbol `bigSum___d' is undefined
test\subroutines.uc.s(59): Error: Symbol `bigSum___c' is undefined
test\subroutines.uc.s(56): Error: Symbol `bigSum___b' is undefined
test\subroutines.uc.s(53): Error: Symbol `bigSum___a' is undefined
test\subroutines.uc.s(19): Error: Symbol `sum__' is undefined


How am I supposed to use ca65 to compile the created assembly file?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114918)
Thanks for being a guinea pig INF! I'll lop off the .uc bit of the file name so it looks a bit cleaner.

The issue you've found with return values is quite embarrassing. I guess I never assembled that test file. I'll get a patch release up today to resolve that (and also pretty up the assembly output a bit).

Edit: I've patched the issues and corrected a few issues with the test files. New release version is 0.3.1 but I don't have a binary release for it yet.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114931)
Cool deal, I'll try things out again with the update when its ready.

One thing I was planning to do once everything is operational, is port shiru's simple C examples to microcode. They are pretty good examples IMO, they'd also be good comparison metrics. Sounds like he might be planning to convert his simple Chase game over. If not, I might give it a try; or just do it myself for the practice so I don't have to worry about coming up with the creative parts.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114932)
Actually I'm thinking to make something new rather than porting Chase.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114933)
I'm so excited to hear that folks! Thank you!

I've come to a bit of a decision point that I'd like some input on. For inline assembly, should I just pass the inlined text directly to the assembler, or have a basic assembler parser that can convert the labels and addressing modes so it can generate cross-assembler code? Honestly I'm not sure which one would be better. Passing the text verbatim would be the most powerful, but also the most error-prone from an end-user's perspective.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114953)
Binary release of 0.3.1 is uploaded now. This corrects the subroutine return value bug, an edge case involving multiple reads from a register, and now removes the .uc bit from output file names.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114959)
Unfortunately I can't even compile the assembly file now... ;(

Code:
C:\Users\Paul\Dropbox\nesdev\uc65-release-0.3.1>java -jar uc65.jar test\subroutines.uc
.\test\subroutines.uc:1 Error - Invalid token ","
.\test\subroutines.uc:5 Error - Invalid token ","
.\test\subroutines.uc:12 Error - Invalid token ","
.\test\subroutines.uc:13 Error - Invalid token ","
.\test\subroutines.uc:16 Error - Invalid token ","
.\test\subroutines.uc:19 Error - Invalid token ","
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114961)
Woops... what I uploaded as 0.3.1 was the uncommitted development branch of 0.4. Obviously I need better release management practices.

Release 0.3.2 is up now with the aforementioned corrections. I fully tested this one by hand and was able to compile, assemble and link all tests. Note that you need to assemble and link against lib\crt0.s to get a complete .nes file.

Before release 0.4 I am going to have an automated regression test in place so I won't be wiping egg off my face so often :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114964)
Nice I got my .nes file! :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114965)
Thank God :) I've learned a valuable lesson today: don't test your trunk build, test your release artifact. Last go-around I tested what I thought I was going to release, but accidentally CD'ed into the wrong directory for the packaging step.

Anyhow, I guess I'm going to go with verbatim assembly blocks for now. Once I get that worked into the file parser and get comparisons done I'll have 0.4-rc1 ready and can start building some NES demos with it. Exciting stuff :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114971)
qbradq wrote:
Anyhow, I guess I'm going to go with verbatim assembly blocks for now.


That was going to be my vote. It sounds like the easier option from your end as well. It gives the user the power to do anything they want in assembly directly. And while it does allow them to make more errors, it's not for the 'beginner' anyways.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114994)
0.4 Release Candidate 1 is now ready (and tested :) ). You can download the binary distribution from the attachement on the first post.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114996)
Code:
G:\uc65>java -jar uc65.jar syntax.uc

G:\uc65>ca65 syntax.s

G:\uc65>ld65 --config lib\memory.cfg syntax.o
ld65.exe: Warning: lib\memory.cfg(31): Segment `HEAD' does not exist
ld65.exe: Warning: lib\memory.cfg(31): Segment `VECT' does not exist

Is it OK?

Also, how CHR is intended to be attached? Included into crt0.s, with memory.cfg modified?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#114999)
Shiru,

All of this stuff is going to be addressed in the Examples that I am working on for the full 0.4 release.

When you link you'll need to include crt0.o as the first object file. This includes the HEAD and VECT segments. The current set-up is for an MMC3 mapper with 32KB ROM and CHR-RAM.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115000)
Hey,

I haven't been posting in this thread now, and I haven't the time to test the compiler right now, but all I can say is that it looks *extremely* promising.

All I can say is that I hope that shifts and function with multiple return values will be supported.
Shifts because they are extremely annoying to deal with in 6502 assembly.
Functions with multiple return values because when I code in assembly I use this all the time, and I feel handicaped by high level language which only allows a single return values. I never understood why this became a standard, there is no logical reason behind this. Except maybe the usage of function within an expression, but I think outside an expression a so called "high level" language should be able to return 2 or more values.

What I use especially all the time in assembly is a subroutine that returns some value in A, and a validity flag in C. That means for example, C=0 means no error, the result is in A, and C=1 means there have been an error, and A contains garbage. I never found a way to replicate this in HLL, exept using the sign bit and returning -1 on error, but this only works if you don't use all the number range in the return value.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115002)
Thank you for the encouragement Bregalad! You'll be happy to know that bitwise shifts are currently supported. However the number of shift positions must be a compile-time constant. Additionally, multiplication and division are not supported at all.

I was thinking about multiple return values for a while now. Because subroutines can't be used in an expression, there's no reason not to support them. But because there was no ask for them, I didn't put them on the road map. I've added this to the road map for version 0.7. It's mainly a change to the parser. Most of the code generation needed for this is already there.

As for things like statuses in the carry bit, this is the 10% of assembly optimization that the language does not attempt to implement. Hopefully the multiple return values will satisfy the need, and if the performance overhead is that important then it probably should be in assembly to begin with :)

The way I envision using this tool is to write most of the code in the high-level language, and performance-sensitive parts like the vblank kernel in assembly. Then if I hit a performance bottleneck during development, I will profile it with Nintendulator and go to optimizing, with inline assembly being the last optimization step.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115003)
There is no rush adding features, just do what you feel like doing. Thanks for listening to my blabbering anyways.

I can see why you don't add variable * variable multiplication and divisions (too many different implementation on them, and picking one over another is going to start a flame war anyways), but variable * constant and constant * constant should definitely be supported (constant at compile time). variable / constant is not too hard to do either.

I can already see this language mixed up with both assembly and C in a big project :
- Time sensitive things : Assembly
- Medium sensitive things : This language
- Complicated logic not sensitive to timing : C
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115005)
OK, I compiled the code, thanks for clarification.

Why MMC3, though? Is there some (planned) dependence, or I can just change it to a configuration of my needs (standart NROM, I think)?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115007)
Awesome to see such rapid progress with this qbradq, good work! I'll be out of town next week and probably won't have much time to play around with it till I return, but this is pretty exciting.

Bregalad wrote:
I can already see this language mixed up with both assembly and C in a big project :
- Time sensitive things : Assembly
- Medium sensitive things : This language
- Complicated logic not sensitive to timing : C

Except with C integration bankswitching becomes an issue again, although not necessarily depending on how you set things up I guess.

Shiru, I don't believe there is any requirement for MMC3 if you can fit it in NROM you should be good I'd imagine. From what I understand MMC3 choice is due to need/desire to support bankswitching with a similar sturcture to MMC3 as we were discussing in this thread. I'm curious as to your plans on this front though qbradq with various structures of bankswitching. Does the current build support banking? I don't see it on the project page.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115009)
Do I need to get working on my math library again so that you can have 8-bit multiply, divide, square root, arctangent, and binary-to-decimal subroutines written in assembly language to use in your programs?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115014)
Currently the rom statement allows you to place your code into any segment you wish. Using that you can implement banking on your own. Just make sure the banking happens in the fixed segment. There's no plan currently to do any sort of automated banking.

The choice of MMC3 is because I have an MMC3 dev board thanks to INF :) To use this for NROM you just need to change the memory.cfg a bit. I think for release 0.4 I'll have an NROM configuration.

tepples wrote:
Do I need to get working on my math library again so that you can have 8-bit multiply, divide, square root, arctangent, and binary-to-decimal subroutines written in assembly language to use in your programs?


I would appreciate it, but it wouldn't fit the core language very well unless the routines supported n-byte arithmetic (or at least 32-bit). It would be useful as a subroutine library though.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115018)
qbradq wrote:
tepples wrote:
Do I need to get working on my math library again so that you can have 8-bit multiply, divide, square root, arctangent, and binary-to-decimal subroutines written in assembly language to use in your programs?

I would appreciate it, but it wouldn't fit the core language very well unless the routines supported n-byte arithmetic (or at least 32-bit). It would be useful as a subroutine library though.

The library as I envision it would be useful even with only 16-bit arithmetic. Several quantities in Thwaite, where the library originated, use the same coordinate format as Balloon Fight and presumably a bunch of other NES games: 16-bit using 8.8 fixed point, where the high byte holds the pixel and the low byte the subpixel.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115024)
Something I forgot to mention earlier: how about 24-bit data types?

EDIT: Or is "long" a 24-bit type?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115025)
thefox wrote:
Something I forgot to mention earlier: how about 24-bit data types?

EDIT: Or is "long" a 24-bit type?


I believe so:

Code:
Type name    Byte Width    Use
byte         1    unsigned integer
word         2    unsigned integer
long         3    unsigned integer
dword        4    unsigned integer
address      2    memory address
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115026)
More questions, as I'm trying to get my head around this.

What is the intended way to include constant arrays of data, like level maps? They needs to be larger than 256 entries. Another thing that is often needed is an array of pointers, like when I have level maps as separate arrays and want to make a list of them to access by index.

Is the segments (banks) a must? What if I'll have more than 16K code or data to place into a segment, should I break them between segments manually, or there is/will be a way to put them linearly, if bankswitching is not needed?

It is also unclear yet how to interact with the hardware, like NMI and pad polling. I guess that should be done in assembly code, but does it have to be inlined, or could it be done in a separate assembly file?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115028)
This is great feedback Shiru, thank you!

Shiru wrote:
More questions, as I'm trying to get my head around this.

What is the intended way to include constant arrays of data, like level maps? They needs to be larger than 256 entries. Another thing that is often needed is an array of pointers, like when I have level maps as separate arrays and want to make a list of them to access by index.


These needs will be addressed in the next release, 0.5. It will introduce structures, arrays of structures, tables (initialized arrays in ROM), and the address data type (pointer).

Shiru wrote:
Is the segments (banks) a must? What if I'll have more than 16K code or data to place into a segment, should I break them between segments manually, or there is/will be a way to put them linearly, if bankswitching is not needed?


The segment sizes are 100% a function of the linker memory map. For NROM you'd just use a single 32KB ROM bank.

Shiru wrote:
It is also unclear yet how to interact with the hardware, like NMI and pad polling. I guess that should be done in assembly code, but does it have to be inlined, or could it be done in a separate assembly file?


NMI is handled by the "frame" required subroutine. This subroutine is set as the NMI vector, and includes register push and pop code automatically. If you wanted to implement this vector in a separate assembly file, just export the label as "frame".

Pad polling can be done with the port data type. A port is basically an absolute memory reference, but it's intended purpose is to interact with hardware registers. I am working on an input example now.

Currently you can't interact with code from other assembly files (or even other uc files). This will be addressed in release 0.6 with the import statement.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115031)
Suggestions:

-If it doesn't exist, a signed integer type (for proper comparisons).
-The language should be able to define a mapper type and output the memory configuration for know mappers without the user having to understand how to make/edit ca65 config files.
-NMI routine should be definable in code. This is leaking into the realm of an API, not sure how far you want to go, but you could have something like:

Code:
.proc NMI
    inc frameCounter

    lda userNMIvector
    ora userNMIvector + 1
    beq exit
        jsr doUserNMI
    exit:
    rti
   
    doUserNMI:
    jmp (userNMIVector)
   
.endproc

; basic example:
; turn off NMI or do something to make sure this macro is not interrupted

.macro setNMIRoutine addressImmediate
    lda #<addressImmediate
    sta userNMIvector
    lda #>addressImmediate
    sta userNMIvector + 1
.endmacro

Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115032)
Signed integer types were deliberately left out because they do not fit the machine architecture. However there are comparison operators that handle the negative flag, namely < 0, <= 0, > 0 and >= 0. It is in the maybe pile though.

As for automatic mapper handling, that's something I've put in the maybe pile. I'm going to see how it goes with having some pre-defined default memory maps.

Finally, the NMI routine is definable in code, as well as the IRQ routine. The "frame" and "interrupt" subroutines are automatically placed in the respective vectors. Upon entry all registers are pushed onto the stack. All return statements (and the implied return at the end of the subroutine) generate code to restore the registers from the stack and RTI.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115033)
qbradq wrote:
These needs will be addressed in the next release, 0.5. It will introduce structures, arrays of structures, tables (initialized arrays in ROM), and the address data type (pointer).

I think it might be wise to create a 24-bit "far pointer" type with the bank number in bits 23-16. This would allow easy manipulation of (address, bank number) pairs, and it'd cover an eventual extension to 65816.

Quote:
NMI is handled by the "frame" required subroutine. This subroutine is set as the NMI vector, and includes register push and pop code automatically. If you wanted to implement this vector in a separate assembly file, just export the label as "frame".

I just wonder how clear the use of "frame" as the name of the NMI handler might be. It might also be useful to provide a default implementation of this required subroutine that just increments a variable on zero page, as seen in Lawn Mower and Thwaite.

Quote:
Pad polling can be done with the port data type. A port is basically an absolute memory reference, but it's intended purpose is to interact with hardware registers.

So sort of like a volatile pointer in C?

EDIT: As for the "frame" and "interrupt", some coding styles use different NMI handlers for different parts of the game, with a JMP trampoline in RAM to switch among them. It might be wise to make a qualifier for subroutines that says "this subroutine uses interrupt calling conventions, including callee-saved A/X/Y, no return value, and RTI instead of RTS."
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115034)
If you wanted to be able to compare variables to other variables, you would need to know if a variable is signed to compare properly: http://www.6502.org/tutorials/compare_beyond.html#5

For the NMI thing, that just feels more high level to me, to have the ability to define your NMI in a statement. If you don't want to go that way it's cool.

EDIT: link.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115138)
Holy cow! I forget to lurk for a few days and this leaps into life!

This project and infiniteneslives flash carts are pretty much the only way someone like me could possibly create their own NES game. I'll be watching and attempting to get this working for myself :)

I've mentioned this before, but, batari BASIC is something I wouldn't be shy about drawing inspiration from:
http://www.randomterrain.com/atari-2600 ... mands.html

I especially enjoy how easy it is to deal with joystick input and sprite positioning
if joy0left then player0x = player0x - 1

Bitwise operations are also dead simple to use in bB. Anything from picking individual bits from variables used as counters (i.e. if counter{4} then goto march) to defining single bits in a byte for use as boolean variables: "def isnekkid=attributes{0}"
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115153)
Quote:
I've mentioned this before, but, batari BASIC is something I wouldn't be shy about drawing inspiration from:


For comparision, In ca65hl:

Code:
if buttons & #BUTTON_A goto label


or

Code:
if buttons & #BUTTON_A
;do stuff
endif


Bitwise stuff:

Code:
setFlag foo, bit
clrFlag  foo, bit

if { flagSet foo, bit }
; do stuff
endif


How to the bit test is determined:

Code:
.macro flagSet addr, bitnum
        .if .not .blank(bitnum)
           
            .if bitnum = 7
                bit addr
                set_flag_test N set
            .elseif bitnum = 6
                bit addr
                set_flag_test V set
            .else
                lda addr
                and #(1 .shl bitnum)
                set_flag_test Z clear
            .endif
           
        .else ; no bitnum specified
            bit addr
            set_flag_test N set
        .endif
    .endmacro
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#115612)
Just wanted to let you folks know I'm not dead yet :) For the past two weeks I've been closing one project and opening another at work, so my workload is essentially doubled. I am looking forward to working on uc65 again within the next two weeks or so when things settle down.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120094)
Necro-Post for great justice!

I'm not dead yet! Due to issues at work I'm basically working double-time until the end of January to take up some slack, so I've not been able to do many side projects of late, and unfortunately uc65 hasn't come back to the top of the stack.

All of my side work continues to be in the 6502 machine space. I've done some work on a prototype Apple II RPG using Integer BASIC as a glue language with assembly routines and learned a lot (hint: it's too slow). I'm now giving myself a proper education in digital logic design and synthesis, and working on a 6502 software-compatible soft processor.

I've come to a kind of peace with my frustrations over the NES platform. Through my learnings about microprocessors, I've come to understand that the 6502 is a very special breed of MPU. It was designed to be coded in assembly. Higher-level languages were never considered at the hardware level, and as such the kind of higher-level languages you can create for it are either non-optimal as is the case with C or BASIC, or closely resemble assembly like uc65 does.

I've also had to learn z/370 assembly for my professional life. I totally felt like a boss when I learned it in under a day thanks to my familiarity with the 6502 architecture :) That experience has given me a number of insights into the technologies of the late 1970's and the development practices that were common at the time.

All of this has lead me to a new vision of the NES as a platform, one that I'm sure many of the more productive members of our community have shared for some time: The NES is what it is. Love it or hate it, but don't try to change it.

I'll be sharing my other project when I'm ready to show it off, and I'm sure my next project will be NES-related, but I think the uc65 concept is misguided. It's better-guided that other high-level languages for the 6502, but that's a personal opinion :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120115)
Suggestion: How about releasing IDE for uc65, when uc65.jar is executed without parameters? I've done Java programming in the past so I could make it (though no screen/chr editors). I am pretty well aquainted with Swing, so if you want help on that...
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120116)
Better yet, figure out how to link it into an existing IDE like Eclipse or NetBeans.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120123)
Eclipse/NetBeans aren't well-suited for such low-level languages. Better is to make new IDE, like Nesicide did (though linking it to NESICIDE would be easy, I think).
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120153)
Brings me sorrow to hear this, but I understand your viewpoint on the matter. Any thoughts to sharing sources so someone could attempt to pickup where they left off if they cared to?
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120180)
uc65 has always been 100% open-source. The first post has links to the project page at Google Code, which hosts all of the source code for the compiler and documentation in an SVN repository. Each download .zip also contained a snapshot of the source code.

I think the best way to get more out of a high-level language on the NES is to follow in the footsteps the SNES. Many titles for the SNES included co-processors on the cartridge to improve computational performance. Although most folks are familiar with the example of StarFox and the SuperFX chip, this practice was more common on high-end titles that some realize. Co-processors were used in titles such as Doom, Winter Gold, Super Mario World 2, Dungeon Master, Mega Man X2 and X3 and even the venerable Super Mario Kart.

The example that really sticks in my mind is Super Mario RPG: Legend of the Seven Stars. It utilized the SA-1 enhancement chip, which is a 65816-variant microcontroller clocked at 10Mhz. I think something similar could be a good platform for NES development in higher-level languages with established toolchains.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120246)
Right, so after thinking about writing a better glue language for my above-mentioned RPG project, I picked up uc65 again :) I still insist that the idea of attempting to make an efficient higher-level language on the 6502 is missing the point, but the idea of using uc65 as a more efficient glue language is looking very promising indeed.

I've written a basic test ROM with the 0.4 release candidate. It's in subversion now. It displays a very basic star field with a small sprite controllable with the D-pad. There's a few assembly blocks thrown about to do some lower-level things like reading the controller port and initializing the PPU and RAM, but the higher-level constructs have really proven themselves to be valuable to me.

Comparing the experience of writing this small program to the small programs I wrote in Integer BASIC, I'd have to say I found uc65 to be more palatable albeit less approachable.

Two major parser defects related to subroutine definitions were discovered while working on the test program, so I'll be correcting those before doing any work on version 0.5. I'm not exactly sure how often I'll be working on uc65 until my workload eases, but I'll be keeping SVN updated.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120265)
qbradq wrote:
the 6502 is a very special breed of MPU. It was designed to be coded in assembly. Higher-level languages were never considered at the hardware level, and as such the kind of higher-level languages you can create for it are either non-optimal as is the case with C or BASIC, or closely resemble assembly like uc65 does.

That or it just won't look like C or BASIC. David A. Wheeler, the fellow who defeated Ken Thompson's trusting trust attack, has made a list of specialized approaches to high(er) level language implementation. You might want to consider some of these approaches if you haven't already.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120270)
Thanks for the link Tepples! I did read a lot of David's papers during my first go at writing a compiled language for the 6502. This reading is what eventually lead me to the core technique used in uc65: stackless overlapping global memory allocation. It also inspired the idea of confining the language primitives to only those that could be efficiently implemented in hardware.

I had never seen this paper until today though. Thanks for the link! I need to comb his site over a bit more carefully.

Also updated the first post with the official binary release of version 0.4 with bug fixes and all, including an example program that does NES initialization, display and control. There's even a build script :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120527)
I am proud to announce the availability of Release Candidate 1 for version 0.5 of uc65. I've added composite types (think C structs), arrays of composites, static data primitives, the Address data type and dereferencing (indirect addressing), self-assignment shorthand operators and a host of new optimization techniques to make these new features efficient.

As always I have updated the first post with a new binary package. The project page also has the latest source code, documentation and binaries. If anyone is interested, please give it a try and let me know if you have any trouble, feedback or feature requests.

At this point I have implemented every language feature that I had originally designed, as well as a few others that were added during development. There's a few other features on the maybe pile, but from a language standpoint it is now feature-complete! WOOT!

I will be using the current version to make some test ROMs for my development flash cart. I hope to find any remaining defects during this phase. Following that I'll be working on release 0.6, which will implement features of the compiler to support large-scale development. These include features to support development across multiple source files, a build management system to automate target architecture and MMU selection and integration, and a set of standard libraries for the NES.

After the completion of the 0.6 release candidate I plan to use the compiler to create my entry for the 2014 NESDev competition.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120528)
Most excellent news! Glad to see things revived even better than before. Earlier today I was trying to decide which route to go with my compo entry deciding between assembly and C. With your decision to go with uc65 for your entry, I'm thinking I'll follow suit and go with uc65 as well. :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120535)
Wow, that's really encouraging to hear! Just keep in mind that as of now there's no support for multiple source files, and everything has to be defined before it's referenced. The 0.6 release will address these two pain points. I can't give any promises when that will come though due to the craziness of my work. I was blessed with a soft week last week ;)

It's interesting how this project is coming along. My attitude toward the approach has done a 180, but it hasn't changed the requirements or the effectiveness of the solution :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120549)
qbradq wrote:
It's interesting how this project is coming along. My attitude toward the approach has done a 180, but it hasn't changed the requirements or the effectiveness of the solution :)

Seems like it'd be easy to integrate into NESICIDE if it supports CC65 debuginfo. I'm all for providing user alternatives...even if I prefer C or assembly at the moment. Not that I've actually *produced* anything.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120557)
Cool! After 0.6 will be done, maybe we could do community library that would allow less knowledgeable people make NES games? It'll be just bunch of assembly wrapped into functions like initializeRAM(), readControler1(int button), etc.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120564)
darkhog wrote:
Cool! After 0.6 will be done, maybe we could do community library that would allow less knowledgeable people make NES games? It'll be just bunch of assembly wrapped into functions like initializeRAM(), readControler1(int button), etc.


That's the idea, yes. You can do those things now without using assembly, but you still have to know the details of the hardware. The community would be able to produce libraries and application frameworks that abstract the user away from the more complex hardware details.

Honestly though, cc65 is better suited for folks that don't want to get down into the assembly and hardware details. uc65 is more of a productivity suite for assembly hackers :)
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120566)
Yeah, but cc65 isn't as fast as assembly can be (which depends mostly on compiler and not language design - if compiler is smart and can optimize code well, there can be even very high level language compiled, such as Python as pyNES has shown), Alter Ego, a standard cc65 game, isn't exactly fast-paced and I'm interested into making bullet-hell shmup in future. UC65 makes good middle ground between assembly and high level language, similarly to what once NESHLA did (the only reason I don't use NESHLA is that isn't being actively developed and documentation is kinda poor).
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120571)
For an action game like Contra you will simply have to use assembly code. For bullet hell you probably will have to move to another platform, not even SNES, because 64 or 128 bullets aren't exactly hellish enough.

cc65 and uc65 could be used to create medium paced scrolling games like Super Mario Bros (proved with Sir Ababol) or Double Dragon.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120575)
Shiru, I think I'll be able to prove that anything you can do with pure ASM you can do with uc65. I've specifically designed the language to map directly to assembly construction patterns, and the code I'm generating these days looks identical to what I write by hand (except for calling subroutines with parameters in the registers).

Time will tell anyhow :) But I think you've given me my official challenge for the NESDev compo this year.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120580)
The same could apply to C as well. The question is just the speed. Do you plan to support things like unrolled loops and pre-generated code natively? Otherwise it is all about asm inlines, which would be the same for both cc65 and uc65.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120588)
Yea, I mean uc65 should produce code that's very near the speed of hand-optimized assembly in most cases. The only cases I've found where I can do a better job than the optimizer I have currently implemented is with branch joins. Like when you have an if/else structure, on the other side of that the optimizer just assumes all register and flag values are unknown. When coding by hand you could know that the X register doesn't change in either branch, for instance. The same is true for subroutine calls.

Well, the way the language works you can write an unrolled loop quite easily without using assembly. The only looping constructs are while and loop (conditional and unconditional looping respectively). So if you implement a loop and want it unrolled, you'll need to do that by hand. The compiler won't do it for you.

This all ties back to the idea of using language constructs that are directly supported by the hardware. Again, it's not a high-level language. I call it a mid-level language, but if it helps you could think of it as high-level assembly.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120589)
Could you make optimizer to check whether e.g. X register (as in your example) doesn't change in either branch and then optimize it further?

Also, could you implement 'for' loop? It is useful when you know you have certain amount of data to loop through (like array). Granted, you technically can do it in while loop, but it isn't elegant solution and you may after some months without seeing code think "what the **** this code is doing?", especially when it is uncommented (worst crime programmer could commit IMO).
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120591)
darkhog wrote:
which depends mostly on compiler and not language design - if compiler is smart and can optimize code well, there can be even very high level language compiled, such as Python as pyNES has shown

As far I understood pyNES is mostly a macro compiler i.e. it just pastes pieces of pre-written code.

On RISC machines a compiler can produces even better code than handwritten assembly, but the 6502 is the furthest from RISC processor you could think about.

CC65 is absolutely terrible at "being smart and optimize code well". Use an array and it'll generate 20 lines of bloated code on each access instead of smartly using indexed addressing modes that were made for this very purpose.

Also the language CAN be a performance issue in rarer cases, for instance if you have an array of pointers in C, you can't split it into low and high halves like you can in assembly. Well you COULD split it but then you wouldn't be able to use it as an array of pointers, which kill the point of it.
Re: uc65, a Mid-Level Language Compiler for the cc65 Toolch
by on (#120953)
Release Candidate 0.5-rc2 is out now. Per usual I've updated the first post with the new distribution package which now also includes full sources to avoid confusion. The project page has also been updated with the new distribution and documentation for the new features.

New Features

The import statement allows you to spread your code into multiple files and import the exported variables, types, subroutines and constants for use in other files. The generated assembly files contain appropriate export, exportzp, import and importzp statements for later use by the linker.

By default the directory containing the current source file is searched for an imported file, but additional search directories may be specified on the command line. Relative paths are also supported.

Finally a new command line option has been added to generate GNU GCC-style auto dependency information suitable for GNU make.

Going Forward

I have decided that instead of rolling my own build management system I am going to provide the support features in the compiler required to enable other standard, well-maintained build management systems to be used, such as GNU make. The new road map reflects this change in direction, as well as my intent to continue development of the NES target, libraries and examples.

At this time no features are planned for immediate development, however I am still taking feature requests under consideration for a possible 0.6 development branch. I am comitted to providing support for the compiler, documentation and related materials until at least the end of the 2014 NESDEV competition. If the compiler proves useful and practical during this time frame I will of course continue it's development and maintenance.

So yea, uc65 now recommended for use! Please send all bug reports or feature requests to this thread or the project issue tracker, including those pertaining to documentation and examples.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120969)
I wonder, how does this compares exactly to the ATALAN language ?

They seem to have about the same goals right (HLL specifically for 6502) ?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120971)
In general, ATALAN is higher-level than uc65 and performs more static code analysis in an attempt to make those higher-level constructs more efficient. This means that, much like C, you can write code that cannot be optimized if you are not careful. uc65 was designed with only language elements that map directly to 6502 machine constructs.

Prior to starting work on uc65 (and it's predecessor project) I evaluated ATALAN. It was rejected as not meeting my requirements because it does not seem to handle banked code at all. I also did not care for the syntax, but then again uc65 also has a non-standard syntax.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120979)
But why not develop NESHLA further since author basically abandoned it, code is floating on net? uc65 is already great, but IMHO the only bad thing about NESHLA is that it isn't developed any further and documentation is lacking (many links on NESHLA page that are supposed to link to docs either link to 404 or to "work in progress" page). Okay, that's two things, but you get my point.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120985)
A simple question. How many actual games were created with NESHLA in all these years?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120986)
A simple question: Which assembler has better docs: ca65 or NESHLA?

It's not about amount of games made with either, it's about docs that explains them. NESHLA has beautiful syntax, I was given copy of sources of Grand Theftendo before it became Retro City Rampage (Brian probably doesn't remember it as it was few years ago) and it was more clear than code made with ca65 and I could exactly make up what each function did (remember that I didn't know jack $h17 about assembly, I still don't know everything).

Unfortunately what it makes in clearness of syntax, it loses in documentation. NESHLA docs are virtually non-existent and if you make most clean language in the world but still won't have docs for it, you know you will fail as devs just won't know how to utilize it properly.

Even pity NESASM has better docs that NESHLA.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120987)
You have source for Grand Theftendo? You can make out what each function does? Then maybe you should be writing the NESHLA docs, because that'd be an excellent way to see how it works in practice. You have more information than probably anyone else to write docs for it.

Seriously, you have like the only thing that has ever used it and you're asking US to write things about it for you. I don't get it. You're asking random people to work from less than the info you have for you.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120990)
First of all, I didn't have full sources, just few files from very early stage. Secondly it was several years ago (few months after ""announcing" GT, was lurker here and on other nes forums, didn't bother to register and contacted Brian via e-mail to get some more details - surprisingly he sent me few source files and few additional screenshots. After so much times, details are so blurry that I only remember it just made sense.

I have since then changed computers and probably don't have those anymore. Will check backup CDs, but I suppose it won't be there. Believe me, if I had still those files, I'd be writing docs instead of bitching how it was good, just as I did with pyNES.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#120993)
I also looked at NESHLA prior to starting this project. It's a big reason that documentation is the first listed feature, and is this first step in feature development. Nothing in uc65 was developed prior to being documented. The source code also contains complete JavaDoc documentation of all methods to help anyone that wants to contribute.

I do understand the skepticism. I think it's very well deserved. I'll be making open source demos and a game based on the compiler to help demonstrate its usefulness, and I hope interested community members will do the same.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121000)
Well, I'm not sceptic at all, I only questioned why you didn't revive some old "high level" project that showed promise but was abandoned :).

Sorry if you took it this way. Anyway, once I'll learn nes assembly well enough (for now I'm just playing around with NESICIDE's Hello World example/template), I'll learn this one as it is promising (though probably still some assembly will be required, pardon a pun, so it's better I'll learn asm first).
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121005)
LOL, I like that line, "Some assembly required". I may make that the moto for the language :) in general you can do anything in uc65 that you could in assembly, but one of the goals for uc65 was to inter-operate very well with inline assembly.

Just as an FYI, I noticed that the JAR I uploaded does not have the import directory and auto-deps features mentioned above due to a versioning mishap. I've merged the other changes back into trunk so nothing has been lost, but it's not in a state right now I can make another RC release as I'm working on a few features that I've realized are needed now that I've started on the example demo.

The import statement is however still usable.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121013)
qbradq wrote:
LOL, I like that line, "Some assembly required". I may make that the moto for the language :) in general you can do anything in uc65 that you could in assembly, but one of the goals for uc65 was to inter-operate very well with inline assembly.

Be my guest :D.

qbradq wrote:
Just as an FYI, I noticed that the JAR I uploaded does not have the import directory and auto-deps features mentioned above due to a versioning mishap. I've merged the other changes back into trunk so nothing has been lost, but it's not in a state right now I can make another RC release as I'm working on a few features that I've realized are needed now that I've started on the example demo.

The import statement is however still usable.


Nice. Anyway, could you make some changes to the syntax so it won't look like BASIC so much? Perhaps use Pascal-like syntax (with declaring variables in runtime instead of var section)? This is purely cosmetic change that would help people who feel aversion to BASIC (I don't, made share of VBA, VB and FreeBASIC code and it was clean - though I admit it is easy to make spaghetti code if you don't know what you are doing and are fan of On Error Resume Next. I guess that's the price for entry-level language) be more at home with uc65. Though as this has subjective nature, feel free to ignore this suggestion if you wish.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121020)
Variables do not have to be declared in any specific section. Global variables may be declared anywhere outside of a subroutine or other block statement such as a type definition. Local variables may be declared at any point in a subroutine and will have non-lexical scope.

Can you help me understand where you got the impression that you had to have your variable declerations in a certain position in the source code? This understanding could help me make this more clear for other users.

Thank you for the input!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121026)
Due to critical defects with no work-arounds the current release candidate has been retracted. I have them patched but am working on final testing. Expect a new release to be available within 24 hours.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121033)
Quote:
I only questioned why you didn't revive some old "high level" project that showed promise but was abandoned :).

I dont understand your critism. You are criticizing dbraq to do something from scratch instad of reviving some old rotten failed project that was never proven any useful in the first place. How is this any constructive ? The goals and rationale behind uc65 as far I can tell are completely different, and making it from scratch was probably a better solution else he would have chosen otherwise.

Quote:
Anyway, could you make some changes to the syntax so it won't look like BASIC so much? Perhaps use Pascal-like syntax (with declaring variables in runtime instead of var section)? This is purely cosmetic change that would help people who feel aversion. This is purely cosmetic change that would help people who feel aversion to BASIC [...]

Seriously what does this mean ? You want to make him changes to the syntax just because you don't like BASIC ? Why not let him choose his favourite syntax since he's the guy behind the language ?
Over the years I learnt that syntax really doesn't matter much in programming, is more about how you understand the scementics behind it.

I think that instead of doing foolish suggetions that are completely out placed you'd rather stay on subject.
I just asked a comparison with ATALAN because both seems to follow the same goal : Mid level languages to target specifically 6502 processors (and work around the problems that implementing C in 6502 is).
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121073)
Uploaded new build, Release Candidate 3, which fixed the afore-mentioned critical defects. I've also added two features that were found to be needed for practical development: binary file inclusion and compiler command-line constant definitions. Both features are well documented in the user guide.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121079)
Bregalad wrote:
Seriously what does this mean ? You want to make him changes to the syntax just because you don't like BASIC ?


You misunderstood me. *I* like BASIC, written many code in that language, as previously stated. Most programmers I know, however, hate this and would be put off by basic-like syntax if I'd show them uc65.

Also you jumped the gun with that post. If you'd read last sentence, you'd see:
Quote:
Though as this has subjective nature, feel free to ignore this suggestion if you wish.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121089)
Honestly I had considered using a more C-like syntax. Considered is too soft a word. The first draft of the user manual had the syntax of C :) But in the end I chose to base it on the BASIC syntax to avoid some confusion. I felt that if the language had the syntax of C people would get confused when some of the most basic functionality of C was unavailable. Couple that with targeting a compiler suite that already has a C compiler, and things get very complicated very quickly.

Please understand that I am open to feature requests. My goal right now is to get this thing useful and stable prior to the NESDev 2014 competition so that I and other community members can use it for their entries. If there's a feature missing that would make this more useful for you, please let me know!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121474)
qbradq wrote:
Honestly I had considered using a more C-like syntax. Considered is too soft a word. The first draft of the user manual had the syntax of C :) But in the end I chose to base it on the BASIC syntax to avoid some confusion. I felt that if the language had the syntax of C people would get confused when some of the most basic functionality of C was unavailable. Couple that with targeting a compiler suite that already has a C compiler, and things get very complicated very quickly.

Please understand that I am open to feature requests. My goal right now is to get this thing useful and stable prior to the NESDev 2014 competition so that I and other community members can use it for their entries. If there's a feature missing that would make this more useful for you, please let me know!


I really, REALLY appreciate this move. Anything that lets me focus on creation instead of syntax is a godsend.

What kind of boards should I order from infinitelives to put games made in this onto a real cart?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121491)
Slobu,

Great to see interest in the compiler! I have provided memory configurations for NROM and MMC3, but if you know your way around ca65 (and that is recommended as uc65 targets this toolchain) then you can target any mapper you want. My personal choice was to get an MMC3 board with 32KB CHR-RAM and 512KB PRG-ROM Flash pre-assembled. I think this is the most versatile of the mapper choices provided with the board.

If you dislike CHR-RAM you can choose a CHR-ROM option. I highly recommend the pre-assembled Flash versions in either case.

INL's boards have several mapper options. As of this post you can order Color Dreams (#11), MMC1, MMC3 or FME7. FME7 is a more capable mapper than MMC3 on paper, but I just prefer MMC3's scan-line counter interrupt over FME7's CPU cycle counter interrupt.

As I said, with a little tinkering you can make the compiler target any of these mappers. And if that's a bit over your head, just let me know what mapper you want to target and I'll create the mapper support for it. Just remember that you'll still have to understand the behavior of the mapper and use it correctly in your code.

Thanks!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121496)
I guess it also depends on what the first example game is going to be. Most experience newbies (ha!) start by hacking the provided examples and work there way towards original code.

I assume the first example would be something like scrolling a happy face around a single screen? Or maybe something a little more grand like a side-scrolling level? In that case all that's needed is MMC1.. right? *shrugs*
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121500)
The mapper does not maketh the game. See Super Mario Brothers, implemented with no mapper at all. It's got 32 levels of side-scrolling awesome :) Castlevania and Mega Man 1 and 2 were implemented with UxROM, which has nothing special in it at all. Just one PRG bank and CHR-RAM.

The first example shows a star field with a sprite-based cursor that can be moved around the screen with the controller. This uses the MMC3 mapper for no other reason than it was the only dev cart I had at the time :) You can find it in the exampes/nes/simple directory in the zip file. The next example is supposed to be some sort of variation on Conway's Game of Life, will target NROM and may end up being my compo entry if I can't get some better inspiration :)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121501)
qbradq wrote:
As of this post you can order Color Dreams (#11)
To be fair, he says he can make any of the discrete mappers. He's just only had demand so far for the color dreams board. And there's only 50¢ difference between what he charges for the MMC1 and discrete logic reproductions.

slobu wrote:
I assume the first example would be something like scrolling a happy face around a single screen? Or maybe something a little more grand like a side-scrolling level? In that case all that's needed is MMC1.. right? *shrugs*
Remember that SMB1 and all of Shiru's homebrews were plain NROM. It's not that mappers are a difficult concept (they're not), but they are largely irrelevant to the first 3/4 of "learning how to program for the NES"
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121512)
lidnariq wrote:
qbradq wrote:
As of this post you can order Color Dreams (#11)
To be fair, he says he can make any of the discrete mappers. He's just only had demand so far for the color dreams board. And there's only 50¢ difference between what he charges for the MMC1 and discrete logic reproductions.

TL;DR: I'm working to make NROM and discrete mapper fully assembled flash boards more efficiently than my current means. I can make any of these on request, just send me a PM email of what you'd like and we can discuss specifics of that board/mapper.

Yeah I haven't focused a lot on getting the discrete mappers to market a whole lot up to this point. The colordreams was requested by several people so I put it up even though I hadn't specifically designed support for it with my v1 eprom boards. After completing my v2 flash boards I recognized I kind of neglected the idea of a simple flashable discrete mapper board. I just ordered another batch of my smaller v2 full flash boards that'll be available in ~month. I added jumpers for cutting the flash down to NROM size and also have BNROM support. I've had a lot of requests for a simple flashable boards for discrete mappers and NROM as of late with more people becoming aware of my projects. Today I've come to realize it would make things simpler to just have a dedicated NROM/Discrete mapper flash board. That'll keep things cleaner from a manufacturing standpoint and allow for significantly fewer jumpers. Not sure when I'll have those ready, but I'm hoping for early next year. I can make any of these boards today fully assembled with flash or in a eprom version. The flash versions just wouldn't be as efficient as I'd like in the end. Sorry I'm realizing that may have made things even more complicated... ;)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121534)
I do try to be fair to INL. I'm a big cheer-leader for him :) But when folks ask me "what do I buy", I try to only talk about what's available for order on the site today.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121544)
I know not what I speak of so please forgive me.

It sounds like mapper 11 + uc65 is the way to go. Some of the examples mentioned use MMC3 though. Is there going to be a difference to the end user (me)? For instance, when I have to switch banks will I have to implement different code?

I may be spoiled because in batari BASIC switching banks is as easy as:

if hp = 0 then goto gameover bank2
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121548)
In uc65 you'll have to implement different code to target different mappers. As of today I don't have any of the memory mappers implemented as libraries because I haven't quite gotten around to it yet :) Let me know which ones you want and I'll make them a priority.

Color Dreams has no fixed PRG bank, and I don't have any examples for that type of setup yet. That gets a bit interesting :)

So here's the basic pattern. First, declare the data or code you wish to bank swap in the swap-able bank. For instance, a 128KB UNROM board would have bank 7 as the fixed upper bank, and banks 0-6 swap-able.

Code:
rom 0
export sub level1BossAI
end sub
rom 1
export sub level2BossAI
end sub


Then you'd need to call a bank swap routine for the memory mapper from the fixed bank and call the banked sub.
Code:
rom 7
export sub main
  if level == 1
    uxromBank 0
    level1BossAI
  else if level == 2
    uxromBank 1
    level2BossAI
  end if
end sub


There's better ways of doing the above, but it serves as a hello world type of example.

So now, I suppose I'd better get on the stick with implementing mapper support, examples and tutorials :) Thanks for the push Slobu!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121550)
I think you're on a roll. Infinitelives too. This could be the one-two punch that gets many more game makers to express themselves on the NES.

One suggestion: can "export" be changed to "declare"? It's a little more expressive and alot more friendly to people coming from BASIC :)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121560)
Well, for the same reasons I didn't want to model the language too closely to C, I'm trying not to make it too close to BASIC so folks won't get freaked out when things like for and multiply don't work. Changing the compiler would be a lot easier than changing the examples and documentation though :)

Also, please understand that uc65 is not targeted at novice users. It's really an assembler on steroids, and requires a deep understanding of the hardware and underlying cc65 tool-chain to use effectively. If you want something that's more friendly, there's cc65 itself which implements a fairly complete C implementation, and has been used successfully on several projects.

Here's Shiru's article on the subject which links to basic texts to get you going, and then dives into the finer points of how to make things more efficient.

The only down sides to cc65 are that 1) with great power comes great complexity, and code that isn't as fast or small as it could be, and 2) it doesn't deal with banking at all. But those are the trade-offs you make for the ease of development. This project was started in response to these issues, to explore if it was possible to eliminate the trade-offs while keeping the ease of development. As it turns out, no, no it's not. uc65 is much harder to develop in than C, but much easier than assembly (once you know it anyway). The generated code is faster and smaller than what comes out of cc65, but not quite as good as what you can do by hand.

I think uc65 may be a useful tool because it tightly integrates with inline assembly, handles banked data, code and variables and is well documented.

These may or may not fit your needs or use cases.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121563)
I appreciate the fair warning about my own expectations. I've read this topic enough to realize you had some of your own internal struggles as to what uc65 is.

From what I've seen of your code here and in the main.uc examples it's almost exactly like batari BASIC for the Atari 2600. BASIC is about clarity - functionality without getting bogged down in syntax and form. I think you've got a great start.

Maybe I just don't get what the key word "export" means in C and asm. Now that I take a closer look it seems that it's used to do more than declare a sub-routine?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121575)
The export keyword makes whatever it applies to, be that a type, variable or subroutine, visible from other source files that use the import statement to reference the source file that defines them. This is how uc65 supports splitting your code into multiple files as well as encapsulation.

At the lower level, variables and subroutines defined with the export keyword also receive exports in the generated assembly files, which makes them visible to other assembly files at link-time without having to reference the source code. This is how C implements static libraries.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121873)
So I'm writing up a "Getting started with uc65 for Dummies" doc. I've found the simple setup stuff can be daunting/near impossible for someone who's never compiled anything before or has limited experience with this stuff. So hopefully my guide will help out the average dude running on ~windows7.

I've been able to create .nes files on my windows machine using shiru's .bat files after using uc65 to compile the .s files and everything. But I'm trying to see if I can get bash running on my windows machine in order to use the provided (or similar) make.sh file.

I'm giving this guy a try: http://win-bash.sourceforge.net/

I got bash running but the initial problem was due to the double brackets? My bash scripting is a little rusty here... So I figured I'd just toss out what I've got and see if you can help me out here getting things going.
Code:
C:\Users\Paul\Dropbox\nesdev\uc65-release-0.5-rc3>bash make.sh
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: : command not found
make.sh: : command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
make.sh: [[: command not found
C:\PROGRA~2\SHELLW~1\find.exe: /lib/: No such file or directory
C:\PROGRA~2\SHELLW~1\find.exe: /lib/: No such file or directory
Error: Unable to access jarfile /uc65.jar
make.sh: option not availible on this NT BASH release
make.sh: fork: No such file or directory


I replaced all double brackets with single brackets, and looks a little better:
Code:
C:\Users\Paul\Dropbox\nesdev\uc65-release-0.5-rc3>bash make_paul.sh
make_paul.sh: ${BASH_SOURCE[0]}: bad substitution
make_paul.sh: [: missing `]'
make_paul.sh: : command not found
make_paul.sh: : command not found
make_paul.sh: 10075696: No such file or directory


But now I'm having trouble with referencing the UC65_HOME...

Code:
if [ -z "$UC65_HOME" ]; then
   UC65_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
fi


Any suggestions? Perhaps it's a lost cause trying to get a bash makefile up and running on windows?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121874)
UC65_HOME should be set to the path of the directory containing uc65.jar

I'd probably recommend using the bash that's part of mingw; it's comparatively modern (while win-bash is bash 1.14 !) I'm not certain how to go about debugging the differences.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121875)
infiniteneslives wrote:
I'm giving this guy a try: http://win-bash.sourceforge.net/

Have you tried MSYS bash?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121877)
infiniteneslives wrote:
So I'm writing up a "Getting started with uc65 for Dummies" doc. I've found the simple setup stuff can be daunting/near impossible for someone who's never compiled anything before or has limited experience with this stuff. So hopefully my guide will help out the average dude running on ~windows7.

...

Any suggestions? Perhaps it's a lost cause trying to get a bash makefile up and running on windows?

I thought the whole point of this topic was uc65 was to make it easier for people to get into NESdev than jumping in with the cc65 toolchain. But now 8 pages into this thread we're talking about how it's "daunting/near impossible for someone who's never compiled anything before"? :roll:

I offered to integrate uc65 into NESICIDE, which would give people a platform that would have large amounts of the setup already done and tied up in easy-to-get-started "template projects" that are already available in the tool for ca65- and cc65-based projects. NESICIDE's Windows installers already come with cc65 toolchain and GNU Make for Windows, and it builds/exports its own makefiles for projects, and invokes them. There wasn't any response, though, so I forgot all about it. As I said in that post, I'm all for providing alternatives and trying to make things easier for people...but I myself likely won't be a "user" of uc65 [unless and until I actually get to the point of trying to create something for the NES] so I'd need help/feedback to make sure the integration of NESICIDE and uc65 is useful and "user friendly" -- to address the "daunting/near impossible" concern.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121879)
There's been a lot of misconceptions about the goals of uc65. The intent was never to provide a user-friendly development environment, it was to provide a more efficient, in terms of development effort, development tool that was reasonably efficient in terms of resource utilization on the target platform. And as I've said countless times, uc65 is a drop-in replacement for cc65 in the tool chain. If you don't know how to compile C sources with cc65, you won't be able to compile uc sources with uc65.

On the subject of make.sh in the recent source release, this requires a recent version of Bash (version 2 at least, preferably version 3+). This was never intended as a full-on build solution, it was just a quickie I threw together for testing purposes because I haven't settled on a build management solution to adopt yet. It will not be supported in the near future.

On the subject of NESICIDE integration, you are free to do as you wish with the sources of uc65. It's all open source. But until I get more of the build management details nailed down it's going to be a moving target.

So there's something to learn here: a lot of folks have the expectation that uc65 should be user-friendly, and a key sore spot on the user-friendliness aspect is the lack of a "go button". As I have said before, I do not want to get into the business of maintaining a build management system, but I will work to include official support for an existing build manager.

Thank you all for your input!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121880)
qbradq wrote:
There's been a lot of misconceptions about the goals of uc65.

Mine included. I apologize. MY goal [I have "tool guy disease"] is to try to make it easier for [myself/]people to dev. If uc65 in a NESICIDE environment achieves that, cool.
qbradq wrote:
On the subject of NESICIDE integration, you are free to do as you wish with the sources of uc65. It's all open source. But until I get more of the build management details nailed down it's going to be a moving target.

If I understand properly, uc65 is just a JAR that can be invoked by a makefile. Thus, integrating it into NESICIDE isn't really integrating two sources together, just adding a bit of "build manager" infrastructure into that which already exists in NESICIDE's ability to create/execute makefiles to build projects out of assembly-, C-, or [using uc65.jar] uc-source files.
qbradq wrote:
So there's something to learn here: a lot of folks have the expectation that uc65 should be user-friendly, and a key sore spot on the user-friendliness aspect is the lack of a "go button". As I have said before, I do not want to get into the business of maintaining a build management system, but I will work to include official support for an existing build manager.

I guess I don't follow what additional work you'd have to do. I just downloaded the package and compiled the example/simple/src/main.uc to see what would happen. I think that should be fairly straightforward to integrate. Guess I'll go give it a try... I might be able to give you that "go button" pert quick. :beer:
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121884)
That'd be awesome cpow! :) But yea, if you have an existing makefile for cc65, you can define another rule that builds .s files from .uc files and that's that. There's even a make-style dependency generation flag for uc65.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121891)
Yeah I'll hold of on the bash stuff. My main goal was to help someone take the step from compiling roms as done by nerdy nights (asm6?) To using uc65. I think using .bat files as provided in shiru's example is the simplest minimalist approach.

That said I'd love to see support for uc65 in NESICIDE. I'll give NESICIDE another try and give you the user freindly feedback you're asking for. To be honest, this 'getting things started' step is where I gave up on NESICIDE when I initially gave it a try. I don't remember the details of what my issue was as it was well over a year ago now. I only remember being new and confused not being able to find that 'go button' to build a program so I was quickly frustrated and tried elsewhere.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121893)
qbradq wrote:
That'd be awesome cpow! :) But yea, if you have an existing makefile for cc65, you can define another rule that builds .s files from .uc files and that's that. There's even a make-style dependency generation flag for uc65.

Ok I'm almost there...but I seem to have hit a snag.
Image
That error is coming from the main.s that is generated by uc65.jar. Here's what I did:
1. Created a new NROM "Hello World" template project.
2. Gutted it [I really should create a "completely empty" template project].
3. Copied the following files into the project folder:
lib/nes/nrom/memory.cfg -> ./
lib/nes/nrom/crt0.s -> ./src/
lib/nes/nes.uc -> ./src/
examples/nes/simple/main.uc -> ./src/
4. Set the project's linker-config file to the memory.cfg file.
5. Added custom build rules to support building a .s from a .uc file.
6. Tried to build...

You can see the uc65.jar being used in the output window.

I verified I get the same error when trying to do ./build.sh nes simple in your examples folder [after fixing the path to CC65 for my setup]:

Code:
$ ./build.sh nes simple
ld65.exe: Error: Missing memory area assignment for segment `ROM31'


Seems like the JAR file is expecting something similar to what is set up in the MMC3 example? That's the only place I see ROM31 segment defined.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121899)
I switched to trying to build the life example.

What's this about?
Code:
java -jar C:/Users/Christopher/Projects/NES/nesicide/deps/cc65-master/bin/uc65.jar -i src -o obj/nes/main.s src/main.uc
src\nes.uc:18 Error - Expected a number or constant reference
src\nes.uc:19 Error - Expected a number or constant reference


Also, when I try ./build.sh nes life in Cygwin:

Code:
$ ./build.sh nes life
Error - Unable to determine parent directory of source file
Compilation failed


Also, if you could make the warning/error message format match CC65's, the snap-to-line functionality already in NESICIDE would work without me having to special case the output parser for uc65. :D

An example of the CC65 message format:
Code:
$ cc65 main.uc
main.uc(1): Warning: Implicit `int' is an obsolete feature
main.uc(1): Error: `;' expected
main.uc(1): Error: Identifier expected
main.uc(1): Warning: Implicit `int' is an obsolete feature
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121922)
Can you please confirm which release you are using? 0.5-rc3 (attached to the first post) is the most recent release and has these issues corrected.

As for build.sh, I'm not sure it's going to work well under msys / cygwin. Again, this is why I'm not wanting to roll my own build system :)

Also, can you try the attached jar and see if the message output works with your snap-to-line feature?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121929)
qbradq wrote:
Can you please confirm which release you are using? 0.5-rc3 (attached to the first post) is the most recent release and has these issues corrected.

As for build.sh, I'm not sure it's going to work well under msys / cygwin. Again, this is why I'm not wanting to roll my own build system :)

Also, can you try the attached jar and see if the message output works with your snap-to-line feature?


I downloaded 0.5-rc3, yes. Your patch works but I've got a little bit of work to do to get the error annunciation markers in the margins working for .uc files.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121934)
cpow wrote:
qbradq wrote:
Can you please confirm which release you are using? 0.5-rc3 (attached to the first post) is the most recent release and has these issues corrected.

As for build.sh, I'm not sure it's going to work well under msys / cygwin. Again, this is why I'm not wanting to roll my own build system :)

Also, can you try the attached jar and see if the message output works with your snap-to-line feature?


I downloaded 0.5-rc3, yes. Your patch works but I've got a little bit of work to do to get the error annunciation markers in the margins working for .uc files.

Couple other small things:

    Output error/warning messages to stderr instead of stdio. That way NESICIDE will colorize the error messages red in contrast to the non-error messages in the build output.
    It seems uc65.jar might be returning a "success" process exit code which causes make to continue on even when there's indicated Error messages in the last invocation?

EDIT: The error/warning thing seems to be a 3-character 'fix': System.out <> System.err - but I don't have your latest code since you sent me just the JAR with the error string format patched. So I will wait for your update.

I might take a look at your code and offer a patch but I am rusty with Java. I bought a book on it in '96, spent a weekend holed up in a UMich computer lab programming a peg solitaire puzzle game, and promptly forgot about the experience. :D
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121976)
Line 31 of main.uc in examples\nes\simple:
Code:
; Put all of this into the high page of ROM and system RAM
rom 31
ram 1

Pretty sure that's not supposed to be rom 31 as I'm getting a compilation error about segment ROM31 not defined...

I changed it to rom 0, but my .nes file still isn't getting built properly as the reset vector is missing/mis-placed.

Ahh nvm, think I figured it out, this simple example is supposed to be mmc3... With setting that to rom 0, and using the nrom config files I was able to compile and looks like it's booting as everything goes black now vice grey screen. There isn't any chr data included and I'm not sure if there was meant to be anyways... Try something else?

I'd like to just get something up and running on NROM. Looks like life is NROM and has chr data provided, so let's give that a try!

Well I was able to compile and create a .nes file, but I had to comment out lines 18 & 19 in nes.uc:
Code:
; NES System Library
rom librom
ram libram


Because I was getting this error:
Code:
C:\Users\Paul\Dropbox\nesdev\uc65-release-0.5-rc3>java -jar uc65.jar lib\nes\nes.uc
lib\nes\nes.uc:18 Error - Expected a number or constant reference
lib\nes\nes.uc:19 Error - Expected a number or constant reference
Compilation failed


Commenting those out allowed me to get a successful build. And I'm getting something as it's booting with a bunch of zeros on the screen. Not sure if whatever I'm missing without those librom/ram lines is causing an issue or if I'm building something improperly.

Here's my hodgepodge .bat file that allowed me to compile things in their locations as downloaded. Only issue was I needed to make a second copy of nes.uc and put it in the src directory so it could be included in the other .uc files.

Code:
java -jar uc65.jar lib\nes\nes.uc
java -jar uc65.jar examples\nes\life\src\blinktext.uc
java -jar uc65.jar examples\nes\life\src\data.uc
java -jar uc65.jar examples\nes\life\src\title.uc
java -jar uc65.jar examples\nes\life\src\main.uc
path=path;cc65\
set CC65_HOME=.
ca65 lib\nes\nrom\crt0.s
ca65 lib\nes\nes.s
ca65 examples\nes\life\src\blinktext.s
ca65 examples\nes\life\src\data.s
ca65 examples\nes\life\src\title.s
ca65 examples\nes\life\src\main.s
ld65 -o life.nes lib\nes\nrom\crt0.o lib\nes\nes.o examples\nes\life\src\blinktext.o examples\nes\life\src\data.o examples\nes\life\src\title.o examples\nes\life\src\main.o -C lib\nes\nrom\memory.cfg
pause
life.nes


Any suggestions on how to fix me up so I can make a successful build of life? After that I'll post my 'getting started' doc to help newbies out and get started on my own project! :)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121979)
I also get what I think infininteneslives is describing once i comment out the
Code:
rom librom
ram libram

in nes.uc.
Image
But it looks like something isn't quite formatted right in the generated debug info file [error in output pane]. I'll take a look. But I too am wondering what we should expect from the "life" example?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121980)
Wow folks, I'm floored by the amount of interest! Thank you so much! I wish I weren't so swamped with work at the moment and could whip all this up into shape. Hopefully this weekend I'll be able to make another release that reduces all the confusion.

The "simple" example uses MMC3 with character RAM. I'll change this to use NROM so it's a lot more simple :)

The "life" example is not anywhere near complete. Honestly I'd never compiled the thing. A screen of zeros is actually what should happen with the code that's present now. I am going to move work-in-progress examples into their own branch in the repo and only merge them into the main trunk when they are complete so as to avoid this confusion. Sorry folks.

The librom and libram bits were part of the build management conventions I was tinkering with before I had to disengage due to the Thanksgiving holiday prep. The thought was the standard libraries would use constants librom and libram to determine what rom and ram banks to use, and then when evoking the compiler you would use the -c argument (twice) to define both. That way you can control at build-time where these things are placed.

Finally, that was a bone-head miss to send the errors to stdout :) I'll get that fixed as soon as I can.

Also, as for the debug info, I have no idea what's going on there. This stuff isn't documented anywhere and honestly I've never tested it.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121985)
I'm still looking into the debug info issue, but...
I removed the offending line and :beer: :beer: :
Image
Not only is source following working, I can set breakpoints. :beer: :beer:
Almost to that "go button", eh? :mrgreen:
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121986)
That's awesome! Can you paste in the offending line so I can track it down?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#121988)
qbradq wrote:
That's awesome! Can you paste in the offending line so I can track it down?

Line 2187 in the debug info is:
Code:
type   id=4,val="90"

But I'm not sure how to figure out what source module that comes from.
For reference, the debug info parser doesn't complain about these lines:
Code:
type   id=0,val="800420"
type   id=1,val="800120"
type   id=2,val="800220"
type   id=3,val="800321"
type   id=5,val="800C20"
type   id=6,val="800320"
type   id=7,val="800820"

Just to be clear, it is the debug info parser provided in the CC65 source that is complaining. This is not a compilation issue.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122018)
qbradq wrote:
The "life" example is not anywhere near complete. Honestly I'd never compiled the thing. A screen of zeros is actually what should happen with the code that's present now. I am going to move work-in-progress examples into their own branch in the repo and only merge them into the main trunk when they are complete so as to avoid this confusion. Sorry folks.
No worries, I'm glad that I'm getting what I should be, I'm not too concerned about getting life to work if it's not yet complete. I'm thinking about working on converting some of shiru's simple examples or at least a hello world to start.

Quote:
The librom and libram bits were part of the build management conventions I was tinkering with before I had to disengage due to the Thanksgiving holiday prep. The thought was the standard libraries would use constants librom and libram to determine what rom and ram banks to use, and then when evoking the compiler you would use the -c argument (twice) to define both. That way you can control at build-time where these things are placed.
I like that idea! :)

I re-read over the documentation today and took some notes for my own learning purposes. Pretty refreshing that I was able to read the entirety of the language's definition in an hour or so. I'm pretty excited to get going with this, especially not that it's ready for use! It really feels like uc65 has the simple elegance of only giving you what's needed to overcome the inefficiencies of assembly. All the extra fat that's not needed just simply isn't there. The fact that it's not highly abstracted away from the hardware is great and really opens the door for mapper use. I also love the easy integration of inline assembly. Time to jump in and see if it's everything I'm cracking it up to be! :)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122110)
Sorry, double post, have things to share, and questions to ask.

I finished a hello world demo in uc65! :D

Here's my Getting Started with uc65 for Dummies guide. There is a .zip download to go along with it for the hello world build. Feel free to do whatever you'd like with it. It's more than welcome to be included in the first post or project page for others to find more easily.

I had some confusion about something on the doc:
Quote:
Loop Statement

The loop statement executes a block of statements indefinitely, or until a conditional expression evaluates as true. The block of statements will execute at least once as the optional conditional expression is evaluated at the end of the loop.
Code:
loop
  [statement block]
end loop [when (conditional expression)]


So it loops until the conditional expression evaluates to true? Or till it's false? If it's the former, I guess i makes more sense now that I read it at "*END* loop when (cond expr)". I originally thought of the "end" as syntactical only, I was reading it without the end, just "loop when (cond expr)" which doesn't make sense.

I have should probably answer my own question here by looking at my compiled assembly files. But I'll ask here anyways. I'm a little curious about RAM management. I understand the 'ram' segment identifier can be used to define where ram will be allocated. Does this apply to ALL allocated ram for the code that follows? (with the obvious exception of zero/fast variables). How are passed in variables handled specifically? Is the stack used for transfer, and then the sub routine allocates ram in it's defined segment? Or is it that the stack isn't used, but the copy which the sub routine receives is allocated it's segment? Or is it still in the calling routines' segment? If one wanted to allocate specific locations of variables/arrays would the best way to do this be define a new segment? If one wanted OAM ram to be in it's typical location is the type of thing I'm thinking here. Additionally down the road I'd like to swap ram and "pseudo-ROM" in $6000-7FFF so with bankswitching RAM around I'd like to ensure my attack is inline with the abilities and methods of uc65 variable allocation.

Couple typos:
Code:
test\subroutines.uc:41 Warning - Possible loss of percision


documentation under address dereferencing:
Code:
address prt
ptr = $0200


All in all, it was pretty fun to play around with and get my hands dirty with the language. Kudos on the great work thus far qbradq! There were a couple times where I knew exactly what I wanted in assembly, and wasn't sure how to get the language to give it to me. So having the ease of inserting assembly without trouble is pretty awesome and allows you to stay close to the hardware.

I'll be working on building my nes.uc library file and share it here from time to time for anyone who's interested. Ping me if you'd like my latest version, not sure how it'll compare to qbradq's but no need to duplicate efforts further.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122143)
I am super excited about this INL! I have the flu right now, but when I'm better I'll fix the typos and put up the links.

Also, there is no end clause for loop. That was dropped from the language spec but apparently forgot to take it out of the docs.

Subroutine parameters are copy-on-call. If you want them in zero-page, use the fast modifier for the subroutine. If you want the subroutine's variables in zero page, use the fast modifier on the variables. uc65 only uses the stack to store register values during interrupt handlers.

rom and ram apply to everything that emits code or variables following those statements until the next such statement.

Again when I am feeling better I will try to make the documentation more clear.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122151)
qbradq wrote:
Also, there is no end clause for loop.
So loop is basically an infinite loop then? Same as:
Code:
while 1==1
...
end while

If that's the case, I'd wonder if it's even worth having loop since the while loop is easily adapted to give the same effect.

Quote:
Subroutine parameters are copy-on-call. If you want them in zero-page, use the fast modifier for the subroutine. If you want the subroutine's variables in zero page, use the fast modifier on the variables. uc65 only uses the stack to store register values during interrupt handlers.

rom and ram apply to everything that emits code or variables following those statements until the next such statement.

Again when I am feeling better I will try to make the documentation more clear.


That makes sense based on the limitation that recursion isn't allowed as the second call will override the variables of the first. So basically every subroutine's variables will ALWAYS occupy a location in ram. A subroutines variables aren't temporary. So if one is trying to conserve ram use try to limit the number of variables used. Using globals for a subroutine to modify themselves, vice using temporary storage variables within a subroutine would be best. Or perhaps a handful of global temp variables which all routines can use as scratch. These things make sense when you understand the underlying assembly going on. :) One can take the easy route and create those temporary variables without trouble, but then when it comes to optimizing it helps to have a good grasp of assembly.

Regarding my discussion of having banked ram, it would sound prudent to put all globals in system ram so they truely are global (regardless of banking). To allow subroutines to use banked ram for variable use would require some specific rules. Let me know if this sounds right:

subroutine parameters: when are variables copied over? I assume it's just before the parent routine jumps to the child subroutine. So by ensuring the child's ram bank is active prior to calling the subroutine, you ensure the subroutine will get the copy over of input parameters.

variables within the subroutine: The subroutine needs to ensure it's ram bank is active before using the variables.

There is no harm in the parent setting up ram banking for the child's variables. But as a design choice you could make the child responsible for setting up banking for it's own variables. Parents MUST initialize child's ram banking when parameters are passed in though to ensure proper copy over. Since ram/rom segments can't be used within subroutines, that means the parameters and variables of a subroutine need to be in the same bank/segment. Starts to get tricky the more I think about this... Having banked SRAM would require a lot of delicate care especially if the parent and child's ram wasn't visible at the same time.

Really my only desire is to put game/graphics data swappable with RAM in FME-7 style. So operating with the assumption that the WRAM was always there except for the routines which swapped in ROM for game/graphics data, then you'd be okay.

The best way to handle funky situations like that were you had to handshake between parent and child ram banking would be to make use of the stack and/or A/X/Y registers for passing/returning variables. Using the stack for passing in parameters could be done with the language as-is by creating a helper 'handshake' function to utilize the stack so you'd pass the parameters into the helper vice the subroutine itself.

So I'm having some confusion on how to best utilize return variables. I was writing a subroutine to read controllers:
Code:
;; Read controller ports
;;
;; @param padnum The controller pad desired to be read
;; return button output A,B,sel,srt,U,D,L,R
export sub nesReadPad byte padnum as byte

   ;strobe latch signal
   controller1 = $10
   controller1 = $00

   if padnum == 1
      asm
         LDX #$08
      joy1_loop:
         LDA $4016
         LSR A         ; bit0 -> Carry
         ROL nesReadPad_return   ; bit0 <- Carry
         DEX   
         BNE joy1_loop
      end asm

   else ;if padnum == 2
      asm
         LDX #$08
      joy2_loop:
         LDA $4017
         LSR A         ; bit0 -> Carry
         ROL nesReadPad_return   ; bit0 <- Carry
         DEX   
         BNE joy2_loop
      end asm
   end if

   return nesReadPad_return

end sub
But I'm not sure I'm doing it right... See I don't want to create a new variable, and use that for ROL'ing the controller data into, because there is already a return variable automatically created. So can I just use the sub_return variable without instantiating it (outside of asm portions too) because I know it will be created by the assembler? Do I need to use the return statement since I know I'm modifying the return variable? Or could just leave out the return statement and assume it's implied? Basically I don't know how to use the return variable within the subroutine. Perhaps I should instantiate a variable which conflicts with the return variable's name intentionally? Normally I wouldn't have thought about doing this except the comment in the documentation regarding asm portions brought it up so now I want to give it a try as it conserves on ram use. I suppose once return variables via A/X/Y registers is implemented then this isn't of much use aside from large return variables I suppose.

Is there any way to utilize macros with uc65?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122157)
Quote:
Or perhaps a handful of global temp variables which all routines can use as scratch.


This sounds good. When a function/routine returns a value it would default to the first temp variable (temp1) and go up from there. Also having them available as plain old temp vars is a plus.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122158)
loop is an explicit infinite loop. "while 1=1" will still execute a comparison. There's no compile-time optimization to remove this comparison.

Banking of both RAM and ROM is left to the user to implement and not mess up. Also, to a previous point you had, the OMA page $0200 is already set up in the memory configs.

The caller of the subroutine copies values into the subroutine's parameter variables before the jsr.

Return values are a syntax convenience. If you want to eliminate the automatic variable created by the subroutine, you can place the value in a global temp variable and not use return values. The the caller will have to copy the value manually.

The thing to remember here is that uc65 will not generate 100% efficient assembly code. There's a trade off between ease of development and resource utilization. There's always the option of using assembly :)

Personally I tend to write subroutines like controller polling in assembly because they are small and easy to write in assembly. In the larger main program I write things in uc65 and call the subroutines I've written because it's easier to maintain and develop.

I am concerned that RAM utilization will be a key limiting factor in the size and complexity of a uc65 program though. We'll have to see how it plays out.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122184)
Just FYI I've created a NESICIDE template project using the hello world that INL put together. It works, but there's still the issue of the error in the debug info. That, unfortunately, prevents being able to do source stepping, setting breakpoints, etc. Any luck on that front yet?

So in order to get going in UC65 all one would have to do is create a new project based on the 'NROM Hello World - UC' template. It builds/runs out of the box. I'm going to add uc65.jar directly into the CC65 bin folder that's delivered with the installer, I think...
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122186)
qbradq wrote:
loop is an explicit infinite loop. "while 1=1" will still execute a comparison. There's no compile-time optimization to remove this comparison.
Gotcha. I'd agree the way you've set things up make sense then. People will probably request things like loop N times, but I can see why you wouldn't want to implement that. Better off to force the user to create a while with their own variable for that use.

Quote:
Banking of both RAM and ROM is left to the user to implement and not mess up. Also, to a previous point you had, the OMA page $0200 is already set up in the memory configs.
Yeah I understand that, I was trying to figure out how to not mess it up. ;) I noticed the OMA defn shortly after posting of course...

Quote:
Return values are a syntax convenience. If you want to eliminate the automatic variable created by the subroutine, you can place the value in a global temp variable and not use return values. The the caller will have to copy the value manually.

I get that, my question is how do I utilize that variable within the subroutine that's about to return it. Perhaps the best answer is just not to try and make use of the return variable before the return statement, but your mention of it's name being 'sub_return' made me want to make use of it. Do I need to instantiate it before making use of it? Or can I just assume it exists with the 'sub_return' name since the subroutine is defined as having a return type?


Quote:
The thing to remember here is that uc65 will not generate 100% efficient assembly code. There's a trade off between ease of development and resource utilization. There's always the option of using assembly :)

I am concerned that RAM utilization will be a key limiting factor in the size and complexity of a uc65 program though. We'll have to see how it plays out.

While I get that we're trading conveince for effeciency when choosing uc65 over assembly, I share your concern about ram utilization. So understanding how the language makes use of and allocates ram aids in trying to write uc65 code that conserves on ram use. From what I'm seeing thus far you have to think about ram use as if you're writing in assembly. I think doing that will go a long way to keeping ram from becoming scarce with uc65.

cpow wrote:
So in order to get going in UC65 all one would have to do is create a new project based on the 'NROM Hello World - UC' template. It builds/runs out of the box. I'm going to add uc65.jar directly into the CC65 bin folder that's delivered with the installer, I think...
Good stuff! Looking forward to playing around with NESICIDE once things are finished up! ;)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122195)
I'm trying to figure out how to rebuild uc65.jar...it's not obvious to me. I'd like to try the following changes to CodeGenerator.java:

Code:
            ".DBG SYM, \"%s\", \"00\", %s, \"%s\"\n",

Code:
            ".DBG FUNC, \"%s\", \"00\", %s, \"%s\"\n",


I looked at CC65 source and it emits "00" not "90" for those.

Hopefully that'll solve the debuginfo parsing problem...but I can't be sure. Can you provide directions for how to rebuild uc65.jar?

EDIT: I manually changed the 90's to 00's in the generated debuginfo file and source stepping works again, so likely the change proposed to uc65.jar will correct the problem.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122229)
Thanks for working that out. The 90 thing was based on reading the source code. Like I said, documentation is no good for this.

I have attached a new zip file, rc4, to the first post. This contains a new JAR file with the 00 fix, the stderr fix and the percision / precision spelling correction. I am over my flu today but still sleeping a lot trying to get my strength back. Should be back in the swing of things tomorrow :)

Edit: Also, if you put uc65.jar into the NESCISIDE bundle, please include the file COPYING (or in some other way note that uc65 is licensed under the GPLv3 or later, and provide the text of the GPLv3) and a link to the project page. This will satisfy the terms of the license as long as you don't make source code changes.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122239)
qbradq wrote:
Thanks for working that out. The 90 thing was based on reading the source code. Like I said, documentation is no good for this.

Works here. I've released a NESICIDE update with a template project for uc65. Eventually I'd like to put a lexer for the language into the editor, and support symbol tool-tips. Actually...if you treat your symbols like C symbols [prepend an underscore in the generated ASM output], what's there for C support might "just work". But anyway, symbol watching appears to work, breakpointing, stepping source, also.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122622)
Not sure if I was supposed to be able to derive this issue from the doc or not, but quoting the doc:
Quote:
IMPORTS/EXPORTS section: Note that the compiler does not compile imported source files into assembly files, nor does it automatically link these assembly files. The user must take care in their build automation steps to separately compile, assemble and link each source file needed to construct the entire program. Failure to do so will result in unresolved symbols at link time. See the section "Build Automation" for more information.


I have 3 files, global.uc, sprite.uc, and main.uc

I want sprite.uc and main.uc to import global.uc, and I want main.uc to import sprite.uc.

The ordering in which the files are imported into main.uc is critical, else errors plague you.


main.uc broke:
Code:
import "sprite.uc"
import "global.uc"


main.uc works:
Code:
import "global.uc"
import "sprite.uc"


I also verified that sprites.uc wasn't bringing global.uc along for the ride when sprites.uc is imported to main.uc, so the issue isn't global.uc getting doubly imported. I'm not used to the order things are imported making much difference.

Not saying it should necessarily needs to be changed. But it threw me for a loop for awhile, perhaps explaining that in the manual (more clearly?) would be helpful. Or maybe the upcoming "build automation" doc will help explain? Just thought it was worth sharing at a minimum.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122659)
Can you help me understand how the first scenario "broke"? Does sprite.uc import global.uc? I think I may have an issue with the way I am preventing multiple imports, let me look into this.

Also, I have updated the documentation regarding the loop statement to be correct.

Thank you all for your patience with this project as I got my day job situation taken care of!
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122661)
qbradq wrote:
Can you help me understand how the first scenario "broke"? Does sprite.uc import global.uc? I think I may have an issue with the way I am preventing multiple imports, let me look into this.

Yes, both main.uc and sprite.uc import global.uc, and main.uc imports sprite.uc

sprite.uc does not import anything besides global.uc, and global.uc imports nothing.

no other files import global.uc

sprite.uc
Code:
import "global.uc"


main.uc
Code:
import "nes.uc"
import "data.uc"
import "sprite.uc"
import "global.uc" ;must come before sprites.uc which also imports global.uc


errors:
Code:
C:\Dropbox\nesdev\dig_deeper2>java -jar ..\uc65.jar source\global.uc

C:\Dropbox\nesdev\dig_deeper2>java -jar ..\uc65.jar source\nes.uc
source\nes.uc(165): Warning: Possible loss of precision

C:\Dropbox\nesdev\dig_deeper2>java -jar ..\uc65.jar source\sprite.uc

C:\Dropbox\nesdev\dig_deeper2>java -jar ..\uc65.jar source\main.uc
source\main.uc(30): Error: Unresolved symbol gameState
source\main.uc(62): Error: Unresolved symbol buttons1
source\main.uc(63): Error: Unresolved symbol buttons2
source\main.uc(69): Error: Unresolved symbol buttons1
source\main.uc(72): Error: Unresolved symbol buttons1
source\main.uc(75): Error: Unresolved symbol buttons1
source\main.uc(78): Error: Unresolved symbol buttons1
Compilation failed


global.uc:
Code:
; along with this program.  If not, see <http://www.gnu.org/licenses/>.

export fast byte gameState
export fast byte buttons1
export fast byte buttons2

;;buttons
export constant   NOTHING      = %00000000

;;gameState
export constant   TITLE      = $00
export constant LEVEL1       = $01
export constant LEVEL2       = $02
export constant GAMEOVER    = $FF


;;metaSprite.state
export constant INACTIVE   = $00
export constant NEWBORN      = $01
export constant NORMAL       = $02
export constant DYING      = $FF


Make this one change to main.uc and errors go away:
Code:
import "nes.uc"
import "data.uc"
import "global.uc" ;must come before sprites.uc which also imports global.uc
import "sprite.uc"




Quote:
Thank you all for your patience with this project as I got my day job situation taken care of!
No problem, thanks for working on things as time permits. :)
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122678)
Thanks for the bug report INL! I have raised Issue 4 in the bug tracker to track the status of this issue. The issue has been reproduced and a failing regression test added to source control. I am working on the fix now. I'll also update this thread when I fix it.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122725)
I'm confused as to how break and continue statements are supposed to work especially with providing number of loops to advance.

Since there are no defined iterators (like a typical for loop would have), how does the language/compiler know what iteration to advance to? I've created the same effect of a for loop using the while statement, but have to create my own iterator. It doesn't seem that the language would support "continue [n]" and know which variable is my iterator. Based on how the while and loop statements work, it would only make sense for the user to have to manually advance the iterator prior to the continue call.

I tried to use continue, and I'm pretty sure it's broken, although due to my confusion above and lack of trust in my surrouding logic I'm not yet certain of the issue. I still need to look through the asm output though too. I wanted your input and improve my understanding before I start trying to debug further.

This is the current definition:
Quote:
Continue and Break

The continue and break statements advance to the next iteration of, or end condition of a containing while or loop statement block respectively. An optional number of nested loops to advance through may be provided.

continue [n]
break [n]

Where n is the number of nested loops to advance through. If omitted, this defaults to one. N must be greater than zero and less than or equal to the nested loop depth.


I'm guessing it's just a carry over issue similar to the loop conditional, so if I were a betting man I'm thinking with the current while and loop definitions the following would be more accurate:
Quote:
Continue and Break

continue within a while block: jump out of the while loop and evaluate the while conditional to determine whether to re-enter the while statement block or to exit the while block.

continue withing a loop statement block: jump out of current iteration of the loop and restart from the loop statement.

break within a while statement block: exit the while block all together.

break within a loop statement block: exit the loop, a means to end the infinite loop.

There is no such thing as: continue [n], but you can create the same effect by manually advancing your own iterator prior to the continue statement. In fact it's 'default' is always "continue 0" because you have to manually advance the iterator, failing to do so would repeat the current iteration from the beginning.

Doesn't make sense: break [n] where n>1, because you can only exit a while or loop statement once. It's as if the 'default' is always 1.


Thoughts? Am I all mixed up here?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122801)
infiniteneslives wrote:
Doesn't make sense: break [n] where n>1, because you can only exit a while or loop statement once. It's as if the 'default' is always 1.

Doesn't the break [n] where n>1 really mean "break out of n nest levels". In other words, if I'm nested three deep and I do a break 2 I'll break not only out of the innermost loop, but the mid-level loop also and find myself back in the outer loop.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122805)
Ahh gotcha, that makes sense. I think the combining of the explanation of break and continue at the same time confused me a little in the doc.

So the only thing I'm confused on now is the continue [n] statement without an explicit iterator.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122832)
So I've been running into issues lately with using variables to index arrays. It took me awhile to nail down exactly what was happening. But I've managed to pin this fatal bug down!

So I've got a simple routine that initializes my hero's metasprite. I initially hardcoded everything to index=0, but now I want to use a variable in order to reuse the routine for initializing other metasprites as well.
Code:
   ;init our hero!
   msprID = 0
   tempLL = msprID
   metaSprite.state[tempLL]    = STILL
   metaSprite.character[tempLL] = HERO
   metaSprite.oam[tempLL]    = $00   ; the xx in $02xx   
   metaSprite.xSpeed[tempLL]    = 0
   metaSprite.ySpeed[tempLL]    = 0
   metaSprite.xSize[tempLL]    = 1   ;one 8x8 sprite currently
   metaSprite.ySize[tempLL]    = 1

   ;For now, hardcode a sprite up in the top left to get things going
   ;TODO: init based on type, location, size, and state etc.
   spriteRam[tempLL] = $10   ;Y pos               ***Line #60***
   tempLL += 1
   spriteRam[tempLL] = $00   ;tile number        ***Using the variable tempLL here causes Y pos above to be overridden to $00...
   spriteRam[2] = $00   ;attrs: 7-flipV 6-flipH 5-Behind 1:0-palette
   spriteRam[3] = $10   ;X pos


The above code compiles to:
Code:
.SEGMENT "ROM0"
.DBG LINE, "source\sprite.uc", 38
.PROC spriteInitMetas
.DBG FUNC, "spriteInitMetas", "00", EXTERN, "spriteInitMetas"
.DBG LINE, "source\sprite.uc", 48
   lda   #$00
   sta   msprID
.DBG LINE, "source\sprite.uc", 49
   lda   msprID
   sta   tempLL
.DBG LINE, "source\sprite.uc", 50
   lda   #$02
   ldx   tempLL                                ;X <= tempLL = 0
   sta   metaSprite_state,x                ;everything is working great indexing with X
.DBG LINE, "source\sprite.uc", 51
   lda   #$00
   sta   metaSprite_character,x
.DBG LINE, "source\sprite.uc", 52             ;still working, all these variables getting set to $00
   sta   metaSprite_oam,x
.DBG LINE, "source\sprite.uc", 53
   sta   metaSprite_xSpeed,x
.DBG LINE, "source\sprite.uc", 54
   sta   metaSprite_ySpeed,x
.DBG LINE, "source\sprite.uc", 55
   lda   #$01
   sta   metaSprite_xSize,x                ;still working, Sizes getting set to $01
.DBG LINE, "source\sprite.uc", 56
   sta   metaSprite_ySize,x
.DBG LINE, "source\sprite.uc", 60             ;***sprite.uc line #60****
   lda   #$10                                  ;loading Y position = $10
   sta   spriteRam,x                          ;X = tempLL = 0, working great, stores $10 into Y pos as expected.
.DBG LINE, "source\sprite.uc", 61
   inc   tempLL                               ;incrementing tempLL just as I asked
   _L000000:                                   ;mysterious label?  What use could this serve???
.DBG LINE, "source\sprite.uc", 62             ;wait a min, you incremented tempLL, but didn't update X which is supposed to equal tempLL... !!!!
   lda   #$00                                  ;okay sure, you're loading $00 for the tile number like I want.
   sta   spriteRam,x                          ;WHAT?  BAD uc65!  no bone!  why did you overwrite the Y-position?!?!?!
.DBG LINE, "source\sprite.uc", 63             ;you just neglected my request to store $00 as the tile number...
   sta   spriteRam+2                         ;okay, now you're doing what I told you to again, but I stopped using the tempLL variable because you were acting up...
.DBG LINE, "source\sprite.uc", 64
   lda   #$10
   sta   spriteRam+3
.DBG LINE, "source\sprite.uc", 76
   lda   #$01
   sta   tempLL
   _L000001:


So it looks to be an off by one error or something like that. tempLL gets incremented, but X is supposed to equal tempLL for indexing. Since X didn't get updated, the Y position got stomped on when trying to store the tile number... Perhaps the creation of that mysterious unused label has something to do with it? IDK...

I'm providing an exact compiled copy of the above code with assembly files and all.
https://dl.dropboxusercontent.com/u/183 ... _broke.zip

Additionally, if I make one change by hard coding the tempLL to 1, things work as expected.
Code:
spriteRam[1] = $00   ;tile number

Here's a compiled copy for comparisons sake. Probably not of much use if one understands my explaination above, it's no surprise that this works.
https://dl.dropboxusercontent.com/u/183 ... _works.zip


Separate unrelated question:
Is there anyway to declare the default ram segment BSSX? For example: say one has a sprite.uc file, and declares oam segment "ram 2" at the top of the file. But then you want the rest of the file to be the default segment BSSX. I can't find a way to declare the default segment for the rest of the file. You can't put them at the bottom of the file either if you want code above to utilize said oam array. Only way I've found is put them in a separate file and import them. The other means was to not use BSSX, but I don't think that's the best route.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122916)
INL,

Thank you so much for your continued bug reports! I have created issue 5 for this issue and have reproduced it in the test files. I took some time off for the holidays, but am working on things now :)

I'm glad you figured out continue / break. I will try to re-write that section to be more clear.

As for the default BSS segment, that is ram 1. So to return to the default, just use ram 1.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122934)
There's a new build on the first post, RC5, which contains the fix for Issue 5 described above. I still haven't dug into the import issue, I should be working on that today after I get caught up on some house work :)

The fix should also avoid some other issues I hadn't considered with the optimizer. Basically the fix was to watch for reference changes, and invalidate the register states that held those referenced values.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#122982)
So rc5 fixed me up in that one spot, but I seem to have found another similar issue...

https://dl.dropboxusercontent.com/u/183 ... BROKEN.zip

There are .uc.BROKEN .s.BROKEN .uc.WORKS and .s.WORKS sprite files in there which toggle the issue on and off.

sprite.uc
Code:
   ;reset to first sprite
   tempLL = metaSprite.oam[msprID]   ;spriteRam[tempLL] -> Y position of first sprite

   attrPtr1 = $0200; + tempLL   ;point to Y location of sprite to be update
   attrPtr2 = $0203; + tempLL   ;point to X location of sprite to be update

   tempJ = 0 ; column * 8
   tempA = spriteRam[tempLL] ; Y location of next sprite to update (redo first sprite)
               ;this allows for sprites of width 8

   tempI = 0 ; row * 8
   tempLL += 3
   tempB = spriteRam[tempLL] ; X location of next sprite to update
   result = tempB        ; extra storage of X location to reset for each row


Compiles to:
Code:
.DBG LINE, "source\sprite.uc", 327
   ldx   msprID
   lda   metaSprite_oam,x
   sta   tempLL         ;setting tempLL = index of first sprite in SpriteRam[]
.DBG LINE, "source\sprite.uc", 329
   lda   #$00
   sta   attrPtr1_a      ;setting pointer to Ypos of first sprite
   lda   #$02
   sta   attrPtr1_b
.DBG LINE, "source\sprite.uc", 330
   lda   #$03
   sta   attrPtr2_a      ;setting pointer to Xpos of first sprite
   lda   #$02
   sta   attrPtr2_b
.DBG LINE, "source\sprite.uc", 332
   lda   #$00
   sta   tempJ         ;tempJ = 0
.DBG LINE, "source\sprite.uc", 333
   ldx   tempLL
   lda   spriteRam,x
   sta   tempA         ;tempA = Ypos of first sprite
.DBG LINE, "source\sprite.uc", 336
   lda   #$00
   sta   tempI         ;tempI = 0
.DBG LINE, "source\sprite.uc", 337
   clc
   lda   tempLL
   adc   #$03
   sta   tempLL         ;tempLL += 3
.DBG LINE, "source\sprite.uc", 338
   lda   spriteRam,x      ;tempLL incremented by 3!!!!, but X didn't!!!
   sta   tempB
.DBG LINE, "source\sprite.uc", 339
   lda   tempB
   sta   result


I'm not sure what's up... It's pretty similar to the original issue, but i doubly confirmed I'm using rc5 uc65.jar

That and I confirmed that updating to rc5 fixed my previous related issue.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123008)
Woops, I forgot to test for the STA case, and that code was not working. I've added another regression test for that case and fixed the issue. Please try RC6, now attached to the first post.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123108)
I've got another issue, seems to be to do with tables and rom segments.

First off, here's my memory.cfg I don't think it's related, but the only thing I've really changed is I don't use BSSX to reserve oam space. I designate it as BSS2 and write uc65 code that manipulates sprite oam memory.

So I switched things around to this:Here is my memory.cfg file. *comments* aren't actually in my file, added for explanation of how I use what.
Code:
MEMORY {
   BSS0:   start = $0000, size = $0100;          *Zero Page*
   STAK:   start = $0100, size = $0100;          *Stack*
   BSS2:   start = $0200, size = $0100;          *sprite OAM memory spriteRam[]
   BSS3:   start = $0300, size = $0100;          *meta sprite objects. I wanted my variables in a fixed location, so sram.s puts them here*
   BSS1:   start = $0400, size = $0400;          *"default" ram space, allocated as the compiler sees fit.*
   HEAD:   start = $0000, size = $0010, fill = yes;
   ROM0:   start = $8000, size = $7FFA, fill = yes;
   VECT:   start = $FFFA, size = $0006, fill = yes;
   ROM1:   start = $0000, size = $2000, fill = yes;
}

SEGMENTS {
   BSS0:   load = BSS0, type = bss, optional = yes;
   BSS2:   load = BSS2, type = bss, optional = yes;
   BSS3:   load = BSS3, type = bss, optional = yes;
   BSS1:   load = BSS1, type = bss, optional = yes;
   HEAD:   load = HEAD, type = ro;
   ROM0:   load = ROM0, type = ro, optional = yes;
   VECT:   load = VECT, type = ro;
   ROM1:   load = ROM1, type = ro, optional = yes;
}

FILES {
   %O: format = bin;
}


So first, a minor comment. Perhaps this is the way it's supposed to be. But it caught me off guard. I found that if I don't declare 'ram 1' in the beginning of my file, all allocated ram ends up in the zero page. So the 'default' (aka no delcaration) puts variables into ZP... But this isn't where the issue is which I found.

The problem is I've created a table in rom 0. But even though I declare rom 0, the compiled assembly doesn't declare which segment of rom to put the table into.

Code:
;-------------------------------------
;Meta-Sprite Character size and tiles
;-------------------------------------
; composite type (struct) used to initialize meta sprites
type metaSpriteCharacter   ;meta sprite init variables
   byte firstTile   ;first sprite tile number, basis of tiles and graphics
   byte numSpr   ;number of sprites in metasprite object (hard math for x/ySize above)
   byte xSize   ;number tiles to be updated in x directoin
   byte ySize   ;8x16 sprites count as one sprite
end type

;;table for sprite data for character definitions
;VERY IMPORTANT that the indexes of this table line up with character constants
; ie HERO=0, is first entry in table

rom 0
table msChar of metaSpriteCharacter   ;must have more than one row!
;recommend copying comment line to msStart table so character defn's and oam location are proper.   
;HERO   = 0            ;2x3 hero
      firstTile=$00,numSpr=4,xSize=16,ySize=16   

;BADDIE1= 1                ;2x2 baddie
      firstTile=$20,numSpr=4,xSize=16,ySize=16

;GOODIE1= 2                              ;2x2 goodie
      firstTile=$10,numSpr=4,xSize=16,ySize=16   

;BADDIE2= 3                               ;2x1 baddie
      firstTile=$29,numSpr=2,xSize=16,ySize=8      

;GOODIE2= 4                              ;2x2 goodie
      firstTile=$18,numSpr=4,xSize=16,ySize=16   

;BULLET1= 5                               ;single sprite 8x8 pixels
      firstTile=$27,numSpr=1,xSize=8,ySize=8      

;THING1   = 6                               ;tall double sprite 8x16 pixels
      firstTile=$2D,numSpr=2,xSize=8,ySize=16    

;BOSS   = 7                               ;3x3 BIG meta sprite
      firstTile=$24,numSpr=9,xSize=32,ySize=32   
end table


But when I compile this, I get an error:

Code:
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>java -jar ..\uc65.jar source\global.uc
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>java -jar ..\uc65.jar source\nes.uc
source\nes.uc(166): Warning: Possible loss of precision
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>java -jar ..\uc65.jar source\sprite.uc
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>java -jar ..\uc65.jar source\main.uc
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>java -jar ..\uc65.jar source\data.uc
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>path=path;..\cc65\
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>set CC65_HOME=..
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 lib\crt0.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\global.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\sram.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\nes.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\sprite.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\main.s
C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ca65 source\data.s

C:\Users\Paul\Dropbox\nesdev\dig_deeper5>ld65 -o dig_deeper.nes lib\crt0.o sourc
e\global.o source\sram.o source\nes.o source\sprite.o source\main.o source\data.
o -C lib\memory.cfg
ld65.exe: Error: Missing memory area assignment for segment `CODE'

Somehow segment "CODE" is being choosen...

I found out the issue is with my xSize and ySize entries of the table...
Looking at the compiled assembly:
Code:
; Assembly generated by uc65
; File: source\sprite.uc
; Built Time: Tue Dec 31 20:49:12 MST 2013
.DBG FILE, "source\sprite.uc", 18155, 1388548144


.IMPORT      metaSprite_ySize
.IMPORTZP   vBlankFlag
.IMPORT      metaSprite_xSize
.IMPORT      metaSprite_aux
.IMPORT      metaSprite_character
.IMPORT      metaSprite_ySpeed
.IMPORTZP   gameState
.IMPORTZP   buttons2
.IMPORTZP   buttons1
.IMPORT      metaSprite_state
.IMPORT      metaSprite_xSpeed
.IMPORT      spriteRam
.IMPORT      metaSprite_oam


   msChar_ySize:                                                           ;;;;;   Hey, these guys don't have a designated ROM segment like the other entries...
      .byte $10, $10, $10, $08, $10, $08, $10, $20
.DBG SYM, "msChar_ySize", "00", STATIC, "msChar_ySize"
   msChar_xSize:
      .byte $10, $10, $10, $10, $10, $08, $08, $20
.DBG SYM, "msChar_xSize", "00", STATIC, "msChar_xSize"
.SEGMENT "BSS0": zeropage
   sprPtr2: .RES 0
.DBG SYM, "sprPtr2", "00", STATIC, "sprPtr2"
   sprPtr2_a: .RES 1
.DBG SYM, "sprPtr2_a", "00", STATIC, "sprPtr2_a"
   sprPtr2_b: .RES 1
.DBG SYM, "sprPtr2_b", "00", STATIC, "sprPtr2_b"
   sprPtr1: .RES 0
.DBG SYM, "sprPtr1", "00", STATIC, "sprPtr1"
   sprPtr1_a: .RES 1
.DBG SYM, "sprPtr1_a", "00", STATIC, "sprPtr1_a"
   sprPtr1_b: .RES 1
.DBG SYM, "sprPtr1_b", "00", STATIC, "sprPtr1_b"
.SEGMENT "ROM0"
   msChar_numSpr:                                                                        ;;;;;;These entries of the table are assigned to ROM as they should be
      .byte $04, $04, $04, $02, $04, $01, $02, $09
.DBG SYM, "msChar_numSpr", "00", STATIC, "msChar_numSpr"
   msStart_oam:
      .byte $00, $20, $30, $ff, $30, $30, $30, $30, $30, $30, $ff
.DBG SYM, "msStart_oam", "00", STATIC, "msStart_oam"
   msStart_state:
      .byte $02, $02, $02, $00, $02, $02, $02, $02, $02, $02, $00
.DBG SYM, "msStart_state", "00", STATIC, "msStart_state"
   msChar_firstTile:
      .byte $00, $20, $10, $29, $18, $27, $2d, $24
.DBG SYM, "msChar_firstTile", "00", STATIC, "msChar_firstTile"
   msStart_palette:
      .byte $01, $02, $03, $00, $02, $03, $02, $01, $00, $00, $00
.DBG SYM, "msStart_palette", "00", STATIC, "msStart_palette"


So I manually modified the assembly which produced the desired result:
Code:
.IMPORT      metaSprite_xSpeed
.IMPORT      spriteRam
.IMPORT      metaSprite_oam


.SEGMENT "ROM0"                                                              ;;;;;I manually added this line in to fix the issue.  No errors.  program works as expected.
   msChar_ySize:
      .byte $10, $10, $10, $08, $10, $08, $10, $20
.DBG SYM, "msChar_ySize", "00", STATIC, "msChar_ySize"
   msChar_xSize:
      .byte $10, $10, $10, $10, $10, $08, $08, $20
.DBG SYM, "msChar_xSize", "00", STATIC, "msChar_xSize"
.SEGMENT "BSS0": zeropage
   sprPtr2: .RES 0
.DBG SYM, "sprPtr2", "00", STATIC, "sprPtr2"
   sprPtr2_a: .RES 1
.DBG SYM, "sprPtr2_a", "00", STATIC, "sprPtr2_a"
   sprPtr2_b: .RES 1
.DBG SYM, "sprPtr2_b", "00", STATIC, "sprPtr2_b"
   sprPtr1: .RES 0
.DBG SYM, "sprPtr1", "00", STATIC, "sprPtr1"
   sprPtr1_a: .RES 1
.DBG SYM, "sprPtr1_a", "00", STATIC, "sprPtr1_a"
   sprPtr1_b: .RES 1
.DBG SYM, "sprPtr1_b", "00", STATIC, "sprPtr1_b"
.SEGMENT "ROM0"
   msChar_numSpr:
      .byte $04, $04, $04, $02, $04, $01, $02, $09
.DBG SYM, "msChar_numSpr", "00", STATIC, "msChar_numSpr"
   msStart_oam:
      .byte $00, $20, $30, $ff, $30, $30, $30, $30,



Also, while we're on the topic of tables...
  • It took me awhile to figure out how to use them. It was pretty much trial and error trying to make sense of the errors when compiling until I realized how to instantiate them. I'd recommend adding a simple example to the documentation.
  • It's a bummer that tables entries can't be assigned by the use of constant types.

    I wish I could do this with my "HERO" constant:
    Code:
    table msChar of metaSpriteCharacter   ;must have more than one row!
    ;HERO   = 0            ;2x3 hero
          firstTile=HERO,numSpr=4,xSize=16,ySize=16   


  • It's also a bummer that I can't set address type variables to equal the address of a table entry.
    I tried this:
    Code:
       fast address ptr
       ptr = @metaSprite.state[msprID]

    and got this:
    Code:
    source\sprite.uc(96): Error: Identifiers may not contain the dot character
    Compilation failed
So in order to set pointers to tables I moved 'fixed' tables I have a 'fake' sram.uc file which is used for importing, but then I use my manually generated sram.s file instead of having uc65 compile it for me. That way I know tables are fixed addresses, then I create constants for those entries and then use those constants to set address variables to point to said tables...

Lastly, here's a copy of my code: https://dl.dropboxusercontent.com/u/183 ... broken.zip There are properly named .s files of broken compiled sprite.s and manually fixed sprite.s
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123496)
INL,

I will try to look into this as soon as I can. Can you help me understand if the table issue is a higher priority for you than the import issue?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123517)
Neither are very big obstacles right now. I actually moved my tables to their own file and was able to releive the issue. I would say the table issue is a bigger issue than import file ordering.

Any thoughts of supporting stack operations in the future?
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123753)
You mean like keywords that push and pop variables? That shouldn't be too hard.

I've been sick sooo dang much recently I'm... well... sick of it :D But once work is caught up I'll start working on this again. Just let me know your priorities.
Re: uc65, a Mid-Level Language Compiler READY FOR USE!
by on (#123764)
Yeah, just simple push, pop, peek would be grand. Perhaps a means to transfer the stack pointer in and out of a variable as well if you want to get fancy.

To be honest the import and table bugs aren't holding me back from anything right now, I can get around them easily. I just wanted to make you aware of them.

I've got some logic I'd like to implement in my game/demo in the near future that could benefit from having easy access to the stack. So if you're able to get those going in the near future I can help you test them shortly there after. No rush on any of this stuff though.