Jump to content
IGNORED

Assembly on the 99/4A


matthew180

Recommended Posts

So I had working code in a routine like this:

 

	; Compare bytes across two character lists, R8 and R6 are indexes into each byte array.
	CB   @CHRBFFL(R8), @FLRCHARS(R6)
I'm trying to make my routine more generic so it can be used to compare two lists of bytes, 
where the addresses to each list are specified in registers before the routine is branched to.

Does this syntax work?  
	MOV  @CHRBFFL,R1
	MOV  @FLRCHARS,R2
	; Compare bytes across two character lists, R8 and R6 are indexes into each byte array.
	CB   @R1(R8), @R2(R6)

 

I mean, it's not working for me at the  moment, but why not?

 

Edited by retrodroid
Link to comment
Share on other sites

1 hour ago, retrodroid said:

I'm trying to make my routine more generic so it can be used to compare two lists of bytes, where the addresses to each list are specified in registers before the routine is branched to. Does this syntax work?  

	MOV  @CHRBFFL,R1
	MOV  @FLRCHARS,R2
	; Compare bytes across two character lists, R8 and R6 are indexes into each byte array.
	CB   @R1(R8), @R2(R6)

 

I use Forth Assembler mostly so I might screw up the syntax details but the best way to do this is:

  1. Put the address of string1 in a register
  2. Put the address of string2 in a 2nd register 
  3. Put the number of bytes to compare in a 3rd register 
  4. Then put compare-byte in a loop using indirect addressing (ie: get the contents of the address) with auto-incrementing 
  5. decrement the counter until it is zero


 

STR1  TEXT 'This is a string but it could be a BYTE statement'
STR2  TEXT 'This is a string but it could be different' 

        LI R0,40		* max length to scan the strings
        LI R1,STR1
        LI R2,STR2

LOOP1   CB *R1+,*R2+
        JNE NMATCH      * different, char jump out 
        DEC R0          * dec loop counter
        JNE LOOP1       * keep going until zero
        
MATCH   *all chars matched         

NMATCH  do something for not a match 

 

Edited by TheBF
CODE mistake
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I didn't want to lead you astray so I quickly tested this idea in Forth Assembler and it seems to work.

Compare STR1 to STR1 for 40 bytes returns -1 (true)

Compare STR1 to STR2 for 40 bytes returns 0

 

Another idea would be to use subtraction and then you could determine > and < as well.

 

Spoiler
INCLUDE DSK1.ASM9900
INCLUDE DSK1.ASMLABELS


\ create byte-counted strings in memory. 1st byte is length
CREATE STR1 S" This is a string but it could be a BYTE statement " S,
CREATE STR2 S" This is a string but it could be different" S,

CODE COMPARE ( addr addr len -- ?)
                              \ len is in R4, (accumulator) in Camel99 Forth
          *SP+ R1 MOV,        \ load string address from stack
          *SP+ R2 MOV,        \ load string address from stack  

1 $:  R1 *+ R2 *+ CMPB,
              2 $ JNE,
               R4 DEC,
              1 $ JNE,
               R4 SETO,       \ set accumaltor register to true
                  NEXT,       \ return to Forth

2 $:           R4 CLR,        \ set accumulator register to false
                  NEXT,       \ return to Forth
ENDCODE



 

 

 

 

 

 

 

compare.jpg

Edited by TheBF
Wrong comment
  • Like 2
Link to comment
Share on other sites

15 hours ago, retrodroid said:
Does this syntax work?  
	MOV  @CHRBFFL,R1
	MOV  @FLRCHARS,R2
	; Compare bytes across two character lists, R8 and R6 are indexes into each byte array.
	CB   @R1(R8), @R2(R6)

I mean, it's not working for me at the  moment, but why not?

 

No, it does not. R1 and R2 are synonyms for 1 and 2 respectively. @R1 is certainly legal syntax, but it does not do what you are expecting. The last line is equivalent to

       CB   @1(R8),@2(R6)

because ‘@’ expects an address, not a register number. If R8 contains 4 and R6 contains 8, that instruction will be

       CB   @5,@10

surely not what you intended. What you want to do is either

       CB   @CHRBFFL(R8),@FLRCHARS(R2)

or add the offsets to your registers by autoincrement or explicit addition:

       MOV  @CHRBFFL(R8),R1
       MOV  @FLRCHARS(R6),R2
* loop thereafter with autoincrements
       CB   *R1+,*R2+
* or add offsets to the registers with the addresses
       A    R8,R1
       A    R6,R2
       CB   *R1,*R2

 

...lee

Edited by Lee Stewart
CORRECTIONS
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

7 hours ago, Tursi said:

I think you'll find that a bubble sort or such actually executes more instructions. The speed of quick sort is obtained by needing to go through the data fewer times. :)

 

I take your point. Bubble will be looping so many more times and therefore executing more instructions.

OK. I got nothin' :) 

 

Link to comment
Share on other sites

Thanks guys - that set me on the correct path and its working well now!

 

