Hey mips5000!
It is always nice to hear that someone is interested in using our tools. 🙂
Regarding VUEngine and VBDE, I would recommend you to try to use our new extension for Visual Studio Code, it is not officially released yet, but we can send it to you and help you through the process of getting it to work. The benefit will be that you will have access to the engine’s latest version (which has tons of improvements compared to the version that is bundled with VBDE) and you will be able to use a syntax closer to C++ than the convoluted macros that we implemented to support object oriented features.
Join the PlanetVB’s discord channel, it will be way easier and faster to help you through there, both to setup the extension for VSC and to easy your way around the engine.
Regarding your concern about higher level vs low level, I guess it is debatable and will depend on your ultimate objectives. Personally, I prefer to being able to concentrate on getting the game logic to work and only then go to the low level stuff to do something fancy or to optimize some algorithm. In any case, the engine’s code is fully open, so you can always get to the bottom of of how it manages the hardware. And since the whole engine supports polymorphism, you can always override any method that doesn’t fit your needs. Things like VIP interrupts and such are already covered, but you can still rewrite them if you are so inclined. And getting the most of the engine’s features will necessarily involve understanding part of the underlying hardware for things like animations, so, you won’t be skipping everything by using the engine.
Regards,
jorgeche
opsakura59 wrote:
I’ve been tinkering around with gccvb and was just starting out with the Vuengine release packed in with VBDE. That’s why I was curious about the tutorials.
What’s different in VES? I might be interested to try it out.
If I’m not wrong, the last release of VBDE dates back to 2018. That means that the VUEngine is a LOT different by now. Although I don’t have a detailed list of new features, the following should make it worthwhile to try, specially inside VES:
1) Full sound support
2) Lots of fixes to the engine itself
3) Lots of fixes to the preprocessor
4) Lots of performance improvements
5) Much better compilation times if you use VES in Linux or OS X, and I think that even in Windows they are a step up from VBDE.
One possible caveat is that the Platformer Demo is lagging behind by a couple of months now with respect to the engine since a lot of our efforts have be focused on Formula V. But it should be possible to bring it up to date without much hassle if you are interested into messing around with that demo.
On top of that, and it is a matter of taste of course, just being able to use VSC instead of IDEA would steer my decision (but I always hated IDEA 😛 ).
opsakura59 wrote:
Were the Vuengine tutorials mentioned in this thread ever made?
We are currently working non stop on Formula V to create a high as possible quality “final”/public demo that reaches the level of polish of an official game before going back to concentrate on the tool chain. We need to get VUEngine Studio (VES) to a releasable state first before it makes sense to create any tutorials (we spent like a third or half of the past year and we’re still not quite there, but thinking about releasing at least a preview). Anyway, if you want to already start messing around with the engine, we can give you access to the tools and give you instructions here or through Discord about how to setup everything.
Hi, our SoundManager is not a standalone program intended to just play sounds. It is one of the VUEngine’s classes and its purpose is to enable sound playback in games built with the engine.
With the above in mind, if you want to test it, you will need to download the latest versions of both the VUEngine core library (https://bitbucket.org/vuengine/vuengine-core/src/master/) and of the sound test project (https://bitbucket.org/vuengine/vuengine-sound-test/src/master/) and replace with these the corresponding sources included with VBDE.
To play PCM sounds, an 8bit WAV file must be converted to a special format using Frostgiant’s WAV converter (vbwav, included with VUEngine: https://bitbucket.org/vuengine/vuengine-core/src/master/lib/utilities/).
To play MIDI sounds, a .mid file must be converted to the corresponding special format using our modified version of thunderstruck’s MIDI converter (https://bitbucket.org/vuengine/vuengine-core/src/master/lib/utilities/MIDI-Converter.zip).
Then, the .c files that those programs produce must be used to built a Spec (the engine’s name for *specification) that can be read by the SoundManager (example: https://bitbucket.org/vuengine/vuengine-sound-test/src/master/assets/sounds/SoundTracks/MIDI/ZeldaLinksAwakeningTitle/Spec/ZeldaLinksAwakeningTitleSpec.c).
Then, the new sound’s reference must be add to the _userSounds array to be accesible through the sound test debug tool.
For the moment, it is a relatively involved process, but it was done this way to avoid constantly having to manage the sound registers, waveforms, etc. We are working on a custom editor for the release of our VS Code extension that will automate most of the above.
Finally, if what you need is a way to have sound playback in a game / program for the VB that is not built with the VUEngine, this won’t work for you. You won’t be able to compile our source code without using all our tool chain since it is not plain C anymore and there are lots of dependencies since we use inheritance in our engine.
PS: It is possible to reproduce raw .mid files, but that requires real time decoding. DanB’s MIDI player can be used for that (https://www.planetvb.com/modules/games/?h046d). We tried to include it to facilitate things, but we couldn’t make it work correctly within our engine and it is too heavy to decode MIDI’s format in real time.
Those sound really good!
If you have a MIDI file that applies that trick, I may try to include it in the sound test.
Or you can try it yourself by writing the track by hand, the sound test’s source code is public:
Fair enough!
As per your suggestion, support has been added to change the tap location on a per note basis when a track uses the noise channel. 🙂
Hi
1) The ROM is available for everybody at the end of the Patreon post:
https://www.patreon.com/posts/29465160
2) Yes, it is possible to use any of the 8 tap locations for noises. Although there is no support to change the tap location per “note” yet. That means that for the time being, each a track that uses the noise channel must set the tap location ahead of being played and cannot change it during playback. Making it so isn’t hard, but I don’t know enough about music to figure out by myself if that is even useful.
Thanks. 🙂
You use those functions as follows:
int yourRandomNumber = randnum(randseed(), 51) + 1;
// randnum will return a value between 0 and 50 inclusively, ie: 0, 1,… , 50, hence the need to add 1
But I don’t like to use them since randseed performs poorly when used inside an intensive loop (with little benefit according to my experience, that is, the number of passes it does doesn’t increase that much the “randomness”); and randnum is not safe since it doesn’t check if the randnums parameter is non zero and, on top of that, there is no action taken for negative numbers since the result of the modulo operation is implementation-defined for them.
In place of those, you can use these (they are not mine, but Isaku Wada’s, 2002):
long randomSeed()
{
static u32 seed = 7; /* Seed value */
if(!seed)
{
seed = 7;
}
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
return (seed);
}
int random(long seed, int randnums)
{
return seed & randnums ? (int)(abs(seed) % abs(randnums)) : 0;
}
These will output the same numbers everytime since there is no way to produce real random numbers within this universe that I'm aware of besides, maybe, the rate of atom decaying... Anyway, you can add some randomness to the output by including values that come "from outside the system", like the user input and the elapsed time or the number of clock ticks. For example:
int random(long seed, int randnums)
{
// _accumulatedUserInput is a global variable where you store or accumulate the user input so far
// _ticks is a global variable where you store the amount of clock ticks so far
seed += _accumulatedUserInput + _ticks;
return seed && randnums ? (int)(abs(seed) % abs(randnums)) : 0;
}
- This reply was modified 5 years, 5 months ago by jorgeche.
Yep, I had to change/fix a bunch of things to get the Linux compilation working again, and those should probably help the compilation on OSX.
I’ve found a site talking about how to compile GCC on OSX, and I may take a look at it myself if somebody doesn’t beat me to it!
Hey Elmer!
I already compiled it on macOS Mojave, but I didn’t really documented the process and it was kind of messy and hackish since I had to even modify one of the config.guess files, among other things. Anyway, I’m still porting our preprocessor before being able to successfully build any of our demos, so, I’m not 100% sure that the compiler is working fine.
I really hope that you guys take a look at using the C++ support in VUEngine since you’re already using an object-oriented design.
Using basic Embedded C++ language features should allow you to make your code a lot more readable/debuggable than using all of those cunning-but-fragile macros.
The plan is to evaluate, in the middle term, if it is feasible given the complexity and memory requirements of the engine. But right now we want to concentrate in implementing a complete game instead of keep pushing developer features. Anyway, thanks to the preprocessor, the code is around 85% based on C++’s syntax (the only missing syntax feature is proper method calling), so, that part of the port should be really easy. The hard part will be, first, to customize the memory handling since I don’t have enough experience on the inners of C++’s compiler and linker so I don’t know if it is possible to instruct it to allocate the virtual tables in specific memory regions or even if they can just be computed at compile time and placed in the ROM area (we load them in DRAM instead of WRAM because they amount to more than 10 KB and they are populated at runtime); and second, to handle the allocation of dynamic objects, although I guess we just have to override the new operator and just use our own MemoryPool to avoid the usage of the heap.
jorgeche
- This reply was modified 5 years, 11 months ago by jorgeche.
speedyink wrote:
So I’ve been enjoying mine for a couple hours now, I’ve successfully “duplicated” one of my cartridges, which is pretty damn cool.Only thing is I can’t seem to get the 128mbit Mario video demo from the patreon to flash. When I choose the file from the SD card I get a ‘SD Card ERROR!’ message. It’s weird because it worked totally fine for the 32mbit rom I dumped and then flashed to the same 128mbit cart.
The SD card is a 4gb sandisk card formatted to FAT32.
Any ideas?
Rename the file in the SD card to something shorter. I got an error when using the default name of the ROM from the Patreon page. Use something short and without dashes, like vplayer.vb, and give it another try.
Hi RetroDan,
We will have to wait for KR1553 for a response on the possibility of an installer, since he handles that part of VBDE. But in the meantime, maybe I can help you solve the issue starting IDEA.
First things first, I’m not sure which program KR1553 recommends to unzip the file, but I usually use 7zip. It seems to being able to handle anything.
Second, which version of Windows are you using? (please include the number of bits and the edition [home, pro, etc.]) I usually don’t have to install .NET in anything that isn’t Windows XP (yup, I still use it, LOL). Windows 7 and above don’t complaint at all and work out of the box, although I never use the home editions, so that may be the problem.
From the error, it seems to be related to a faulty dll in your system. Did you try this:
jorgeche
Hi Guy:
I tried to implement a custom abs function based on your findings, but I guess the compiler that I’m using doesn’t have support for the system registers 26-31.
Given that I don’t want to bother ElmerPCFX and I don’t want to go through the whole process of trying to compile the compiler again, I would like to know if there is any way to write the hex op code for the stsr and ldsr instructions in my C code without having to hack the ROM directly.
jorgeche
Attachments:
We have uploaded new builds containing, besides the usual bug fixes and performance improvements, a couple of cool special effects that we hope you will enjoy!
As before, they are FlashBoy-ready. That is, you don’t need to pad the ROMs. A warning: only the “release” and “tools” builds are meant to be used in the VB; the “debug” is designed for running on Mednafen only.
VirtualChris schrieb:
I deleted it using Robocopy. But what’s weird is that VDBE worked for a while and then stopped because the name got too long. How did it get too long?
I’m not sure about how VBDE’s makefile handles the building of its sample projects, since I only work with the VUEngine, but that makefile is a port of the VUEngine’s so the problem may be related to what I previously pointed. For the moment, just delete the release folder each time you compile until KR1553 can chime in.
- This reply was modified 7 years, 7 months ago by jorgeche.
VirtualChris wrote:
I can’t delete the release folder. It says it’s too long.
VirtualChris wrote:
I opened the file “release” and it had a file folder called “release” and I opened it and it had a file folder called “release.” It goes to infinity apparently. It’s a wonder I still have room on my hard drive.
This generally happens when the incorrect bulding type is passed to the makefile. Make sure that you replicated exaclty the folder structure of the VBDE sample projects, delete the release folder, and try to compile from VBDE’s Notepad++ again (I guess you’re using that).
Inheritance doesn’t automatically make scaleable software, abstraction does. But abstraction is not exclusive to OOP or inheritance. A function is a form of abstraction.
And inheritance is a form of abstraction too. But since abstraction makes scalable software, according to you, then inheritance makes scalable software.
I didn’t say that there were no other means of making scalable software, nor did I say that abstraction is exclusive to OOP, don’t put words in my mouth.
Maybe we just pass it to a function then as a const parameter?
void step( const unsigned time );
I don’t see what would be the purpose of adding “const”, besides self documentation, to a functions’ argument that is not a pointer, since you can copy the variable’s value into a non constant variable and modify it. But the point wasn’t self documentation.
Global state can be a problem, but at the same time, all games need it. It’s crazy to work in languages that forbid global state…
If we are trying to reuse memory space for game structs, why not use a union? It’s a language feature instead of a macro.
You’re using a straw man argument and moving the goalposts. I didn’t say that globals are to be forbidden, I just implied that they preferably are to be avoided if possible. And I was only responding to your concern about how classes attributes “indicates multiple time variables”, which is false, since it is not necessarily the case.
The purpose of inheritance is to reuse DATA…
I don’t want to derail the thread, whose initial idea is very good, into a discussion about programming paradigms and concepts. If you think that there is no real advantage in the usage of OOP features or libraries that abstracts part of the problem of providing a single interface to work with multiple game mechanics, you’re more than welcome to pursue your project as you see fit.
I’m out.
The game won’t be running all 50 at a time, it just runs 1 at a time. You could have as many minigames as the memory allows, and performance will only matter at the level of the individual minigame code itself.
Well performance does indeed matter only at the level of the individual minigame’s code itself, but if you don’t provide a variable delta time at the level of your “primary game” then you’re defeating yourself in your goal of avoiding to reimplement the same solution to the same problem in each miningame, since variable time delta won’t affect the minigames that are light enough to run at a locked frame rate, but will allow for those which aren’t to adapt their simulations based on the CPU’s load. While if you fix the time delta, the heavy minigames, if there are any, will be penalized unnecessarily, forcing the programmer to have to deal with timer interrupts himself if he wants a stable simulation.
I agree, delta time sounds like it would allow for a much more gradual speedup. Should we use fixed-point as the delta? I would imagine floats would be too slow.
Yeah, fixed math should be preferable since floats are very slow on the VB. In any case, they come with caveats in the way of precision, and their resolution (the number of bits destined to hold the decimal part of the number) needs to be carefully planned.
We use 19 bits for the integer part and 13 bits for the decimal part in our engine for spatial and time calculations, with good enough results, but different games could need different values. In any case, other bit distributions are not difficult to implement.
If we were to use inheritance from the base game, each minigame would get unnecessary copies of the main game state. Only one minigame will ever run at a time, so the copies of main game state don’t need to be a part of the minigame at all. They can exist in one place independent of the minigames that don’t need to access it.
Let me explain. The VUEngine has one singleton class called Game that coordinates all the VB’s resources, it is the “Operative System”. It has a StateMachine that holds a stack of states. In our games, each game screen is a GameState that is pushed into that stack, each with their own stage of game entities, and the Game only updates its current or top most state. Our suggestion is to use GameStates because the state machine pattern is a nice way to swap functionality by using a common interface, and because states generalize common phases liking initialization, execution and exiting. We didn’t suggest to inherit from Game (it is not possible in the VUEngine), but from GameState, and we didn’t suggest to add the stats to the class that inherits from GameState, but to use a manager, that is a singleton class that holds such values. So no, even in the impossible case of inheriting from the Game class, inheritance doesn’t imply that there will be redundant copies of any data.
The purpose of a classes and inheritance is to create a template that you can create instances of. However, only one instance of a game will ever exist, so why make it a class?
If we are trying to encapsulate, we can encapsulate at the file level. If you make a variable STATIC inside a .c file, its the same as making a variable PRIVATE inside of a class: it can’t be accessed, not even with EXTERN.
No, the purpose of classes is to model software in the same way that we conceive our phenomenical experience which consists of objects that have properties that determine their behavior, and by doing that, problems that are complex to solve using structural programming become easier under the object oriented programming paradigm. The purpose of inheritance is to reuse code and, by polymorphism, to allow for scalability by means of generic programming (among many other things). The fact that there only needs to be one instance of a single class doesn’t nullify those advantages.
Yeah, you can achieve something analogous to encapsulation by the use of “static” in C, but you still cannot achieve polymorphism. Still, what this has to do with the suggestion to avoid global variables for the game’s stats?
There isn’t really a difference between:
globals.time
vs self.time?
The difference is in the semantics of the program. Globals allow unrestricted modification of the program’s state, while classes’ attributes restricts those modifications to parts of the program. This is important because the comprehension of the meaning of a class attribute restricts itself to the class’ definition, while the meaning of a global variable requires a comprehension of the program as a whole, a much harder task.
Plus, self.time indicates multiple time variables (one per minigame), when in reality we only need one time variable that is applied to all minigames. A global variable makes more sense here because the one parameter would affect everything.
You’re confusing classes instances with classes attributes. Inheritance, classes, or OOP in general for that matter, do not imply that all the minigames need to be loaded at the same time in work RAM. Since there is only one minigame active at any time, there needs to exists only the singleton instance of that minigame class in work RAM, therefore only one time variable. When it ends, the instance is deleted and the instance of the new minigame class is created..