matthew180 Posted May 19, 2011 Share Posted May 19, 2011 So I'm thinking on how to enhance spectra2 while keeping code size as small as possible. Features I'm gonna include: * Viewport handling You may want to check out the map scroller I worked on for Owen. I spent a few days writing and rewriting the code, trying different methods of virtual window scrolling, and what I ended up with was the most efficient I could come up with at the time. The main theories I tested were focused on handling the "edge cases": 1. Keep the player in the middle of the window and having buffer data in the map. A lot of modern games (Diablo2 is an example I'm very familiar with... ) use this method, but they also don't have to worry about memory or speed so much. 2. Like #1, keep the player in the middle of the window, but instead of having a half-window worth of extra data around the map, there is just a default character that is used to draw any characters that are in the window but not part of the map. 3. Keep the player in the middle of the window until an edge is encountered, then the player moves from the middle up to the edges. This keeps the map data inside the window at all times. 4. The player moves freely in the map and scrolling happens when the player bumps in to a virtual edge, usually a character or two from the edge of the window. Like #3, the map data is inside the window at all times. What I found was that the logic to handle edges (#1 and #2) was prohibitive and added a lot of extra code and time to process the window. The theory is easy, the implementation gets tricky to keep things simple and efficient. I went with #3 because for a game like Owen's, you want to be able to see what is coming, and if you have to be right up against the edge to get the map to scroll (option #4), then it is easy to be surprised by a monster or something on the map popping up within 1 character of your current location. With option #3, you have half a window worth of map to see what is coming. Anyway, the code is heavily commented and you may want to look at it. * I'm gonna need to bug-fix my sound player to make it fully compatible with the sound player inside the console ISR. I currently don't support branches in my player. Only learned that just today. Again, thanks to working on something for Owen, you may want to look in to the sound player I wrote for his games. If I remember correctly, I made it compatible with the system ISR player, as well as adding additional features like looping within a sound (to save data in songs that have repeating parts), and some other things (I can't remember the details now.) One sound can stop another, but I didn't do any kind of "merging" of sounds. Another idea is to provide the user an single voice for each sound, or let them choose how many to use for a given sound, then you can more easily merge and play sounds simultaneously that are using separate voices. Also, you could do something like two voices for continuous game music, and one voice plus the noise voice for short sound effects. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted May 19, 2011 Share Posted May 19, 2011 Et voila. This approach avoids the requirement of having to duplicate routines at identical memory addresses in both banks. You can treat the bank0/bank1 as though it's one big 16K address space. It's handled by the little helper routines. Works for me Mark Something you have to keep in mind though, when making a program that runs from a cartridge, is that the logic to select a bank does not have a known state at power-on, so you don't know which bank will be initially selected. Typically all banks have a "banking" instruction at the start-up address (i.e. part of the cartridge header) that forces selection of the proper start-up bank. The 64K multi-cart boards, and any bank-switching I have seen to date, use a TTL logic chips to manage the bank selection, and the flip-flops inside those ICs do not have resets and there is no facility within the chip to "initialize" it at power on. The selected bank at power on is not guaranteed. Quote Link to comment Share on other sites More sharing options...
Willsy Posted May 19, 2011 Share Posted May 19, 2011 Something you have to keep in mind though, when making a program that runs from a cartridge, is that the logic to select a bank does not have a known state at power-on, so you don't know which bank will be initially selected. Typically all banks have a "banking" instruction at the start-up address (i.e. part of the cartridge header) that forces selection of the proper start-up bank. The 64K multi-cart boards, and any bank-switching I have seen to date, use a TTL logic chips to manage the bank selection, and the flip-flops inside those ICs do not have resets and there is no facility within the chip to "initialize" it at power on. The selected bank at power on is not guaranteed. Hi Matthew Indeed. TF has code in bank 1 to force it to jump to bank 0 to do its initialisation. Basically, I have duplicated the cart header exactly in both banks. Thus: If the cart wakes up in bank 0: Selecting TF from the TI menu will cause it to run its normal init code If the cart wakes up in bank 1: Selecting TF from the TI menu will cause it to run some code in bank 1 which does a bank switch to bank 0 and jumps to the normal init code. Works a treat Mark Quote Link to comment Share on other sites More sharing options...
Willsy Posted May 19, 2011 Share Posted May 19, 2011 Again, thanks to working on something for Owen, you may want to look in to the sound player I wrote for his games. If I remember correctly, I made it compatible with the system ISR player, as well as adding additional features like looping within a sound (to save data in songs that have repeating parts), and some other things (I can't remember the details now.) One sound can stop another, but I didn't do any kind of "merging" of sounds. Another idea is to provide the user an single voice for each sound, or let them choose how many to use for a given sound, then you can more easily merge and play sounds simultaneously that are using separate voices. Also, you could do something like two voices for continuous game music, and one voice plus the noise voice for short sound effects. Matthew, any chance I can see your code? I need something similar for TurboForth. It doesn't have to be compatible with the built in TI ISR player though (and it doesn't have to run from VDP). Maybe I can steal, er, get some ideas from your code? Mark Quote Link to comment Share on other sites More sharing options...
matthew180 Posted May 19, 2011 Share Posted May 19, 2011 (edited) All the code is here in the forum. I'll see if I can find the thread. Here you go: http://www.atariage.com/forums/topic/158605-assembly-sound-player-for-xb/ Edited May 19, 2011 by matthew180 Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted June 2, 2011 Author Share Posted June 2, 2011 Small update: Today I got the "viewport" functionality in place. I wasn't able to do much assembly programming in the last few weeks, due to various real-life issues. Anyway, this week I started doing some preparations and today I coded the viewport routine in one go. It only took me 2 assembly cycles to get the thing working. I was happy about that Ofcourse there is still a lot of testing to do For those who don't know what the viewport is for: It is used to display part of a virtual screen on the physical screen. You pretty much define a game map in a virtual screen (up to 255 columns and 255 rows) and you then use the viewport for displaying part of it on the physical screen. You can easily build a "scroller" around this functionality. I won't include such high-level scroller as part of spectra2 though. Remember spectra2 is only a basic functionality library. Perhaps I'll make an example on how to do that. Actually Matthew made a great scroller for Owen. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted June 3, 2011 Share Posted June 3, 2011 Cool. So what method of mapping the data to the viewport did you go with? Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted July 6, 2011 Author Share Posted July 6, 2011 (edited) While working on the Tutankham title screen I needed some more subroutines. I added the RLE2V subroutine (Decompress run-length encoded data to VRAM). I use this subroutine to decompress an RLE encoded bit-map screen. It's compatible with the binary files generated by Tursi's convert9918 utility. An excellent tool by the way. If you didn't have a chance yet check it out Here the code * RLE2V (DATA P0,P1,P2) ..: *************************************************************** * RLE2V - RLE decompress to VRAM memory *************************************************************** * BL @RLE2V * DATA P0,P1,P2 *-------------------------------------------------------------- * P0 = ROM/RAM source address * P1 = VDP target address * P2 = Length of RLE encoded data *-------------------------------------------------------------- * BL @RLE2VX * * TMP0 = VDP target address * TMP2 (!) = ROM/RAM source address * TMP3 (!) = Length of RLE encoded data *-------------------------------------------------------------- * Detail on RLE compression format: * - If high bit is set, remaining 7 bits indicate to copy * the next byte that many times. * - If high bit is clear, remaining 7 bits indicate how many * data bytes (non-repeated) follow. ********@*****@*********************@************************** RLE2V MOV *R11+,TMP2 ; ROM/RAM source address MOV *R11+,TMP0 ; VDP target address MOV *R11+,TMP3 ; Length of RLE encoded data RLE2VX MOV R11,@WAUX1 ; Save return address BL @VDWA ; Setup VDP address from TMP0 MOV TMP2,TMP0 ; We can safely reuse TMP0 now RLE2V0 MOVB *TMP0+,TMP2 ; Get control byte into TMP2 DEC TMP3 ; Update length SLA TMP2,1 ; Check bit 0 of control byte JOC RLE2V2 ; Yes, next byte is compressed *-------------------------------------------------------------- * Dump uncompressed bytes *-------------------------------------------------------------- RLE2V1 MOV @RLEDAT,@MCLOOP ; Setup machine code (MOVB *TMP0+,*R15) SRL TMP2,9 ; Use control byte as counter S TMP2,TMP3 ; Update length BL @MCLOOP ; Write data to VDP JMP RLE2V3 *-------------------------------------------------------------- * Dump compressed bytes *-------------------------------------------------------------- RLE2V2 MOV @FILZZ,@MCLOOP ; Setup machine code(MOVB TMP1,*R15) SRL TMP2,9 ; Use control byte as counter DEC TMP3 ; Update length MOVB *TMP0+,TMP1 ; Byte to fill BL @MCLOOP ; Write data to VDP *-------------------------------------------------------------- * Check if more data to decompress *-------------------------------------------------------------- RLE2V3 MOV TMP3,TMP3 ; Length counter = 0 ? JNE RLE2V0 ; Not yet, process data *-------------------------------------------------------------- * Exit *-------------------------------------------------------------- RLE2VZ MOV @WAUX1,R11 B *R11 ; Return RLEDAT DATA >D7F4 ; MOVB *TMP0+,*R15 * :.. I use this little perl program, for generating the byte statements I can then include in my source code ########################################### # bin2byte - Binary file dumper # (c)2011 retroclouds ########################################### # 03.07.2011 - Initial version # 06.07.2011 - Fixed bug in file counter ########################################### if (@ARGV == 0) { print "\n"; print "bin2byte v1.1 - Dump binary file as TMS9900 byte statemens\n"; print "Usage: bin2byte file1 file2 file3 ...\n\n"; exit; } my $filecnt=0; while (@ARGV > 0) { $filecnt++; my $label = ' BYTE '; my $bfile = shift; my $data = ''; my $cnt = 0; open (FH,"<",$bfile) || die("Couldn't open file \"$bfile\"\n"); binmode(FH) || die("Couldn't set binary mode on file \"$bfile\"\n"); while (read(FH,$buf,2)) { if ($cnt % 8 == 0) { $data .= "\n$label"; } else { $data .= ","; } my $val = sprintf("%04X", unpack("n",$buf)); $data .= ">" . substr($val,0,2) . ","; $data .= ">" . substr($val,2,2); # printf ("%X",unpack("n",$buf)); $cnt+=2; }; close(FH) || die("Couldn't close file \"$bfile\"\n"); substr($data,0,6) = 'DUMP' . $filecnt; print "* ", '#' x 74, "\n"; print "* # Dump of binary file \"$bfile\"\n"; print "* ", '#' x 74, "\n"; print "LEN" . $filecnt . " EQU ", $cnt, "\n"; print "$data\n"; print " EVEN\n" if ($cnt % 2 == 1); } EDIT: I'm heading for a spectra2 v1.1 release. Probably to be released in the next two weeks. Just still have to update my documentation. Edited July 6, 2011 by retroclouds 2 Quote Link to comment Share on other sites More sharing options...
+retroclouds Posted October 9, 2011 Author Share Posted October 9, 2011 (edited) Time flies like an arrow; fruit flies like a banana Those 2 weeks are more than 2 months ago and still haven't released, Sorry guys, too much stuff on my plate right now. No more target dates, I'll release when it's done. Edited October 9, 2011 by retroclouds 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.