diff --git a/tools/bitmap editor/apple2_hires.md b/tools/bitmap editor/apple2_hires.md index 6c55cbd..7d36317 100644 --- a/tools/bitmap editor/apple2_hires.md +++ b/tools/bitmap editor/apple2_hires.md @@ -88,4 +88,109 @@ The following code will do it ![screenshot](img/apple2_hires_lines_8.png) -So what happens next ? +So what happens next ? Well, a `POKE 9216,255` will show you that you're plotting on line 1 ! And once line 1 has been filled, you'll plot on line 65 ! And then on line 129 ! Then back to first section of 64-lines but on line 8+1=9, then on line 16+1=17, etc. + + 10 HGR + 20 A = 8192: REM $2000 + 30 FOR L = 0 TO 7 + 40 FOR K = 0 TO 7 + 50 FOR J = 0 TO 2 + 60 FOR I = 0 TO 39 + 70 POKE A, 255 + 80 A = A + 1 + 90 NEXT I,J + 100 A = A + 8 + 110 NEXT K,L + 120 PRINT A + +If you run the above code, your screen will be filled and A will point to 16384 (or $4000) which is the start of page 2. + +To sum it up, the logical structure in RAM is as follows: + + 1. There are 3 sections of 64 lines beginning at lines 0, 64 and 128 + 2. A Y-line subindex is set to zero + 3. A Y-line index is set to zero + 4. Section number is set to zero + 5. RAM holds the three lines corresponding to the section + index + subindex + 6. Section number is incremented by 64 + 7. Back to step 5, three times + 8. Then 8 bytes are wasted + 9. Y-Line index is incremented by 8 + 10. Back to step 4, eight times + 11. Y-line SUBindex is incremented by 1 + 12. Back to step 3, eight times + +In code that would be + + 10 HGR: A = 8192 + 20 Y0 = 0 : N0 = 0 : REM Y-SUBINDEX AND COUNTER + 30 Y1 = 0 : N1 = 0 : REM Y-INDEX AND COUNTER + 40 S = 0 : NS = 0 : REM SECTION NUMBER AND COUNTER + 50 HPLOT 0, S + Y0 + Y1 TO 279, S + Y0 + Y1: REM DRAW A WHOLE LINE + 60 PRINT S + Y0 + Y1;": ";A" ";: S = S + 64: A = A + 40 + 70 NS = NS + 1 : IF NS < 3 THEN GOTO 50 + 80 A = A + 8: REM HERE 8 BYTES ARE NOT USED + 90 Y1 = Y1 + 8 + 100 N1 = N1 + 1: IF N1<8 THEN GOTO 40 + 110 Y0 = Y0 + 1 + 120 N0 = N0 + 1: IF N0<8 THEN GOTO 30: REM WE COULD HAVE USED Y0 ONLY SINCE IT'S ALWAYS EQUAL TO N0 + +Notice how the HPLOTs draw the lines in the same order as the `POKE`s in the previous programs. + +The starting address of a line Y in hires page 1 is found using the following formula: + + S = INT(Y/64) + Y1 = INT( (Y - 64 * S) / 8) + Y0 = INT(Y - 64 * S - 8 * Y1) + A = 8192 + S * 40 + Y1 * 128 + Y0 * 1024 + + +|Line| Start | End | Line | Start | End | Line | Start | End | Line | Start | End |Line | Start | End | Line | Start | End |Line | Start | End | Line | Start | End | +|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--| +| **0** | $2000 | $2027 | **1** | $2400 | $2427 | **2** | $2800 | $2827 | **3** | $2C00 | $2C27 | **4** | $3000 | $3027 | **5** | $3400 | $3427 | **6** | $3800 | $3827 | **7** | $3C00 | $3C27 | +| **64** | $2028 | $204F | **65** | $2428 | $244F | **66** | $2828 | $284F | **67** | $2C28 | $2C4F | **68** | $3028 | $304F | **69** | $3428 | $344F | **70** | $3828 | $384F | **71** | $3C28 | $3C4F | +| **128** | $2050 | $2077 | **129** | $2450 | $2477 | **130** | $2850 | $2877 | **131** | $2C50 | $2C77 | **132** | $3050 | $3077 | **133** | $3450 | $3477 | **134** | $3850 | $3877 | **135** | $3C50 | $3C77 | +| **wasted** | $2078 | $207F | **wasted** | $2478 | $247F | **wasted** | $2878 | $287F | **wasted** | $2C78 | $2C7F | **wasted** | $3078 | $307F | **wasted** | $3478 | $347F | **wasted** | $3878 | $387F | **wasted** | $3C78 | $3C7F | +| **8** | $2080 | $20A7 | **9** | $2480 | $24A7 | **10** | $2880 | $28A7 | **11** | $2C80 | $2CA7 | **12** | $3080 | $30A7 | **13** | $3480 | $34A7 | **14** | $3880 | $38A7 | **15** | $3C80 | $3CA7 | +| **72** | $20A8 | $20CF | **73** | $24A8 | $24CF | **74** | $28A8 | $28CF | **75** | $2CA8 | $2CCF | **76** | $30A8 | $30CF | **77** | $34A8 | $34CF | **78** | $38A8 | $38CF | **79** | $3CA8 | $3CCF | +| **136** | $20D0 | $20F7 | **137** | $24D0 | $24F7 | **138** | $28D0 | $28F7 | **139** | $2CD0 | $2CF7 | **140** | $30D0 | $30F7 | **141** | $34D0 | $34F7 | **142** | $38D0 | $38F7 | **143** | $3CD0 | $3CF7 | +| **wasted** | $20F8 | $20FF | **wasted** | $24F8 | $24FF | **wasted** | $28F8 | $28FF | **wasted** | $2CF8 | $2CFF | **wasted** | $30F8 | $30FF | **wasted** | $34F8 | $34FF | **wasted** | $38F8 | $38FF | **wasted** | $3CF8 | $3CFF | +| **16** | $2100 | $2127 | **17** | $2500 | $2527 | **18** | $2900 | $2927 | **19** | $2D00 | $2D27 | **20** | $3100 | $3127 | **21** | $3500 | $3527 | **22** | $3900 | $3927 | **23** | $3D00 | $3D27 | +| **80** | $2128 | $214F | **81** | $2528 | $254F | **82** | $2928 | $294F | **83** | $2D28 | $2D4F | **84** | $3128 | $314F | **85** | $3528 | $354F | **86** | $3928 | $394F | **87** | $3D28 | $3D4F | +| **144** | $2150 | $2177 | **145** | $2550 | $2577 | **146** | $2950 | $2977 | **147** | $2D50 | $2D77 | **148** | $3150 | $3177 | **149** | $3550 | $3577 | **150** | $3950 | $3977 | **151** | $3D50 | $3D77 | +| **wasted** | $2178 | $217F | **wasted** | $2578 | $257F | **wasted** | $2978 | $297F | **wasted** | $2D78 | $2D7F | **wasted** | $3178 | $317F | **wasted** | $3578 | $357F | **wasted** | $3978 | $397F | **wasted** | $3D78 | $3D7F | +| **24** | $2180 | $21A7 | **25** | $2580 | $25A7 | **26** | $2980 | $29A7 | **27** | $2D80 | $2DA7 | **28** | $3180 | $31A7 | **29** | $3580 | $35A7 | **30** | $3980 | $39A7 | **31** | $3D80 | $3DA7 | +| **88** | $21A8 | $21CF | **89** | $25A8 | $25CF | **90** | $29A8 | $29CF | **91** | $2DA8 | $2DCF | **92** | $31A8 | $31CF | **93** | $35A8 | $35CF | **94** | $39A8 | $39CF | **95** | $3DA8 | $3DCF | +| **152** | $21D0 | $21F7 | **153** | $25D0 | $25F7 | **154** | $29D0 | $29F7 | **155** | $2DD0 | $2DF7 | **156** | $31D0 | $31F7 | **157** | $35D0 | $35F7 | **158** | $39D0 | $39F7 | **159** | $3DD0 | $3DF7 | +| **wasted** | $21F8 | $21FF | **wasted** | $25F8 | $25FF | **wasted** | $29F8 | $29FF | **wasted** | $2DF8 | $2DFF | **wasted** | $31F8 | $31FF | **wasted** | $35F8 | $35FF | **wasted** | $39F8 | $39FF | **wasted** | $3DF8 | $3DFF | +| **32** | $2200 | $2227 | **33** | $2600 | $2627 | **34** | $2A00 | $2A27 | **35** | $2E00 | $2E27 | **36** | $3200 | $3227 | **37** | $3600 | $3627 | **38** | $3A00 | $3A27 | **39** | $3E00 | $3E27 | +| **96** | $2228 | $224F | **97** | $2628 | $264F | **98** | $2A28 | $2A4F | **99** | $2E28 | $2E4F | **100** | $3228 | $324F | **101** | $3628 | $364F | **102** | $3A28 | $3A4F | **103** | $3E28 | $3E4F | +| **160** | $2250 | $2277 | **161** | $2650 | $2677 | **162** | $2A50 | $2A77 | **163** | $2E50 | $2E77 | **164** | $3250 | $3277 | **165** | $3650 | $3677 | **166** | $3A50 | $3A77 | **167** | $3E50 | $3E77 | +| **wasted** | $2278 | $227F | **wasted** | $2678 | $267F | **wasted** | $2A78 | $2A7F | **wasted** | $2E78 | $2E7F | **wasted** | $3278 | $327F | **wasted** | $3678 | $367F | **wasted** | $3A78 | $3A7F | **wasted** | $3E78 | $3E7F | +| **40** | $2280 | $22A7 | **41** | $2680 | $26A7 | **42** | $2A80 | $2AA7 | **43** | $2E80 | $2EA7 | **44** | $3280 | $32A7 | **45** | $3680 | $36A7 | **46** | $3A80 | $3AA7 | **47** | $3E80 | $3EA7 | +| **104** | $22A8 | $22CF | **105** | $26A8 | $26CF | **106** | $2AA8 | $2ACF | **107** | $2EA8 | $2ECF | **108** | $32A8 | $32CF | **109** | $36A8 | $36CF | **110** | $3AA8 | $3ACF | **111** | $3EA8 | $3ECF | +| **168** | $22D0 | $22F7 | **169** | $26D0 | $26F7 | **170** | $2AD0 | $2AF7 | **171** | $2ED0 | $2EF7 | **172** | $32D0 | $32F7 | **173** | $36D0 | $36F7 | **174** | $3AD0 | $3AF7 | **175** | $3ED0 | $3EF7 | +| **wasted** | $22F8 | $22FF | **wasted** | $26F8 | $26FF | **wasted** | $2AF8 | $2AFF | **wasted** | $2EF8 | $2EFF | **wasted** | $32F8 | $32FF | **wasted** | $36F8 | $36FF | **wasted** | $3AF8 | $3AFF | **wasted** | $3EF8 | $3EFF | +| **48** | $2300 | $2327 | **49** | $2700 | $2727 | **50** | $2B00 | $2B27 | **51** | $2F00 | $2F27 | **52** | $3300 | $3327 | **53** | $3700 | $3727 | **54** | $3B00 | $3B27 | **55** | $3F00 | $3F27 | +| **112** | $2328 | $234F | **113** | $2728 | $274F | **114** | $2B28 | $2B4F | **115** | $2F28 | $2F4F | **116** | $3328 | $334F | **117** | $3728 | $374F | **118** | $3B28 | $3B4F | **119** | $3F28 | $3F4F | +| **176** | $2350 | $2377 | **177** | $2750 | $2777 | **178** | $2B50 | $2B77 | **179** | $2F50 | $2F77 | **180** | $3350 | $3377 | **181** | $3750 | $3777 | **182** | $3B50 | $3B77 | **183** | $3F50 | $3F77 | +| **wasted** | $2378 | $237F | **wasted** | $2778 | $277F | **wasted** | $2B78 | $2B7F | **wasted** | $2F78 | $2F7F | **wasted** | $3378 | $337F | **wasted** | $3778 | $377F | **wasted** | $3B78 | $3B7F | **wasted** | $3F78 | $3F7F | +| **56** | $2380 | $23A7 | **57** | $2780 | $27A7 | **58** | $2B80 | $2BA7 | **59** | $2F80 | $2FA7 | **60** | $3380 | $33A7 | **61** | $3780 | $37A7 | **62** | $3B80 | $3BA7 | **63** | $3F80 | $3FA7 | +| **120** | $23A8 | $23CF | **121** | $27A8 | $27CF | **122** | $2BA8 | $2BCF | **123** | $2FA8 | $2FCF | **124** | $33A8 | $33CF | **125** | $37A8 | $37CF | **126** | $3BA8 | $3BCF | **127** | $3FA8 | $3FCF | +| **184** | $23D0 | $23F7 | **185** | $27D0 | $27F7 | **186** | $2BD0 | $2BF7 | **187** | $2FD0 | $2FF7 | **188** | $33D0 | $33F7 | **189** | $37D0 | $37F7 | **190** | $3BD0 | $3BF7 | **191** | $3FD0 | $3FF7 | + +This structure might seem confusing and it's true that most of the time programmers will use lookup tables to find the starting address of a line instead of using the above formula. + +Nonetheless, even such an interlaced structure could be used without resorting to lookup tables, depending on the use case. + +For example, if we're on a line that's a multiple of 8 (that's the first 3 columns in the table above), all we have to do to find the address of the 8 next lines is to add 1 to the most significant byte (MSB) of the address. + +For instance, if we draw bitmaps starting from a line that is a multiple of 8, like it might be the case when displaying tiles in a game, we only need the address of the first line, while the address of the other lines have the same LSB but an MSB that is incremented by one each time. + +Another example is when you write a fast routine to clear the hires screen. You'll want to skip the hires holes for two reasons: +1. It's 512 bytes that don't need to be cleared and that will waste cycles +2. You may want to use these 512 bytes to store data and so you don't want to erase it + +The position of the screen holes is also very regular. First they are all within the third section of the screen. Then their address range is either `$xx78-$xx7F` or `$xxF8-$xxFF`. + +We make use of this information by looping down from `#$F7` (thus skipping the second kind of hole area) to `#$00` but skipping to `#$77` once we reach `#$7F`.