This is an archived, read-only copy of the United-TI subforum , including posts and topic from May 2003 to April 2012. If you would like to discuss any of the topics in this forum, you can visit Cemetech's z80 & ez80 Assembly subforum. Some of these topics may also be directly-linked to active Cemetech topics. If you are a Cemetech member with a linked United-TI account, you can link United-TI topics here with your current Cemetech topics.

This forum is locked: you cannot post, reply to, or edit topics. Z80 & 68k Assembly => z80 & ez80 Assembly
Author Message
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 23 Apr 2009 09:44:31 pm    Post subject:

I am coding for a Galaxian-type game, and would like to use jump tables to switch levels. I'm fairly new to this concept, so any help would be greatly appreciated Smile.

By the way, I DID look up the jump table and vector table section of Learning ASM in 28 Days tutorial, so I have a light idea of what it's about, but I simply cannot get it to work for me. Also, I'm coding for the TI83+/TI84+ family, if that matters.
Back to top
DigiTan
Unregistered HyperCam 2


Super Elite (Last Title)


Joined: 10 Nov 2003
Posts: 4468

Posted: 23 Apr 2009 10:07:59 pm    Post subject:

Basically, with jump tables all it takes is the slightest mistake and things will get horribly ugly. Like shaving. Since you already tried it, I'm betting it's something minor. But just to get started, here's a small routine that loads 1 of 3 levels. It takes in register <A>, locates to right spot in the table, moves that address to HL, and BAM! ...a jp (hl) command to win the game. ...Well...load it anyway.


Code:
;-------------------------------------------------------\
Level_loader:                              ;
; IN: A = level number to load (0-2)             ;
; OUT: -nothing-                            ;
; RESULT: Will jump to the proper level based on    ;
;       what <A> register is               ;
;--------------------------------------------------------
 ld hl,jump_table   ; HL -> Table of places to jump
 add a,a          ; Table entries are 2 bytes.  So multiply by 2
 ld e,a      ; E == the offset of the table
 ld d,0      ; Clear unused byte
 add hl,de      ; HL -> The address of where to jump
 ld e,(hl)      ; These 3 instructions act like "LD DE,(HL)"
 inc hl            
 ld d,(hl)      ; Now DE == Address to jump to
 ex de,hl         ; Now HL == Address to jump to
 jp (hl)          ; Go ahead and jump!

jump_table:
.dw ForestLevel, CaveLevel, SkyLevel



Things to keep in mind:

  • The <A> register had to be multiplied by two because ForestLevel, CaveLevel, and SkyLevel are 2-byte numbers.
  • TI's store these addresses with the least-significant byte first. At least when ".dw" is used.
  • Make sure it's ".dw" instead of ".db"
  • Make sure the places you're jumping into have working code too, or else the jump table code may get the blame!


Last edited by Guest on 23 Apr 2009 10:10:16 pm; edited 1 time in total
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 23 Apr 2009 10:32:48 pm    Post subject:

ah, you're right! One little mistake...I forgot to multiply the input ('a', in this case) by 2. Does .dw always form 2-byte numbers? Also, would the following code be acceptable, for the sake of organization?


Code:
jumptable:
.dw level1
.dw level2
.dw boss1
....
Back to top
DigiTan
Unregistered HyperCam 2


Super Elite (Last Title)


Joined: 10 Nov 2003
Posts: 4468

Posted: 23 Apr 2009 10:50:16 pm    Post subject:

Yep. They're exactly the same. .DW (or .word for some assmblers) will always make it a 16-bit number, even if it's a zero. Others like .db, .byte, and .text will be 8-bit.
Back to top
darkstone knight


Advanced Member


Joined: 07 Sep 2008
Posts: 438

Posted: 24 Apr 2009 05:06:56 am    Post subject:

note that:

.dw $1234
is different than:
.db $12,$34
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 24 Apr 2009 04:03:34 pm    Post subject:

ok, great, thanks! That was a huge help. Makes my programming life a lot easier Laughing. Oh, and one more quick question. To multiply by 2, you added 'a' onto itself. Wouldn't the RLA instruction do the same thing? If so, which method is quicker?

Last edited by Guest on 24 Apr 2009 04:04:04 pm; edited 1 time in total
Back to top
darkstone knight


Advanced Member


