Jump to content
IGNORED

Java mobile games to Atari lynx games (Theory)


Europatari

Recommended Posts

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 :lol:  ), 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 :)

  • Like 1
Link to comment
Share on other sites

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 by LordKraken
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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 ;-)

Link to comment
Share on other sites

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 by VladR
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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)...

Link to comment
Share on other sites

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 :)

 

  • Haha 1
Link to comment
Share on other sites

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

 

  • Like 2
Link to comment
Share on other sites

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 by laoo
Link to comment
Share on other sites

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).

 

Link to comment
Share on other sites

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 by laoo
  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by agradeneu
Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

 

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 ?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by 42bs
  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...