Jump to content
IGNORED

Simon (game) in assembly language


Dexter

Recommended Posts

 

If displaying the score was time critical, I could set it up with a look up table.

I've tried this routing, but it doesn't display anything except "00". Did I mis a byte / word conversion, again?

 

 

Apart from the fact that there is an INC R5 missing in your loop, for displaying numbers I would rather go for the DIV method. If you only have two decimal digits, you get your result by a single DIV (quotient is the first digit, remainder is the second digit (after adding the offset for the 0)).

Link to comment
Share on other sites

 

 

Apart from the fact that there is an INC R5 missing in your loop, for displaying numbers I would rather go for the DIV method. If you only have two decimal digits, you get your result by a single DIV (quotient is the first digit, remainder is the second digit (after adding the offset for the 0)).

 

Well, it’s just a proof of concept, two of the above methods already work perfectly, but as you pointed out, we’re trying to keep our code as small as possible, to preserve memory. So I thought make a version with a look up table. Totally needless, just to look if it’s faster, which I’m sure it is.

R5 will be incremented during gameplay, at each round, the round number will be moved to R5 and so on. I'll try to get it working, as it doesn't yet.

Link to comment
Share on other sites

 

If displaying the score was time critical, I could set it up with a look up table.


shwrn1 MOVB @scco(r5),@VDPWD  * Write byte to VDP RAM
       DEC  R2                * Byte counter
       JNE  shwrn1            * Check if done

I've tried this routing, but it doesn't display anything except "00". Did I mis a byte / word conversion, again?

 

I was referring to this location. You have to include an INC R5 before DEC R2; I assume you want to write two consecutive bytes, don't you?

 

Or you unroll the loop:

 

MOVB @scco(r5),@VDPWD

MOVB @scco+1(r5),@VDPWD

Link to comment
Share on other sites

 

You have to include an INC R5 before DEC R2;

 

Thanks! That did the trick. Now it's working as intended.

 

No, I won't keep that routine as the final one, but I'll store it for reference. :)

The single DIV method is indeed the one that stays.

Link to comment
Share on other sites

If you really need to save clock cycles another option is to store the number as individual ascii digits that can be transferred directly to the VDP. This works well with a score where you usually only add (especially if you only add one), so the math is simple. The number you add can also be stored as individual digits so you can add them one by one as when you add two numbers on paper. I used this is Titanium and other games.

Link to comment
Share on other sites

If you really need to save clock cycles ...

 

Well, maybe one should take a step back and look at the context: How often could the score possibly be updated? I'd go for space rather than speed here.

 

(But yes, I like the discussion about saving cycles ...)

Link to comment
Share on other sites

If you really need to save clock cycles another option is to store the number as individual ascii digits that can be transferred directly to the VDP. This works well with a score where you usually only add (especially if you only add one), so the math is simple. The number you add can also be stored as individual digits so you can add them one by one as when you add two numbers on paper. I used this is Titanium and other games.

 

 

 

Well, maybe one should take a step back and look at the context: How often could the score possibly be updated? I'd go for space rather than speed here.

 

(But yes, I like the discussion about saving cycles ...)

 

The discussion was hypothetical, *if* the routine were time critical, and memory usage wouldn't be an issue.

This is the result:

shwrn
       mov  @rndnum,r5        * move round number into r5
       ai   r5,-1             * Start from 0 instead of 1
       sla  r5,1              * index for bytes to look up
       li   r0,>3910          * line 8 position 15
       li   r2,2              * 2 bytes to transfer

*      part of VMBW
       MOVB @R0LB,@VDPWA      * Send low byte of VDP RAM write address
       ORI  R0,>4000          * Set read/write bits 14 and 15 to write (01)
       MOVB R0,@VDPWA         * Send high byte of VDP RAM write address

shwrn1 MOVB @scco(r5),@VDPWD  * Write byte to VDP RAM
       MOVB @scco+1(r5),@VDPWD

       B    *R11

scco   byte 212,212,212,213,212,214,212,215,212,216,212,217,212,218,212,219,212,220,212,221
       byte 213,212,213,213,213,214,213,215,213,216,213,217,213,218,213,219,213,220,213,221
       byte 214,212,214,213,214,214,214,215,214,216,214,217,214,218,214,219,214,220,214,221