Joined: 07 Sep 2008
Posts: 438

Posted: 24 Apr 2009 04:11:08 pm    Post subject:

add (reg8): 4 or 7 (HL)
rra: 4 cycles, but uses the carry

i use add... iets easier to understand than shifts, and does work on registers other than A
Back to top
simplethinker
snjwffl


Active Member


Joined: 25 Jul 2006
Posts: 700

Posted: 24 Apr 2009 04:12:19 pm    Post subject:

TKD_01 wrote:
ok, great, thanks! That was a huge help. Makes my programming life a lot easier Laughing. Oh, and one more quick question. To multiply by 2, you added 'a' onto itself. Wouldn't the RLA instruction do the same thing? If so, which method is quicker?

They both take four T-states and are one-byte each. The only difference is the flags they affect; for add, S Z H C are affected as defined, P/V detects overflow, N is cleared; for rla: S Z P/V are not affected, H N are reset, C is the previous bit 7.
Back to top
calc84maniac


Elite


Joined: 22 Jan 2007
Posts: 770

Posted: 24 Apr 2009 04:24:34 pm    Post subject:

simplethinker wrote:
TKD_01 wrote:
ok, great, thanks! That was a huge help. Makes my programming life a lot easier Laughing. Oh, and one more quick question. To multiply by 2, you added 'a' onto itself. Wouldn't the RLA instruction do the same thing? If so, which method is quicker?

They both take four T-states and are one-byte each. The only difference is the flags they affect; for add, S Z H C are affected as defined, P/V detects overflow, N is cleared; for rla: S Z P/V are not affected, H N are reset, C is the previous bit 7.

Actually, RLA is more similar to ADC A,A since it shifts the carry flag into the lsb. Wink


Last edited by Guest on 11 Jul 2010 05:45:58 pm; edited 1 time in total
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 24 Apr 2009 06:35:30 pm    Post subject:

Ah, ok, got it. Now just one more question Wink. What would be the fastest way to clear the graph buffer, a.k.a. plotsScreen?

Last edited by Guest on 24 Apr 2009 06:36:34 pm; edited 1 time in total
Back to top
Taricorp


Member


Joined: 09 Mar 2006
Posts: 188

Posted: 24 Apr 2009 09:23:26 pm    Post subject:

Fast:

Code:
 ld hl,plotSScreen
 ld (hl),0
 ld de,plotSScreen+1
 ld bc,767
 ldir

Faster, but requires disabling interrupts:

Code:
 di
 ld b,(768/2)/6
 ld hl,0
 add hl,sp
 ld de,0
 ld sp,plotSScreen+767
loop:
 push de
 push de
 push de
 push de
 push de
 push de
 djnz loop
 ld sp,hl
 ei
Back to top
Galandros


Active Member


Joined: 29 Aug 2008
Posts: 565

Posted: 25 Apr 2009 03:58:22 am    Post subject:

If you clear the graph buffer right after printing it to screen see this routine to write to screen and erase it after:
http://wikiti.brandonw.net/index.php?title...nd_Improvements

This is better than writing to the screen and after that clearing gbuf, using one of the routines above, because instead of wasting time in waiting, it erases the gbuf.

Also ldir could be unrolled to ldi's (8 or more compensate) to improve speed at cost of space.
Back to top
darkstone knight


Advanced Member


Joined: 07 Sep 2008
Posts: 438

Posted: 25 Apr 2009 05:27:48 am    Post subject:

Galandros wrote:
Also ldir could be unrolled to ldi's (8 or more compensate) to improve speed at cost of space.


i wanted to say that, but it will erase plotsscreen+768, wich destroys randseed
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 25 Apr 2009 09:00:37 am    Post subject:

I believe that for my needs, I'm going to stick with Taricorp's Fast portion of code. The code contained with the link you gave me, Galandros, does not do sprite clipping, which I need Smile. And I dont really want to have to go in and modify the code.

Thanks again for all the help!

Oh and one more thing, the last byte of the plotsscreen contains the randseed? I'm assuming we acces this through plotsscreen+767?


Last edited by Guest on 25 Apr 2009 09:02:30 am; edited 1 time in total
Back to top
darkstone knight


Advanced Member


Joined: 07 Sep 2008
Posts: 438

