GDR Forum Index
Podcast Podcast
Dev Dev Logs
Search Search
RSS RSS
Register Register
Log in Log in
Reply to topic GDR Forum Index -> Game Developer's Refuge -> The Commodore 64 (6502 and Friends) Page Previous  1, 2, 3, 4  Next
View previous topic :: View next topic  
Author Message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Fri Nov 28, 2014 8:55 pm    Post subject: Reply with quote

This is kinda cool. Somebody labelled the memory map of various SNES games. In some cases it's just where the music is. In others, it's audio, game assets, enemy definitions (strength), etc. Pretty cool.

Master list: http://wiki.superfamicom.org/snes/list

http://wiki.superfamicom.org/snes/show/Final+Fantasy+-+Mystic+Quest
http://wiki.superfamicom.org/snes/show/Final+Fantasy+5
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sat Nov 29, 2014 12:59 am    Post subject: Reply with quote



Interrupt is working. Painful to have to queue all this stuff from Assembly, but hey.

It's still not 100% as I'm having troubles detecting beyond raster line 255. I should be reading the extra bit, but it's not quite acting as expected yet. Ah well.

Reference: http://www.c64-wiki.com/index.php/Raster_interrupt


Code:
cl65 -t c64 -g -Ln main.lbl -O -o main.prg main.c irq.s
x64 -moncommands main.lbl main.prg


Updated compile commands to generate debug info. -g generates extra symbols (all symbols). -Ln generates a labels file for Vice. -moncommands feeds the label file to Vice. Then you have to start "the monitor" to do debugging by clicking "Activate Monitor" on the File menu. Then you can do "m .MySymbol" to dump memory, and some other things.

Still haven't figured out if there's a nice way to place breakpoints inside code. There is a command accepted by the label files to represent a breakpoint, I just don't know how to automatically emit them.

References:
http://codebase64.org/doku.php?id=base:using_the_vice_monitor
http://www.cs.cmu.edu/~dsladic/vice/doc/html/vice_9.html
http://www.cc65.org/doc/debugging.html

And some more:
http://www.6502.org/tutorials/compare_beyond.html - Was helpful for figuring out the greater/less than flag error I was having.

* * *

Anyways, I think I'm happy with this test. I can see the effect of Bad Lines, and I can see my refreshes getting out-of-sync. I would like to fix the bottom glitch and improve the sync, but I'm certainly understanding the C64 better.

Now I'd like to know how difficult it is to play back SID audio. I'm guessing its a matter of exporting SID data and calling the output as a function every frame but *shrug*.

EDIT: Yep. Sounds like PSID's are exactly that. File Header with an offset to the Init and Play Functions.

http://cpansearch.perl.org/src/LALA/Audio-SID-3.11/SID_file_format.txt

EDIT2: Newer version of spec:

http://www.hvsc.c64.org/download/C64Music/DOCUMENTS/SID_file_format.txt
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar


Edited by PoV on Sat Nov 29, 2014 2:04 am; edited 2 times
View user's profile Send private message
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1666
Location: Your consciousness.
PostPosted: Sat Nov 29, 2014 1:52 am    Post subject: Reply with quote

\o/ Good stuff!

I think emulating SID output is not easy/trivial or straightforward. I read somewhere, the output on the original hardware goes through analog filters. Also, there is probably many different sound/tracker/whatever formats for storing/compiling audio on the C64, making it impossible for there being a single way of playing "SID audio".

On the C64 itself, I think audio playback can be handled as a parallel process automatically after punching the parameters into the respective memory addresses, so it might not even be necessary to call anything each frame after the playback has been initialized, unless the audio data must be streamed from disk or otherwise generated at run-time in a way not already handled by the sound chip itself (would have to look into C64 trackers to research that).

I am torn between so many things and find it difficult to make a decision on where I want to direct my attention (options include but are not limited to: Drawing, Pixelling, Refugee Lib, learning C64 Assembly, giving Allegro 5 another go (possibly resurrecting the Spacegame project and/or porting all my stuff to A5), optimizing my Arch Linux system and setting up a fresh/clean development environment in there (learning/evaluating several IDEs like Geany, LiteIDE, Bluefish, Emacs), getting into music composition (using Rosegarden and/or LMMS)) ... seriously... there is too much interesting stuff to explore in a single lifetime.
_________________
0xDB
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sat Nov 29, 2014 2:15 am    Post subject: Reply with quote

On creating a stable interrupt. http://www.antimon.org/dl/c64/code/stable.txt
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sat Nov 29, 2014 10:22 am    Post subject: Reply with quote

