Igor Posted September 9, 2019 Share Posted September 9, 2019 My understanding is some of these games were made for very early mobiles (I could be mistaken), those could have something useful in them. It would be a manual/tedious process of course. 1 Quote Link to comment Share on other sites More sharing options...
VladR Posted September 9, 2019 Share Posted September 9, 2019 9 hours ago, necrocia said: My understanding is some of these games were made for very early mobiles (I could be mistaken), those could have something useful in them. It would be a manual/tedious process of course. You actually are bringing great point. I completely forgot about that very first wave of mobile games - like Snake and Space Invaders that were preinstalled on each phone of the era. Only god knows, how many other such games are out there. Must be hundreds. Hell, at one point, about ~12 yrs ago, I just remembered that I worked for one local mobile game company (joined less than 6 months before it folded ), and even at such a late date, we were still not redrawing whole screen (as we do on Lynx), but merely updating portions of screen that changed. We also had to make very,very sure we only used bitshift and 8-bit values for everything. If we're talking about compiled games, there really is no difference in handling loops and arrays and variables, between C and Java. Array access has to be LDA MyArray,X and variables must be LDA MyVariable. I vaguely recall (can't be bothered to go look up Java 1.0 spec now) there was some Java gfx lib, so we would have to remap those functions into Suzy's sprite drawing. Last year I have been working on a C-style language compiler for Jaguar (that is simply embedded within the Asm - I can freely combine the two within one source file, no need for any special "asm" directives or somesuch ridiculous nonsense), so I have some recent experience with compilers (I routinely create new language features that make sense in given CPU Target). I currently have 3 targets : 68000, GPU RISC, DSP RISC. When I was working on the Lynx 3D engine, as much as I enjoyed the option of having cc65, I can't say how I missed the option of simply combining C with Asm without any special directives. It was very tempting to go implement a fourth target : .6502, but I knew that then I wouldn't even finish the engine by the deadline, let alone the crude gameplay that is there now. After PRGE, I don't think I'll have an excuse not to 1 Quote Link to comment Share on other sites More sharing options...
LordKraken Posted September 9, 2019 Share Posted September 9, 2019 (edited) Quote When I was working on the Lynx 3D engine, as much as I enjoyed the option of having cc65, I can't say how I missed the option of simply combining C with Asm without any special directives. You should looked at the old BLL "newcc65" toolkit. As buggy as newcc65 is, it actually supports inline ASM within C function. As far as I know, two games of the recent competition were made with newcc65: YNXA and "The Inside World" Edited September 9, 2019 by LordKraken Quote Link to comment Share on other sites More sharing options...
Igor Posted September 9, 2019 Share Posted September 9, 2019 46 minutes ago, LordKraken said: You should looked at the old BLL "newcc65" toolkit. As buggy as newcc65 is, it actually supports inline ASM within C function. As far as I know, two games of the recent competition were made with newcc65: YNXA and "The Inside World" If you're talking about things like this - asm("brk"); then the launcher I made for the Lynx SD (both the 30th birthday and the Lynx SD Menu Loader 2) use that. Excuse my ignorance, but I guess I've always been using the Github version of CC65. ? @VladR - There has to be a repository of these ancient games out there somewhere. Quote Link to comment Share on other sites More sharing options...
LordKraken Posted September 9, 2019 Share Posted September 9, 2019 But can you do that Quote void LYNKS_VSync() { #asm vretrace: lda $fd0a bne vretrace #endasm } Quote Link to comment Share on other sites More sharing options...
Igor Posted September 9, 2019 Share Posted September 9, 2019 Doesn't look like it, though that would be very handy (heh heh). Quote Link to comment Share on other sites More sharing options...
VladR Posted September 9, 2019 Share Posted September 9, 2019 2 hours ago, LordKraken said: You should looked at the old BLL "newcc65" toolkit. As buggy as newcc65 is, it actually supports inline ASM within C function. As far as I know, two games of the recent competition were made with newcc65: YNXA and "The Inside World" Yeah, that would make it more practical, but since you don't have a control over the compilation process, you still can't have the exact some access to all variables and methods in both. And on top of that, you certainly couldn't reliably mix both C and asm in same method due to the optimizations that CC65 makes. Which is understandable. Which is exactly the reason why I started from scratch the other way around (from Asm) with my C-like language and made sure I can intermix both freely. Here's one such method (68000 code): SEnemy_ProcessStrafing: { ; Strafing register d1:strafeSpeed register d2:localX register d3:rFrame rFrame.w = Frame strafeSpeed.w = SEnemy.StrafeSpeed if.w (SEnemy.StrafeState == #STRAFE_SWITCHING) { ; Don't strafe for requested number of frames if.w (rFrame > SEnemy.FrameStrafe) { ; Time elapsed, continue strafing SEnemy.StrafeState = #STRAFE_STRAFING } jmp ai_strafing_done ; We need to bypass strafing, as the direction was already updated } if.w (SEnemy.StrafeState == #STRAFE_STRAFING) { if.w (SEnemy.StrafeDirection == #STRAFE_RIGHT) { ; Rightwards localX.w = SEnemy.X + strafeSpeed if.w (localX > SEnemy.MaxX) { print.b #255,128,24 localX.w = SEnemy.MaxX SEnemy.StrafeDirection = #STRAFE_LEFT SEnemy.StrafeState = #STRAFE_SWITCHING SEnemy.FrameStrafe = SEnemy.StrafeSwitchingDelay + rFrame } SEnemy.X = localX } else { ; Leftwards localX.w = SEnemy.X - strafeSpeed if.w (localX < SEnemy.MinX) { print.b #0,100,24 localX.w = SEnemy.MinX SEnemy.StrafeDirection = #STRAFE_RIGHT SEnemy.StrafeState = #STRAFE_SWITCHING SEnemy.FrameStrafe = SEnemy.StrafeSwitchingDelay + rFrame } SEnemy.X = localX } } ai_strafing_done: ; rts } And here's an example of GPU method intermixing both: quad_save_2: { register r3:a0 register r4:d1 register r5:d2 a0 = &edge1gpu_2 loopShort (d1 = #7) { d2 = (a0)+ (a2)+ = d2 } register r11:d0 register r12:d1 register r13:d2 movei #-1, r1 imult r1, d1 d0 -= r8 d1 += r9 d2 -= r10 if.l (d2 < #1) d2 = #1 imult r7, d0 imult r7, d1 gdiv d2, d0 gdiv d2, d1 d0 += r5 d1 += r6 Return_2 } I can totally see doing the exact same thing with 6502 target. Automate the mundane repeated things via dynamic macros made more powerful by introducing types and making compiler replace what is needed, thus not cluttering the codebase with pages of code that doesn't let you see woods for the trees (or having to update 4 versions of the same macro)... I experienced, first-hand, how much more productive your ASM coding becomes when only these first few features are implemented (less than 3 days of work): - local constants and variables - nested scopes { } - nested conditions - loop - 1-op expressions (A = B + C) Performance-wise, my compiler will generate exact same code you would have written by hand, so performance is not affected in the least. Best of both worlds and for just a few days of .NET coding. But you save 10x more time in less debugging. Of course, this is not C, if you go by the C specs. I don't care for that in the least. My goal isn't to import billion lines of C code someone else wrote. My goal is to make sure the C-style code I write is as fast as hand-written ASM and doesn't need to be debugged. I only regret not having done this years ago... Quote Link to comment Share on other sites More sharing options...
42bs Posted September 10, 2019 Share Posted September 10, 2019 12 hours ago, VladR said: You actually are bringing great point. I completely forgot about that very first wave of mobile games - like Snake and Space Invaders that were preinstalled on each phone of the era. Only god knows, how many other such games are out there. Must be hundreds. Invaders, Mines and Snake already ported to the Lynx Quote Link to comment Share on other sites More sharing options...
VladR Posted September 10, 2019 Share Posted September 10, 2019 (edited) 15 minutes ago, 42bs said: Invaders, Mines and Snake already ported to the Lynx Yeah, sure - but every company created a slightly different version of each of those. It was never exactly the same game (just gameplay - roughly). Some had very interesting twists or a great story / art to accompany the gameplay. Plus, the art assets, they were done by professional pixel artists. Though, it might be harder to find those commercial releases available with full art assets. But, there's always decompilers. Plenty of those early mobiles had a very similar resolution as Lynx, so art assets should be mostly transferrable. I remember meetings where we were arguing about which colors to put into the 16-color palette, so certainly that particular phone must have had an awful low resolution, similar to Lynx - remember those flip phones which fit only 3-4 rows of the text message on screen and you had to scroll SMS 5 times ? That couldn't possibly have been 102 pixels vertically... Edited September 10, 2019 by VladR Quote Link to comment Share on other sites More sharing options...
laoo Posted September 10, 2019 Share Posted September 10, 2019 8 hours ago, VladR said: I experienced, first-hand, how much more productive your ASM coding becomes when only these first few features are implemented (less than 3 days of work): - local constants and variables - nested scopes { } - nested conditions - loop - 1-op expressions (A = B + C) Performance-wise, my compiler will generate exact same code you would have written by hand, so performance is not affected in the least. Best of both worlds and for just a few days of .NET coding. But you save 10x more time in less debugging. Sorry to destroy your dreams, but as it may work for 68000, such approach won't work for 6502. Quote Link to comment Share on other sites More sharing options...
+karri Posted September 10, 2019 Share Posted September 10, 2019 I assume that lots of programmers code structural asm code for 6502. The BLL kit contains all the relevant control structures (if, else, then. while do plus lots of macros). run LOMEM Start:: START_UP CLEAR_MEM CLEAR_ZP +STACK INITMIKEY INITSUZY IF DOUBLEBUFFER SCRBASE screen0,screen1 ELSE SCRBASE screen0 ENDIF IF DOUBLEBUFFER SWITCHBUF jsr cls ENDIF SETRGB pal ; set color ; ; Initialize board area ; set tactics $02 is the most desired place $80 the least ; ldx #Rows*Columns lda #$20 _WHILENE dex sta board,x _WEND This looks so much like C. But it is BLL. 1 Quote Link to comment Share on other sites More sharing options...
VladR Posted September 10, 2019 Share Posted September 10, 2019 58 minutes ago, laoo said: Sorry to destroy your dreams, but as it may work for 68000, such approach won't work for 6502. Can you explain what exactly do you mean ? Now, I do have different language constructs for 68000 and different ones for RISC (GPU/DSP) - they are all designed around the instruction set (rather than the other way around), hence I can guarantee the exact same output compiled code as I would write by hand. Meaning, 68000's constructs are much more verbose, there's more flexibility (especially thanks to the rich addressing modes). Which is why I don't see why I can't create a set of 6502 ops per each such language construct from within a compiler (same way as I would manually from within the assembler). It's not just a theory. I've started working on this last October, and almost every single month since then, I've tweaked/added new language construct to each processor target. Now, on RISC, there's an opportunity to manually rearrange ops for better use of pipelining, however I stopped doing that, because it makes the resulting code virtually undebuggable (considering all the RISC HW bugs). So, in theory you could produce a faster code for inner loops by hand, but any subsequent change to that code would become extremely expensive to make, so I don't do that anymore - as it's basically not worth my time. I probably will do some pipelining for division, as you can make the division execute for free by clever pipelining, assuming it's not the last op in the method. To some extent, you can do the same , as a manual postprocess, on 6502 code with CLC/SEC, etc. But, again, even when it's nicely documented, it makes it very hard to make adjustments to the code later. The only place I did that on Lynx was for the inner scanline loop, as that's what's executed most often. But, that's like, 1% of the code (exception to the rule)... Quote Link to comment Share on other sites More sharing options...
VladR Posted September 10, 2019 Share Posted September 10, 2019 52 minutes ago, karri said: I assume that lots of programmers code structural asm code for 6502. The BLL kit contains all the relevant control structures (if, else, then. while do plus lots of macros). run LOMEM Start:: START_UP CLEAR_MEM CLEAR_ZP +STACK INITMIKEY INITSUZY IF DOUBLEBUFFER SCRBASE screen0,screen1 ELSE SCRBASE screen0 ENDIF IF DOUBLEBUFFER SWITCHBUF jsr cls ENDIF SETRGB pal ; set color ; ; Initialize board area ; set tactics $02 is the most desired place $80 the least ; ldx #Rows*Columns lda #$20 _WHILENE dex sta board,x _WEND This looks so much like C. But it is BLL. Damn, this looks nice ! Wish I realized that 6-8 weeks ago 1 Quote Link to comment Share on other sites More sharing options...
+karri Posted September 10, 2019 Share Posted September 10, 2019 Yep. Doing a new 3D engine is perhaps not the easiest way to familiarize yourself with a new architecture. Some simple 1 minute game in C or BLL would have been a good introduction to existing tools. It is also possible to get a fairly decent starting point by creating something in C and compiling it with --add-source to an asm file. There is also a lot of optimizers available like: -O Optimize code -Oi Optimize code, inline more code -Or Enable register variables -Os Inline some known functions -T Include source as comment --check-stack Generate stack overflow checks --disable-opt name Disable an optimization step --enable-opt name Enable an optimization step --register-space b Set space available for register variables --register-vars Enable register variables A simple compilation like cc65 -t lynx -O -T game.c -o game.s creates a nice asm source file that allows you to look in detail for how the cc65 planned to optimize the code. You can then use cl65 to compile the asm file and link the final executable. cl65 -t lynx -o game.lnx -C lynx.cfg game.s lynx.lib 2 Quote Link to comment Share on other sites More sharing options...
laoo Posted September 10, 2019 Share Posted September 10, 2019 (edited) In my opinion what you are trying to accomplish is only a syntactic sugar of replacing "cmp/bne" alike sequences with fancy "if" statements and similar sorts of things. That's not the place where lies the real architecturally relevant difference in programming paradigms. The main problem in 6502 programming is really efficient memory management. On systems with 68000 your memory management is easy. You have plenty of registers and addressing modes that permit you to use memory easily. On 6502 on the other hand you have only 3 non-orthogonal registers and addressing modes that hardly can be called being flexible so making code fast boils down to using zero page memory in a smart way. Good luck with "local constants and variables" management that will produce code rivaling hand crafted assembly. Edited September 10, 2019 by laoo Quote Link to comment Share on other sites More sharing options...
VladR Posted September 10, 2019 Share Posted September 10, 2019 3 minutes ago, laoo said: In my opinion what you are trying to accomplish is only a syntactic sugar of replacing "cmp/bne" alike sequences with fancy "if" statements and similar sorts of things. That's not the place where lies the real architecturally relevant difference in programming paradigms. The main problem in 6502 programming is really efficient memory management. On systems with 68000 your memory management is easy. You have plenty of registers and addressing modes that permit you to use memory easily. On 6502 on the other hand you have only 3 non-orthogonal registers and addressing modes that hardly can be called being flexible so making code fast boils down to using zero page memory in a smart way. Good luck with "local constants and variables" management that will produce code rivaling hand crafted assembly. Oh, now I understand what you mean. I guess I didn't make my point clear before - I don't really care for "real architecturally relevant difference in programming paradigms". All I care about is get the most amount of stable and fast code working in as short time as possible BUT with easy refreshing of its purpose even if I don't see the code for weeks/months. I know it works with Jag, because I switched back to it many times over last year. Pure asm code is a mess to get back into (though, 68000 Asm is much easier than RISC Asm, from that standpoint), but the Asm/C hybrid makes the switch almost instant and very easy. Every day that I work on whichever Atari I choose to (Jaguar, Lynx, A800) is costing me real money as life ain't free. Given how bare the 3D landscape is on either platform, I could spend 3 lifetimes filling the gaps in their game library. So, to me personally it's not important to use "zero page memory" in a smart way (though, I obviously get your point). It's way much more important to use my time in a smart way. Sure, as an example, if I spent 4 weeks optimizing my rasterizer, I know that I could make it much faster. But, in the same timeframe, using stable codebase and tools, you can produce full another game in the same time... TLDR: The performance difference from manually handcrafted / refactored code is absolutely not worth the effort it takes to write (and the disastrously low refactorability in the future). Quote Link to comment Share on other sites More sharing options...
laoo Posted September 10, 2019 Share Posted September 10, 2019 (edited) I agree 100%. On 6502 there is just no sweet spot and you have to choose which resource to manage better - CPU time and memory usage, or... your life-time, and there is no such compiler that will "generate exact same code you would have written by hand". To be precise: I agree with your overall observation, but the TLDR part is a matter of personal decision and preferences what kind of game or games you want to produce. I have my paid job, writing games is my hobby and personally I spend on it as much time as I want (or actually how much my wife allows me to). Edited September 10, 2019 by laoo 1 Quote Link to comment Share on other sites More sharing options...
enthusi Posted September 10, 2019 Share Posted September 10, 2019 This goes for any 80ies 6502-based game. They were all written in assembly by hand (with very few exceptions). You can reverse it and rewrite it and in C64-land that did and does happen in fact Except for compiled BASIC (horrible, horrible, horrible) you can read almost any routine in a disassembly rather well. Personally, I believe that you only want hand-written assembly in 6502/65C02. Quote Link to comment Share on other sites More sharing options...
agradeneu Posted September 10, 2019 Share Posted September 10, 2019 (edited) 1 hour ago, VladR said: Every day that I work on whichever Atari I choose to (Jaguar, Lynx, A800) is costing me real money as life ain't free. Given how bare the 3D landscape is on either platform, I could spend 3 lifetimes filling the gaps in their game library. . Edited September 10, 2019 by agradeneu Quote Link to comment Share on other sites More sharing options...
laoo Posted September 10, 2019 Share Posted September 10, 2019 18 minutes ago, enthusi said: Personally, I believe that you only want hand-written assembly in 6502/65C02. On modern processors it's just hard to write better code than compiler can generate. It's not the case for 65(C)02 - it is extremely compiler-resistant. I believe that it is possible that a good compiler could exist, but none has created one yet (as none desires to allocated enough money/time to do it). Nevertheless I'm sort of tempted to write a game for GBA in thumb assembly. It might be as fun as programming 6502 Quote Link to comment Share on other sites More sharing options...
42bs Posted September 10, 2019 Share Posted September 10, 2019 5 hours ago, karri said: I assume that lots of programmers code structural asm code for 6502. The BLL kit contains all the relevant control structures (if, else, then. while do plus lots of macros). ; Initialize board area ; set tactics $02 is the most desired place $80 the least ; ldx #Rows*Columns lda #$20 _WHILENE dex sta board,x _WEND This looks so much like C. But it is BLL. Every now and then (actually now), I am working on a VM (like SWEET16, but complete ISA). One idea is to have a VM which runs 65C02 code extended by special opcodes like IF,THEN,ELSE. I thought to use BRK #n to add the new opcodes, but BRK takes about 9 cycles, so I am not sure if it is worth it. So likely a Game-BASIC would be the most efficient. Quote Link to comment Share on other sites More sharing options...
42bs Posted September 10, 2019 Share Posted September 10, 2019 13 minutes ago, agradeneu said: STNICCC is fake! At least respective 3D as the 3D->2D projection is done off-line. But it is a good benchmark for polygon rendering. Quote Link to comment Share on other sites More sharing options...
42bs Posted September 10, 2019 Share Posted September 10, 2019 7 minutes ago, laoo said: On modern processors it's just hard to write better code than compiler can generate. It's not the case for 65(C)02 - it is extremely compiler-resistant. I believe that it is possible that a good compiler could exist, but none has created one yet (as none desires to allocated enough money/time to do it). Nevertheless I'm sort of tempted to write a game for GBA in thumb assembly. It might be as fun as programming 6502 I earn my living writing Assembly, and a lot Thumb(-2) code: I can assure you: 65C02 is more fun ? Quote Link to comment Share on other sites More sharing options...
laoo Posted September 10, 2019 Share Posted September 10, 2019 3 minutes ago, 42bs said: I earn my living writing Assembly, and a lot Thumb(-2) code: I can assure you: 65C02 is more fun ? No no... thumb2 is too much. I'm tempted by old good arm7tdmi (with odschool non-unified syntax - it looks quite like 6502 then). But indeed I haven't wrote anything in this assembly so my expectation might be too high. Quote Link to comment Share on other sites More sharing options...
42bs Posted September 10, 2019 Share Posted September 10, 2019 (edited) 5 minutes ago, laoo said: No no... thumb2 is too much. I'm tempted by old good arm7tdmi (with odschool non-unified syntax - it looks quite like 6502 then). But indeed I haven't wrote anything in this assembly so my expectation might be too high. Ok, I agree ? ARM assembly (all variants, ARMv6-M up to Aarch64) is fun. Esp. when hand-optimizing. There are several nasty tricks possible esp. in ARM mode. 3-op instructions are fun It is an easy language to start Assembly. But a good emulator with debugger is a must. Edited September 10, 2019 by 42bs 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.