In this case the value of the character "0" is 212.

  • Like 1
Link to comment
Share on other sites

Finally, I can present a real playable version!
V0.81b

 

SYSTEM REQUIREMENTS:
TI-99/4A Home Computer
32KiB RAM expansion
One disk drive
Extended BASIC

 

STARTING THE GAME:
The game automatically starts by selecting Extended BASIC

 

During gameplay, the game is over when pressing a wrong key, or wait for longer than 5 seconds when an input is expected.

Enjoy and comment!

 

runme.dsk

  • Like 6
Link to comment
Share on other sites

Very nice. And funny how it was actually playing a tune - sort of. :)

Thanks!

During emulation, music doesn't play very accurately. Don't know why though.

Edited by Dexter
  • Like 1
Link to comment
Share on other sites

very Good playable :) i like it ... just with numbers is easier for who have good memory with them... suggestion could be to add a choice for only colors or some different chars from numbers.

also a progressive difficult level-up i'd like. for example speed up every 10 or 15 levels ?

funny intro music :)


(played on Classic99, no problem, scored 11)

Link to comment
Share on other sites

Very nice! I like it!

 

Regarding the illegal opcode - you can't actually execute at odd addresses, I see the Classic99 debugger screwed up there (displaying and executing the right bytes, but not adjusting the address. But it's an actual explicitly branch and link to A971 (which will be run at A970), which contains >0000 bytes.

 

   A0A8  06A0  bl   @>a971                 (28)
         A971
   A971  0000  data >0000                  (10)
>  A973  CE8B  mov  R11,*R10+             
It would be nice if you enabled QUIT to reset the system. You can scan for it yourself easily, or if they don't conflict with your code, just enable interrupts in your main loop with a LIMI 2/LIMI 0 sequence. On hardware it's kind of annoying to have to power off the machine to exit a program. Or provide a quit option. :)

 

To scan for it yourself, you just need R12 and another register available (I use R13 here). This code is adapted from the console ROM. BL @CKQUIT somewhere convenient, it will either return or reset. ;)

 

CKQUIT
	LI R12,>0024 		* Load CRU
	CLR R13			* column select
	LDCR R13,3		* set the hardware
	SRC R12,7		* Delay?
	LI 12,>0006		* CRU row to read
	STCR R13,8 		* Fetch CRU
	LI R12,>1100		* match value for QUIT
	CZC R12,R13 		* QUIT keys?
	JEQ DOQUIT		* Matched, need to reset
	B *R11			* no match, go to caller
DOQUIT
	LI R0,>83FE		* clear scratchpad to prevent reset crashes
ENDCL1	CLR *R0			* probably only need to clear the user interrupt
	DECT R0			* but this is fine 
	CI R0,>8300
	JNE ENDCL1
	BLWP @>0000		* ( yeah, it's okay to leave R0 )
The "DOQUIT" loop is probably a little surprising. I do a lot of code that basically takes over scratchpad. Certain values in scratchpad can crash the OS, even on a reset with BLWP @>0000. Eventually I just started putting the above code in anything I wrote that messes with scratchpad enough to not be able to use interrupts. The one assumption in that clear loop is you have your workspace at >8300 (with LWPI), because if it's anywhere else, it will clear your R0 in the middle of the loop and eventually crash. ;) If you have workspace elsewhere, you can just add a LWPI >8300 at DOQUIT and it's done.

 

F18A apps can do a test similar to the above and add in the F18A reset before exiting. ;)

Link to comment
Share on other sites

Kind of thrilling, now that I’ve got a playable version. 8)

 

Great !! And the sound works good, no problems (I use Mess)...

 

schmiddy

 

Sound is probably hardware related, on another PC it's working OK.

 

I scored 14. I will test it on my son tomorrow.

 

P.S. You are excuting an illegal opcode at >A971.

 

Hope your son likes it. :) I bugged my wife till she finally tried, and she surprisingly likes it very much.
I’ll come back to the illegal opcode at >A971 right ahead.

 

 

very Good playable :) i like it ... just with numbers is easier for who have good memory with them... suggestion could be to add a choice for only colors or some different chars from numbers.
also a progressive difficult level-up i'd like. for example speed up every 10 or 15 levels ?
funny intro music :)
(played on Classic99, no problem, scored 11)

 

 

