sometimes99er Posted December 5, 2010 Share Posted December 5, 2010 Here's one Marc wrote: LI R0,>9F00 MOVB R0,@>8400 That part is dealing with the sound-chip, so it's not relevant to VMBW. Obviously Matthew's is dependant on other VDP routines he wrote, but I have them all in the Beryl scroller that he sent me. It's really interesting to read through that source... just so neat and clean. =) Yes, often you'll discover, that you will help yourself to better and more quickly reread/understand and debug your own code, if you have a lot of comments like that. I'm studying "ORI" right now.... Looks like it compares two words and sets the bits to the new word if either of the bits are set in either of the compared words. Yes, a bit set in either will set a bit in the "output". The comment "Set read/write bits 14 and 15 to write (01)" might be slightly off (no big deal). The assembler instruction is "just" setting bit 14 and not carrying about the state of bit 15. We must assume bit 15 to be 0 to get to 01. I don't know if 11 will work. The three possible commands should be, write to register (10), set address for write (01), and set address for read (00). Quote Link to comment Share on other sites More sharing options...
matthew180 Posted December 5, 2010 Share Posted December 5, 2010 (edited) Obviously Matthew's is dependant on other VDP routines he wrote, but I have them all in the Beryl scroller that he sent me. It's really interesting to read through that source... just so neat and clean. =) Actually, each of my VDP routines is stand alone. If you set the equates in your code, you can use only the ones you need. If you don't want to set the equates, then just change the routine and hard code the VDP addresses. I'm studying "ORI" right now.... Looks like it compares two words and sets the bits to the new word if either of the bits are set in either of the compared words. Therefore: 0101100110011001 and 0011101111000100 becomes 0111101111011101 I guess I'm just trying to figure out why this is so crucial in a VDP write routine.... The ORI itself is not crucial to the VDP in any direct way. It is just convenient for what we have to do to communicate with the VDP. I think I covered some of this in the assembly thread, but I'll do it here to make sure. The VDP has a few things the programmer needs to be aware of: 1. An internal "auto incrementing" address register. This register is FOURTEEN bits, so 2^14 = 16,384 (16K) which is the maximum RAM the 9918A can address. 2. Seven internal WRITE ONLY registers that control the VDP's video mode, location of various "tables" used to define patterns, sprites, etc. 3. An 8-bit data bus to communicate with the host computer. 4. A specific protocol for communicating. There are four things we can do with the VDP: 1. Read the status register. 2. Write one of the seven registers. 3. Write a byte to a VRAM location. 4. Read a byte from a VRAM location. So let's just focus on writing a byte to the VDP right now, since that's what you are trying to do. The VDP's protocol for writing a byte is this: 1. Set up the VDP's internal 14-bit address register to the location in VRAM where you want to write the byte. 2. Write the byte. In the 9918A datasheet are the details of the protocols we have to follow, in case you want a detailed reference. NOTE: The VDP only reads and writes to VRAM at the memory address pointed to by its internal address register. That's why we have to set this register, otherwise we have no idea where the byte will be written. You can not read the current address of the VDP's internal address register, it is write only. Now, when setting the VDP's internal address register, we have to tell the VDP if we intend to read or write after setting the address. Because the VDP's address register is 14-bits, and we transfer data to / from the VDP 8-bits (1 byte) at a time, we have to make two 1-byte write operations to set the VDP's internal address. Now, since the VDP's address register will only use 14 of the 16 bits we are sending, the two MOST SIGNIFICANT bits are used by the VDP to know if we intend to read or write after setting the internal address. There is also a MODE pin on the VDP that indicates if a register is being written to (the address register, or one of the other internal registers), or if a byte of VRAM is being read or written. This mode pin is controlled by logic on the motherboard that is controlled by the CPU address we indicate. Basically that's why we have to use different address for the VDP, that and because the 9900 does a read-before-write. You don't have to worry about the details of this mode pin, you just have to make sure you use the proper HARD WIRED addresses to communicate with the VDP. In code it is easier to use EQUates, but you can use the addresses directly in your code if you want, they will NEVER change (but it is considered bad practice to use hard coded values in code, so use EQUates.) VDP Hard Wired Addresses: >8800 Used to read data from the VDP >8802 Used to read the VDP status register >8C00 Used to write data to the VDP >8C02 Used to set the VDP's internal address register So, logic chips in the console will set the MODE pin correctly when we are writing to address >8C02, and that is how the VDP can tell the difference between when we are trying to set up its internal address or when we are just writing data bytes. After all, bytes of an address look just like bytes of data, so this is how the VDP knows the difference. Now, the VDP uses those two MSb (most significant bits) of the 16-bit address to know if we intend to read or write data after setting the address register. Technically there is really no difference, however internally the VDP will to a pre-fetch of the data byte if we indicate we intend to read vs. write a byte. Also, if you tell the VDP you are setting up a read address, but then do a write operation, your byte will not go to the address you set up. But don't worry about that right now, just follow the rules and things will work. Leave the rule breaking to Marc. To set the address we have to make two writes, since we can only send a byte at a time. The VDP expects the LSB first, then the MSB of the address. So we usually put the VRAM address we want to write to into a CPU register, then pass the bytes: LWPI >8300 . . . LI R0,some_vram_address MOVB @8301,@>8C02 We generally *ASSUME* that R0 will never have an address greater than 16,385 since that's the largest VRAM address the VDP can accept. That means that we *ASSUME* the top two bits of the CPU register we are using will always be ZERO when we start this code. Because we have to send the LSB first, the MOVB uses the byte address of R0. Remember that the 9900 will always send the MBS of a register when using byte instructions. You will also see a lot of people do this: SWPB R0 MOVB R0,>8C02 SWPB R0 MOVB R0,>8C02 That puts the LSB into the MSB, then sends the MSB (LSB of the address) to the VDP. I don't like to do this personally because I'm a freak about speed and memory use, and you then have to do another SWPB to get the original MSB back into the MSB of the register. To me, it makes more sense to exploit the fact that our VDP keeps its registers in RAM, and we know where those registers are, so just reference the LBS of R0 directly. That's where you see in my code where I set up R0LB, R1LB, etc. So my initial code above is usually written: LI R0,some_vram_address MOVB R0LB,@>8C02 Next we send the MSB of the address to the VDP. At this point we need to make sure the top two bits are set accordingly: MSB of setup byte, ie. second byte set to address >8C02 -------- 00xxxxxx - Read from VRAM 01xxxxxx - Write to VRAM 10xxxxxx - Write to VDP Register 11xxxxxx - Illegal (undefined) The xxxxxx is the top part of the 14-bit address we are sending. The low 8 bits were sent first. So, if we are setting up the address and intend to do a read operation, we don't have to do anything but send the MSB of R0 now (ASSUMING we don't have a address greater than 16,385 in R0!!!) To indicate we are setting up an address and intend to WRITE, we need to set the two top bits of R0 to 01. This is where we use ORI instruction. The logical OR operation will let us set zero bits to one bits without affecting the other bits in the register, which is exactly what we need. Also note that the 9900 only has an OR-immediate, ie. can only OR with an immediate value. The OR value is called a "MASK" and is a common term when using OR, AND, and XOR to do "bit twiddling". ORI R0,>4000 MOVB R0,>8C02 If you convert >40 to bits, it looks like this: 01000000. So, ORing that with R0 will leave all the other bits as they are, but will ensure that the second top bit is set to 1. Now, we again ASSUME that R0 did not have a value over 16,385, so the top MSb would already have been zero. So we end up with the proper "01" in the top two bits of the second byte to let the VDP know we are going to write after setting up this address. If we were reading, we do not have to do the ORI since we assume the top two bits are already "00", and "00" tells the VDP we intend to read. Now that the address is set, the VDP is expecting bytes to read or write. So, for VSBW we just write the byte: VSBW 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 MOVB R1,@VDPWD Write byte to VDP RAM B *R11 Return This code assumes the normal setup of the address in R0, and the byte to write in the MSB of R1, and called with BL @VSBW. The last thing you need to understand is the "auto increment" feature of the VDP. After *any* byte read or write operation, the VDP auto increments the internal address register. Thus if you were doing a bulk read or write of data, you only have to set the start address of the block, then read or write the data over and over without having to mess with the address again. That's what VMBW does. This is also why using VSBW in a loop is SLOW! VSBW sets the VDP address every time you call it, since it assumes you are writing a single byte, then changing the address to somewhere else totally different. When you need to write the same byte to multiple VRAM locations (like clearing the screen) it is better to use a new VDP function with did not exist in the one's TI came up with: VSMW. I came up with this as a natural conclusion, as did many other people independently. It just makes sense. Hopefully this makes more sense to you now. It is not really that mysterious, you just have a learn a little more about the 99/4A and how the VDP is wired into it. Since setting up the address all the time is a pain and repetitive, we write up routines like we have. The console routines ultimately do the same thing, however they use the slow BLWP, an 8-bit workspace, and internally branch again. Last note: speed. Many people used the SWPB instruction between writes to the VDP because of the problem of overwriting the VDP. This extra instruction between writes to the VDP (when setting up the address) was to give the VDP the time it needed to function. However, we have proved that on the 99/4A that you cannot over run the VDP unless you specifically run from the scratch pad RAM to get the most speed you can. Or if you have 32K in the console on the 16-bit bus. Matthew Edited December 5, 2010 by matthew180 Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 6, 2010 Author Share Posted December 6, 2010 Thank you Matthew. That is a very nice explanation. =) I should have some stuff to show on this process very soon... just spent two days rebuilding my computer after a big crash. NOT fun. Does this sound familiar to any of you? -Run virus scan -Defrag -Memory scan -Disk Scan -GOTO Run virus scan. Dude.... I'm so thankful it's over.... Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 6, 2010 Share Posted December 6, 2010 If you wanna see some pictures and listen to a couple songs we've been working on in the studio, check out Listened to the live myspace stuff too. I like it. Cool. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 6, 2010 Author Share Posted December 6, 2010 That's a pretty wild graphic there, sometimes. =) Thanks for that. Also glad you like the myspace site. =) Right now I'm getting the XB motion routines together for the player character. I'm currently using strings to display the viewport in XB while I work on the VMBW routine. When I have something to show, I'll post it. For the here and now, I'm slogging through this crap and trying to figure out "why". =) Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 6, 2010 Share Posted December 6, 2010 Try and extract and "run" the files. Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 6, 2010 Share Posted December 6, 2010 That's a pretty wild graphic there, sometimes. =) Thanks for that. It is of course turning into 256x192 bitmap compliant graphics. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 6, 2010 Author Share Posted December 6, 2010 Okay... it ran and put the bytes on the screen... just the first line. Looks to work quite nicely. I imagine that long pause before it actually draws is just XB creating the INIT space for the assembly routines.... Thanks, sometimes. Looking good. =) Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 6, 2010 Share Posted December 6, 2010 Okay... it ran and put the bytes on the screen... just the first line. Looks to work quite nicely. I imagine that long pause before it actually draws is just XB creating the INIT space for the assembly routines.... Thanks, sometimes. Looking good. =) Oh, that was quick. That's good. You know how to do that. Excellent. Now try and understand the assembler code and add comments (to the code). The source only has the first 3 rows from the big map. If I have all 72 rows in the source, the CALL LOAD takes like forever. Have you ever tried the Debugger of Classic99 ? Finally, try and display 3 rows instead of just 1. Careful now. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 6, 2010 Author Share Posted December 6, 2010 You got it... I'll have it knocked out here pretty quick. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 6, 2010 Author Share Posted December 6, 2010 Well, I failed with some very pretty colors. =) DRAW MOV R11,R10 SAVE XB RETURN ADDRESS LI R0,>0 LI R1,MAPDAT LI R2,>1C LI R3,3 DRW BL @VMBW AI R0,32 AI R1,28 DEC R3 JNE DRW I need to read up on what auto increments and what doesn't. I also noticed that the VMBW uses R0 and R2, so whatever WAS there in the DRAW routine is no longer there... I was planning to add a new label and instead of using RT at the end of the VMBW routine, have it JMP to that label (which will reload all the registers after incrementing R0 by 32) but it failed as well.... I'll need to experiment more... using VSBW is ALOT easier for me... just because I understand it. Quote Link to comment Share on other sites More sharing options...
matthew180 Posted December 6, 2010 Share Posted December 6, 2010 The main difference between using the VDP routines in the console vs. the ones I wrote is R0, R1, and R2 are usually destroyed. The workspace used by the routines is the same one you are using. What is it about VMBW that you don't understand? The only thing that auto-increments are instructions with + signs in them, like: MOVB *R1+,@>8C00 That would move the MSB of R0 to the address >8C00, then increment the *value* in R1 by 1. VMBW uses an instruction like that to move data from a location in CPU RAM to VRAM. >8C00 is the hard wired address you use to write *data* to the VDP. Remember, the VDP will auto-increment its internal address after each write. So, R1 starts out pointing at the beginning of your data and is auto-incremented by the MOVB instruction after each byte written. The VDP is also auto-incrementing its internal address, so you end up writing a block or bytes from CPU RAM to VRAM. R2 is used as a counter. So, R0 holds the start address in VRAM, R1 holds the start address in CPU RAM, and R2 is the number of bytes to write. After VMBW, R0 will be the same, R1 will have been incremented by the count that was in R2. R2 will be zero. The VDP's internal address will also be incremented by the count that was in R2. Use VSBW when you need to write a single byte to some VRAM location, and the next data you write needs to go to some totally different address. Use VMBW when you have a block of data in CPU RAM that you need to write to VRAM, like character patterns, a whole screen of data, etc. The reason you might be getting confused in this case is because you are used to your workspace not being overwritten when you called BLWP @VMBW vs. BL @VMBW. Remember, BLWP stands for Branch and Load Workspace Pointer. Which means the called routine will use a different workspace than the calling workspace. Your code looks like you need to write 28 bytes to the screen, which means you are 4 short of a full line. You might want to consider adding those 4 bytes as padding, which would make your routine a *lot* easier. Short of that, to do what you are needing to do, you just need to set up some temporary registers since VMBW will modify R1 and R2. Something like this: LI R0,>0000 Start of VRAM screen name table (top left corner) LI R1,MAPDAT CPU Map Data, 28 bytes per line LI R3,3 Write 3 lines until Owen sees what is going on * Set up the R2 counter each time a line is written. DRW LI R2,28 Write 28 bytes at a time (don't use hex if you don't have to) BL @VMBW Write the line AI R0,32 R0 was not affected, so bump down 1 line in VRAM DEC R3 Count the line JNE DRW Loop if not done Note that I'm not doing anything with R1. You started R1 pointing to the MAPDAT, and I assume the data is 28 bytes per line. So after the VMBW call, R1 will already be pointing to the start of the next line of map data. All you have to do is adjust the screen address to start writing to, which is in R0 and is not modified by VMBW (well, it is restored anyway.) Ask specific questions if you don't understand something. Matthew Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) BL vs. BLWP..... That is the issue primarily. So, after a block of data is written using VMBW, the Byte at the next address will be written by the following VMBW.... Therefore it is unnecessary to attempt to increment R1, as it is already done..... Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) I just sat here debugging for the last 15 minutes... I realized that removed RT from the VMBW routine and forgot to put it back in... stupid. Got it now... I wasn't TOO far away, just needed a bit of direction. =) Thank you Matthew and sometimes. =) Now I will attempt to draw the entire viewport in the proper location. I will leave the border out for now... That's why I can't really pad the write data, because on the left and right of the viewport there will be a permanent border. Blasting 2 ">20's" on each side of the map data would blow out my border. This is one reason I had thought about doing individual maps as opposed to one BIG map and doing math to display the proper section... CALL LINK (MAP2) could have the entire border in the map data... that adds 160 or so extra bytes to each map though... ***edit*** Then again, it would be easy to draw the border AFTER the viewport each time. This would allow me to pad the map as you suggest, Matthew.... That way, only 92 bytes need be in memory for the viewport TOTAL. Just redraw it each time Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) Okay, I'm going to try loading the entire map into memory and draw from that. I will need to skip 28 bytes for each line. here's how it looks in ASCII form: *--------*--------* * * * * 1 * 2 * *--------*--------* * * * * 3 * 4 * *--------*--------* * * * * 5 * 6 * *--------*--------* I want to draw section 1. So I will need to write 28 bytes, skip 28 bytes, carriage return, write 28 bytes, skip 28 bytes, carriage return, continue...... Can I use an AI R1,28? Will that work? ***God, that ASCII art really sucks... even using Notepad++ and code tags. eek Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) Yeeeeee haw!!!! DEF DRAW VDPWD EQU >8C00 VDP RAM WRITE DATA VDPWA EQU >8C02 VDP RAM READ/WRITE ADDRESS DRAW MOV R11,R10 SAVE XB RETURN ADDRESS *Draw border (inefficient, but by golly it works) LI R0,256 starting location in VRAM LI R1,BORDER CPU data LI R2,512 number of bytes to write BL @VMBW write it LI R0,322 Start of VRAM screen name table (top left corner) LI R1,MAPDAT CPU Map Data, 28 bytes per line LI R3,12 12 rows of map data for viewport * Set up the R2 counter each time a line is written. DRW LI R2,28 Write 28 bytes at a time (don't use hex if you don't have to) BL @VMBW Write the line AI R0,32 R0 was not affected, so bump down 1 line in VRAM AI R1,28 Offset for next line of viewport DEC R3 Count the line JNE DRW Loop if not done B *R10 RETURN TO XB Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) Entire source below DEF DRAW VDPWD EQU >8C00 VDP RAM WRITE DATA VDPWA EQU >8C02 VDP RAM READ/WRITE ADDRESS DRAW MOV R11,R10 SAVE XB RETURN ADDRESS *Draw border (inefficient, but by golly it works) LI R0,256 starting location in VRAM LI R1,BORDER CPU data LI R2,512 number of bytes to write BL @VMBW write it LI R0,322 Start of VRAM screen name table (top left corner) LI R1,MAPDAT CPU Map Data, 28 bytes per line LI R3,12 12 rows of map data for viewport * Set up the R2 counter each time a line is written. DRW LI R2,28 Write 28 bytes at a time (don't use hex if you don't have to) BL @VMBW Write the line AI R0,32 R0 was not affected, so bump down 1 line in VRAM AI R1,28 Offset for next line of viewport DEC R3 Count the line JNE DRW Loop if not done B *R10 RETURN TO XB * VDP MULTIPLE BYTE WRITE VMBW ORI R0,>4000 SWPB R0 MOVB R0,@VDPWA SWPB R0 MOVB R0,@VDPWA VMBW1 MOVB *R1+,R12 AI R12,>6000 ADD OFFSET MOVB R12,@VDPWD DEC R2 JNE VMBW1 RT BORDER DATA >6265,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6564 ; * -- Map Row 9 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 10 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 11 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 12 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 13 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 14 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 15 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 16 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 17 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 18 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 19 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 20 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 21 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 22 -- DATA >6120,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2020 ; DATA >2020,>2020,>2020,>2061 ; * -- Map Row 23 -- DATA >6365,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6565 ; DATA >6565,>6565,>6565,>6560 ; MAPDAT MD10 DATA >8989,>8989,>8989,>8989 ; DATA >8989,>8989,>8989,>8989 ; DATA >8989,>8989,>8989,>7289 ; DATA >7272,>7089,>8989,>8989 ; DATA >8989,>8989,>8989,>8989 ; DATA >8989,>8989,>8989,>8989 ; DATA >8989,>8989,>7070,>7070 ; * -- Map Row 1 -- DATA >8989,>8989,>8989,>8966 ; DATA >6666,>6666,>6666,>6666 ; DATA >6666,>6689,>8989,>8989 ; DATA >8989,>7070,>8889,>8988 ; DATA >888C,>8D8F,>8889,>8988 ; DATA >8889,>8989,>8989,>8988 ; DATA >8888,>8989,>7070,>7270 ; * -- Map Row 2 -- DATA >8989,>8888,>8888,>8866 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>6689,>6666,>6666 ; DATA >6666,>7089,>8970,>8888 ; DATA >888B,>8A8E,>8866,>6666 ; DATA >6666,>6689,>8988,>8888 ; DATA >8888,>8989,>7070,>7070 ; * -- Map Row 3 -- DATA >8988,>8888,>8888,>8866 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>6689,>6688,>8989 ; DATA >8966,>7070,>7070,>7070 ; DATA >8884,>8283,>8866,>8888 ; DATA >8888,>6689,>8866,>6666 ; DATA >6666,>8889,>7270,>7070 ; * -- Map Row 4 -- DATA >8988,>8888,>8888,>8866 ; DATA >8888,>8888,>8888,>8888 ; DATA >8889,>6689,>6670,>7270 ; DATA >8966,>7270,>7072,>7072 ; DATA >8988,>8888,>8866,>8888 ; DATA >8888,>6688,>8866,>8888 ; DATA >8866,>8889,>7072,>7070 ; * -- Map Row 5 -- DATA >8989,>8988,>8888,>8866 ; DATA >6666,>6666,>6666,>6666 ; DATA >8888,>6666,>6689,>7072 ; DATA >7066,>7070,>7270,>8989 ; DATA >8989,>8888,>8866,>8888 ; DATA >8888,>6666,>6666,>8888 ; DATA >8866,>8989,>7070,>7070 ; * -- Map Row 6 -- DATA >8989,>8888,>8888,>6666 ; DATA >6666,>6666,>8888,>8866 ; DATA >8888,>8888,>8889,>8972 ; DATA >7266,>7270,>8989,>8989 ; DATA >8888,>8889,>8866,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8866,>8972,>7072,>7272 ; * -- Map Row 7 -- DATA >8988,>8866,>6666,>6666 ; DATA >6666,>6666,>8888,>8866 ; DATA >8888,>8888,>8888,>8889 ; DATA >7066,>7070,>8989,>8988 ; DATA >8888,>8888,>8866,>8888 ; DATA >8988,>8888,>8888,>8889 ; DATA >8866,>8970,>7070,>7270 ; * -- Map Row 8 -- DATA >8988,>8866,>8888,>6666 ; DATA >6666,>6666,>8888,>8866 ; DATA >6666,>6666,>6666,>6666 ; DATA >6666,>6666,>6666,>6666 ; DATA >6666,>6688,>8866,>8889 ; DATA >8888,>8888,>8988,>8888 ; DATA >8866,>8972,>7070,>7070 ; * -- Map Row 9 -- DATA >8988,>8866,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8989,>7089,>8988,>8888 ; DATA >8888,>6688,>8866,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8866,>7270,>7070,>7070 ; * -- Map Row 10 -- DATA >8989,>8866,>8888,>8888 ; DATA >8888,>8888,>888C,>8D8F ; DATA >8888,>8888,>8888,>8989 ; DATA >8972,>7070,>8989,>8888 ; DATA >8888,>6688,>8866,>8888 ; DATA >8889,>8989,>6666,>6666 ; DATA >6666,>7272,>7072,>7072 ; * -- Map Row 11 -- DATA >8989,>8866,>8888,>8888 ; DATA >8888,>8888,>888B,>8A8E ; DATA >8888,>8888,>8889,>8989 ; DATA >7070,>7272,>8989,>8988 ; DATA >8888,>6688,>8866,>8888 ; DATA >8870,>8989,>6666,>6666 ; DATA >6666,>7272,>7070,>7070 ; * -- Map Row 12 -- DATA >8988,>8866,>8888,>8888 ; DATA >8888,>8888,>8884,>8283 ; DATA >8888,>8888,>8889,>8970 ; DATA >7270,>7070,>7070,>8989 ; DATA >8888,>6666,>6666,>8889 ; DATA >7072,>7089,>6666,>6666 ; DATA >6666,>7072,>7066,>6666 ; * -- Map Row 13 -- DATA >8988,>8866,>6666,>6666 ; DATA >6666,>8888,>8888,>8888 ; DATA >8888,>8888,>8889,>7070 ; DATA >7070,>7270,>2070,>7089 ; DATA >8989,>8989,>8889,>8870 ; DATA >2072,>7089,>6666,>6666 ; DATA >6672,>7272,>7066,>7070 ; * -- Map Row 14 -- DATA >8989,>8988,>8888,>8888 ; DATA >8866,>6666,>6667,>6767 ; DATA >6767,>6767,>8989,>7020 ; DATA >7070,>7070,>7070,>7270 ; DATA >8989,>8989,>8989,>8988 ; DATA >7270,>7272,>6666,>6666 ; DATA >7072,>7270,>7066,>7070 ; * -- Map Row 15 -- DATA >8989,>8988,>8888,>8888 ; DATA >8888,>8888,>8867,>6767 ; DATA >6767,>6767,>7270,>7070 ; DATA >7072,>7270,>7070,>7270 ; DATA >7270,>7072,>7089,>8989 ; DATA >7070,>7270,>7289,>8972 ; DATA >7270,>7270,>6666,>6670 ; * -- Map Row 16 -- DATA >8C8D,>8F89,>8989,>8989 ; DATA >8989,>8988,>8867,>6667 ; DATA >6767,>6767,>7272,>7070 ; DATA >7270,>7070,>7270,>7072 ; DATA >7270,>7070,>7070,>7070 ; DATA >7070,>7272,>7272,>7070 ; DATA >7070,>7072,>6666,>6672 ; * -- Map Row 17 -- DATA >8B8A,>8E89,>8989,>8988 ; DATA >8888,>8888,>8866,>6767 ; DATA >7366,>6766,>8888,>7270 ; DATA >7072,>7270,>7072,>8989 ; DATA >7072,>7270,>7270,>7070 ; DATA >7072,>7270,>7089,>7272 ; DATA >7070,>7070,>6666,>6670 ; * -- Map Row 18 -- DATA >8482,>8389,>8988,>8888 ; DATA >8888,>8888,>8867,>6766 ; DATA >6767,>6767,>8888,>8970 ; DATA >7270,>7070,>7089,>8989 ; DATA >8888,>8888,>7072,>7088 ; DATA >8888,>8888,>8989,>8970 ; DATA >7070,>7270,>6666,>6670 ; * -- Map Row 19 -- DATA >6766,>6766,>6767,>8888 ; DATA >8888,>8888,>8867,>6767 ; DATA >6767,>6766,>8888,>8989 ; DATA >7072,>7272,>7089,>8988 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8989 ; DATA >7070,>7270,>7066,>7072 ; * -- Map Row 20 -- DATA >8989,>8988,>8866,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >6788,>8888,>8888,>8889 ; DATA >8972,>7072,>7289,>8988 ; DATA >8888,>6666,>6666,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8970,>7070,>7066,>7070 ; * -- Map Row 21 -- DATA >8989,>8988,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >6788,>8888,>8888,>8888 ; DATA >8972,>7072,>7089,>8988 ; DATA >8888,>6666,>7166,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8989,>7270,>7066,>7270 ; * -- Map Row 22 -- DATA >8989,>8888,>8867,>6766 ; DATA >6767,>6767,>8888,>8888 ; DATA >6688,>8888,>8888,>8888 ; DATA >8972,>7070,>8989,>8988 ; DATA >8888,>6666,>6666,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8989,>7270,>7066,>7070 ; * -- Map Row 23 -- DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8867,>6766,>6767 ; DATA >6788,>8888,>8888,>8888 ; DATA >8989,>7272,>8989,>8888 ; DATA >8888,>7166,>6666,>6666 ; DATA >6666,>8888,>8888,>8889 ; DATA >8972,>7270,>7066,>7070 ; * -- Map Row 24 -- DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >6788,>8888,>8888,>8888 ; DATA >8989,>7072,>8989,>8888 ; DATA >8888,>6666,>6666,>8888 ; DATA >8866,>8888,>8888,>8888 ; DATA >8989,>7070,>7066,>7272 ; * -- Map Row 25 -- DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >6788,>8888,>8888,>8888 ; DATA >8989,>7070,>8988,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8866,>8888,>8888,>8889 ; DATA >8972,>7070,>7066,>7070 ; * -- Map Row 26 -- DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8867,>8989,>8888 ; DATA >6767,>8888,>8888,>8888 ; DATA >8989,>7089,>8988,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8866,>8888,>8889,>8989 ; DATA >7270,>7067,>6767,>6770 ; * -- Map Row 27 -- DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8867,>8988,>8888 ; DATA >6767,>6767,>6788,>8888 ; DATA >8989,>8989,>898C,>8D8F ; DATA >8888,>8888,>6666,>6666 ; DATA >6666,>8888,>8989,>8972 ; DATA >7070,>7067,>6767,>6770 ; * -- Map Row 28 -- DATA >8988,>8888,>8888,>6666 ; DATA >6666,>6667,>8888,>8888 ; DATA >8888,>8888,>6788,>8888 ; DATA >8989,>8988,>888B,>8A8E ; DATA >8888,>8888,>6688,>8888 ; DATA >8888,>8888,>8989,>8989 ; DATA >7070,>7067,>6767,>6770 ; * -- Map Row 29 -- DATA >8989,>8888,>8888,>6688 ; DATA >8888,>8889,>8888,>8888 ; DATA >8888,>8888,>6788,>8888 ; DATA >8989,>8988,>8884,>8283 ; DATA >8888,>8888,>6688,>8888 ; DATA >8888,>8888,>8989,>8989 ; DATA >7270,>7070,>6767,>6772 ; * -- Map Row 30 -- DATA >8989,>8988,>8888,>6688 ; DATA >8889,>8989,>8888,>8888 ; DATA >8888,>8888,>6788,>8889 ; DATA >8989,>8888,>8888,>8888 ; DATA >8888,>8888,>6666,>6666 ; DATA >6666,>8889,>8989,>8970 ; DATA >7272,>7270,>6767,>6770 ; * -- Map Row 31 -- DATA >8989,>8989,>8988,>6688 ; DATA >8989,>8989,>8988,>8867 ; DATA >6767,>6767,>6788,>8889 ; DATA >8989,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8866,>8888,>8989,>7070 ; DATA >7070,>7070,>6770,>7072 ; * -- Map Row 32 -- DATA >8989,>8989,>8888,>6688 ; DATA >8989,>8989,>8988,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8866,>8888,>8870,>7070 ; DATA >7070,>7070,>6770,>7070 ; * -- Map Row 33 -- DATA >8989,>8988,>8888,>6688 ; DATA >8989,>8989,>8888,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8989,>8889,>8989 ; DATA >8866,>8888,>7070,>7070 ; DATA >7272,>7070,>6770,>7270 ; * -- Map Row 34 -- DATA >8988,>8867,>6767,>6688 ; DATA >8889,>8989,>8888,>8866 ; DATA >6666,>6666,>6688,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8989,>8989,>8989,>8988 ; DATA >8866,>8888,>7070,>7272 ; DATA >7272,>7270,>6770,>7070 ; * -- Map Row 35 -- DATA >8989,>8867,>6767,>6688 ; DATA >8888,>8889,>8989,>8888 ; DATA >8888,>8888,>6666,>6667 ; DATA >6767,>6666,>6666,>6666 ; DATA >6666,>6666,>6666,>6666 ; DATA >6666,>8872,>7272,>7070 ; DATA >7270,>7270,>6770,>7070 ; * -- Map Row 36 -- DATA >8988,>8867,>6767,>6788 ; DATA >8888,>8889,>8989,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8888,>8872,>7070,>7270 ; DATA >7072,>7270,>6770,>7020 ; * -- Map Row 37 -- DATA >7088,>8867,>6767,>6767 ; DATA >6767,>678C,>8D8F,>8988 ; DATA >8989,>8989,>8989,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8989,>8889,>8989 ; DATA >8888,>8888,>8888,>7072 ; DATA >7272,>7270,>6770,>7070 ; * -- Map Row 38 -- DATA >7088,>8867,>8888,>8888 ; DATA >8888,>678B,>8A8E,>8988 ; DATA >8989,>8888,>8888,>8889 ; DATA >8989,>8888,>8888,>8888 ; DATA >8989,>8989,>8989,>8988 ; DATA >8888,>8888,>8888,>8870 ; DATA >7072,>7070,>6770,>7070 ; * -- Map Row 39 -- DATA >7089,>8867,>6788,>8888 ; DATA >8888,>6784,>8283,>8989 ; DATA >8888,>8888,>8888,>8889 ; DATA >8989,>8989,>8888,>8889 ; DATA >8989,>8989,>8889,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >7070,>7070,>6770,>7270 ; * -- Map Row 40 -- DATA >7089,>8888,>6788,>8888 ; DATA >8888,>6767,>6667,>6667 ; DATA >6788,>8888,>8888,>8889 ; DATA >8989,>8989,>8989,>8989 ; DATA >8967,>6767,>6767,>6788 ; DATA >8888,>8888,>8888,>8888 ; DATA >8870,>7270,>6770,>7070 ; * -- Map Row 41 -- DATA >7070,>8988,>6788,>8C8D ; DATA >8F88,>8889,>8989,>8888 ; DATA >6688,>8888,>8888,>8888 ; DATA >8988,>8989,>8989,>8989 ; DATA >8967,>8888,>8888,>6688 ; DATA >8888,>8888,>6767,>6767 ; DATA >6788,>7070,>6770,>7070 ; * -- Map Row 42 -- DATA >7070,>8989,>6788,>8B8A ; DATA >8E88,>8889,>8989,>8888 ; DATA >6788,>8888,>8888,>8888 ; DATA >8888,>8989,>8989,>8989 ; DATA >8967,>8888,>8888,>6688 ; DATA >8888,>8888,>6767,>6767 ; DATA >6767,>6767,>6770,>7070 ; * -- Map Row 43 -- DATA >7070,>7067,>6788,>8482 ; DATA >8388,>8889,>8988,>8888 ; DATA >6767,>6667,>6767,>6767 ; DATA >6767,>6767,>6767,>6767 ; DATA >6767,>8889,>8888,>6688 ; DATA >8888,>8888,>6767,>6767 ; DATA >6788,>7070,>7070,>7270 ; * -- Map Row 44 -- DATA >7070,>7067,>8888,>8888 ; DATA >8888,>8889,>8888,>8888 ; DATA >6767,>6767,>6767,>6688 ; DATA >8888,>8889,>8989,>8888 ; DATA >8888,>8889,>8988,>6688 ; DATA >8888,>8888,>6767,>6767 ; DATA >6788,>7070,>7070,>7270 ; * -- Map Row 45 -- DATA >7070,>7067,>7270,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >6767,>6767,>6767,>6788 ; DATA >8888,>7070,>8889,>8989 ; DATA >8989,>8989,>8988,>6688 ; DATA >8888,>8888,>6788,>8989 ; DATA >8989,>7072,>7072,>7070 ; * -- Map Row 46 -- DATA >7070,>7067,>7072,>7070 ; DATA >8888,>8888,>8888,>8888 ; DATA >7270,>7067,>6767,>6788 ; DATA >8870,>7070,>7070,>7089 ; DATA >8989,>8989,>8989,>6666 ; DATA >6666,>6666,>6789,>8972 ; DATA >7270,>7272,>7070,>7072 ; * -- Map Row 47 -- DATA >7072,>7067,>7070,>7270 ; DATA >7070,>7072,>7272,>7070 ; DATA >7070,>7070,>7070,>7270 ; DATA >7070,>7072,>7089,>7070 ; DATA >7070,>7089,>8989,>8989 ; DATA >8989,>8989,>8989,>8972 ; DATA >7072,>7270,>7070,>7070 ; * -- Map Row 48 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7070,>7270 ; DATA >7089,>8989,>8989,>8989 ; DATA >7088,>8889,>8989,>8889 ; DATA >8989,>8989,>8989,>8970 ; DATA >7070,>7070,>7070,>7070 ; * -- Map Row 49 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7072,>7089 ; DATA >8989,>8989,>8989,>8989 ; DATA >8988,>8888,>8888,>8888 ; DATA >8989,>8989,>8989,>8970 ; DATA >7070,>7070,>7070,>7070 ; * -- Map Row 50 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7289,>8989 ; DATA >8888,>8989,>8989,>8989 ; DATA >8988,>8888,>8888,>8888 ; DATA >8989,>8889,>8989,>8970 ; DATA >7070,>7070,>7070,>7070 ; * -- Map Row 51 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7072,>8989,>8989 ; DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8889,>8989,>8970 ; DATA >7070,>7020,>7070,>7070 ; * -- Map Row 52 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7289,>8989,>8988 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8889,>8989,>8970 ; DATA >2070,>7070,>7070,>7070 ; * -- Map Row 53 -- DATA >7070,>7067,>7070,>7070 ; DATA >7070,>7070,>7070,>7070 ; DATA >7070,>8989,>8989,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8989,>8970 ; DATA >7070,>7070,>7070,>7070 ; * -- Map Row 54 -- DATA >7070,>7067,>6767,>6767 ; DATA >6767,>6767,>6767,>6767 ; DATA >6767,>6767,>6767,>6767 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8989,>8989 ; DATA >7070,>7070,>7070,>7070 ; * -- Map Row 55 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>6767,>7070,>7072 ; DATA >7289,>8967,>6767,>6767 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8989 ; DATA >8920,>7070,>7070,>7070 ; * -- Map Row 56 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7070,>7270 ; DATA >8989,>8967,>6767,>6767 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8970,>7070,>7020,>7070 ; * -- Map Row 57 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7072,>7089 ; DATA >8989,>8967,>6767,>6767 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8889 ; DATA >8989,>7020,>7070,>7020 ; * -- Map Row 58 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7072,>7089 ; DATA >8989,>8867,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8989,>7070,>7070,>7070 ; * -- Map Row 59 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7070,>7270,>8988 ; DATA >8988,>8867,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8989,>7067,>6767,>6767 ; * -- Map Row 60 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7072,>7089,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >8888,>8888,>8867,>6767 ; DATA >6767,>6767,>6767,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8889,>2067,>7070,>7070 ; * -- Map Row 61 -- DATA >7070,>7070,>7070,>7070 ; DATA >7070,>7270,>8988,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >8888,>8888,>8867,>8888 ; DATA >8888,>8888,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8967,>2070,>7070 ; * -- Map Row 62 -- DATA >7070,>7070,>7070,>7070 ; DATA >7072,>7289,>8989,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >8888,>8888,>8867,>8888 ; DATA >8C8D,>8F88,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8967,>7070,>7070 ; * -- Map Row 63 -- DATA >7070,>7070,>7070,>7070 ; DATA >7270,>8989,>8988,>8888 ; DATA >8888,>8867,>888C,>8D8F ; DATA >8888,>8888,>8867,>8888 ; DATA >8B8A,>8E88,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>7070,>7020 ; * -- Map Row 64 -- DATA >7070,>7070,>7070,>7072 ; DATA >7089,>8989,>8888,>8888 ; DATA >8888,>8867,>888B,>8A8E ; DATA >8888,>8888,>8867,>8888 ; DATA >8482,>8388,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>8970,>7070 ; * -- Map Row 65 -- DATA >7070,>7070,>7072,>7270 ; DATA >8989,>8988,>8888,>8888 ; DATA >8888,>8867,>8884,>8283 ; DATA >8888,>8888,>8867,>8888 ; DATA >8888,>8888,>8867,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>8970,>7020 ; * -- Map Row 66 -- DATA >7070,>7070,>7072,>7089 ; DATA >8989,>8888,>8888,>8888 ; DATA >8888,>8867,>6767,>6767 ; DATA >6767,>6767,>6767,>6767 ; DATA >6767,>6767,>6767,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>8989,>7070 ; * -- Map Row 67 -- DATA >7070,>7070,>7072,>8989 ; DATA >8989,>8888,>8888,>8888 ; DATA >8888,>8867,>8888,>8888 ; DATA >8888,>8888,>8888,>8867 ; DATA >8888,>8888,>6767,>6767 ; DATA >6767,>6767,>6767,>8888 ; DATA >8888,>8867,>8989,>7070 ; * -- Map Row 68 -- DATA >7070,>7070,>7270,>8989 ; DATA >8988,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>6767,>8888 ; DATA >8888,>8867,>6789,>7070 ; * -- Map Row 69 -- DATA >7070,>7072,>7070,>8989 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>6767,>6767 ; DATA >6767,>6767,>6788,>8970 ; * -- Map Row 70 -- DATA >7070,>7272,>7089,>8988 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8867,>6767,>8888 ; DATA >8888,>8888,>8888,>8989 ; * -- Map Row 71 -- DATA >7070,>7220,>7089,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8867 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8888 ; DATA >8888,>8888,>8888,>8989 ; END Entire XB program listing below 90 CALL SCREEN(2) REM COLORSET DECLARATIONS 100 DATA 1,2,1,2,2,1,3,2,1,4,2,1,5,2,1,6,2,1,7,2,1,8,2,1 110 DATA 9,11,1,10,6,5,11,15,1,12,2,11,13,7,3,14,2,3 REM CHARACTER DATA 500 DATA 96,"C3C303030303FFFF",97,"C3C3C3C3C3C3C3C3",98,"FFFFC0C0C0C0C3C3",99,"C3C3C0C0C0C0FFFF" 510 DATA 100,"FFFF03030303C3C3",101,"FFFF00000000FFFF",102,"FFDFFFFFF7BFFDFF",103,"FFFDBFFBFFDFFEFF" 520 DATA 104,"C3241800C3241800",112,"181C36315E448212",113,"1818FFFF18181818",114,"0018382464D08202" 530 DATA 115,"03070E9C7830D0C8",120,"070F1F1C1C1F1F1F",121,"E0F0F83838F8F8F8",122,"8080F0888880C0E0" 540 DATA 123,"01010F1111010307",128,"005555FFDFFBBFFD",129,"FFF7BFEDFF00AAAA",130,"1CFC3F1E3E3EFEFF" 550 DATA 131,"30E0800000000000",132,"0603000000000003",136,"8104002002882200",137,"380AD1C988087337" 560 DATA 138,"01000000804000FF",139,"88C141602030180F",140,"0001070C3860C488",141,"7EC3003040000006" 570 DATA 142,"0181011322C60CF8",143,"00C0780CC6222311" REM LOAD COLORSET 3430 RESTORE 100::FOR C=1 TO 14::READ CS,CF,CB::CALL COLOR(CS,CF,CB)::NEXT C REM LOAD CHARACTERS 3440 RESTORE 500::FOR C=1 TO 30::READ CN,CC$::CALL CHAR(CN,CC$)::NEXT C 3600 CALL INIT 3610 CALL LOAD("DSK1.FOREST3O") 3620 CALL LINK("DRAW") 3630 GOTO 3630 Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 NOT DONE GRAPHICALLY.... This is JUST mockup. 56x72 Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 7, 2010 Share Posted December 7, 2010 *Draw border (inefficient, but by golly it works) LI R0,256 starting location in VRAM LI R1,BORDER CPU data LI R2,512 number of bytes to write BL @VMBW write it With 512 bytes in the "forest3o", the extra loadtime and the drag on the "draw" routine, is, yes, inefficient, even to a total of 8 H- and VCHARs. The viewport itself is "cleared" anyway when a chunk of the big map is displayed. Now, I guess we would want to tell the routine, which part of the big map to draw. We could pass a parameter with the LINK, we could LOAD a value into a certain memory location or use other trickery like assemble a string like "31" and use a character pattern to pass information. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 (edited) The XB workspace starts at >83E0, so passing the proper value directly into the register from XB shouldn't be a problem. =) Edited December 7, 2010 by Opry99er Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 With 512 bytes in the "forest3o", the extra loadtime and the drag on the "draw" routine, is, yes, inefficient, even to a total of 8 H- and VCHARs. The viewport itself is "cleared" anyway when a chunk of the big map is displayed. True, but this longer load time would only happen once per "world". That's expected. But if you think 2 CALL VCHARs and 6 HCHARs would be faster, then that is what shall be. As long as that only has to happen once per world as well... =) I thought it might be a bit inefficient, but it seemed quicker than doing it via BASIC before the CALL COLORs happened... leaving the screen and all info on the screen black before displaying all at once. I'll test further. In the meantime, I'm looking forward to setting up another "virtual tour" using the assembly routine and seeing how fast we can "page" the screens. =) Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 7, 2010 Share Posted December 7, 2010 The XB workspace starts at >83E0, so passing the proper value directly into the register from XB shouldn't be a problem. =) Holy shit, Owen, I didn't even think of being that direct. But before we get there (get inside our DRAW routine), I guess XB and what's more, may already have destroyed most of the workspace. Maybe somewhere else in Scratchpad ? Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 7, 2010 Share Posted December 7, 2010 With 512 bytes in the "forest3o", the extra loadtime and the drag on the "draw" routine, is, yes, inefficient, even to a total of 8 H- and VCHARs. The viewport itself is "cleared" anyway when a chunk of the big map is displayed. True, but this longer load time would only happen once per "world". That's expected. But if you think 2 CALL VCHARs and 6 HCHARs would be faster, then that is what shall be. As long as that only has to happen once per world as well... =) I thought it might be a bit inefficient, but it seemed quicker than doing it via BASIC before the CALL COLORs happened... leaving the screen and all info on the screen black before displaying all at once. I'll test further. In the meantime, I'm looking forward to setting up another "virtual tour" using the assembly routine and seeing how fast we can "page" the screens. =) Let's try and make the viewport routine only. We can move/put the border in later, and assembler code more like H- and VCHAR would be much less than 512 bytes - no doubt. And I expect that code to be quite reusable with a twist et al. Quote Link to comment Share on other sites More sharing options...
Opry99er Posted December 7, 2010 Author Share Posted December 7, 2010 I have a feeling scratchpad is blown out.... We can either use a direct load into a register or find an obscure location to pass it to. I think a direct load is the way to go... We have open registers.... Outside of our registers which are available to us, scratchpad is pretty much cannibalized by XB... Quote Link to comment Share on other sites More sharing options...
sometimes99er Posted December 7, 2010 Share Posted December 7, 2010 We share the workspace with the system @>83E0. We have to assume that workspace is out of the question. We could swap workspace to an area (and back), but we would need and potentially destroy 32 bytes. quote: >8300 to >8313 is used to support parameter passing from XB to machine language subprograms. So I guess we could safely load a byte @>8300. quote: The address is a decimal value from -32768 to 32767, representing two byte addresses. Addresses above >7FFF are written as negative numbers, treating the two byte quantity as a two's complement integer. (i.e. to access an address above 32767, subtract 65536 from it.) 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.