Jump to content

sarkeizen

New Members
  • Posts

    12
  • Joined

  • Last visited

sarkeizen's Achievements

Space Invader

Space Invader (2/9)

14

Reputation

  1. I apologize. Things have been busy for me for a while now. I do have some work half done (one on character generators, one on using a slice algorithm and other line drawing enhancements) but I'm not sure when I'll get them up.
  2. Part Nine - is now up, where I tie everything together with a nice API -- as an added bonus I show off my (lack of) artistic talent! I've also started using the domain http://battlestations.zone - all the old links to my previous (and somewhat pretentious) domain http://lastrationalman.blogspot.com will get redirected.
  3. New post: Double hi-res from the ground up part 8. https://lastrationalman.blogspot.ca/2017/05/apple-ii-double-hi-res-from-ground-up_11.html
  4. Definitely not! The seventh one just went up five minutes ago in which I do some code management and provide some graphic demos of the plot algorithm and it's performance. I also start laying out an implementation of Bresenham's Line algorithm entirely using 8 bit math. I also tried to put a few copy-and-pasteable demos in this one. http://lastrationalman.blogspot.ca/2017/05/apple-ii-double-hi-res-from-ground-up.html Sorry for the delays. My job goes through somewhat unpredictable fits of activity. I also had some things I wanted to change about the blog and it's presentation. I'm still tweaking it now and then. For example I wrote a syntax highlighter for the 6502 assembly because I started hating the long streams of code I had to post. I have the eighth post all planned out. My plan is to get it doing some Wizardry / Dungeons of Daggorath type plots which will run nicely into the next topic which will be doing a DHR character generator. From there I haven't decided if I should go down the path of sketching out how you write an engine for that type of game or switch to another graphic archetype i.e. simple tile based games like Ultima. Then on to arcade style games... Any feedback is welcome, for example right now I have comments using Disqus. Considering the number of people in the Apple II community who are on Facebook I'm thinking of switching over.
  5. Added the second part here... http://lastrationalman.blogspot.ca/2017/04/apple-ii-double-hi-res-from-ground-up_12.html So I've partially written up (but not yet published) a couple more where I cover some assembly code for plotting colour DHR pixels fast enough to be useful. ( I have some REALLY fast plotting code but it's a little cryptic) After that I'll give a couple of examples using that code as a macro - maybe touch on why that in performance oriented assembly having code that you can drop in places is often more important than having high-speed code that you can call. From there, I'll move to simple character graphics and then larger bitmap graphics. Hopefully these will get people where they want to go.
  6. For what it's worth I've fixed up what I've been writing here and posted it on my blog. Any comments welcome! http://lastrationalman.blogspot.ca/2017/04/apple-ii-double-hi-res-from-ground-up.html
  7. Great question! How do the HIRES pages work under DHR? This is actually pretty interesting. While I didn't touch on it earlier, there is more than one way to access AUX memory and therefore the DHR pages. In my prior post I mentioned using the 80STOREON softswitch $C001 to change the function of the PAGE1/PAGE2 softswitchs to map $2000-$3FFF (hires page 1) between MAIN and AUX memory. However for whatever reason (remember that DHR was kind of an accident) it doesn't change page two $4000-$5FFF, So what do we do? Well there is another softtswitch 80STOREOFF $C000 this returns the PAGE1/PAGE2 function to normal. Once you do you can use a different set of softswitches:. $C005 RAMWRTON and $C004 RAMWRTOFF to allow you to write to AUX memory. These switches act in a fundamentally different way. When $C005 is invoked all memory WRITE operations (e.g. STA $2222) go to AUX memory and when $C004 is invoked all memory WRITE operations go to main memory. READ operations (including fetching the next instruction in your program) always go to MAIN memory. In this configuration we can use PAGE1/PAGE2 to display the DHR pages 1 and 2 respectively. Example (in friggin machine code!): STA $C050 ;Turn on GRAPHICS STA $C057 ;Turn on Hi-res STA $C052 ;Turn on Full screen STA $C05E ;Turn on DHR STA $C00D ;Turn on 80 Columns STA $C000 ;Turn OFF 80STORE STA $C005 ;Turn ON RAMWRT LDA #$00 ;Load bitpattern %00000000 STA $2000 ;Store on DHR PAGE 1, line 1 STA $4400 ;Store on DHR PAGE 2, line 2 STA $2800 ;Store on DHR PAGE 1, line 3 STA $4C00 ;Store on DHR PAGE 2, line 4 STA $3000 ;Store on DHR PAGE 1, line 5 STA $5400 ;Store on DHR PAGE 2, line 6 STA $3800 ;Store on DHR PAGE 1, line 7 STA $5C00 ;Store on DHR PAGE 2, line 8 LDA #$0F ;Load bitpattern %00001111 STA $4000 ;Store on DHR PAGE 2, line 1 STA $2400 ;Store on DHR PAGE 1, line 2 STA $4800 ;Store on DHR PAGE 2, line 3 STA $2C00 ;Store on DHR PAGE 1, line 4 STA $5000 ;Store on DHR PAGE 2, line 5 STA $3400 ;Store on DHR PAGE 1, line 6 STA $5800 ;Store on DHR PAGE 2, line 7 STA $3C00 ;Store on DHR PAGE 1, line 8 LOOP: STA $C055 ;Show PAGE 2 STA $C054 ;Show PAGE 1 JMP LOOP So here we just store alternating black and white pixels in the first pixel of the first eight lines of the DHR PAGE1. Which starts at AUX memory location $2000. Then we store white pixels where we put black pixels and vice versa on DHR PAGE2. Which is at AUX memory locaiton $4000. Finally we enter into a loop which just flips between PAGE1 and PAGE2. (I'll assume, for now that everyone understands the insane HORIZONTAL structure of all the Apple II hi-res screens - if you don't then just take it for granted that each line in the first eight lines are $400 apart) Here's the program in binary form. 6000: 8d 50 c0 8d 57 c0 8d 52 c0 8d 5e c0 8d 0d c0 8d 00 c0 8d 05 c0 a9 00 8d 00 20 8d 00 44 8d 00 28 8d 00 4c 8d 00 30 8d 00 54 8d 00 38 8d 00 5c a9 0f 8d 00 40 8d 00 24 8d 00 48 8d 00 2c 8d 00 50 8d 00 34 8d 00 58 8d 00 3c 8d 55 c0 8d 54 c0 4c 46 60 So why would we ever use 80STORE? Virtually every graphic mode on every computer involves trade-offs. 80STORE is no different. When 80STORE is active we can read and write from DHR PAGE1. When 80STORE is OFF using RAMWRT only lets us WRITE to DHR PAGE1 and PAGE2. If we wanted to read the screen, for example if we wanted to XOR a graphic the DHR screen - a common trick to preserve the background - it simply wouldn't work. The result would be the value we are writing to the memory location in AUX XORed against the same location in MAIN memory. So what happens if we want to read from both DHR pages? There is a way - there are two more softswitches $C002 RAMRDOFF and $C003 RAMRDON. However using them is tricky. Why? Remember when I said that even when RAMWRT is on our program is being read from MAIN memory? Well as soon as you invoke $C003 - Immediately the 6502 program counter starts reading from AUX memory. If you don't have a program sitting at that exact location in AUX memory then the program will just act unpredictably. How we manage this is by using RAMWRT to write a program into the memory location the Program Counter will be at the instant we INVOKE RAMRDON. We also need a program sitting in MAIN ram exactly where we expect our program to be when we invoke RAMRDOFF again. Does that sound like a pain in the ass? You'd be right.
  8. I'll give some commentary on these because I've used some of these. Beagle Bros Dbl.Plot on the beagle graphics disk: This is an actual art program written by Mark Simonsen and it does do DHR drawings. It can even do single pixel manipulation (in what it calls Mode 1) however there is no zoomed mode for doing this so I find it hard to work with. Graphics Magician: There is indeed a DHR version of the graphics magician. However it's worth pointing out that the GM is pretty much a vector drawing program. You draw an image using lines, points, shapes and fills and then the software can play those back. It can do some interesting things like create primitive animation but I think it would be hard to adapt for anything other than a graphic adventure game. IIRC Shadowkeep (an RPG) was written with it and it was pretty slow. That said there is a raster graphics system (famous for it's dancing letters demo) but I doubt it works in DHR. The rainbow painter: The only program I know of my this name is a kids drawing program and I've never seen a DHR version. The program I'm thinking of uses a "colouring book" approach.
  9. So where's the assembly code? Well originally I didn't see the point in writing assembly for something as simply as turning on the screen and putting a dot on it. The point is to understand how the screen is structured. If you don't get that then you're not really going to understand a sophisticated example. Not to mention that BASIC pokes translate pretty directly to assembly code. For example this program: 10 POKE 49232,100: REM TURN ON GRAPHICS 20 POKE 49239,100: REM TURN ON HIRES 30 POKE 49234,100: REM TURN ON FULLSCREEN 40 POKE 49246,100: REM TURN ON DHR 50 POKE 49165,100: REM TURN ON 80COLUMS 60 POKE 49153,100:POKE 49237,100:POKE 8192,14: REM TURN ON 80STOR, TURN ON PAGE2, WRITE AQUA PIXEL RUN Trivially becomes: STA $C050 ;TURN ON GRAPHICS STA $C057 ;TURN ON HIRES STA $C052 ;TURN ON FULLSCREEN STA $C05E ;TURN ON DHR STA $C00D ;TURN ON 80 COLUMNS STA $C001 ;TURN ON 80STOR STA $C055 ;TURN ON PAGE2 LDA #$0E ;LOAD 14 STA $2000 ;Put in first location on HIRES PAGE 1 in MAIN RAM. or you can just paste the following into your emulator... CALL -151 6000:8d 50 c0 8d 57 c0 8d 52 c0 8d 5e c0 8d 0d c0 8d 01 c0 8d 55 c0 a9 0e 8d 00 20 60 6000g I've got an idea or two for a good next step. Illustrating how to address a specific pixel. I'll see if I can write it up in the next day or two.
  10. Sorry that should have read: I keep an Apple //gs around too since it doesn't support artifacting and tends to render DHR colours slightly differently. While were on the subject, in case it isn't obvious RGB monitors don't support artifacting either.
  11. Ok thanks for the questions everyone.... So first, if it's not too much of a review I'll give an overview of the Apple Hires screen layout. It's pretty crazy and it will be easier if everyone is on the same page. Hi-res Overview: Looking strictly at hi-res graphics on the Apple II's with 48k or more. There are two hi-res screens called PAGE1 and PAGE2. These are mapped to two 8KB areas of memory starting at $2000 (8192) for PAGE1 and $4000 (16384) for PAGE2. You can tell the hardware to display either one and since these are simply big blocks of memory you can write to either. So a common method of making smoother animation is to write to PAGE1 while telling the Apple to display PAGE2 Once you are finished drawing you then tell the Apple to display PAGE1 and start drawing to PAGE2. One other feature I'll mention is the ability to choose between having the whole screen hires graphics, we call this mode FULLSCREEN or to have graphics everywhere but the last four lines of text at the bottom of the screen. We call this mode MIXED. This can be done on either hires page. So you can see this in action by doing the following. From BASIC type the following: HGR2 HGR POKE 8192,63 POKE 16384,21 You should now see a white bar at the top left corner of the screen. How it works: The first BASIC command clears PAGE2, sets it up as the visible page, and sets FULLSCREEN mode (so you can no longer see what you are typing). The second clears PAGE1, sets it up as the visible page and sets the mode to be MIXED. You still might not see your cursor because these four lines of text are just a window into the bottom four lines of the text screen. Hitting "return" a few times will bring the cursor down far enough for you to see, The third puts the value 63 into memory location 8192. Which if you remember is the beginning of the first hi-res page. So you should have seen the white bar appear as soon as you typed that. The last command puts 21 into location 16384 which is the top left corner of PAGE2. So how do we see PAGE2 without erasing it? All these modes and pages are controlled by a series of "softswitches'. These are memory locations that don't contain real memory, instead they let you talk to the video hardware. $C054 (49236) tells the hardware to display PAGE1 and $C055 (49237) tells the hardware to display PAGE2. So if we type: POKE 49237,100 Will turn on PAGE2. You will also notice that the text at the bottom of the screen looks crazy. This is because the PAGE2 softswitch also turns on text page 2 as well as hires page 2. Text page 2 is generally never used even by the built-in BASIC firmware so all you see is whatever garbage was in that portion of memory. So you should notice that there's also a bar at the top left corner and it's a magenta colour (or if it's a monochrome monitor it's a dotted line). By the way you don't need to put the exact value 100 into 49237 to activate PAGE2. You don't even need to store a value there. You can just read that memory location by doing: PRINT PEEK(49237) Anything that "touches" that location flips the switch. If you want to get back to PAGE1 just use: POKE 49236,100 Apple II's crazy colour system: The colour we see on the screen is, unsurprisingly related to the value we poked into memory. To get a better understanding let's look at the binary representation of each number: 63 = 00111111 21 = 00010101 The relationship between bits and pixels on the screen is just a little odd. On a NTSC monochrome screen the Apple II video appears to be made of pixels that are 1 bit wide. Which is why on a monocrhome screen poking 21 into 8192 produces a dotted line. On an NTSC (TV, composite monitor) the Apple II video appears to be made of pixels 2 bits wide. So that same set of bits looks like a solid magenta line. it's worth pointing out that there are no colour/monochrome "modes" here. It just depends what screen you're plugged into. Each line on the display maps to a row of 40 bytes in memory. So from $2000 (8192) - $2039 (8231) is the first line on PAGE1 and from $4000 (16384) - $4039 (16423) So it would seem reasonable that 8 bits * 40 bytes = 320 monochrome pixels OR 160 colour pixels. Right? Well not exactly.... You'll notice that he first bit in every byte (which we call the HIGH BIT) of our example POKE's is zero. That's because the first bit doesn't represent a pixel it actually selects between one of two colour pallets. You can see this by adding 128 (the value of the leftmost bit) to the value 21. 21+128=149 POKE 16384,149 So by changing the value from 00010101 to 10010101. The line will turn from magenta to blue. So if we have two bits per pixel and two different pallets we must have eight different colours to choose from. Right? Well not really... Here are the colours when the high bit is zero: 00 = Black 01 = Magenta 10 = Green 11 = White Here are the colours when the high bit is one. 00 = Black 01 = Blue 10 = Orange 11 = White So there are TWO whites and TWO blacks leaving us with only six different hires colours. Wonder what happens on a monochrome monitor? Turning the high bit on shifts everything half a pixel to the right. You can try this like so: HGR 10 POKE 8192,21 20 POKE 8192,149 30 GOTO 10 RUN On a colour screen you would see a three pixel wide line shift between magenta and blue and on a monochrome screen you would see a dotted line do a little half-pixel dance from left to right. Another counter-intuitive thing about the hires display is the order of mapping bits to pixels. So poking 21 into 8192 turns the first, second and third pixels magenta. If you remember the binary representation of this is 00010101. If you check the chart above you will see that magenta is represented by the bit pattern 01. You should be able to see that the first, second and third pixels on the screen occupy the LOWEST six bits in that byte. We also know that the highest bit selects the pallet. We can illustrate this by replacing 01 with MM to represent a magenta pixel and P to represent the pallet bit like so: P0MMMMMM Notice something? There's an extra zero right after the pallet bit? So what's this leftover bit do? Well actually that's HALF of the fourth pixel's information. What? So where's the other half? In the next byte! If I draw another picture but this time use AA to represent the first pixel, BB to represent the second pixel, and so on... the first two bytes of hires page one would look like this: PDCCBBAA PGGFFEED --8192-- --8193-- Which means we have 7 pixels across 16 bits. If you recall there are 40 bytes in a single line on the Apple II hires screen. This means the horizontal resolution is 40*3.5 = 140 coloured pixels in six colours or 280 monochrome pixels. Ok that's the short short version of the Apple II hires system. Next up... Bank switched memory: Ok most people who use 8 bit micros know what this is but just as a quick refresher. Every CPU has a limit to the number of memory locations it can address. The 6502 is no different it can't understand an address that is larger than 16 bits in size. Which means it can't address more than 216 possible memory locations. In other words 65536 bytes (64KB). To get around this many computer systems use a technique called bank switching. This involves having circuitry which allows you to take some part of the memory in the computer and switch it with another piece of memory of the same size. When the Apple //e shipped with 128KB of memory the extra 64KB was accessed using bank switching. That extra memory is often called the AUXILIARY MEMORY or simply AUX memory. The story goes that someone realized that if you made a small change to the motherboard you could cause the Apple II video circuitry to read BOTH the main and AUX memory at the same time. The result was instead of having a color display that was 280 monochrome pixels or 140 colour pixels. You could have a display that was 560 monochrome pixels OR 140 coloured pixels but using 4 bits per pixel rather than 2. Yielding 16 colours! Once this was realized Apple made this change to their production line resulting in the Revision B motherboard. Thus the following machines can use this special mode. Apple //e Revision A with modification, Apple //e Revision B, Apple //c and the Apple //gs. The pixels are read first from the AUX memory and then from the MAIN memory. So using letters to represent pixels again we would have the following: PBBBAAAA PDDCCCCB PFEEEEDD PHHHHGGG 8192 AUX 8192MAIN 8193 AUX 8193MAIN Perhaps you've noticed that the pallet bit is still there. When DHR is active it simply gets ignored (in the vast, vast majority of cases). So how do we activate this magical mode? You guessed it! Softswitches! You need FIVE - in no particular order. Here they are: $C050 (49232) - Graphics $C057 (49239) - Hires $C052 (49234) - Fullscreen $C05E (49246) - DHR $C00D (49165) - 80 Column mode POKE something into each one of those locations and you will be on the DHR screen. You should notice a kind of stripe pattern. This is due to the fact that the main hires page is on power up filled with garbage and the AUX page gets cleared. Let's put a DHR pixel on the screen now! So remembering our diagram: PBBBAAAA PDDCCCCB PFEEEEDD PHHHHGGG 8192 AUX 8192MAIN 8193 AUX 8193MAIN Keeping in mind that currently we don't know how to access the AUX bank of memory. The first memory location we have access to is 8192 MAIN. As you can see it has one bit from pixel B, all four from pixel C and two from pixel D. So the only pixel we can fully draw by looking at this byte is C! Now the bit pattern for aqua is 1110 and putting that into the spot where pixel C is in our diagram we get PDD1110B we can assume that all the other pixels around this are black so we set all the other bits to zero and the result is 00011100 or 28! There's probably a lot of junk on the screen so you might consider a simple program to flicker the pixel between aqua and black (for which the bit pattern is 0000 in case you haven't guessed) 10 POKE 8192,0 20 POKE 8192,28 30 GOTO 10 Accessing AUX memory Here are the colours and their associated bit patterns for DHR mode Color Pattern Black 0000 Magenta 0001 Brown 0010 Orange 0011 Dark Green 0100 Grey1 0101 Green 0110 Yellow 0111 Dark Blue 1000 Violet 1001 Grey2 1010 Pink 1011 Medium Blue 1100 Light Blue 1101 Aqua 1110 White 1111 Ok now all you need to do is figure out how to set the AUX memory bytes. To do that the hardware provides a specail softswitch called 80STORON $C001 (49153) this one changes the behavior of the PAGE1 and PAGE2 softswitches. Instead of switching which page is displayed it swaps the MAIN PAGE1 with the AUX PAGE1. The PAGE1 softswitch swaps them back. So looking back at our diagram again for the first byte of hires page one in aux memory. We see: PBBBAAAA and we recall aqua is 1110. To set pixel A to aqua we again insert it into our diagram PBBB1110 and zero the other bits 00001110 which gives us 14. So starting from the beginning our program for writing looks like this 10 POKE 49232,100: REM TURN ON GRAPHICS 20 POKE 49239,100: REM TURN ON HIRES 30 POKE 49234,100: REM TURN ON FULLSCREEN 40 POKE 49246,100: REM TURN ON DHR 50 POKE 49165,100: REM TURN ON 80COLUMS 60 POKE 49153,100:POKE 49237,100:POKE 8192,14: REM TURN ON 80STOR, TURN ON PAGE2, WRITE AQUA PIXEL RUN Ok so now you pretty much know everything to activate the DHR screen and turn on any DHR pixel in any DHR colour. If everyone's following that. Then feel free to ask more specific questions. Oh what about sprite tools! Well it's worth pointing out that the entire Apple II graphics hardware is a framebuffer. It's just some memory that represents pixels on the screen. So there is no hardware support for sprites. Any image drawing program is as much a sprite editor as anything else. Speaking of DHR drawing programs, there are only two I know of for the Apple II - 816 Paint and Dazzle Draw. I use them both. Often I draw a sprite sheet using Dazzle Draw then write a BASIC program to load it and get it into the format I want and save it as a binary file. One annoying thing is that neither of these programs lets you manipulate individual bits. When I said that the "Apple II appears to be made of pixels 2 bits wide" I meant it. The reality is actually more complicated and often you can, by putting just the right colours adjacent to each other smooth out the jagged edges of a graphic through NTSC artifacting. Because of this, the hardware I use to view my work is as important as the tools I use to draw it. For example, I'm always cycling between the monochrome, colour monitor and colour TV profiles in AppleWin. I keep an Apple //gs around to since it support artifacting and tends to render DHR colours slightly differently. The final test is on my Ikegami TM9 broadcast colour video monitor which is the closest thing to NTSC spec I own. I'll also do a run against my flat screen TV to see just how badly it mangles the signal. :-) Getting back to manipulating individual bits. If you want to do DHR monochrome work then I've ended up building my own tools. There are graphic conversion tools like bmp2dhr. However I've never found an option that turns off all the dithering. So what I ended up doing is writing a program in Python which converted TGA output from Paint.NET into a Dazzle Draw file. The main difficulty is that the Apple monochrome screen has a weird aspect ratio and it's hard to judge what you are doing. It was good enough to work on some proportionally spaced font routines I was working on though. Here's an screen cap of an Ultima II style engine I put together with my 11 year old daughter .
  12. Sorry for arriving late to this party. I'm pretty experienced in doing DHR from 6502 assembly. If you have any specific questions feel free to ask me.
×
×
  • Create New...