Link6415 Posted October 13, 2015 Author Share Posted October 13, 2015 I thought bitmap scrolling would be easier. My idea was to write a program to plot the tiles on the screen (getting data from the charset) then write an algorithm to shift them manually. They would all be black and white so I wouldn't have to worry about color memory. Quote Link to comment Share on other sites More sharing options...
TMR Posted October 13, 2015 Share Posted October 13, 2015 I thought bitmap scrolling would be easier. My idea was to write a program to plot the tiles on the screen (getting data from the charset) then write an algorithm to shift them manually. They would all be black and white so I wouldn't have to worry about color memory. Nope, scrolling a bitmap is, unless you go for demo-style code which isn't guaranteed to work PAL/NTSC or at all on some machines, harder on both C64 and programmer than moving characters. 1,000 bytes of screen RAM versus 8,000 of bitmapped screen. Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 13, 2015 Share Posted October 13, 2015 Would you need it to scroll one pixel at a time as the player moves along, and are you talking about vertical scroll up/down as well as horizontal scroll left/right? Besides being less data to move, another benefit with character mode is that it is easier to peek the screen and find out which character = which graphic object you've touched once you implement some form of sprite to background collission. If you work with hires, and monochrome hires as well, you would either need a logical map elsewhere in memory or compare a lot of pixels to find out what you found or hit. This is by the way one of the weaknesses with the ZX Speccy, if we allow ourselves one short intermission. It always operates in bitmapped mode and plots its characters. There is a BASIC command to determine which character is on a certain position, and that command works by comparing bitmap data on the screen with the ROM font, meaning it can't detect user definable graphics (UDG). I believe though that you can redirect the entire character generator instead of using just a few UDG's, forcing you to spend RAM on a complete font and then the BASIC command will work towards that memory space. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 13, 2015 Author Share Posted October 13, 2015 (edited) Yes yes. I know about char mode's benefits. But I didn't realize smooth char scrolling was so simple. Edited October 13, 2015 by Link6415 Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 14, 2015 Share Posted October 14, 2015 Fair enough. Now you know the hardware scrolls one pixel at a time in either direction, no matter if you're in character or bitmap mode, and the hard work is to handle the case when data needs to be shifted to create a flow, so the same data doesn't get reset to its original position and scrolled again. If you want to add colours to your game, here are a few variations of character mode you might want to consider: Multicolour graphics: POKE 53270,24 : POKE 53282,AUX1 : POKE 53283,AUX2 It makes foreground colours 0-7 work like normal 8x8 cells, while 8-15 enables 4x8 cells that can have two screen wide auxillary colours (0-15) as well as the foreground (value - 8 = 0-7) and background (0-15). It can be useful for e.g. walls where you want two colours of which one is different from the general background colour. Extended colour mode: POKE 53265,27 + 64 : POKE 53282,BG2 : POKE 53283,BG3 : POKE 53284,BG4 It restricts the font to 64 characters (compared to the regular 256) and uses three additional background colours (0-15). Foreground can be any of the 16 and all cells have the 8x8 resolution. For some displays this mode might be useful. You can experiment with this by trying shifted, reversed and reverse shifted characters. Both those modes would be possible to combine with the scrolling bits, but for obvious (?) reasons you can't combine multicolour with extended colour, it makes the display go black. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 14, 2015 Author Share Posted October 14, 2015 (edited) Would you need it to scroll one pixel at a time as the player moves along... *sigh* Yes. I just tested the code you gave me. The whole point of bitmap mode was to get a smooth scroll. Now that I see that we had a misunderstanding, I know why you were confused about why I would want to use bitmap mode in the first place. I know how to move a character based map around. I was trying to do a smooth scroll. I knew there was a way to do it with characters, but I thought it would be more difficult. That was why I wanted to use bitmap mode. Okay, now that we're on the same page, what is more easy, smooth scrolling a bitmap, or smooth character scrolling (as in scrolling each individual pixel.) (sorry if I sound a little rude, I don't mean to be) Edited October 14, 2015 by Link6415 Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 14, 2015 Share Posted October 14, 2015 (edited) No worries, we're here to exchange expertise and I don't think you came out as rude, obnoxious or anything like that. As mentioned, the hardware will scroll your display one pixel at a time no matter which graphics mode you are working with. The hard work comes when you have used up all seven steps of scrolling, and need to shift all the data in the same direction, preferrably at a point of time where the raster beam is outside the visible area so you won't notice any stuttering or flicker. In character mode, you shift at most 1000 bytes - in practise you can probably shave off a little since you probably want 38 columns x 23 rows visible to make room for new graphics to be hidden in the border and appear when you scroll. If you use BASIC, you might be able to PRINT CHR$(29);CHR$(20) on each row and get any colour attributes at the same time, but a short dedicated ML routine might be faster. A custom ML routine would also support double buffered character matrix, so you can copy data from screen #1 to screen #2 at the same time you scroll screen #1, and then switch to screen #2 once the copy is done. In bitmap mode, you shift at most 8000 bytes. You can shave a little here as well, under the same circumstances as above. If you would work with colour attributes on the bitmapped screen, add the same ~1000 bytes to shift those as well. That is not counting the effort to plot new data onto the bitmap as you need. If you were drawing e.g. a sinus curve that would scroll along the screen, I can understand why one would want to use a bitmap instead of using a smart routine to allocate custom characters for each part of the curve. So with everything sorted out, I would summarize it: Character mode + Eight times less data to move + Easier to check which symbol is a certain position - Limited to 256 different character patterns unless you would get into raster line timed changes of character generator - You can only position elements in "whole" character positions, or define multiple characters representing a combination of objects Bitmap mode + You can plot dots, lines, arcs, characters, symbols etc as you find required + With the right routine, you can plot them anywhere on screen, even across two logical character positions - More work to plot each symbol - Eight times more data to move when you scroll - Could be difficult to check which graphic is at a certain position, if required Good luck, and don't hesitate if you have additional questions or perhaps need a small ML helper routine (unless you write those yourself). Edited October 14, 2015 by carlsson Quote Link to comment Share on other sites More sharing options...
TMR Posted October 14, 2015 Share Posted October 14, 2015 Okay, now that we're on the same page, what is more easy, smooth scrolling a bitmap, or smooth character scrolling (as in scrolling each individual pixel.) They both use the same principles (the hardware fine scrolling applies to either mode) but the bitmap is dealing with nine or ten times the data and you won't be moving that smoothly without some fairly optimised assembly language code and two bitmaps to double buffer it; characters are always going to be easier and more memory efficient every time, although it still needs either assembly language or a good compiler to move smoothly. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 15, 2015 Author Share Posted October 15, 2015 Hmm. How does smooth char scrolling work, just out of curiosity? Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 15, 2015 Share Posted October 15, 2015 (edited) The hardware has the ability to shift the visible portion of the screen by a range of 0-7 pixels horizontally and 0-7 pixels vertically. The actual screen area remains in the same position, just the content that is shifted. Thus it really is smooth screen scrolling, not particularly char scrolling. If you only want a smaller part of the screen scrolling, you would need to get into machine code and set up the raster interrupt to trigger at a certain line, scroll/shift that area and at a later line, reset the register to the non-scrolling value. It will be a trick on your eyes that you see only part of the display scrolling. (Sprites are not affected by scrolling, so they always remain in the same position) You can do it the hard way too, by setting up either a block of custom graphics or go back to the bitmap mode, and then manually rotate byte by byte. It will be much slower, much more work but on computers that lack hardware support for scrolling (e.g. VIC-20 but many other) it is the way to do it if you want it to be somewhat smooth. I would doubt you want to explore this on the C64, as it has so much more convenient ways to do it. Edited October 15, 2015 by carlsson Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 16, 2015 Author Share Posted October 16, 2015 *Sigh* Smooth scrolling is so simple! I wasted a lot of time with the bitmap thing. Been playing around with the scrolling registers lately. So, from what I can tell, I just make a copy of the screen shifted in a certain direction, scroll in that direction, the replace the current screen with the copy. Okay, I think I get it now. Where in memory should the 1000 byte copy go? (Is there a best place?) And I must consider that the charset is at $C800. Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 16, 2015 Share Posted October 16, 2015 I would suggest that you keep your main screen matrix at $C000, your alternative screen matrix at $C400 and your character set at $C800 (2K = 256 characters). All that memory is readable and writable. If you involve colours too, you probably want a buffer of the colour matrix somewhere, but since you can't change the location of the colour matrix, you would have to copy chunks of already shifted data from buffer to actual matrix. For now I fully understand if you're working with monochrome graphics and don't have to worry about this. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 16, 2015 Author Share Posted October 16, 2015 Actually, I was only using monochrome graphics because of bitmap mode, not anymore. Where's a good place for the color copy? Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 16, 2015 Share Posted October 16, 2015 Are you going to modify the character set as the game plays, or will you define/load it once and then use the symbols? If you have no need to modify it as the game goes on, you probably can knock up the character set to $E000 which is writable but not as easily readable, i.e. the same location where you initially planned to put your bitmap. It would free all four kilobytes at $C000 - $CFFF for two copies of the screen matrix (which can be switched between with a single POKE), one buffer copy of the colour matrix (which would need to copied to 55296 anyway) and still have 1K free for e.g. short helper routines in ML. Your room for BASIC is uncompromised in this layout. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 16, 2015 Author Share Posted October 16, 2015 I'm only loading the chars once. Since I no longer need to read the data values (since I'm not using bitmap mode) $E000 sounds like a good place for the chars. Okay. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 17, 2015 Author Share Posted October 17, 2015 Hmm. This code should smooth scroll the screen, but something is off... I can't attach a snapshot, so you may need to type it in Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 17, 2015 Share Posted October 17, 2015 (edited) You should treat each row on its own when you shift data, unless you really want characters at the extreme end on one row to appear on the other. Also you can only scroll in 8 steps, so the loop to reflect 53270 shouldn't run for 16 steps. I made a completely different program, that will scroll 24 lines of text. It is far beyond dog slow, much because each line is copied on its own and is double buffered. A bit of machine code would do wonders here. I'm not sure you can move 1000 characters of text within one raster frame, so you might find you want double buffering unless you want it to be jerky. Oh well, I wrote a lot of text below the code segment to explain how it works, but the forum software ate all of it so I can't be bothered typing it in again. 10 poke56333,127:poke1,51:fori=0to511 12 poke57344+i,peek(53248+i):next:poke1,55:poke56333,129 14 poke56576,196:poke53272,9:poke648,192:poke53270,199:rem printchr$(147) 16 sp=0:rem here comes the scroll 18 poke53270,199-sp:s1=49152:s2=50176 20 ifpeek(53272)>9thent=s2:s2=s1:s1=t 22 fori=0to2:forx=0to38:pokes2+sp*120+i*40+x,peek(s1+sp*120+i*40+x+1) 24 nextx:pokes2+sp*120+i*40+39,int(rnd(1)*63):nexti 26 sp=sp+1:ifsp<8then18 28 rem here comes the switch 30 poke53272,1+(40-peek(53272)and24) 34 goto16 Edited October 17, 2015 by carlsson Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 17, 2015 Author Share Posted October 17, 2015 Okay thanks. I was messing with double buffering earlier, but decided to try some other stuff first. Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 17, 2015 Share Posted October 17, 2015 Variant of the same program: 10 poke56333,127:poke1,51:fori=0to511 12 poke57344+i,peek(53248+i):next:poke1,55:poke56333,129 14 poke56576,196:poke53272,9:poke648,192:poke53270,199:rem printchr$(147) 16 sp=0:rem here comes the scroll 18 poke53270,199-sp:s1=49152:s2=50176 20 ifpeek(53272)>9thent=s2:s2=s1:s1=t 21 poke51201,s1/256:poke51205,s2/256 22 fori=0to2:poke767,sp*3+i:sys51200:pokes2+sp*120+i*40+39,int(rnd(1)*63):next 26 sp=sp+1:ifsp<8then18 28 rem here comes the switch 30 poke53272,1+(40-peek(53272)and24) 34 goto16Notice this one comes with a custom machine code routine, that I put at $C800 = 51200. .C:c800 A9 C0 LDA #$C0 .C:c802 85 FC STA $FC .C:c804 A9 C4 LDA #$C4 .C:c806 85 FE STA $FE .C:c808 AD FF 02 LDA $02FF .C:c80b 0A ASL A .C:c80c 0A ASL A .C:c80d 0A ASL A .C:c80e 8D FE 02 STA $02FE .C:c811 0A ASL A .C:c812 90 08 BCC $C81C .C:c814 E6 FC INC $FC .C:c816 E6 FE INC $FE .C:c818 E6 FC INC $FC .C:c81a E6 FE INC $FE .C:c81c 0A ASL A .C:c81d 90 04 BCC $C823 .C:c81f E6 FC INC $FC .C:c821 E6 FE INC $FE .C:c823 18 CLC .C:c824 6D FE 02 ADC $02FE .C:c827 90 04 BCC $C82D .C:c829 E6 FC INC $FC .C:c82b E6 FE INC $FE .C:c82d 85 FB STA $FB .C:c82f 85 FD STA $FD .C:c831 E6 FB INC $FB .C:c833 A0 00 LDY #$00 .C:c835 B1 FB LDA ($FB),Y .C:c837 91 FD STA ($FD),Y .C:c839 C8 INY .C:c83a C0 27 CPY #$27 .C:c83c D0 F7 BNE $C835 .C:c83e 60 RTSThis routine will, just like the BASIC program previously, copy one row at a time. The speedup is noticable, but to avoid the flickering you really would need to wait for the raster line before swapping 53272 back and forth. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted October 18, 2015 Author Share Posted October 18, 2015 Hey, where should I put the maps for the dungeon? (This is a roguelike) I will have each 64x64 level loaded from the disk, but I need a place for them to go. 64*64=4096 bytes Quote Link to comment Share on other sites More sharing options...
carlsson Posted October 18, 2015 Share Posted October 18, 2015 POKE 56,144:CLR will lower BASIC RAMTOP by 4K, which means you safely can load the level to $9000 without getting it overwritten by BASIC variables. You need to issue the POKE at the beginning of the program. It would reduce your BASIC program from 38 to 34K. In theory, since you're moving the VIC-II into another bank, you have 1K between 1024-2047 unused, but in case of RUN/STOP + RESTORE, you probably want to keep that kilobyte available so you don't accidentally overwrite the start of your program. While running though, you could use it for temporary data storage of the POKE kind. Quote Link to comment Share on other sites More sharing options...
Link6415 Posted November 3, 2015 Author Share Posted November 3, 2015 What do you think? Quote Link to comment Share on other sites More sharing options...
carlsson Posted November 3, 2015 Share Posted November 3, 2015 By tile, does it mean all the graphics will be based on 3x3 tiles with one character of border around every edge, or is that a wall that can flow either way, a bit like how rooms in Nethack are drawn? Quote Link to comment Share on other sites More sharing options...
Link6415 Posted November 3, 2015 Author Share Posted November 3, 2015 Wall. They are 1*1 tiles. Quote Link to comment Share on other sites More sharing options...
carlsson Posted November 3, 2015 Share Posted November 3, 2015 Yes, but you drew them like a border around a 3x3 area, thus my question. Good luck! 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.