DB48X: HP48-like RPL implementation for DM42
|
07-16-2023, 09:36 AM
(This post was last modified: 07-16-2023 09:42 AM by Gilles.)
Post: #21
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
Very promising and complementary to newRPL! That could make me buy a DM42 ;D
The work remains immense, but I suggest if possible integrating the local variables with the LSTO command as in newRPL, in complement of the syntax -> << >> |
|||
07-17-2023, 06:27 AM
Post: #22
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-16-2023 09:36 AM)Gilles Wrote: Very promising and complementary to newRPL! That could make me buy a DM42 ;D I've not looked in details at the implementation of local variables in newRPL, but I'm afraid I won't implement LSTO as described in their manual. You can, however, `STO` in an existing local. The reason is that local variables in db48x are designed to be as efficient as the stack. Internally, they are like numbered registers. Each local access is a two-bytes opcode. For example, << -> A B << B A >> >> will create two local names A and B. The two references that you see in the inner block are then turned into local(0) and local(1) respectively (so two bytes, one for 'ID_local", one for the index, which is one byte unless you declare more than 127 local variables in a single block, something that should work but that I frankly have not tested yet...). This means that evaluating local(0) is just an array index, there is no name lookup (name lookup was done at parsing time). Note that the index of a 'for' loop is also a local. You can "simulate" the effect of LSTO with something like << 0 -> X << do-something 'X' STO do-something-else >> >>. In other words, you *can* store to a local variable, and it's much faster than store to a global variable, again because it's just an array access. But this optimization, which I believe is really important, also means that the parser and renderer need to be aware of local names, so you cannot declare them anywhere. |
|||
07-17-2023, 10:03 AM
Post: #23
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-10-2023 03:41 PM)TomC Wrote: OH my!! This sounds great - I will try it out shortly on the DM42. Ah, you changed my priorities (for the better). I spent my week-end implementing complex numbers ;-) Try it out https://github.com/c3d/DB48X-on-DM42/releases/tag/v0.3 |
|||
07-17-2023, 04:55 PM
Post: #24
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
If you want to see what it looks like, but don't have a DM42 handy, I recorded a video of version 0.3 operating:
https://www.youtube.com/watch?v=I5jgLzw_0-o Feel free to make comments and suggestions, or to ask questions. |
|||
07-17-2023, 06:20 PM
Post: #25
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
Bonjour,
Personally, I hope you won't stray too far from the standard RPL. Finally, its main flaw, at least on the latest RPL calculators (hp-49g+, hp-48gII and 50g), is that it hasn't been rewritten for the new ARM platform (+ possibly a few uncorrected bugs). But things are what they are... In my opinion, the best thing is for RPL on DM-42 to be compatible with what already exists, even if it means adding a few new features. I'm thinking possibly of the possibility of using anonymous (lambda) functions and even more so of the possibility of creating "STRUCT" structures à la C. I know that all this is a question of room (and time...) but, speaking of room, is it useful to have as many mathematical functions as those available on a hp-50g? I'll let you answer that question A fine project in any case! Bruno Sanyo CZ-0124 ⋅ TI-57 ⋅ HP-15C ⋅ Canon X-07 + XP-140 Monitor Card ⋅ HP-41CX ⋅ HP-28S ⋅ HP-50G ⋅ HP-50G |
|||
07-17-2023, 07:13 PM
Post: #26
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-17-2023 06:20 PM)FLISZT Wrote: Personally, I hope you won't stray too far from the standard RPL. Finally, its main flaw, at least on the latest RPL calculators (hp-49g+, hp-48gII and 50g), is that it hasn't been rewritten for the new ARM platform (+ possibly a few uncorrected bugs). Indeed. My approach is to always parse the standard RPL as input, but to be able to render it (and parse it) differently. For example, consider the `Dup` function. In DB48X, this can also be spelled `Duplicate`. There are preferences that let you display (and see it in the editor) as either `dup`, `DUP`, `Dup` or `Duplicate`. On input, you can spell it either way, as well as all case variants, e.g. `DUPLiCATE`. As another example, complex numbers can be entered as `(1;2)`, which is the standard RPL syntax, or as `1ⅈ2` (which is a bit faster to type), or `1+ⅈ2`, or `1+2ⅈ`. They can render using the old RPL syntax or using the fancy display. The same logic applies to exponents, i.e. you can type 1E32 even if it's rendered with a fancy small "x10" and superscript exponent; or to based numbers, where you can type #1AE3h even if it shows with a subscript 16 on screen. Even the ->Text command uses the compatibility format, just in case. And the plan is for the state files to also always use it (though that is not the case today). Quote:In my opinion, the best thing is for RPL on DM-42 to be compatible with what already exists, even if it means adding a few new features. The new features being added don't normally get in the way of compatibility, except maybe in corner cases that will have to be treated like bugs. If you can elaborate on how you see new features breaking compatibility (even if you don't have a precise example yet), please file issues on the project's GitHub's page to track it. Quote:I'm thinking possibly of the possibility of using anonymous (lambda) functions and even more so of the possibility of creating "STRUCT" structures à la C. Lambdas are already a part of standard RPL. \lambdax(x+1) is written « → x 'x+1' » in RPL. You do not need to name that object. Structs also exist, they are called "lists". However, RPL is a dynamically typed language, and I do not plan on adding statically typed data (it would really not help much in terms of speed or size given how things are implemented today). What could integrate well into RPL is an extension of the current local syntax to split lists into components. Something like « → { x y } « x x * y y * + » » would turn { 1 2 } into 5. The same could make sense for arrays as well, e.g. « → [ x y z ] 'sqrt(sq(x)+sq(y)+sq(z))' » would compute the norm of a 3-vector. We could have a variant where the last variable could get "the rest" if there are too many items, something like « → { x y z… } « x y z » » with { 1 2 3 4 } would give 1 2 { 3 4 }. Need to think about the precise way for this to "work well". Note that this integrates well with an existing extension which is planned (does not work at the moment) which is local variables with lists, e.g. « → x { x x } », which builds a list with the same item twice (currently broken). Quote:I know that all this is a question of room (and time...) but, speaking of room, is it useful to have as many mathematical functions as those available on a hp-50g? The way the DM42 is structures, you have about 700K available for the "PGM", and about 2M in "QSPI". I tried to use the QSPI for code, but it's broken on the DM42, not enough power when on battery (works fine on USB power). So I can use it only for read-only data, e.g. tables. At the moment, I'm at 597K for the PGM, but I was at 583K for the last release before complex numbers were implemented. In short, all of complex arithmetic and trancendental functions cost me about 14K of PGM space. That gives me hope I can fit almot all the original HP48 functionality there. And maybe a few HP50 extensions which are already there, like large integers. As for all the mathematical capabilities of the HP50, maybe this will require the next DM32-based platform, which is speedier and has more room. I have a DM32 to try things out, but I need SwissMicros to release a SDK for it. |
|||
07-17-2023, 11:31 PM
Post: #27
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-17-2023 04:55 PM)c3d Wrote: If you want to see what it looks like, but don't have a DM42 handy, I recorded a video of version 0.3 operating: Very enlightening video. I see some difficulties to edit large programs on the calculator: the font in edit mode is big, and moving to the next line requires two keystrokes. Unless a long press is possible after the shift key? Is it possible to change the font size, and is there a way to go directly to the next page? Jean-Charles |
|||
07-17-2023, 11:41 PM
Post: #28
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
Thanks for your reply.
(07-17-2023 07:13 PM)c3d Wrote: The new features being added don't normally get in the way of compatibility, except maybe in corner cases that will have to be treated like bugs. If you can elaborate on how you see new features breaking compatibility (even if you don't have a precise example yet), please file issues on the project's GitHub's page to track it. More precisely, I was thinking of backward compatibility... if possible. (07-17-2023 07:13 PM)c3d Wrote: For example, consider the `Dup` function. In DB48X, this can also be spelled `Duplicate`. There are preferences that let you display (and see it in the editor) as either `dup`, `DUP`, `Dup` or `Duplicate`. On input, you can spell it either way, as well as all case variants, e.g. `DUPLiCATE`. Interesting, but it makes a big difference with RPL. As you know, on an hp-28 or hp-50, DUP is a command, whereas dup, Dup, dUP (...) will be considered as different variables. In my opinion << Duplicate >> isn't very useful because it's too long. But I do understand that this is just an example. It reminds me of WinDev (French Software Engineering Workshop) whose programming language can use English or French keywords. I don't know much more... (07-17-2023 07:13 PM)c3d Wrote: << Lambdas are already a part of standard RPL. \lambdax(x+1) is written « → x 'x+1' » in RPL. You do not need to name that object. Yes, that's right! When I talked about anonymous functions, I was thinking of something simpler in terms of syntax (no chevrons). But it's true that algebraic writing is, in this case, a very good alternative that I rarely think of. Nevertheless, you need to have one variable (or more). Something like this (Python) Code: lambda : print('Hello World') À oublier… (07-17-2023 07:13 PM)c3d Wrote: What could integrate well into RPL is an extension of the current local syntax to split lists into components. Something like « → { x y } « x x * y y * + » » would turn { 1 2 } into 5. The same could make sense for arrays as well, e.g. « → [ x y z ] 'sqrt(sq(x)+sq(y)+sq(z))' » would compute the norm of a 3-vector. Interesting, but it requires a function capable of accurately processing the number of elements contained in the list. Or ?? https://www.hpmuseum.org/forum/thread-12902.html Otherwise, the difference with this Code: << On the other hand, if you do it for an array (or vector), why not do it for a list… or even a string. (07-17-2023 07:13 PM)c3d Wrote: Structs also exist, they are called "lists". However, RPL is a dynamically typed language, and I do not plan on adding statically typed data (it would really not help much in terms of speed or size given how things are implemented today). I don't know much about the underside of RPL (sysRPL). It's quite possible that adding a static data structure is very difficult. In LISP (very list-oriented... ), it's possible to do this: Code: (defstruct book I'm still convinced that it would be interesting to be able to do something similar, provided it's feasible, of course. Another thing I'd thought of was the possibility of managing a (sequential) file… but there's no SD card reader in DM42 nor in DM32! Last but not least, I'm sure there are possibilities in https://www.hpcalc.org/details/7971 that could inspire you, if they haven't already. Regards Bruno Sanyo CZ-0124 ⋅ TI-57 ⋅ HP-15C ⋅ Canon X-07 + XP-140 Monitor Card ⋅ HP-41CX ⋅ HP-28S ⋅ HP-50G ⋅ HP-50G |
|||
07-18-2023, 06:40 AM
(This post was last modified: 07-18-2023 07:08 AM by c3d.)
Post: #29
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-17-2023 11:31 PM)Helix Wrote: I see some difficulties to edit large programs on the calculator: the font in edit mode is big, and moving to the next line requires two keystrokes. Unless a long press is possible after the shift key?Yes, you can long press after shift, and it scrolls down "fast". I will make sure to highlight that in a next video. Quote:Is it possible to change the font size, and is there a way to go directly to the next page?Yes, there are settings to change the font size. Here is the editor with the smallest font size There are no page-up / page-down functions yet, but I plan to have an "Edit" menu that does include this kind of functionality. |
|||
07-18-2023, 08:06 AM
(This post was last modified: 07-18-2023 08:09 AM by c3d.)
Post: #30
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-17-2023 11:41 PM)FLISZT Wrote: More precisely, I was thinking of backward compatibility... if possible.That was the way I read it. Quote:(07-17-2023 07:13 PM)c3d Wrote: For example, consider the `Dup` function. In DB48X, this can also be spelled `Duplicate`. There are preferences that let you display (and see it in the editor) as either `dup`, `DUP`, `Dup` or `Duplicate`. On input, you can spell it either way, as well as all case variants, e.g. `DUPLiCATE`. Good point. I opened an issue to remember that. However, note that the space of reserved keywords kept changing with each revision of RPL, so there is no real guarantee about which names you can use in your program across RPL implementations (only within one specific implementation). The rationale for accepting multiple spelling is because the usage model for the DM42 is in my opinion quite different from the traditional usage model on the HP48 due to the presence of a standard USB port and a disk mode. To me, this means that I must be able to accept programs typed on the calculator's keyboard (typically uppercase) as well as from a computer (where I DON'T WANT TO SHOUT ALL THE TIME :-). This is why the state file is in clear text, not in binary format like on the stock DM42 firmware. Quote:In my opinion << Duplicate >> isn't very useful because it's too long. But I do understand that this is just an example. This is exactly why there is a preference for that. I happen to like the long spelling. Not necessarily for DUP, which is common enough, but for functions like RNRM, RRK, RSBERR, SIDENS or TDELTA. If you can remember what they do without looking up the manual, congrats. I cannot, so I'd much rather have them display as RowNorm, RosenbrockErrorEstimate, RosenbrockRungeKuttaSolver, SiliconDensity and TemperatureDelta and save myself a trip to the manual. Hopefully, the built-in help will also make it easier to remember what these functions do and how to use them. Quote:It reminds me of WinDev (French Software Engineering Workshop) whose programming language can use English or French keywords. I don't know much more... Not sure I appreciate the comparison ;-) Quote:(07-17-2023 07:13 PM)c3d Wrote: << Lambdas are already a part of standard RPL. \lambdax(x+1) is written « → x 'x+1' » in RPL. You do not need to name that object. But again, lambdas are nothing but functions or programs without a name, which is exactly what RPL equations or program objects are. Your "Hello World" equivalent would be something like: Code:
Quote:(07-17-2023 07:13 PM)c3d Wrote: What could integrate well into RPL is an extension of the current local syntax to split lists into components. Something like « → { x y } « x x * y y * + » » would turn { 1 2 } into 5. The same could make sense for arrays as well, e.g. « → [ x y z ] 'sqrt(sq(x)+sq(y)+sq(z))' » would compute the norm of a 3-vector. This is the intent of the "rest" notation. This would allow you to recurse efficiently. Another thing I am considering is a "list processing" variant of `for`, e.g. Code:
would give you X+1+2+3+45 Quote:Otherwise, the difference with this It would be in terms of efficiency. A global storage like you L does not just pollute the user-visible variable space, it is very slow (relatively speaking) both in classical RPL and in db48x. Global variables are stored in one place which requires to (at least potentially) move many other objects when you change their values. By contrast, local variables use the same kind of fast temporary storage as the stack. Quote: But for an array... yes! This was exactly the idea of my proposed new construct. You would use a list to pass the data around, and extract fields with Code:
It might be useful to have something that builds a tagged list. For example Code:
(a clear plug for a fascinating book) would produce this list: Code:
I could even call it →Struct instead of →TaggedList. Quote:Another thing I'd thought of was the possibility of managing a (sequential) file… but there's no SD card reader in DM42 nor in DM32! But there is a local FAT filesystem which is easily accessible over USB. So file access make sense. I'm still thinking about how to expose that functionality. Today, the only feature that is implemented lets you save the calculator state to disk, and is mapped to double-shift EXIT. Quote:Last but not least, I'm sure there are possibilities in https://www.hpcalc.org/details/7971 that could inspire you, if they haven't already. Thanks for the insights. |
|||
07-18-2023, 08:30 PM
Post: #31
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(…) Neither WinDev nor FenDev?
(07-18-2023 08:06 AM)c3d Wrote: I happen to like the long spelling. Not necessarily for DUP, which is common enough, but for functions like RNRM, RRK, RSBERR, SIDENS or TDELTA. If you can remember what they do without looking up the manual, congrats. I cannot, so I'd much rather have them display as RowNorm, RosenbrockErrorEstimate, RosenbrockRungeKuttaSolver, SiliconDensity and TemperatureDelta and save myself a trip to the manual. Hopefully, the built-in help will also make it easier to remember what these functions do and how to use them.Not Wrong! Another point: I didn't get very well what you meant with "rest" notation in your previous post. Now it's clear. Nice improvement! (07-18-2023 08:06 AM)c3d Wrote:I suppose the + operator could be replaced by any command or function (as long as it makes sense). About possible developments on the FOR loop, things like (Python) in the following examples may be interesting too. Code:
Code:
I'm far from knowing all the functions by heart. (07-18-2023 08:06 AM)c3d Wrote: Otherwise, the difference with thisIn this previous example, I used a global variable for a single reason: time saving! (in typing) But I could have written this as well: Code:
Anyway, it's true that… Code: « → { x y } « x x * y y * + » Code: « → { x y z… } « x y z » » A question about your idea of a new construct: - would it be possible, after having created (e.g.) my_Structure, to create (e.g.) Struct_1, Struct_2 … with this new template? Asked differently (with your example): Code: About the idea of managing a (sequential) file, I mentioned the SD card reader (or its lack) because this could have been a "portable" and a "all-in-on solution". But an "at-home solution" suits, at least for me. Bruno Sanyo CZ-0124 ⋅ TI-57 ⋅ HP-15C ⋅ Canon X-07 + XP-140 Monitor Card ⋅ HP-41CX ⋅ HP-28S ⋅ HP-50G ⋅ HP-50G |
|||
07-19-2023, 12:41 PM
Post: #32
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-18-2023 08:06 AM)c3d Wrote: Another thing I am considering is a "list processing" variant of `for`, e.g. I like this, but wouldn't it be better to perhaps name it 'foreach'? so as to not confuse the user with the usage of for. I'm also liking your extension to use vectors and lists in local variable definitions. We should try and coordinate (standardize?) these extensions to RPL so as to minimize differences between dialects. |
|||
07-19-2023, 01:17 PM
Post: #33
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-18-2023 08:06 AM)c3d Wrote: Another thing I am considering is a "list processing" variant of `for`, e.g. The ListExt library has a LXEQ command which does pretty much the same thing. Using your above example, the code would look like this: Code: 'X' { 1 2 3 45 } « + » LXEQ The above LXEQ code gives the same result: 'X+1+2+3+45' There's some other functionality built into LXEQ (an automatic local containing the index, variations for the executable object), but it was originally designed specifically as a "foreach" type of command. Just a slightly different perspective on the same theme. |
|||
07-21-2023, 11:07 AM
Post: #34
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-19-2023 12:41 PM)Claudio L. Wrote: We should try and coordinate (standardize?) these extensions to RPL so as to minimize differences between dialects. Please do! The two of you are the saviors of all who rely on RPL. Diverging would be damaging, keeping it interoperable enables us to have as many options as possible for hardware to run RPL on going forward. Which helps us all. I think I speak for all of us when I say that we would be very very grateful if you can keep your two systems as compatible as possible. I'd like to help out with this effort specifically, if I can, I'd very much like both of these projects to have continued success. I don't have hardware to run DB48x yet (planning on a DM32 after Christmas) but I do have one 50g running newRPL and one stock. I have not used newRPL much yet. I also have somewhat limited time, don't we all, but I should be able to set up the emulators next month. |
|||
07-21-2023, 11:58 AM
Post: #35
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
I have a spare DM42 - just need a faceplace (sticker). Nice project, keep going! :-)
|
|||
07-22-2023, 11:56 AM
(This post was last modified: 07-22-2023 12:05 PM by Gilles.)
Post: #36
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-19-2023 12:41 PM)Claudio L. Wrote:(07-18-2023 08:06 AM)c3d Wrote: Another thing I am considering is a "list processing" variant of `for`, e.g. I vote for "foreach". But in this case : 'X' { 1 2 3 45 } ADD ΣLIST does the job (or + in RPL vs ADD newRPL) and is more in the "spirit" of RPL imho I started to write a ListExt library for newRPL ( it's easy except for the DOCOMB and DOPERM commands where I have to study the algorithm)), but I'm running out of time. I'm going to get back to it while enjoying a few days of vacation ListExt library is a gem ;D |
|||
07-22-2023, 03:44 PM
(This post was last modified: 07-22-2023 03:45 PM by c3d.)
Post: #37
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-22-2023 11:56 AM)Gilles Wrote:(07-19-2023 12:41 PM)Claudio L. Wrote: I like this, but wouldn't it be better to perhaps name it 'foreach'? so as to not confuse the user with the usage of for. Regarding foreach, I don't like it. RPL tends to overload operators when there is no ambiguity, and I see no ambiguity there. There is already a precedent for operators that take different number of arguments as input, e.g. DOSUBS. Regarding 'X' { 1 2 3 45 } ADD ΣLIST, this is clever, but is obviously much less general. |
|||
07-22-2023, 04:11 PM
Post: #38
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-21-2023 11:07 AM)LinusSch Wrote:(07-19-2023 12:41 PM)Claudio L. Wrote: We should try and coordinate (standardize?) these extensions to RPL so as to minimize differences between dialects. Wow. Thanks. But no pressure! ;-) Quote: Diverging would be damaging, keeping it interoperable enables us to have as many options as possible for hardware to run RPL on going forward. Which helps us all. I think I speak for all of us when I say that we would be very very grateful if you can keep your two systems as compatible as possible. In practice, this will be difficult without a spec to refer to. For the moment, I am trying to stick to what is described in the HP50G advanced reference manual. But there are interesting divergences with newRPL already. Claudio just pointed to ADD vs. + for list concatenation. It turns out that in my implementation, ADD and + produce the same opcode, and that's "sort of" to address that issue. We could consider a given reference implementation as the spec (e.g. HP48 or HP50), but that limits extensions. As an example, GET in newRPL can extract a character from a text object. That seems useful, and not really getting in the way of source code compatibility with HP RPL. So I plan to implement that. As a matter of fact, I am using the newRPL help file as another reference point. Quote:I'd like to help out with this effort specifically, if I can, I'd very much like both of these projects to have continued success. I don't have hardware to run DB48x yet (planning on a DM32 after Christmas) but I do have one 50g running newRPL and one stock. I have not used newRPL much yet. I also have somewhat limited time, don't we all, but I should be able to set up the emulators next month. I really need to buy a 50g to run it. Right now, I can only run it in emulation. Good enough for most cases. In any case, thanks a lot for the proposal. What about starting with some kind of unified help file that we could use as a basis for documentation (and to document differences between variants if necessary)? Claudio, I am not sure if you ever noticed the work I did for the DM42 on newRPL? https://github.com/c3d/db48x/tree/dm42 This is a massive series of changes, many of which you are likely to not like. One major change in particular was regarding the graphic engine and automated layout of the various UI elements. The idea being to be able to display things easily at different locations for the DM42, the 50G and the prime, because their function keys are at different spots. Another big change I made which you might want to consider at some point is refactoring the help system to use a markdown file based on the HTML documentation. This is what I use on the DM42 for now, but most of the work is done for newRPL (but, again, not necessarily in a state you would be happy to merge) In any case, I realize these are really invasive changes, and you are unlikely to ever merge them, but you might want to try them out at least in the simulator. |
|||
07-22-2023, 04:16 PM
Post: #39
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-22-2023 04:11 PM)c3d Wrote: We could consider a given reference implementation as the spec (e.g. HP48 or HP50), but that limits extensions. As an example, GET in newRPL can extract a character from a text object. That seems useful, and not really getting in the way of source code compatibility with HP RPL. So I plan to implement that. As a matter of fact, I am using the newRPL help file as another reference point. Well, after implementing it, I decided to try it on newRPL, and I get an error "expected a composite object". The documentation states: Code:
So I was expecting a string to be a composite object. Maybe that's now how newRPL sees it? |
|||
07-22-2023, 04:32 PM
Post: #40
|
|||
|
|||
RE: DB48X: HP48-like RPL implementation for DM42
(07-22-2023 04:11 PM)c3d Wrote:(07-21-2023 11:07 AM)LinusSch Wrote: Please do! The two of you are the saviors of all who rely on RPL. Am I misunderstanding something, or is there a DM42 emulator for Mac? Or is that a newRPL emulator? |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 18 Guest(s)