Jump to content
geek504

My First C64/X16 Programs!

Recommended Posts

5 minutes ago, rje said:

Thanks for posting the tables, Mr. Geek 504.  It is a Big Gulp for sure, but it's always nice to discuss options, be it ROM or a card or whatever.  Wolf3D on the X16.... whoo....

 

Did you say you were new to the Commodore Line of Stuff?  You do know about the KERNAL though, right?  And the X16's pseudo-16-bit routines?  And Bruce's variant of SWEET16?

 

Yeah, I grew up on the other side, the dark side known as Apple ][. The only Commodore I owned was an Amiga500. I'm not familiar with the term KERNAL but I assume it to be all the built-in ROM functions for all sort of stuff needed by the computer (e.g. input, output, clear screen, parser, commands, graphics, etc.) and accessible by the programmer using SYS (Apple ][ is CALL) and JSR (in assembly). I'm also assuming that X16 new commands were implemented in ROM as well using 6502 assembly. But when you say "pseudo", I'm not sure now. An 16-bit routines? I am aware of Steve Wozniak's SWEET16 implementation for the Apple ][ Integer ROM but that wasn't used much and didn't include math functions, just simple 16-bit LDA and STA. Why does X16 need a SWEET16 implementation?

I have studied the entire Apple ROM disassembly... have yet to do the same with C64 when time is available. What I find the most peculiar and impressive is how C64 handles graphics and sprites with layers! That is amazing for an Apple ][ guy. I just watched yesterday The 8-Bit Guy's video on "Oldschool Graphics" and C64's use of COLOR CELLS versus Apple ]['s NTSC ARTIFACT COLORING.

The most impressive of all is using the C64's CPU to change the color palette on each scanline of each color cell and achieve amazing pictures! (it's in Part 2 at 5:00)

Share this post


Link to post
Share on other sites

I admit the things people did/do with the C64 is Scary Magic, and I'm not worthy.

Yes, the KERNAL is the jump table common to all 8-bit Commodore computers for handling I/O (mostly?).  It's a Good Thing.

The X16 doesn't have a SWEET 16, although Bruce has created a variant of it "for fun" somewhere around here.

However, the X16 does have new routines for handling 16 bit values, stored in pseudo-registers in zero page.  It's not a VM, but simply a set of convenience routines.  Michael is to blame for them, at least partly, and I think they're a Good Thing too.

 

Edited by rje

Share this post


Link to post
Share on other sites
19 minutes ago, rje said:

Yes, the KERNAL is the jump table common to all 8-bit Commodore computers for handling I/O (mostly?).  It's a Good Thing.

Ah, the KERNAL is a JUMP TABLE! The Macintosh 128K et al. has the same feature... allowing ROM bugs to be fixed in RAM and simply changing the value in the JUMP TABLE. It is a GOOD THING! Especially because I read the following:

Quote

All Commodore BASICs, except BASIC 7.0 for the Commodore 128, have a bug in the multiply routine which can produce incorrect results for some pairs of operands.

Someone might actually want to fix that in the ROM itself...

Share this post


Link to post
Share on other sites

Okay, I was misleading.  The KERNAL routines developed a bit up until the VIC-20, but there still is compatibility, and the intent was to provide a separation -- an API -- between the system and MS BASIC.  By the time of the VIC-20, the KERNAL was documented and forward-compatible.

Your (fun!) reading assignment:

https://www.pagetable.com/?p=926

And the (even funner!) KERNAL API reference:

https://www.pagetable.com/?p=1401

Edited by rje
  • Like 1

Share this post


Link to post
Share on other sites
18 hours ago, geek504 said:

Ah, the KERNAL is a JUMP TABLE! The Macintosh 128K et al. has the same feature... allowing ROM bugs to be fixed in RAM and simply changing the value in the JUMP TABLE. It is a GOOD THING! Especially because I read the following:

Someone might actually want to fix that in the ROM itself...

The KERAL is actually the all the functions sitting in the ROM required for the bare IO functions for the Commodore Computers to work. BASIC is another part which is interfacing with the KERNAL for more low level access..  It is not the jump table, but it has a jump table. The jump table is in ROM.. but obviously you could copy the jump table to anywhere, (a bank for instance) and change some parameters. However the Jump Table assumes, that you are and stay within the current selected banks. You cannot jump across banks with the KERNAL, as the KERNAL is not aware of banked RAM like the X16 has. It can only bank-in ROMs into the addressable space (e.g. CHARROM, KERNAL ROM, BASIC ROM) and as I said if you are inside the KERNAL, you can only jmp within the KERNAL - not into another ROM bank for instance...