Here's my code:

 

       LI   R2,FLRCHARS           ; Test for floor chars...
       LI   R1,CHRBFFL            ; ...under the feet.
       LI   R3,7                  ; 7 floor chars to test
       MOV  @STSTAND,R4           ; Set new state to Stand if char found.
       MOV  @STFALL,@NPSTATE      ; Default to falling if no floor chars found.
       BL   @CHKFTCHR             ; Branch to char detection routine
	   ...


CHKFTCHR
       MOV  R2,R6                  ; Save address to reset with
       CLR  R8
CHK1   MOV  R3,R7
CHK2
       CB   *R1, *R2
       JEQ  CHK3                    ; Target char found! 
       INC  R2
       DEC  R7
       JNE  CHK2		; Out of inner-loop chars?
       MOV  R6,R2                   ; reset R2
       INC  R1
       INC  R8
       C    R8,@CHRCNT		; How many chars under the feet are we checking (2 or 3)?
       JLT  CHK1		; Out of under-the-feet / outer-loop chars?	
       JMP  CHK4                    ; No target chars found
CHK3
       MOV  R4,@NPSTATE             ; Target char found, set state
CHK4
	RT	

 

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

10 hours ago, TheBF said:

I take your point. Bubble will be looping so many more times and therefore executing more instructions.

OK. I got nothin' :) 

Exactly. But don't be sorry about that.

However, if you think about it, you'll realize that the CPU is normally always executing instructions (yes, IDLE is an exception, but we can leave that to the side). So when a certain time passes by, it has executed roughly the same amount of instructions each time, since the different cycle counts will even out.

Thus a fast algorithm is one that uses few instructions almost always. You could imagine some special cases where a few simple instructions are faster than MPY or DIV, and may accomplish the result just as well, but they are few. Looking at the instructions you'll see that most math-related instructions are at least 14 cycles minimum, and access memory almost as much as MPY does. If you get away with three such instructions you are faster than MPY, but just by a hair. Four and you have lost.

Even DIV is frequently faster than being smart, since even at 92-124 cycles, it takes that you work with multiples of two to really be better. Especially if you consider that it takes 32 bits into account.

 

Even a 32-bit addition is not much quicker than a multiplication. Assume you want to add register pair R0,R1 to R2,R3.

 

A   R1,R3

JNC over next instruction

INC R2

A   R0,R2

 

That's three/four instructions just for that, 38 or 46 cycles, and MPY is 52.

  • Like 1
Link to comment
Share on other sites

2 hours ago, 9640News said:

I think I got it figured out now.  Self modifying code, 14 bytes ahead of current position is modified.

It's not quite self modifying code. It's storing a parameter value in one of three words of DATA that follow and are read by a call to a BLWP routine. $ is simply the current memory location.

  • Like 1
Link to comment
Share on other sites

4 hours ago, 9640News said:

Yeah, I finally figured that out.  At first, I counted bytes incorrectly and thought it was modifying an instruction.

 

 

To avoid headaches in the future, I'd suggest that you label the data element and update the "$+14" accordingly.  If/when you add something between the MOV and the DATA statements, you won't have to worry about chasing down the hard-coded reference.  

 

  • Like 1
Link to comment
Share on other sites

I want my game to be able to run off a cartridge on an unexpanded console. That means I need to store my data/maps/graphics on ROM or GROM, and use VDP memory for everything that won't fit in the fast 256 bytes of 16-bit memory.

 

Up to now I've been assembling with xas99 and loading and running using the Editor Assembler cartridge. I've been adding variables as I need them without too much concern for my overall memory consumption, but have avoided loading any bulk data outside of VDP memory.

 

Can anyone point me to relevant resources that would explain how I need to configure my code to run off a cartridge image, on an unexpanded console? 

I'm mostly looking for AL code structure requirements. What are the Do's and Do Not's for this? I don't want to get too far down the development road only to find out I've done something that will require a bunch of rework, etc. to deploy off a cartridge. 

 

I do have several of @Asmusr's game projects downloaded and intend to borrow heavily from them as I see they have a .bat + Java build process that can create cartridge images. I haven't looked into the details of that yet or tried to get it to build my project that way.

 

 

 

Edited by retrodroid
Link to comment
Share on other sites

47 minutes ago, retrodroid said:

I want my game to be able to run off a cartridge on an unexpanded console. That means I need to store my data/maps/graphics on ROM or GROM, and use VDP memory for everything that won't fit in the fast 256 bytes of 16-bit memory.

Do you have a specific cartridge in mind? You seem to have self-imposed hardware related constraints(ROM/GROM). FinalGROM 99, for instance, offers RAM/GRAM, as well! ...Then there's PAGED memory to consider!!!:ponder:

 

If you're running under E/A, you must already be using 32K... Though you want to eliminate this requirement for the final user?

Link to comment
Share on other sites

16 minutes ago, HOME AUTOMATION said:

Do you have a specific cartridge in mind? You seem to have self-imposed hardware related constraints(ROM/GROM). FinalGROM 99, for instance, offers RAM/GRAM, as well! ...Then there's PAGED memory to consider!!!:ponder:

 

