Subject: Re: Hires calculations Path: lobby!newstf02.news.aol.com!portc01.blue.aol.com!news-peer.gip.net!news.gsl.net!gip.net!newsfeed.berkeley.edu!cyclone.swbell.net!typhoon01.swbell.net.POSTED!not-for-mail Message-ID: <372E9E17.5D557EEF@swbell.net> From: Rubywand Reply-To: rubywand@swbell.net X-Mailer: Mozilla 4.51 [en] (Win95; U) X-Accept-Language: en MIME-Version: 1.0 Newsgroups: comp.sys.apple2 References: <7gigif$gtu$1@nnrp1.dejanews.com> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Lines: 162 Date: Tue, 04 May 1999 02:13:27 -0500 NNTP-Posting-Host: 207.193.8.190 X-Complaints-To: abuse@swbell.net X-Trace: typhoon01.swbell.net 925801560 207.193.8.190 (Tue, 04 May 1999 00:06:00 PDT) NNTP-Posting-Date: Tue, 04 May 1999 00:06:00 PDT Organization: SBC Internet Services bobryan9@my-dejanews.com writes ... > > How do I calculate the MEMORY LOCATION of a byte on the LEFT SIDE of the > Hires screen, given the Y location? > > I would like something like: > > MEMLOC=Y (insert math here) .... As has been noted, doing math calculations is a fairly slow method of translating hires coordinates to an address in memory. Hires addresses are mapped using outputs from the video countdown chain (originally, to save on adding IC's to early Apple II designs). The natural way to obtain an address given screen coordinates is a 'decoder' table. Exactly how you get from coordinates to an address depends upon the particular application. For example, suppose you have a set of hires characters or figures used for creating an Ultima-style map display. If each figure is 1 byte wide x 8 bytes high, you can have 24 'lines' of 40 figures. In this case, the coordinates are for a 40 x 24 grid of figures. All you need from your Get Address routine is the address of the first (top) byte for each group of 8 bytes in a figure. (Your character drawing routine will take care of the rest.) The code for the Get Address (or "XLATE") could be something like this ... You have a table-- this one starts at address $1F00. It is for using Hires 'Page' 2 ($4000-5FFF) for the display. 1F00: 00 80 00 80 00 80 00 80 LO BYTE DATA IF08: 28 A8 28 A8 28 A8 28 A8 1F10: 50 D0 50 D0 50 D0 50 D0 1F18: 40 40 41 41 42 42 43 43 HI BYTE DATA IF20: 40 40 41 41 42 42 43 43 1F28: 40 40 41 41 42 42 43 43 And, you have a routine which uses the table to convert coords to an address-- this routine starts at address $1F39. When this routine is called-- e.g. 20 39 1F (JSR $1F39) ... XREG, register X, has the y-coord (for some 'line' in the range 0-23 decimal) Address $0009 has the x-coord (i.e. a 'column' loc in the range 0-39 decimal) Upon exiting (via the RTS at $1F46), the address of the top byte in screen memory for the figure you want to draw at x,y will be at $0006 (lo byte) and $0007 (hi byte). 1F39: 18 CLC (CLEAR CARRY) 1F3A: BD 00 1F LOAD LO-BYTE (XREG IS INDEX INTO LO BYTE TABLE) 1F3D: 65 09 ADD COLUMN POSITION 1F3F: 85 06 SAVE LO BYTE OF ADDRESS AT $0006 1F41: BD 18 1F LOAD HI BYTE (XREG IS INDEX INTO HI BYTE TABLE) 1F44: 85 07 SAVE HI BYTE OF ADDRESS AT $0007 1F46: 60 RTS (RETURN FROM SUBROUTINE) Once you have the top byte address, the character drawing routine just needs to add $04 to the hi byte (at $0007) to get the address for each successive screen line in the 8-line character. Example: Your game map has coordinates spanning the range 0,0 through 39,23 (decimal). The decimal coordinates for the figure you want to place are x,y: 2,5. The x coord would be maintained at $0009. The y coord ($05) gives this result from the table: $4280 (address of top byte for left-most character on char line 5). Adding $02 for the x-coord results in ... $4282 (address of top byte for a figure in column 2 on char line 5). The addresses the character drawing routine would be writing to are ... $4282 top byte (address for the figure's top hires line of dots) $4682 $4A82 $4E82 $5282 $5682 $5A82 $5E82 bottom byte By the way, the character drawing routine here does not "draw" as in drawing a shape using a shape table. It just moves 8 bytes from a table of pre-made (1-byte x 8 line) mini-pics into screen memory so that you see the desired figure at the specified map location. The above goes a bit beyond your question in one respect since it includes an adjustment (at $1F3D) to obtain the address for any figure position (x-coord) on a line. If you really just care about the left-most byte address, the addition at $1F3D and the CLC are not needed. The reason for placing the address at $0006 and $0007 (or some other pair of Zero Page locations) is that it is easy to use the address via the $B1 (load A), $91 (store A), and $D1 (compare A) 6502 indirect addressing operations. And, $0006 and $0007 are usually open for use by the programmer. Ultima, Questron, and many other 'map adventures' actually use 2-byte x 16 line map characters. This gives much better detail and looks nicer. A full screen hires display can have 12 'lines' of 20 such figures; so, handling the display requires an even smaller address translation table! (You can scrap every other byte.) However, there is a small extra burden on the character drawing routine. Besides adding $04 to the hi byte for each successive line in an 8-line group, it has to add $01 to the lo byte of the address when it 'draws' the right half of the figure and $80 to the lo byte of the address when it starts 'drawing' the lower group of 8 lines. If you want to obtain the address of the left-most byte on a hires scanline given the line number (in the range 0-191 decimal), you can use the 48-byte table shown earlier. Working in hexadecimal, the basic approach is reduce the task to finding the address of some line in one of 24 groups of 8 lines. So, you save the lower three bits of the line number and divide the line number by 8 (e.g. do three right-shifts). Example: Line 41 ---> $29 in hex and 0010 1001 in binary. 1. You do an AND with the value $07 (0000 0111) and save the resulting lower three bits (001) as $01, say at address $0008. 2. Do three right shifts on $29 (divide by 8) which gives 0000 0101 or $05. 3. Using an XLATE routine like the one given above (but without the column offset addition) and entering the table with $05 (in the X register) gives $4280-- the address of the top byte in the group of 8 lines which includes line $29. 4. To get the address for the left-most byte on line $29 you just add the contents of $0008 x4 to the hi byte of the address: $01 x 4 = $04. $42 + $04 = $46. So, as expected, the address for the left-most byte on hires line $29 (41 decimal) is $4680. The above is easier if, in step 1, you also do two left shifts to multiply by 4 before storing to $0008. (That is, after isolating the lower three bits, you take care of the x4 multiplication here instead of later.) So; you would store the value $04 at address $0008. In Step 4 you just need to add the contents of $0008 to the hi byte of the address to end up with $4680. Again, the above examples are for working with Hires 'Page' 2. To work with Hires 'Page' 1 ($2000-$3FFF), you replace the 4's in the hi byte table with 2's: 1F18: 20 20 21 21 22 22 23 23 HI BYTE DATA IF20: 20 20 21 21 22 22 23 23 1F28: 20 20 21 21 22 22 23 23 Rubywand