That brings me to one question: KERNAL and BASIC live in different ROM banks. So how is it possible that BASIC calls a KERNAL function? What is happening to switch the BANK before the JSR ? The more I think of it, the more my head is spinning. So you would need to do a bank switch, and then the next instruction from the ROM you worked in is not available anymore.

Lets assume you have the BASIC ROM paged in (#4). You work in a routine and want to call CHROUT (for instance) from KERNAL. So you prepare the page for KERNAL ROM (#0) and then the next instruction executed is the on sitting in KERNEL ROM ad the address in PC instead of the instrcution in BASIC ROM. 

Any idea how that works in X16?

 

Share this post


Link to post
Share on other sites
1 hour ago, SerErris said:

Any idea how that works in X16?

The BASIC bank has a shadow Kernal jump table that points to a "bridge" that lets you do a JSRFAR to the Kernal bank and then return to the BASIC bank thanks to storing that bank index into a "magical" memory location ($0105 - a reminder to not touch any RAM between $0100 and $03FF!) that can be picked up after returning from the Kernal routine.

  • Like 1
  • Thanks 1
  • Confused 1

Share this post


Link to post
Share on other sites
On 9/2/2020 at 1:03 AM, SerErris said:

So you would need to reduce the viewport massively. Full Screen DOOM or Wolfenstein is not realistic. (I know you did not mention Full Screen). 
 

Though AFAIU, full screen DOOM and full screen Wolfenstein are two distinct levels of difficulty, since Wolfenstein only requires vertical scaling. If you prescale Wolfenstein assets so that only (16*8)/8 scaling is required for intermediate scales between the pre-scaled levels, and work in low-res video mode, it seems like it could be done. 16x8/8 can be done as with intermediate step tables that fit into single 8K high RAM segments: eg, unsigned 8x4->12 fits into two 4K tables, one for the low byte and one for the high nybble of the result. Rather than shifting the "d4-d15" result, simply have a second 8x4->(12 lshift 4). So:

1] Bring in low 12 bit table High RAM segment
1] low byte of the 16, low nybble of the 8, store in the first two bytes of result, zero third
2] High byte of the 16, low nybble of the 8, add into the second and third bytes of result
3] Bring in high 12bit table High RAM segment
4] low byte of the 16, high nybble of the 8, add into the first two bytes of result, increment third byte on carry set
5] High byte of the 16, high nybble of the 8, add into the second and third bytes of result
6] RTS

And the division doesn't really need to be perfectly precise, so perhaps 4bitx(1/8bit)->4bit.12bit is enough precision ... that would involve two operaitons into result0 and two operations into result1, then shift the result0 down four bits before summing result1 in. ... And of course, that still leaves room for 4K of more tables.
So 16x8/8->16 in a total of 4 table set-ups and 16 LDA (TBLx),Y or ADC (TBLx),Y operations, one 24bit shift right by 4 bits and supporting glue.

You always use the same nybble twice not only because it is the same low or hygh nybble base of the resulting value, but also because the table reading heart is:
; Nybble in low bits of A, Table BANK in X, Y used, returns with previous BANK on top of stack.
SETTBL: LDY BANK : STX BANK : ORA #$A0 : STZ TBL0 : STA TBL0+1 : #ORA $B0 : STZ TBL1 : STA TBL1+1
L1: PLA : PLX : PHY : PHX : PHA : RTS

_____________________________
Note we don't have to mask the $A0+nybble page address for the $B0 table because $A0 is $10100000 and $B0 is %10110000 and we are looking for the pages corresponding to the same nybble in both cases.

Edited by BruceMcF
  • Like 3

Share this post


Link to post
Share on other sites
On 9/4/2020 at 1:12 AM, BruceMcF said:

Though AFAIU, full screen DOOM and full screen Wolfenstein are two distinct levels of difficulty, since Wolfenstein only requires vertical scaling.

That's some serious stuff there Bruce! Thanks for the food for thought! I'm starting to brush up on 3D fundamentals... rotating 3D cube without hidden line removal...

Wolf3D version 0.00001a LOL!

x16-cube.PNG.8e35872dd42196fef70e15a0354ba331.PNG

Share this post


Link to post
Share on other sites

@geek504 cool I made that as well, am currently busy implementing the Elite game's ship models into it 🙂    How did you make your version of this? In basic or C or something else?

Share this post


Link to post
Share on other sites
23 minutes ago, desertfish said:

@geek504 cool I made that as well, am currently busy implementing the Elite game's ship models into it 🙂    How did you make your version of this? In basic or C or something else?

Proof-of-concept always in BASIC 🙂 then slowly adding trig tables, SYS calls to assembly code, maybe a C version, then finally full assembly!

Might as well ask now since I am trying to eliminate FLICKER: Is it possible to have two GRAPHICS pages (mode $80) and flip between them? (aka page-flipping). If not, is there any other graphics mode that does?

  • Like 1