Forgot to mention last night, I did some digging on the SNES's 65816 CPU (i.e. 16bit 6502).

I'm starting to understand why the SNES has such a lack of homebrew: There isn't a good 16bit 6502 family C compiler out there. Everything else is well covered (6502 via CC65, Z80 via SDCC/GBTK, 68000 via GCC).

The SNES options are:

- **NOTE** snesc is a C Library, NOT A COMPILER!
- TCC compiler (modified to use wla_dx assembler), part of the snes-sdk. Folks say it's buggy. https://code.google.com/p/snes-sdk/ http://www.portabledev.com/wiki/doku.php
- WDC C Compiler. Was $40, but I just checked an they have it marked as "out of stock". So much for that. http://65xx.com/Products/WDCTools/ (WDC816CC)
- LCC compiler. No real info on getting this to work. http://www.6502.org/tools/lang/
- AVOCET C, terrible website, and $700. nuff said. http://www.avocetsystems.com/

That said, the 65816 is backwards compatible with the 6502, and actually starts-up in 6502 mode, which means less address space (64k max, i.e. 16bit). I think some of important stuff on the SNES requires access to the full 24bit address space though.

So it sounds like SNES dev is either a fight with a sub-par C compiler, or Assembly.

EDIT: Dead end. a GCC port patch for 6502 (not 65816) that was never merged back in to mainline: http://forum.6502.org/viewtopic.php?t=535

EDIT2: The LCC port is from 1994 (LCC 1.9). LCC has received minor updates since Y2k, but the documentation suggests the code may be too old to upgrade. https://github.com/drh/lcc

EDIT3: Yep. Just did some digging through the LCC's. The old one, dude wrote a custom way to generate operations, a pair of "optX.dag" files that list operations and assembly instructions for implementing them. New one, there are these massive "blah.md" files that list operations, and you re-implement them for your respected architecture. Sadly, LCC has no optimization support what-so-ever.

EDIT4: And just for reference, TCC also doesn't do optimizations. "-Ox is ignored"

Alright. So it seems the only decent C compiler for SNES is the WDC C Complier (WDCTools), which costs $40, but is currently not available for purchase.


EDIT5: Seems it might not be that great after all.
Quote:
This version of the compiler comes with a post-pass-peephole optimizer called WDC816OP. This optimizer operates on the assembly language output of the compiler and performs a number of optimizations that generally save about 10 percent on code size depending on the program. To invoke the optimizer, use the -SP option. If -SP is used in conjunction with -A, the output file will contain the optimized assembly language. Note that the optimizer makes assumptions about the format of the assembly language output of the compiler and will not operate properly on hand-written assembly language programs.

Or all things considered, maybe that's actually good. *shrug*