Posted: 25 Apr 2009 09:03:56 am    Post subject:

look here:
http://dragonfire.unitedti.org/asmin28/lesson/toc.html
day 25

also, the "fast" code is waaaay overkill
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 25 Apr 2009 09:44:41 am    Post subject:

darkstone knight wrote:
look here:
http://dragonfire.unitedti.org/asmin28/lesson/toc.html
day 25

also, the "fast" code is waaaay overkill

Ok..I didn't find anything about the randseed. But that doesnt really matter.

@Galandros:
What would you then recommend to clear the plotsscreen? I dont need to write it, only to clear it.


Last edited by Guest on 25 Apr 2009 09:44:55 am; edited 1 time in total
Back to top
darkstone knight


Advanced Member


Joined: 07 Sep 2008
Posts: 438

Posted: 25 Apr 2009 09:53:14 am    Post subject:

if you dont need faster than 1/1000 seconds stick to LDIR, oterwise use the push method

randseed1 and randseed2 are 9 bytes (each) located at plotsscreen+767, corrupting then will make rand return numbers out of bounds (like 3,27071e53


Last edited by Guest on 11 Jul 2010 05:46:13 pm; edited 1 time in total
Back to top
TKD_01


Advanced Newbie


Joined: 20 Feb 2009
Posts: 51

Posted: 25 Apr 2009 10:00:03 am    Post subject:

darkstone knight wrote:
if you dont need faster than 1/1000 seconds stick to LDIR, oterwise use the push method

randseed1 and randseed2 are 9 bytes (each) located at plotsscreen+767, corrupting then will make rand return numbers out of bounds (like 3,27071e53

Ah, ok. That makes sense. And ya, I'll give the push method a try.
Thanks again!

EDIT:
The push method works a bit faster, but the only problem is that the last 7 pixel pixels of the bottom row constantly flash on and off when one of my sprites goes on top of that section.


Last edited by Guest on 11 Jul 2010 05:46:29 pm; edited 1 time in total
Back to top
simplethinker
snjwffl


Active Member


Joined: 25 Jul 2006
Posts: 700

Posted: 25 Apr 2009 12:33:57 pm    Post subject:

darkstone knight wrote:
if you dont need faster than 1/1000 seconds stick to LDIR, oterwise use the push method

randseed1 and randseed2 are 9 bytes (each) located at plotsscreen+767, corrupting then will make rand return numbers out of bounds (like 3,27071e53

So that's why sometimes ASM games cause funky random numbers to be returned?


Last edited by Guest on 11 Jul 2010 05:45:42 pm; edited 1 time in total
Back to top
FloppusMaximus


Advanced Member


Joined: 22 Aug 2008
Posts: 472

Posted: 25 Apr 2009 02:28:56 pm    Post subject:

Back up a minute, guys. No, the random seed is not located at plotSScreen plus 767. (Think about it: if that were true, wouldn't you expect to see garbage in the lower right corner of the graph screen?)

What darkstone knight originally said was correct:

darkstone knight wrote:
Galandros wrote:
Also ldir could be unrolled to ldi's (8 or more compensate) to improve speed at cost of space.


i wanted to say that, but it will erase plotsscreen+768, wich destroys randseed


seed1 is located at plotSScreen plus 768. Therefore, correctly written assembly programs, which write to at most (plotSScreen + 767), will not affect the RNG. Buggy assembly programs, however, sometimes do.

darkstone knight's point above, which was a good one, was that unrolling the LDIR into 8 LDIs in the obvious way would not work, because 767 is not divisible by 8. Now, there are ways that you could still unroll it if you wanted to, e.g.

Code:
   ld b,96
   jr loopstart
loop:
   ldi
loopstart:
   ldi \ ldi \ ldi \ ldi \ ldi \ ldi \ ldi
   djnz loop

But that is still not as efficient, in either speed or code size, as using PUSHes.

In any case I think this is a rather silly thing to be arguing about. For most purposes, LDIR is quite fast enough to clear the screen. If you really need the extra speed, use the PUSH loop or the funky copy-and-clear routine Galandros mentioned.
Back to top
Display posts from previous:   
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
    » Goto page 1, 2  Next
» View previous topic :: View next topic  
Page 1 of 2 » All times are UTC - 5 Hours

 

Advertisement