Share this post


Link to post
Share on other sites

Good stuff, @geek504  .  I don't have an answer to your question and am struggling with a similar idea myself as you can read on the description of my own demo program https://www.commanderx16.com/forum/index.php?/files/file/71-3d-wire-frame-spinning-cube/    I was wondering if there is a way to wait for Vertical Blank.   (won't help much to reduce flicker still I am afraid because I don't think the program will be fast enough to redraw everything within one frame, but hey)

Share this post


Link to post
Share on other sites

There is a vector located at $0314 that points to the interrupt routine (which is by default called at vertical blank every frame). Changing this vector to point to your own code will allow you to write a routine that runs at vertical blank. To make sure the original interrupt routine still runs, save the original value of the vector, and jump there at the end of your routine.

  • Like 1

Share this post


Link to post
Share on other sites

I have started working on a double-buffered line graphics capability with this: 

 

Using the GEOS frame buffer API gives you flicker, it seems, no matter what. My implementation has two 16-color frame buffers that it switches between, drawing one while displaying the other.

Share this post


Link to post
Share on other sites

"but you will need  C64/C128 with a SuperCPU v2 and 16MB RAM"  <- from that wolf3d page.. that's not really a c64 as I remember it 😛

Share this post


Link to post
Share on other sites
1 hour ago, desertfish said:

"but you will need  C64/C128 with a SuperCPU v2 and 16MB RAM"  <- from that wolf3d page.. that's not really a c64 as I remember it 😛

That’s why I am wanting the X16 to be at least 20MHz! We could do so much with that 🤪

SuperCPUv2
Processor:  WDC 65C816S
Architecture:  8/16-bit
Clock Speed:  20 MHz
Opcodes:  Documented 6510 opcodes only

Share this post


Link to post
Share on other sites
4 hours ago, desertfish said:

The 65c02 cpu can't run that fast as far as I know and remember: constraints spark creativity 😉

Max speed as per spec is 14MHz, that's acceptable!

FPGA implementation at 100MHz with pin-compatible format: (need some adjustments for X16's memory banks)

http://www.e-basteln.de/computing/65f02/65f02/

I admit, I am suffering from feature-request syndrome! Coming from an Apple ][, the X16's 320x200x256 and 640x480x16 is nirvana in itself, the X16's 8MHz clock speed is way better than the ]['s 1MHz, and 2MB is more than I would need for my programming desires. So yeah, the X16 is just fine the way it is... let's make use of our creativity as you say! Our version of Wolf3D has to be creatively different!

Edited by geek504
  • Like 1

Share this post


Link to post
Share on other sites
11 hours ago, SlithyMatt said:

My implementation has two 16-color frame buffers that it switches between

Is this documented anywhere? I couldn't find any info on other graphics mode.

Share this post


Link to post
Share on other sites
1 hour ago, geek504 said:

Is this documented anywhere? I couldn't find any info on other graphics mode.

It's all in the VERA doc. Bitmap graphics modes can be 2, 4, 16, or 256 colors.

image.thumb.png.2eec93f064a7fc5fb9e299a8c633d4f1.png

Share this post


Link to post
Share on other sites

AND .. you can set both layers to Bitmap mode However that is most likely not what you want.

What you want is:

Lets assume you want a 320x200x4bpp bitmap with double buffer

You start to use Layer0 for that. You set tile base to $04000 (if you do not need your text buffer, you can start at $00000) then build whatever you want in that screen ...

Then you start building your next frame in area starting @$10000 .. after you are finished rendering it, you set the tilebase to $10000

Then you start to build in $04000 again ... flip back tilebase and so on.

That is how you can do double buffering with VERA.

  • Thanks 1

Share this post


Link to post
Share on other sites
1 hour ago, SlithyMatt said:

Bitmap graphics modes can be 2, 4, 16, or 256 colors.

 

Gotcha! I just did a cursory view at the SCREEN function and only saw this:

Mode Description Comment
$00 40x30 text  
$01 80x30 text (currently unsupported)
$02 80x60 text  
$80 320x200@256c
40x25 text
 
$81 640x400@16c (currently unsupported)

I expected other "modes" to be already pre-defined and not for the user to set it up manually...

Share this post


Link to post
Share on other sites
18 minutes ago, SerErris said:

That is how you can do double buffering with VERA.

Gotcha! But I think we don't have enough VRAM for two 320x200x256 buffers... that's why SlithyMatt did 2 pages with 16 colors each.

Edit: DOH! 4bpp = 16 colors... I should go get my coffee...

I'm going to start some assembly coding and would like to ask: What workflow are you guys following? Which assembler? What steps to get the binary file inside the emulator? etc. I think my way is just too slow...

Edited by geek504
Brain-fart

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Please review our Terms of Use