If you're running under E/A, you must already be using 32K... Though you want to eliminate this requirement for the final user?

Well I fall under the "a little bit of knowledge..." at the moment, so take my assumptions with a grain of salt please. My goal is to run off a cartridge as if it was 1982 again.  :)

 

 

 

Link to comment
Share on other sites

1 hour ago, retrodroid said:

Well I fall under the "a little bit of knowledge..." at the moment, so take my assumptions with a grain of salt please. My goal is to run off a cartridge as if it was 1982 again.  :)

Bouncy's obstacle course is my only game that runs from a cartridge that it would have been realistic to produce in 1982 (2 banks of ROM, 32K not required). I have just updated it to build with the latest XDT99.

https://github.com/Rasmus-M/obstacle

Edited by Asmusr
Missing word
  • Thanks 1
Link to comment
Share on other sites

9 minutes ago, Asmusr said:

Bouncy's obstacle course is my only game that runs from a cartridge that it would have been realistic to produce in 1982 (2 banks of ROM, 32K not required). I have just updated it build with the latest XDT99.

https://github.com/Rasmus-M/obstacle

 

"With 16K cartridge", that's my current goal.  Is that 2 banks of 8KB ROMs that need to be switched? Or 1 8KB ROM and 1 8KB GROM, or??  

 

Quote

2 banks of ROM

 

Got it!  I'll study this example and post any questions, etc. as required.

 

Thanks a bunch!

 

Edited by retrodroid
Link to comment
Share on other sites

1 minute ago, retrodroid said:

 

"With 16K cartridge", that's my current goal.  Is that 2 banks of 8KB ROMs that need to be switched? Or 1 8KB ROM and 1 8KB GROM, or??  Any references to where I can learn about the makeup of the cartridge format?

 

Thanks.

 

It's two banks of 8K ROM each that needs to be switched. The first part of each bank is the same. You should be able to get some ideas from the source code.

  • Like 1
Link to comment
Share on other sites

1 hour ago, retrodroid said:

My goal is to run off a cartridge as if it was 1982 again.

Well, I would have liked to make a cartridge during the '80s, too! However, considering the info availability, and big moolah, required at that time... To me that simply equates as being unrealistic.:(

 

My first-hand cartridge knowledge is all related to developing on the FG99.

 

Classic99's, E/A image, offers RAM, at >6000->7FFF.;-)
 

Link to comment
Share on other sites

3 hours ago, retrodroid said:

Well I fall under the "a little bit of knowledge..." at the moment, so take my assumptions with a grain of salt please. My goal is to run off a cartridge as if it was 1982 again.  :)

 

 

 

Most carts are GPL GROM based so any game or application would need to be in GPL.

Now you can run ROM instead or GROM both in FinalGROM.

My RXB 2023 is 5 pages of 8K GROM and 3 pages of 8K ROM and RXB 2023 will run from CONSOLE ONLY with some Assembly built in the ROMs.

Link to comment
Share on other sites

7 hours ago, retrodroid said:

I want my game to be able to run off a cartridge on an unexpanded console. That means I need to store my data/maps/graphics on ROM or GROM, and use VDP memory for everything that won't fit in the fast 256 bytes of 16-bit memory.

 

Up to now I've been assembling with xas99 and loading and running using the Editor Assembler cartridge. I've been adding variables as I need them without too much concern for my overall memory consumption, but have avoided loading any bulk data outside of VDP memory.

 

Can anyone point me to relevant resources that would explain how I need to configure my code to run off a cartridge image, on an unexpanded console? 

I'm mostly looking for AL code structure requirements. What are the Do's and Do Not's for this? I don't want to get too far down the development road only to find out I've done something that will require a bunch of rework, etc. to deploy off a cartridge. 

 

I do have several of @Asmusr's game projects downloaded and intend to borrow heavily from them as I see they have a .bat + Java build process that can create cartridge images. I haven't looked into the details of that yet or tried to get it to build my project that way.

 

 

 

Here's another banked cartridge project that runs on unexpanded console: https://github.com/peberlein/bounce-n-pounce/blob/master/bnp.asm

(Bounce'n'Pounce is unrelated to Bouncy's obstacle course, despite the name)

I found the DORG directive useful, so I can declare variables using a label with DATA or BYTE statements in the 256B memory space at >8300.  The variables still need to be initialized elsewhere, but it does make it easier than calculating variable addresses manually.

 

  • Like 1
  • Thanks 2
Link to comment
Share on other sites

15 hours ago, PeteE said:

Here's another banked cartridge project that runs on unexpanded console: https://github.com/peberlein/bounce-n-pounce/blob/master/bnp.asm

(Bounce'n'Pounce is unrelated to Bouncy's obstacle course, despite the name)

I found the DORG directive useful, so I can declare variables using a label with DATA or BYTE statements in the 256B memory space at >8300.  The variables still need to be initialized elsewhere, but it does make it easier than calculating variable addresses manually.

 

What I've learned so far is that if you want your game to run off a 16KB cartridge it has to have "bounce" in the name...  😁

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