Indeed, the numbers help, but eventually the sequence will get too long to remember. However, I could squeeze in a menu item to choose between squares and numbers. I have a game mode, to build in the game, on my to-do list, to add progressive speed build-up, like the original toy from 1978.
I entered the music by hand from a YouTube video. I liked it because it only contains the four notes from the SIMON game, an A minor chord.

 

RXB (XB) LOAD program:

 

100 CALL EAPGM("DSK1.RUNME")

 

I assume you imply an improvement of the music playback? Unfortunately, it doesn’t.

 

Very nice! I like it!

Regarding the illegal opcode - you can't actually execute at odd addresses, I see the Classic99 debugger screwed up there (displaying and executing the right bytes, but not adjusting the address. But it's an actual explicitly branch and link to A971 (which will be run at A970), which contains >0000 bytes.

   A0A8  06A0  bl   @>a971                 (28)
         A971
   A971  0000  data >0000                  (10)
>  A973  CE8B  mov  R11,*R10+             
It would be nice if you enabled QUIT to reset the system. You can scan for it yourself easily, or if they don't conflict with your code, just enable interrupts in your main loop with a LIMI 2/LIMI 0 sequence. On hardware it's kind of annoying to have to power off the machine to exit a program. Or provide a quit option. :)

To scan for it yourself, you just need R12 and another register available (I use R13 here). This code is adapted from the console ROM. BL @CKQUIT somewhere convenient, it will either return or reset. ;)

CKQUIT
	LI R12,>0024 		* Load CRU
	CLR R13			* column select
	LDCR R13,3		* set the hardware
	SRC R12,7		* Delay?
	LI 12,>0006		* CRU row to read
	STCR R13,8 		* Fetch CRU
	LI R12,>1100		* match value for QUIT
	CZC R12,R13 		* QUIT keys?
	JEQ DOQUIT		* Matched, need to reset
	B *R11			* no match, go to caller
DOQUIT
	LI R0,>83FE		* clear scratchpad to prevent reset crashes
ENDCL1	CLR *R0			* probably only need to clear the user interrupt
	DECT R0			* but this is fine 
	CI R0,>8300
	JNE ENDCL1
	BLWP @>0000		* ( yeah, it's okay to leave R0 )
The "DOQUIT" loop is probably a little surprising. I do a lot of code that basically takes over scratchpad. Certain values in scratchpad can crash the OS, even on a reset with BLWP @>0000. Eventually I just started putting the above code in anything I wrote that messes with scratchpad enough to not be able to use interrupts. The one assumption in that clear loop is you have your workspace at >8300 (with LWPI), because if it's anywhere else, it will clear your R0 in the middle of the loop and eventually crash. ;) If you have workspace elsewhere, you can just add a LWPI >8300 at DOQUIT and it's done.

F18A apps can do a test similar to the above and add in the F18A reset before exiting. ;)

 

 

It seems that I branched to odd an address. In front of that address there were “byte” pseudo commands, and naturally, there was an odd amount of them. :)
I placed an “even” opcode after them, which resolved the problem.

I also neglected to place an “aorg >a000”, which isn’t mandatory, but I did it now anyway.

A QUIT option is on my to-do list. However, you’re suggesting for checking CTRL=. Either way, I saved the routine in my archive.

 

(Oh, I got 14. ;) )

 

My hi-score is 13. Wow, such bad, many improve! :-D

 

--------

 

To-do:

  • Add 1978 mode (progressinve)
  • Add blind mode
  • Add silent mode
  • Add reverse mode
  • Add normal mode
  • Add different speeds
  • Implement squares instead of numbers
  • Add help screen
  • Add quit option
  • providing a nice user manual in PDF format

 

Eventually the menu could look like this:


PRESS B TO BEGIN GAME
PRESS M FOR MODE: XXXXXXX        NORMAL / 1978 / BLIND / SILENT / REVERSE
PRESS S FOR SPEED: XXXXXX        SLOW / MEDIUM / FAST / INSANE
PRESS A FOR APPEARANCE: XXXXXXX  SQUARES / NUMBERS
PRESS H HELP
PRESS Q TO QUIT


But first I’ll clean up the code so far, now I know what is meant by that! :)
Then I’ll see what I can implement from the to-do list.
Thanks to all so far.

  • Like 3
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...