I guess whatever has the best workflow is the best option. WDC is Windows-Only and $40. LCC is ancient (and I'm not even sure what assembler/linker it uses). TCC, at least, is part of a complete package with WLA_DX.

Bottom line, you're going to want a good Assembler to back you up.


EDIT6:

TCC has had only 3 updates since SNES-SDK. This means merging/upgrading seems more doable. It might also be necessary to support 64bit OSs. http://bellard.org/tcc/changelog.html

http://bellard.org/tcc/

Only 1 new version of the Assembler, but there is now an active GitHub repo for WLA_DX: https://github.com/vhelin/wla-dx

http://www.villehelin.com/wla.html
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Sat Nov 29, 2014 6:46 pm    Post subject: Reply with quote

Great. I leave for a couple of days and you start busting out the retro goodness.

Quote:

C-looking code.

Magic happens


Oh man, WTF did I miss this time? Gotta see what this CC65 thing is.
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sat Nov 29, 2014 8:17 pm    Post subject: Reply with quote

Yeah, that's the dirty little secret. (Almost) everything has a C compiler. :)

Given how weak these 6502 devices are though (C64, NES), you'll probably want a hybrid approach. Some ASM here and there, since the optimizer doesn't necessarily generate best-case code (even though the 6502 really can't do much).

2 of the 4 GameBoy games I worked on we also did hybrid C+ASM, but back then (2001) the compiler has some of the most insane bugs. It looks like SDCC has continued to be worked on since, so I'd expect things to be better today.
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Mon Dec 01, 2014 4:20 pm    Post subject: Reply with quote

Quote:

Yeah, that's the dirty little secret. (Almost) everything has a C compiler. :)

Good thing I still know a little C :)

This looks like it might occupy some of my Christmas break....
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sun Dec 28, 2014 2:00 pm    Post subject: Reply with quote

http://codebase64.org/doku.php?id=base:6510_instruction_timing
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Tue Dec 30, 2014 11:08 pm    Post subject: Reply with quote

Last day of 2014 is tomorrow (today if you're reading this). I think I may start a new tradition:

On December 31st, do one quick project before 2014 ends. I.e. a "Last Day" project.

Of course, I'm posting in the Commodore 64/6502 thread, so I'm obviously thinking C64. I want to do NES eventually, but I've done more C64 homework. Next year's Last Day project can be NES or something.


To make things more interesting, I'm going to take a look through my old game design notes from when I was a kid, and see if I can find something to inspire me. Something that was beyond my skills then.
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Wed Dec 31, 2014 9:58 pm    Post subject: Reply with quote

One of the better references for the VIC-II Graphics Chip, 5 part series.

http://dustlayer.com/vic-ii/2013/4/22/when-visibility-matters
http://dustlayer.com/vic-ii/2013/4/23/vic-ii-for-beginners-part-2-to-have-or-to-not-have-character
http://dustlayer.com/vic-ii/2013/4/25/vic-ii-for-beginners-beyond-the-screen-rasters-cycle
http://dustlayer.com/vic-ii/2013/4/26/vic-ii-for-beginners-screen-modes-cheaper-by-the-dozen
http://dustlayer.com/vic-ii/2013/4/28/vic-ii-for-beginners-part-5-bringing-sprites-in-shape

Also the Commodore 64 Wiki.

http://www.c64-wiki.com/index.php/C64
http://www.c64-wiki.com/index.php/Sprite
http://www.c64-wiki.com/index.php/joystick
http://www.c64-wiki.com/index.php/Page_208-211 (VIC)
http://www.c64-wiki.com/index.php/SID
http://www.c64-wiki.com/index.php/CIA (1 and 2. First bytes of #1 are Joystick. First bytes of #2 are VIC RAM bank control. The rest is IO, clocks, and IRQ's)

Full memory map:

http://sta.c64.org/cbm64mem.html
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sun Jan 04, 2015 2:54 am    Post subject: Reply with quote

These guys sell cool stuff:

http://store.go4retro.com/
http://www.commodoreserver.com/
http://www.1541ultimate.net
http://www.thefuturewas8bit.com/shop/commodore.html

http://www.kryoflux.com/

And it seems at the end of the 1980's, some dude put together replacement ROMs for the c64 and 1541 floppy. If you swap out the chips, instead of getting 400 bytes/sec read speeds, you get about 2.4k bytes/sec (6x faster). Fully backwards and forwards compatible with all software, even fast loaders.

http://www.c64-wiki.com/index.php/JiffyDOS

Go4Retro above seems to sell them.

I discovered this while reading about C64 serial ports (for my backup project).

http://www.c64-wiki.com/index.php/Serial_Port
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sun Jan 04, 2015 3:22 am    Post subject: Reply with quote

SD2IEC's are pretty cool. Somebody had the clever idea to make them look like small floppy drives.




_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Sun Jan 04, 2015 3:52 am    Post subject: Reply with quote

Neither of these are 6502, but they're somewhat rare.


Apparently there's a dude making Neo Geo Pocket flashcarts, very limited supply.

http://www.flashmasta.com/purchase/

I actually have an older Parallel Port Flashcart, but no compatible parallel ports handy.


Apparently the Dreamcast got some pretty-sweet SD card mods recently.

http://www.dreamcast-scene.com/community/viewtopic.php?f=24&t=4254

I like this serial port one, but I can seem to find a source anymore, as the links mentioned in the post all go to Shell Replacement mods (that are likely faster, but still).

http://xckdiy.taobao.com/
http://item.taobao.com/item.htm?id=7818275499

There used to be a site for buying from that Taobao Chinese store, but they don't seem to exist anymore.

http://www.aliexpress.com/item/DIY-SD-SDHC-Card-Reader-Adapter-For-SEGA-DC-Dreamcast-XCKDIY-2012-New-Version-Dreamshell/673004678.html

No more stock.

Yeah, I'm pretty sure these don't exist anymore. 3 years late. :(


EDIT: ah yes, apparently they are simple SD Card Reader hacks.

These links have details, but be warned, will probably open a bunch of crap on you.

http://www.theisozone.com/tutorials/dreamcast/hardware-and-modding/how-to-buybuild-a-dreamcast-sandisk-adapter/
http://www.dc-swat.ru/forum/forum-29.html

Quote:
Some things you'll need:
A resistor 470.
A capacitor 47 uf.
A capacitor 0.1 uf.
An LED (not mandatory).
An SD Card port.

I'll assume you know how to do advanced things like soldering and modding, so I'll leave you to your own devices. You should be able to get one built with all the info on that page, if not, you might want to swing by the SWAT forums and speak with the creator of Dreamshell, mister SWAT himself for a few pointers.

http://www.dc-swat.ru/forum/forum-29.html

TRANSLATED FROM JAPANESE!!!!!



You can connect the SD card as an example on the application of the SPI interface. It can be used without any particular problem is a simplified version is omitted, such as the detection of the write-protect switch on the control and power, however.

Can be written in block 4 seconds (500Kbytes/sec) and output files to SD card BIOS ROM 2MBytes of DC to try. The speed will be equal to or greater than that of the BBA lip when converted to the draft GD-ROM, speed may be slightly lower, to strengthen the recovery error CRC error checking, etc. in order to increase the reliability of the written file.
(This is identical to the circuit in kind of photograph is using VHC244 on hand.)




PS: It was using the HC126 to buffer in the previous circuit, I changed to the circuit without delay buffer for the buffer will affect the speed. pic

I leave here the demo software SD card. screen shot sdcard_test.bin
SD card and message SD Card set and hit CR key!! Use will appear in the ip-upload, binary run when you start
I will start by pressing the carriage return key to set. Bios.bin flash.bin and especially if there is no error message
Files will be written. On the time stamp of the file is using clock Dreamcast.


EDIT2: some French instructions for literally hacking up an SD card reader and soldering it directly to a Dreamcast serial port.

http://igalsirour.hautetfort.com/sega-dreamcast/
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1666
Location: Your consciousness.
PostPosted: Sat Feb 07, 2015 8:22 am    Post subject: Reply with quote

Nice summary of some available tools and docs:
http://towp8.com/2015/02/01/coding-for-the-commodore-64-what-happened-in-the-last-25-years/
_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Mon Mar 09, 2015 5:47 pm    Post subject: Reply with quote

I've playing around with cc65 for a few days. Very cool and simple; the allure of doing c64 stuff with C+ASM is just too much to resist. I must... I must!
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Mon Mar 09, 2015 6:10 pm    Post subject: Reply with quote

Do eet!
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Fri Mar 13, 2015 5:45 pm    Post subject: Reply with quote

As promised, here's where I left off doing the 'Gardez 64' demo.

Again, I cheated, without file loading. I bin-include the SID file, in an assembly file, then copy where it should be in the C file. I'm pretty sure $7e was how many bytes to skip in the header.

Once I have the data where it's expected (0x4000), I can call the short assembly functions SIDInit() and SIDStep() from the C code.

sprites.s
Code:

.export _Music
_Music: .INCBIN "Droid.sid", $7e


; http://www.cc65.org/mailarchive/2011-11/9665.html
; http://www.cc65.org/mailarchive/2006-11/5612.html

;.SEGMENT "AUDIO"

;_Music:

;.INCBIN "Knucklebusters.sid", $7e
;.INCBIN "Knucklebusters10.sid", $7e
;.INCBIN "One_Man_and_His_Droid.sid", $7e
;.INCBIN "Droid.sid", $7e

;.CODE

.export _SIDInit
.export _SIDStep

_SIDInit:
    lda #0
    tax
    tay
    jsr $4000
    rts

_SIDStep:
    jsr $4012
    rts
    
; ----------------------------------------------------------------------------------------------- ;

.export _SpriteHeader
.export _SpriteColor
.export _SpriteData

; ----------------------------------------------------------------------------------------------- ;

_SpriteHeader:
.BYTE 32, 0            ; Count, PADDING
_SpriteColor:
.BYTE 0, 1            ; Black, White
_SpriteData:        ; Sprite Data (63+1 bytes each, raw plus attributes (MxxOCCCC))
.INCBIN "sprites.raw"

; ----------------------------------------------------------------------------------------------- ;

.export _CharHeader
.export _CharColor
.export _CharData
.export _TileData
.export _TileAttribData

.export _MapHeader
.export _MapData

; ----------------------------------------------------------------------------------------------- ;

_CharHeader:
.BYTE 24, 0            ; Count, PADDING
_CharColor:
.BYTE 9, 11, 7, 0    ; Brown, Gray, Yellow, PADDING
_CharData:            ; Charactar Data (8 bytes per, raw data)
.INCBIN "chars.raw"

_TileData:            ; Tile Data (9 bytes per, each an index in to the Char table)
.INCBIN "tiles.raw"
_TileAttribData:    ; Tile Attribute Data (Color, etc). **BE SURE TO SELECT *PER CHARACTER* ON EXPORT!**
.INCBIN "attribs.raw"

_MapHeader:
.BYTE 13, 8            ; Width, Height
_MapData:
.INCBIN "map.raw"

; ----------------------------------------------------------------------------------------------- ;


main.c
Code:
// - ----------------------------------------------------------------------------------------- - //
#include <c64.h>
#include <string.h>
// - ----------------------------------------------------------------------------------------- - //
#include "vickers.h"
// - ----------------------------------------------------------------------------------------- - //

extern char Music[];

extern void SIDInit();
extern void SIDStep();
/*
//#define SIDPlay() {
void SIDInit( const char Song ) {
    __asm__("lda #0");
    __asm__("tax");
    __asm__("tay");
    __asm__("jsr #$1000");
}
//_Music+$00");//,Music+0x7C+2);//$400");//%w", 0x40D);//0x1000);
//}

void SIDStep() {
    __asm__("jsr #$1012");//, 0x1013);// 0x1006);
}*/
    
// - ----------------------------------------------------------------------------------------- - //
extern char SpriteColor[2];
extern char SpriteData[];
// - ----------------------------------------------------------------------------------------- - //
extern char CharColor[4];
extern char CharData[];
extern char TileData[];
extern char TileAttribData[];
// - ----------------------------------------------------------------------------------------- - //

// - ----------------------------------------------------------------------------------------- - //
struct sMapHeader {
    unsigned char Width;
    unsigned char Height;
};
// - ----------------------------------------------------------------------------------------- - //
extern struct sMapHeader MapHeader;
extern char MapData[];
// - ----------------------------------------------------------------------------------------- - //

// - ----------------------------------------------------------------------------------------- - //
#define Mul9(_In) (((_In)<<3)+(_In))
// - ----------------------------------------------------------------------------------------- - //

// - ----------------------------------------------------------------------------------------- - //
    extern char Music[];

int main(void) {
    VICSetAddr( 0, 2 );    // Fun Mode (shows neat garbage) //

    memcpy((void*)(0x4000),(void*)&Music,1024*8);

    SIDInit();

    // Load Sprites //
    memcpy((void*)(MySpriteBase),(void*)&SpriteData,32*64);
    VIC.spr_mcolors[0] = SpriteColor[0];//COLOR_BLACK;
    VIC.spr_mcolors[1] = SpriteColor[1];//COLOR_WHITE;

    // Load Chars //
    memcpy((void*)(MyCharBase),(void*)&CharData,24*8);
    VIC.bgcolor[0] = CharColor[0];
    VIC.bgcolor[1] = CharColor[1];
    VIC.bgcolor[2] = CharColor[2];
    VIC.bgcolor[3] = CharColor[3];

    // Load Map //
    //memset((void*)0xD800,COLOR_BROWN,1024); // 1000 actually //
    memset((void*)MyScreenBase,0,1024);
    {
        char x, y;
        char w = MapHeader.Width;
        char h = MapHeader.Height;
        
        // Screen Width //
        const unsigned char sw = 40;
        const unsigned char sw2 = 40+40;
        
        for ( y = 0; y < h; y++ ) {    
            char Line = w*y;
            unsigned short SLine = 40*y;
            
            for ( x = 0; x < w; x++ ) {
                unsigned char c = MapData[Line+x];
                unsigned char* TileAddr = &TileData[Mul9(c)];
                unsigned char* Out = (unsigned char*)MyScreenBase+(SLine+SLine+SLine)+(x+x+x);
                Out[0] = TileAddr[0];
                Out[1] = TileAddr[1];
                Out[2] = TileAddr[2];
                Out[sw+0] = TileAddr[3];
                Out[sw+1] = TileAddr[4];
                Out[sw+2] = TileAddr[5];
                Out[sw2+0] = TileAddr[6];
                Out[sw2+1] = TileAddr[7];
                Out[sw2+2] = TileAddr[8];
                
                Out = (unsigned char*)0xD800+(SLine+SLine+SLine)+(x+x+x);
                Out[0] = TileAttribData[TileAddr[0]];
                Out[1] = TileAttribData[TileAddr[1]];
                Out[2] = TileAttribData[TileAddr[2]];
                Out[sw+0] = TileAttribData[TileAddr[3]];
                Out[sw+1] = TileAttribData[TileAddr[4]];
                Out[sw+2] = TileAttribData[TileAddr[5]];
                Out[sw2+0] = TileAttribData[TileAddr[6]];
                Out[sw2+1] = TileAttribData[TileAddr[7]];
                Out[sw2+2] = TileAttribData[TileAddr[8]];
            }
        }
    }
    

    VICSetPage( 2 );
    VICSetAddr( 0, 1 );

    VIC.bordercolor = COLOR_ORANGE;
    VIC.ctrl2 = (VIC.ctrl2 & (~0x10)) | 0x10;    // Enable Multicolor Mode //

    // Scroll Registers //
    VIC.ctrl1 = (VIC.ctrl1 & (~0x7)) | 6;         // Y Scroll //
    VIC.ctrl2 = (VIC.ctrl2 & (~0x7)) | 4;        // X Scroll //

    // Sprite Setup //
    SprInit();

    {
        short x = 50+(24*5)+4;
        short y = 50+(24*3)+6;
        char Facing = 0;
        char Firing = 0;
        
        short FireX = 0;
        short FireY = 0;
        short FireLife = 0;
        short FireVelX = 0;
        short FireVelY = 0;
        
        while (1) {
            // Step //
            {
                unsigned char Input = PadGet1();
                if ( Input & PAD_LEFT ) {
                    x--;
                    Facing = 0;
                }
                else if ( Input & PAD_RIGHT ) {
                    x++;
                    Facing = 1;
                }
                
                Firing = Input & PAD_FIRE;
            }
            
            if ( FireLife == 0 ) {
                if ( Firing ) {
                    FireLife = 60;
                    FireX = x;
                    FireY = y;
                    
                    FireVelX = Facing ? +2 : -2;
                    FireX += FireVelX << 3;
                    FireVelY = 0;
                }
            }
            else {
                FireX += FireVelX;
                FireY += FireVelY;
                FireLife--;
            }
            
            SIDStep();
            
            // Draw //    
            VICWaitNotVBlank();
            VICWaitVBlank();
            
            if ( FireLife > 0 ) {
                SprAlloc( 16 + ((FireVelX > 0) ? 1 : 0), FireX, FireY );
            }
            
            SprAlloc( (2*Facing)+(Firing?12:0), x,y );
            
            SprDraw();
        }
    }

    return 0;
}


Compiling Shell Script (make.sh)
Code:
#!/bin/bash

cl65 -t c64 -g -Ln main.lbl -O -o main.prg sprites.s main.c


Running Shell Script (run.sh)
Code:
#!/bin/bash

x64 -moncommands main.lbl main.prg


Assets were made in SpritePad and CharPad.
_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Fri Mar 13, 2015 5:57 pm    Post subject: Reply with quote

Quote:

Again, I cheated, without file loading.


I dunno... as crazy as that shit is, I feel like I cheated using the fopen/get/close functions :)


Quote:

//#define SIDPlay() {
void SIDInit( const char Song ) {
__asm__("lda #0");
__asm__("tax");
__asm__("tay");
__asm__("jsr #$1000");
}
//_Music+$00");//,Music+0x7C+2);//$400");//%w", 0x40D);//0x1000);
//}

void SIDStep() {
__asm__("jsr #$1012");//, 0x1013);// 0x1006);
}*/


Yeah, that's what I'm missing.

I also wish I had a huge, wall-sized map of the C64 memory map I could hang somewhere, just because...

Again, allow me to say (if I hadn't earlier) that I'm hugely impressed with the amount of progress you made in just a few days. I've been banging away at it a few hours a night this week, and I feel comfy with it, but I've got some important gaps in my knowledge still.

Also, this page is super useful for when you need a quick and dirty sine LUT banged out.
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
PoV
Moderator

Joined: 21 Aug 2005
Posts: 10892
Location: Canadia
PostPosted: Fri Mar 13, 2015 6:07 pm    Post subject: Reply with quote

The code I use for SID playback is in the assembly (.s) file. You can't see it because the forum lacks syntax highlighting, but that inline code is commented out. I forget what the inline assembly was about. I think it may have been an early attempt to re-jig a linker script solution, so the addresses suggested don't exactly make the most sense. Either way, if you wanted to know how to do inline assembly, that should be a decent starting place.

To be fair, I've shipped games with tools exactly like cc65 before, so I knew what I had to do. Just had to remember how to, and learn about the VIC and 6502.

EDIT: Oh right, here's "Vickers.h". A library I was starting to write.

c64.h (included with cc65) defines some symbols like VIC, CIA2, etc, each a piece of hardware in the C64. It gives you nice names for the hardware registers in the memory map.

vickers.h
Code:

// - ----------------------------------------------------------------------------------------- - //
// VIC is assigned to a 16k RAM block. 16k RAM broken down as: //
// - Screen RAM (Character Map) - 16 blocks (1024 bytes each) //
// - Character Set - 8 blocks (2048 bytes each) //
// - Sprite Data - 256 blocks (63+1 bytes each) //

// Character ROM (VIC always sees this) - 0x1000 and 0x1800, 0x9000 and 0x9800
// - 2k bytes each
// - 0x1000-0x17FF is Upper Case PETSCII
// - 0x1800-0x1FFF is Lower Case PETSCII

// Program starts at 0x800 //
// Screen RAM typically starts at 0x400 (0x400-0x7FF) //
// 0x000-0x3E7 - 1000 bytes of characters (40x25 display)
// 0x3E8-0x3F7 - 16 bytes unused
// 0x3F8-0x3FF - 8 bytes of block data addresses (0-255, 63+1 bytes each)
// - ----------------------------------------------------------------------------------------- - //
void VICSetPage( char VICBase ) {
    // 0xDD00 //
    CIA2.pra = (CIA2.pra & 0xFC) | (3-VICBase);    
    // Lower 2 bits only. Pages are in reverse order. //
}
// - ----------------------------------------------------------------------------------------- - //
void VICSetAddr( char ScreenBase, char CharBase ) {
    // 0xD018 //
    VIC.addr = (ScreenBase << 4) | (CharBase << 1);
    // NOTE: When on Pages 0 or 2, Upper Case is Charset 2 and Lower Case is Charset 3 //
}
// - ----------------------------------------------------------------------------------------- - //


// - ----------------------------------------------------------------------------------------- - //
#define VIC_TOP_BORDER_TOP (8)
#define VIC_TOP_BORDER_BOTTOM (50)
#define VIC_BOTTOM_BORDER_TOP (250)
#define VIC_BOTTOM_BORDER_BOTTOM (299)
// - ----------------------------------------------------------------------------------------- - //
unsigned short VICGetLine() {
    return ((unsigned short)VIC.rasterline) | ((VIC.ctrl1 & 0x80) ? 0x100 : 0);
}
// - ----------------------------------------------------------------------------------------- - //
void VICWaitVBlank() {
    while ( VICGetLine() < VIC_BOTTOM_BORDER_TOP );
}
// - ----------------------------------------------------------------------------------------- - //
void VICWaitNotVBlank() {
    while ( VICGetLine() >= VIC_BOTTOM_BORDER_TOP );
}
// - ----------------------------------------------------------------------------------------- - //

// ** My VIC Memory Map ** //
// 0x0000 - VRAM Map (1st half only) //
// 0x0400 - (unused)
// 0x0800 - VRAM Tileset
// 0x1000 - ROM Upper Case
// 0x1800 - ROM Lower Case
// 0x2000 - Sprites (128 total, 63+1 bytes each)
// 0x2800 - Sprites
// 0x3000 - Sprites
// 0x3800 - Sprites

#define MyVICBase        (0x8000)
#define MyScreenBase    (MyVICBase+(0x0))
#define MyCharBase        (MyVICBase+(0x800))
#define MySpriteBase    (MyVICBase+(0x2000))

// - ----------------------------------------------------------------------------------------- - //


// - ----------------------------------------------------------------------------------------- - //
char Spr_Alloc;
// - ----------------------------------------------------------------------------------------- - //
const unsigned char Spr_Bit[] = {0x1,0x2,0x4,0x8, 0x10,0x20,0x40,0x80};
const unsigned char Spr_EnableBit[] = {0x0, 0x1,0x3,0x7,0xF, 0x1F,0x3F,0x7F,0xFF};
unsigned short Spr_InfoAddr[128]; // Addresses of Sprite 128-255 Information //
// - ----------------------------------------------------------------------------------------- - //
void SprInit() {
    unsigned char idx;
    for ( idx = 0; idx < 128; idx++ ) {
        Spr_InfoAddr[idx] = MySpriteBase + (idx<<6) + 63; // Last Byte (64-1) //
    }
    
    Spr_Alloc = 0;
}
// - ----------------------------------------------------------------------------------------- - //
void SprAlloc( unsigned char Index, unsigned short x, unsigned char y ) {
    unsigned char Info = *((unsigned char*)Spr_InfoAddr[Index]);
        
    // Check for Overlay bit //    
    if ( Info & 0x10 ) {
        // Recursively call this function //
        SprAlloc(Index+1,x,y);
    }

    // Bail on too many sprites //
    if ( Spr_Alloc >= 8 )
        return;
    
    // Write Position //
    VIC.spr_pos[Spr_Alloc].x = x;//(x & 0xFF);
    VIC.spr_pos[Spr_Alloc].y = y;
    
    VIC.spr_hi_x = (VIC.spr_hi_x & (~Spr_Bit[Spr_Alloc])) | ((x>255) ? Spr_Bit[Spr_Alloc] : 0 );

    // Write Color Mode and Color //
    VIC.spr_mcolor = (VIC.spr_mcolor & (~Spr_Bit[Spr_Alloc])) | ((Info & 0x80) ? Spr_Bit[Spr_Alloc] : 0 );
    VIC.spr_color[Spr_Alloc] = Info;// & 0xF;

    // Write Sprite Block used //
    *((unsigned char*)(MyScreenBase+0x3F8+Spr_Alloc)) = 128u + Index;

    // Next Sprite Slot //
    Spr_Alloc++;
}
// - ----------------------------------------------------------------------------------------- - //
void SprDraw() {
    VIC.spr_ena = Spr_EnableBit[Spr_Alloc];
    Spr_Alloc = 0;
}
// - ----------------------------------------------------------------------------------------- - //


// - ----------------------------------------------------------------------------------------- - //
char PadGet1() {
    return ~CIA1.prb;// & 0x1F;
}
// - ----------------------------------------------------------------------------------------- - //
char PadGet2() {
    return ~CIA1.pra;// & 0x1F;
}
// - ----------------------------------------------------------------------------------------- - //
#define PAD_UP        (0x1)
#define PAD_DOWN    (0x2)
#define PAD_LEFT    (0x4)
#define PAD_RIGHT    (0x8)
#define PAD_FIRE    (0x10)
// - ----------------------------------------------------------------------------------------- - //

_________________
Mike Kasprzak
'eh whatever. I used to make AAA and Indie games | Ludum Dare | Blog | Tweetar
View user's profile Send private message
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Fri Mar 13, 2015 6:30 pm    Post subject: Reply with quote

Quote:

The code I use for SID playback is in the assembly (.s) file. You can't see it because the forum lacks syntax highlighting, but that inline code is commented out.


I noticed that after I posted ^__^ Gotta slow down and READ.

I started working on a dirt-simple lib for what I feel will be commonly used things, but I'm not going to put too much effort into it until I bang out something to confirm I really want to this on a c64 (I'm like 99% certain, but the world is an uncertain place, so there you go).

I'm also running into little oddities like fseek not existing (CMB doesn't support moving the file pointer!) and there not being sin/cos functions, which I sorely miss. I will eventually want to do simple 3D projection of points, so I'll need proper sin/cos stuff, but for a now a LUT makes my sprites bounce like I want them to.
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1666
Location: Your consciousness.
PostPosted: Fri Mar 20, 2015 5:29 am    Post subject: Reply with quote

Found a huge collection of downloadable books (many in .pdf format (might be highly useful)): http://www.bombjack.org/commodore/
_________________
0xDB
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1666
Location: Your consciousness.
PostPosted: Mon Mar 30, 2015 4:03 pm    Post subject: Reply with quote

Guess this is the most appropriate thread for this:

http://magervalp.github.io/2015/03/28/u4-remastered-teaser.html

http://csdb.dk/release/?id=137331
_________________
0xDB
View user's profile Send private message Visit poster's website
Sirocco
Moderator

Joined: 19 Aug 2005
Posts: 9453
Location: Not Finland
PostPosted: Mon Mar 30, 2015 5:17 pm    Post subject: Reply with quote

I dunno. I think that probably warrants an entire thread unto itself....
_________________
NoOP / Reyn Time -- The $ is screwing everyone these days. (0xDB)
View user's profile Send private message Visit poster's website
0xDB
Developer

Joined: 26 Dec 2005
Posts: 1666
Location: Your consciousness.
PostPosted: Wed Apr 01, 2015 10:20 am    Post subject: Reply with quote

Ok... split it off! (though interest seems minimal at the moment)
_________________
0xDB
View user's profile Send private message Visit poster's website
Reply to topic GDR Forum Index -> Game Developer's Refuge -> The Commodore 64 (6502 and Friends) Page Previous  1, 2, 3, 4  Next
Game Developer's Refuge
is proudly hosted by,

HostGator

All trademarks and copyrights on this page are owned by their respective owners. All comments owned by their respective posters.
phpBB code © 2001, 2005 phpBB Group. Other message board code © Kevin Reems.