sborodavkin
sborodavkin
How I Have Grown a Hobby
19 posts
Don't wanna be here? Send us removal request.
sborodavkin · 7 years ago
Photo
Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media Tumblr media
I Am Computer by Docubyte
‘I am computer’ celebrates the visual character of desktop computing machines from a colourless period in industrial design.
From word processors and video terminals, to the very first desktop personal computers, these compact machines heralded a beige age, a period of microcomputing from the the 1970s and early 80s when design standards had conformed to realise a palette of neutral coloured machines throughout offices and later the home.
4K notes · View notes
sborodavkin · 7 years ago
Photo
Tumblr media
‘on_my_way’
78K notes · View notes
sborodavkin · 7 years ago
Link
0 notes
sborodavkin · 7 years ago
Text
Digger Architecture part 2
Music and sound effects. I was lucky to work with Uctumi who created charming music and all SFX. As I have explained in my “Playing the memory tetris” post, Digger has 2 SID files that Uctumi created with GoatTracker. They contain the following subtunes:
SID1 located at $C000: MUSIC_POPCORN (main theme), MUSIC_DEATH (funeral march) and MUSIC_SUCCESS (level completed)
SID2 located at $A200: MUSIC_BONUS (bonus mode theme), MUSIC_INTRO, MUSIC_ENDING.
Now, music playback is the only Assembler routine in the game. It’s implemented with the global sid_index variable and the play_popcorn() function. To start playing e.g. MUSIC_SUCCESS, I am calling sid_index = 2; play_popcorn(). The function sets the subtune index and points the raster interrupt (happening at line 40) vector at int_music or int2_music function, depending on sid_index. These interrupt handlers simply jump to SID playing routing from SID1 or SID2.
For SFX playback, each subtune has also GoatTracker’s SFX player built in. There are functions play_sfx_eat(), play_sfx_gold_broken() etc. that point AX to SFX binary data and jump to SFX playing routine of SID1 or SID2, depending on which music is currently playing, for example:
.proc _play_sfx_eat_gold lda _sid_index ; Check which SID is active. cmp #03 bmi sfxeatgoldbank_1 lda #<(_sfx_eat_gold_data) ; Load SFX address. ldy #>(_sfx_eat_gold_data) ldx #14 ; Always use voice 3. bmi sfxeatgoldbank_1 jsr sid2_play+3 rts sfxeatgoldbank_1: lda #<(_sfx_eat_gold_data) ldy #>(_sfx_eat_gold_data) ldx #14 jsr sid_play+3 rts .endproc _sfx_gold_fall_data: .byte $00, $F8, $00, $D2, ...
Worth mentioning that our music uses 3 voices, and when SFX is playing, the 3rd voice is interrupted. However the music composed in such way that it’s barely noticeable.
0 notes
sborodavkin · 7 years ago
Text
Digger Architecture part 1
Let me actually explain how Digger is built and the rationale for some decisions.
Digger is written in C with cc65 for an obvious reason: I don't know the 6502 assembly well enough, and will hardly manage to learn it better anytime soon. Plain assembler is used only for music & sound effects playback because they are controlled by a raster IRQ which can hardly be implemented in C.
Levels data. There are 14 2D 15x10 arrays filled with map elements (MAP_EMPTY, MAP_EMERALD, MAP_GOLD etc.) They are stored in a binary file sized 2100 bytes that is loaded into $B300 by the linker. These layouts 0-13 are repeated throughout levels 0-253 as follows: 0-1-2-...-12, then 7-8-9-...-12, then 3-4-...-12, 3-...-12, etc. until 253. The level 254 (displayed as 255) is special because its layout #13 arranges emeralds in the “HOKUTO” word (game is released by the HOKUTO FORCE group):
Tumblr media
Main game loop. In pseudocode it’s fairly self explanatory:
while(1) { update_digger_sprite(); process_bonus_mode(); c = input(); process_input(c); update_bullet(); update_monsters(); update_gold(); spawn_monster_if_needed(); adjust_game_speed(); }
The possible values for input are KEY_(UP|DOWN|LEFT|RIGHT|PAUSE|SHOOT|SKIP_LEVEL). The most interesting part is adjust_game_speed() - problem is, depending on the complexity of the current screen (number of monsters alive, gold bags on screen, whether a gold bag(s) is/are falling, if a bullet is fired) the update_()* functions require varying number of CPU beats. To keep FPS and movement speed constant there is a global variable step which is increased when a complexity of scene goes up (e.g. a new monster is spawned) and decreased when it goes down (e.g. when a monster is killed). All objects including Digger move by multiples of step pixels at a time and so the game speed is maintained nearly, though not exactly constant. 
0 notes
sborodavkin · 7 years ago
Link
0 notes
sborodavkin · 7 years ago
Photo
Aaaand here we go! The game I worked on last 2 months got released today! 😄
Tumblr media Tumblr media Tumblr media
(via Digger - IBM PC classic remade for the C64 and it’s GOOD! )
7 notes · View notes
sborodavkin · 7 years ago
Text
Coordinate system of Digger as its major fault
From my previous post you know already that I have thought of characters forming the maze “grid”, and sprites that can move freely in it. C64 can display 8 sprites at a time (if you need more you need to implement something called “sprite multiplexing” yourself). There are 16 registers (0xD000 - 0xD00F) to store X and Y coords of each sprite, and 1 extra register 0xD010 whose bit i is 1 if sprite i’s X coord > 255. So to move sprites around and at the same time to know in which maze tile they are I invented the following coordinate system:
Tumblr media
Each object has X and Y coordinates that correspond to X and Y indices of a tile where it’s located, and also X_OFFSET and Y_OFFSET that store offset from a tile top left corner, in pixels, measured between -15 and 15.
When Digger moves right, its X_OFFSET increases. When it becomes 16, its X increments and X_OFFSET becomes 0. Correspondingly when Digger moves left, its X_OFFSET decreases. When it becomes -16, its X decrements and X_OFFSET becomes 0.
This turned out to become a fundamental design mistake. Problem is, such coordinate system allows storing the same “physical” position of sprite (in screen pixels) in multiple possible ways. Assume on the picture above that X_OFFSET = 9, Y_OFFSET = 2. Then all following positions are valid and represent the same position of Digger on screen:
X=1, Y=1, X_OFFSET=9, Y_OFFSET=2
X=2, Y=1, X_OFFSET=-7, Y_OFFSET=2
X=1, Y=2, X_OFFSET=9, Y_OFFSET=-14
So when I need to check for collisions (e.g. whether a falling gold bag has hit the Digger) I have to check all possible combinations of logical coordinates instead of simply checking the physical pixel coordinates!
Instead I could for example just store Digger’s X and Y, and use smth like X>>4 to determine a horizontal tile index. I have even tried to implement this but realized it’s too late - the project has been close enough to release. But surprisingly enough, the changes I started to make didn’t look any simpler or faster - just the accuracy of collision detection would have benefited from this change, so not a big deal after all :)
0 notes
sborodavkin · 7 years ago
Text
Digger graphics: the charset
Let’s have a deeper look at Digger’s charset. A short explanation: Digger is a Multicolor Character mode game like Boulder Dash, so the entire setting is composed from 8x8 characters that form 2x2 tiles. We need 4 characters to draw a gold bag (2 in a row arranged in 2 rows), 4 characters to draw an emerald and so on. This is the complete set of characters that I have drawn:
Tumblr media
(Of course a character can only reside within the 40x25 grid, so in order to have smooth movements of Digger, monsters, bullet etc. - unlike Boulder Dash :) - we also need sprites which I’ll talk about some other time).
Here is the same charset with some bits of explanation:
Tumblr media
The fun fact about this charset is that I was going to release the game as it is before we announced the internal testing in HF. A few folks out there pointed out that in original Digger a gold bag “wobbles” for a few seconds before it falls down. In my implementation however it was steady, and then fell. To add that wobbling, I needed:
1 extra Gold tile (tilted a bit off from the “intact” one)
x 4 characters
x 8 bytes per character
x 6 level art packs,
plus 1 extra Gold tile x 4 chars for “gold on blank” (when gold falls down 1 square it doesn’t break but is no longer displayed on a “maze” background - rather on black background), which resulted in 192 + 32 = 224 extra bytes:
Tumblr media
But my charset was already 2048 bytes - 100% full. To overcome this, I am unloading a part of 2x2 alphabet that is not needed for the gameplay when the game starts, and loading it again when it ends (obviously I need an extra 224 bytes buffer to store the alphabet during the game, so that you don’t see gold bags instead of letters once the game ends :))
0 notes
sborodavkin · 7 years ago
Text
Pirates, or Why I Moved from Github
I kept Digger source code on GitHub from the beginning. It was convenient to work on it when I had time from my both home computers or remotely.
On Feb-26 I recorded this video run of my early Digger work-in-progress code and put it on my YouTube channel that had almost zero traffic:
youtube
A few days after I decided to google for “c64 digger” to check if this video has been indexed already. How surprised I was when I found this: http://www.indieretronews.com/2018/02/digger-preview-very-early-port-preview.html, and this: http://idpixel.ru/news/772-digger-skoro-vyjdet-na-commodore-64/ (in Russian, with a link to my GitHub repo), and so on.
So what’s happened was one of C64 “demoscene” groups took my repository, compiled the sources from it, added their intro and released under their logo (but kept my copyright for code, big thanks for that!) I became famous :D Seriously - they have been watching either my repo, or YouTube channel, or even both.
I put the “MIT License” note on the repo and into each source file but it didn’t help. As I continued with development, 2 other groups built their “releases” called “digger preview”. By that time Digger could already die from gold bags falling on him or from a monster, so they even bothered adding trainers :) My game, even not released yet, was already pirated 3 times and cracked!
So I got fame. At the same time I didn’t want that an unfinished game is spread any further. People would get annoyed about the bugs, lack of features and rusty gameplay. As GitHub doesn’t offer any private repos for free, I had to delete Digger source code from it. I still plan to open source the game, but after it’s released to the public.
0 notes
sborodavkin · 7 years ago
Text
Playing the Memory Tetris: why is Digger memory map so weird
My problem was to arrange all data I needed for the game into the available memory. C64 has 64K of RAM but what’s available to an app is in fact less. 
In my setup, as I was using VIC bank 2 since the times I couldn’t link Digger without sprites being overwritten by code, I had 36K RAM: 2000-8000 for code and A000-D000 for everything else. My initial hi-memory map was as follows:
Tumblr media
With SFX files taking ~100 bytes, which I placed after A5C0, I was good and still had some bytes left.
But then our composer came with more tracks: when Digger eats a bonus, an intro to Rossini’s Wilhelm Teil should play instead of Popcorn. Also Intro and Ending screens got their music too. With these 3 extra tracks the SID file became 5.2 KB and couldn’t fit between C000 and D000 anymore. Expanding to B000-C000 wasn’t an option because this segment was a mystery: I couldn’t read from it what linker placed there apparently because of some sort of ROM mirroring it.
But I haven’t had time to solve the mystery. Instead I asked the composer to split the SID file into 2 parts. Its size ballooned because of that but now the size of each file was smaller and I could readjust the memory as follows:
Tumblr media
It was almost perfect but 14+8=22, and I needed to store 23 sprites. I was lacking 64 bytes for 1 sprite! I was so desperate. But then I tried to expand the sprites segment AC80-B000 to B040 and it worked! I finally understood why B000-C000 wasn’t available for me: I did a mistake in my memory configuration file for linker and didn’t expand the HIRAM segment from 8800 to C000 where my SIDRAM started. If I did so from the beginning, it would work.
So, because of this error in memory config, Digger has sprites split into 2 segments or “banks” how I call them, and music also split into 2 banks. Not a big deal, but introduces a minor additional complexity at the code layer.
0 notes
sborodavkin · 7 years ago
Text
How not to Manage Memory
As I was creating more GFX for Digger, I also needed more memory to store it. I had absolutely no idea how to do it, or how others do it. My attempts to define a linker memory configuration failed so I have chosen the most simple approach I could think of:
I created the charset.c module with a looong array containing bytes for chars forming game tiles
also I created the sprites.c module with another array containing sprite bytes
in the beginning of game’s main() function I was memcpy’ing both arrays where they actually had to reside: charset array to 0x8800 and sprites array - to 0xA000.
Then I hardcoded the sprite offsets for each sprite based on the assumption that sprites always exist in 0xA000, and configured game startup routine to switch to VIC bank 2 which would expect charset to be at 0x8800.
All that looked good to me and worked pretty well until I had only 1 monster in game. When I added 2 more monsters, or even 1 more monster, the game started crashing. The disassembler told that it tried to execute some random sequence of bytes which put the CPU into jammed state. By looking closer I found out that these bytes were actually part of my charset! Why would it try to interpret the charset data as if it was code?
The answer was simple: linker linked the PRG so that there was a code segment covering memory segment at 0x8800. When the program started, I manually wrote there my charset but the labels offset table wasn’t aware of that and all surrounding code that was still alive and not overwritten still expected there to be code, not the charset! And as I wrote wrong bytes there, everything crashed. I spent several days on disassembling everything, looking into VICE monitor, trying to understand what’s happening and fixing the memory config for the linker.
Tumblr media
I have found a photo which I made one coding night to look into it next morning. Not sure if it depicts a fully correct config or not, but the important thing is there: I had to define my MEMORY areas, mark them as “fill=yes” so that linker knows that the entire space from start till start+size has to be reserved, and then map one or more SEGMENTS to it. With this approach I was able to load my sprites and charset directly into the needed addresses, delete the memcpy code and the modules that hardcoded them as arrays.
0 notes
sborodavkin · 7 years ago
Text
Some Digger GFX
Fancy exploring some GFX I created for Digger? Here are all Digger sprites:
Tumblr media
As Digger is being animated all time, we need 2 sprites for each position to switch between them.
Fun fact 1: with Digger, I took the approach not to proceed with coding until I’m done with GFX and like it. In my previous Why Digger post there’s a photo of an early prototype, but the level 1 maze tiles and Digger sprite are the same as you would find in the released version! Despite the C64 multicolor character graphics mode limitations I love the result. Compared to the original PC game that had 16x16 sprites I had for example only 8 pixel per sprite width!
Here are the monsters (called Nobbin and Hobbin) and bullet:
Tumblr media
Fun fact 2: as you can see, I have created the “Hobbin looking right” sprite but you won’t see it in the game. There is just a boolean flag that distinguishes between a Nobbin and a Hobbin, so having 2 sprites for each makes monster display a lot easier.
Tiles for level 2 (there’s similar set of tiles for each of 6 possible level decorations):
Tumblr media
2x2 alphabet that I have redrawn, pixel by pixel, from the screenshots of the original Digger:
Tumblr media
SpritePad and CharPad are two amazing pieces of software that are used by any C64 game developer to create game graphics.
0 notes
sborodavkin · 7 years ago
Text
What I have learnt from creating a C64 Web server
Tumblr media
That first app I created for C64 hasn't been a state of the art tbh. It was a generic C app, written without taking almost anything C64 specific into consideration. Anyway, this is what I have learnt from it, in no particular order.
It’s a bad idea to code for C64 on C64. Lack of copy & paste & save & other stuff.
Furthermore it’s a bad idea to code in Basic. What is supposed to work doesn’t work, and there are weird limitations everywhere. Two letters max for a variable name isn’t that much, tbh.
I have learnt about wonderful CC65 development platform containing a C-crosscompiler, macroassembler, linker and some other useful tools.
Strings are tough to handle correctly on C64 from C :D As it can be seen from the screenshot above (showing Python script running an HTTP proxy on Raspberry Pi and Vice running Web server on C64), the char case is inverted (”aCCEPT-lANGUAGE”)
New line chars are also hard to deal with. For example, \r is one char (#13) but \n is #13 #10 (two chars), which might have also been dependent on a platform where CC65 was running.
Rebuilding gzip with CC65 and running it on C64 was a bad idea because slow :)
Otherwise I have learnt how to interact with RS232 interface. Trying to separate my Web server into modules failed because I had no idea how to link them, but I decided not to bother with it as long as I have made my C64 to do what it hasn’t been meant to do - to serve the web pages!
0 notes
sborodavkin · 7 years ago
Text
Why Digger
Tumblr media
I have never considered 100% done with my raycaster project. It still runs at less than 1 FPS making itself usable only in Warp mode on Vice. Also it was again much more a generic C application you would write for any other platform, than a C64 program.
But I still wanted to do something fun.
Taking a PC-only game and cloning it on C64 - an old game which C64 could handle - seemed like an obvious choice. Not sure why I have chosen 1983′s Digger by Windmill Software tbh. Anyway, by that time I have already known about Charpad (to make tiles) and Spritepad (to make sprites) so I have quickly drawn some tile art and drafted a program that displayed a 2D array of tiles.
Then I drew 2 Digger sprites looking right and added an animation loop to switch between them:
Tumblr media
I ended up with 8 Digger sprites (2 x each direction) and a simple keyboard polling routine detecting keypresses via $00C5 (197). That's how Digger started moving and probably the moment I embraced I could make it.
0 notes
sborodavkin · 7 years ago
Photo
Tumblr media Tumblr media
I had hard times choosing a good C64-VGA video convertor. The black and white with stripes is so called “Porta”, and the one showing Elite is that I’m using now (”StarTech”). It gives stable and sharp picture and also sound output, highly recommend (not an advertisement! :))
0 notes
sborodavkin · 7 years ago
Photo
Tumblr media
GGLabs’ GLINKUSB-LT extension card to connect C64 to anything via mini-USB.
0 notes