mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-29 18:49:42 +00:00
Working on lazynes print.c demonstrating lnList()
This commit is contained in:
parent
858c5de57a
commit
1f02f81b3d
@ -96,10 +96,16 @@ char ppuDataRead();
|
|||||||
void ppuDataFill(void* const ppuData, char val, unsigned int size);
|
void ppuDataFill(void* const ppuData, char val, unsigned int size);
|
||||||
|
|
||||||
// Transfer a number of bytes from the CPU memory to the PPU memory
|
// Transfer a number of bytes from the CPU memory to the PPU memory
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
||||||
|
// - size : The number of bytes to transfer
|
||||||
|
void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size);
|
||||||
|
|
||||||
|
// Transfer a number of bytes from the PPU memory to the CPU memory
|
||||||
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
// - size : The number of bytes to transfer
|
// - size : The number of bytes to transfer
|
||||||
void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size);
|
void ppuDataFetch(void* const cpuData, void* const ppuData, unsigned int size);
|
||||||
|
|
||||||
// Transfer a 2x2 tile into the PPU memory
|
// Transfer a 2x2 tile into the PPU memory
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
@ -142,8 +142,8 @@ void ppuDataFill(void* const ppuData, char val, unsigned int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer a number of bytes from the CPU memory to the PPU memory
|
// Transfer a number of bytes from the CPU memory to the PPU memory
|
||||||
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
|
||||||
// - ppuData : Pointer in the PPU memory
|
// - ppuData : Pointer in the PPU memory
|
||||||
|
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
||||||
// - size : The number of bytes to transfer
|
// - size : The number of bytes to transfer
|
||||||
void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size) {
|
void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size) {
|
||||||
ppuDataPrepare(ppuData);
|
ppuDataPrepare(ppuData);
|
||||||
@ -154,8 +154,8 @@ void ppuDataTransfer(void* const ppuData, void* const cpuData, unsigned int size
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transfer a number of bytes from the PPU memory to the CPU memory
|
// Transfer a number of bytes from the PPU memory to the CPU memory
|
||||||
// - ppuData : Pointer in the PPU memory
|
|
||||||
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
// - cpuData : Pointer to the CPU memory (RAM of ROM)
|
||||||
|
// - ppuData : Pointer in the PPU memory
|
||||||
// - size : The number of bytes to transfer
|
// - size : The number of bytes to transfer
|
||||||
void ppuDataFetch(void* const cpuData, void* const ppuData, unsigned int size) {
|
void ppuDataFetch(void* const cpuData, void* const ppuData, unsigned int size) {
|
||||||
ppuDataPrepare(ppuData);
|
ppuDataPrepare(ppuData);
|
||||||
|
@ -76,6 +76,20 @@ volatile char scroll_x;
|
|||||||
// Scroll y-position
|
// Scroll y-position
|
||||||
volatile char scroll_y;
|
volatile char scroll_y;
|
||||||
|
|
||||||
|
// Update list with data to be moved to VRAM during blank
|
||||||
|
// The data is moved by when lnSync() is called
|
||||||
|
// - The format of the update list is an array of unsigned bytes.
|
||||||
|
// - There can be 3 different commands in the update list:
|
||||||
|
// a) addressHi, addressLo, value
|
||||||
|
// b) addressHi|lfHor, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// c) addressHi|lfVer, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// - Multiple commands can be queued in one list,
|
||||||
|
// but there can only be one activated updatelist at a time.
|
||||||
|
// - The end of the list is marked by lfEnd! (important!)
|
||||||
|
// - It's the same format that's used in set_vram_update() of Shiru's neslib
|
||||||
|
// See https://nesdoug.com/2017/04/13/my-neslib-notes/
|
||||||
|
char * volatile vram_update_list;
|
||||||
|
|
||||||
// NMI Called when the PPU refreshes the screen (also known as the V-Blank period)
|
// NMI Called when the PPU refreshes the screen (also known as the V-Blank period)
|
||||||
interrupt(hardware_stack) void vblank() {
|
interrupt(hardware_stack) void vblank() {
|
||||||
// DMA transfer the entire sprite buffer to the PPU
|
// DMA transfer the entire sprite buffer to the PPU
|
||||||
@ -130,7 +144,11 @@ ubyte lnSync(ubyte flags) {
|
|||||||
// Update the mode
|
// Update the mode
|
||||||
sync_mode = flags;
|
sync_mode = flags;
|
||||||
|
|
||||||
|
// Move any pending data to the VRAM
|
||||||
|
lnListTransfer();
|
||||||
|
|
||||||
// TODO: Handle lfSplit = 2 : activates split mode, NMI waits for SPR0HIT and sets registers
|
// TODO: Handle lfSplit = 2 : activates split mode, NMI waits for SPR0HIT and sets registers
|
||||||
|
|
||||||
// Return number of vblank since last sync
|
// Return number of vblank since last sync
|
||||||
char res = vblank_count;
|
char res = vblank_count;
|
||||||
vblank_count = 0;
|
vblank_count = 0;
|
||||||
@ -147,23 +165,65 @@ void lnPush(uword o, ubyte a, void* s) {
|
|||||||
ppuDataTransfer(o, s, a);
|
ppuDataTransfer(o, s, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write data into nametables, palettes, CHRRAM, etc.
|
// Plan a write of data into nametables, palettes, CHRRAM, etc.
|
||||||
|
// The data will be written next time lnSync() is called.
|
||||||
// (Screen has to be visible, doesn't work in blank mode!)
|
// (Screen has to be visible, doesn't work in blank mode!)
|
||||||
// updateList: Pointer to update list
|
// updateList: Pointer to update list
|
||||||
//
|
//
|
||||||
// TODO: void lnList(void* updateList);
|
// remarks:
|
||||||
// TODO: enum { lfHor=64, lfVer=128, lfEnd=255 };
|
// - The format of the update list is an array of unsigned bytes.
|
||||||
|
// - There can be 3 different commands in the update list:
|
||||||
|
// a) addressHi, addressLo, value
|
||||||
|
// b) addressHi|lfHor, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// c) addressHi|lfVer, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// - Multiple commands can be queued in one list,
|
||||||
|
// but there can only be one activated updatelist at a time.
|
||||||
|
// - The end of the list is marked by lfEnd! (important!)
|
||||||
|
// - It's the same format that's used in set_vram_update() of Shiru's neslib
|
||||||
|
// See https://nesdoug.com/2017/04/13/my-neslib-notes/
|
||||||
|
void lnList(void* update_list) {
|
||||||
|
vram_update_list = update_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute any planned transfer of data into nametables, palettes, CHRRAM, etc. by lnList()
|
||||||
|
void lnListTransfer() {
|
||||||
|
if(vram_update_list) {
|
||||||
|
// Index into the update list (assumes no more than 256 bytes)
|
||||||
|
char idx = 0;
|
||||||
|
for(;;) {
|
||||||
|
char addrHi = vram_update_list[idx++];
|
||||||
|
// Have we reached the end of the lsit
|
||||||
|
if(addrHi==0xff) break;
|
||||||
|
if(addrHi&lfHor) {
|
||||||
|
// The write is horizontal
|
||||||
|
char addrLo = vram_update_list[idx++];
|
||||||
|
char* ppuAddr = (char*)(uword){ addrHi&0x3f, addrLo };
|
||||||
|
char size = vram_update_list[idx++];
|
||||||
|
ppuDataTransfer(ppuAddr, vram_update_list+idx, size);
|
||||||
|
} else if(addrHi&lfVer) {
|
||||||
|
// The write is vertical
|
||||||
|
char addrLo = vram_update_list[idx++];
|
||||||
|
char* ppuAddr = (char*)(uword){ addrHi&0x3f, addrLo };
|
||||||
|
char size = vram_update_list[idx++];
|
||||||
|
// Set vertical mode ibit in PPUCTRL
|
||||||
|
char ppuCtrl = PPU->PPUCTRL;
|
||||||
|
PPU->PPUCTRL = ppuCtrl|4;
|
||||||
|
ppuDataTransfer(ppuAddr, vram_update_list+idx, size);
|
||||||
|
// restore PPUCTRL
|
||||||
|
PPU->PPUCTRL = ppuCtrl;
|
||||||
|
} else {
|
||||||
|
// The write is single-byte
|
||||||
|
char addrLo = vram_update_list[idx++];
|
||||||
|
char* ppuAddr = (char*)(uword){ addrHi, addrLo };
|
||||||
|
char value = vram_update_list[idx++];
|
||||||
|
ppuDataSet(ppuAddr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set update list to zero
|
||||||
|
vram_update_list = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remarks:
|
|
||||||
// - The format of the update list is an array of unsigned bytes.
|
|
||||||
// - There can be 3 different commands in the update list:
|
|
||||||
// a) addressHi, addressLo, value
|
|
||||||
// b) addressHi|lfHor, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
|
||||||
// c) addressHi|lfVer, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
|
||||||
// - Multiple commands can be queued in one list,
|
|
||||||
// but there can only be one activated updatelist at a time.
|
|
||||||
// - The end of the list is marked by lfEnd! (important!)
|
|
||||||
// - It's the same format that's used in set_vram_update() of Shiru's neslib
|
|
||||||
|
|
||||||
|
|
||||||
// Scroll background
|
// Scroll background
|
||||||
|
@ -39,27 +39,28 @@ void lnPush(uword o, ubyte a, void* s);
|
|||||||
// (Screen has to be visible, doesn't work in blank mode!)
|
// (Screen has to be visible, doesn't work in blank mode!)
|
||||||
// updateList: Pointer to update list
|
// updateList: Pointer to update list
|
||||||
//
|
//
|
||||||
// TODO: void lnList(void* updateList);
|
// remarks:
|
||||||
|
// - The format of the update list is an array of unsigned bytes.
|
||||||
|
// - There can be 3 different commands in the update list:
|
||||||
|
// a) addressHi, addressLo, value
|
||||||
|
// b) addressHi|lfHor, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// c) addressHi|lfVer, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
||||||
|
// - Multiple commands can be queued in one list,
|
||||||
|
// but there can only be one activated updatelist at a time.
|
||||||
|
// - The end of the list is marked by lfEnd! (important!)
|
||||||
|
// - It's the same format that's used in set_vram_update() of Shiru's neslib
|
||||||
|
// See https://nesdoug.com/2017/04/13/my-neslib-notes/
|
||||||
|
void lnList(void* update_list);
|
||||||
|
|
||||||
|
// Constants used to control VRAM updates in the list passed to lnList()
|
||||||
enum { lfHor=64, lfVer=128, lfEnd=255 };
|
enum { lfHor=64, lfVer=128, lfEnd=255 };
|
||||||
//
|
|
||||||
// remarks:
|
|
||||||
// - The format of the update list is an array of unsigned bytes.
|
|
||||||
// - There can be 3 different commands in the update list:
|
|
||||||
// a) addressHi, addressLo, value
|
|
||||||
// b) addressHi|lfHor, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
|
||||||
// c) addressHi|lfVer, addressLo, amountOfBytes, byte1, byte2, byte3, ...
|
|
||||||
// - Multiple commands can be queued in one list,
|
|
||||||
// but there can only be one activated updatelist at a time.
|
|
||||||
// - The end of the list is marked by lfEnd! (important!)
|
|
||||||
// - It's the same format that's used in set_vram_update() of Shiru's neslib
|
|
||||||
|
|
||||||
|
// Common offsets for lnPush() and lnList()
|
||||||
// Common offsets for lnPush() and lnList()
|
const uword lnNameTab0=0x2000, lnNameTab1=0x2400, lnNameTab2=0x2800, lnNameTab3=0x2C00,
|
||||||
const uword lnNameTab0=0x2000, lnNameTab1=0x2400, lnNameTab2=0x2800, lnNameTab3=0x2C00,
|
|
||||||
lnAttrTab0=0x23C0, lnAttrTab1=0x27C0, lnAttrTab2=0x2BC0, lnAttrTab3=0x2FC0,
|
lnAttrTab0=0x23C0, lnAttrTab1=0x27C0, lnAttrTab2=0x2BC0, lnAttrTab3=0x2FC0,
|
||||||
lnBackCol=0x3F00,
|
lnBackCol=0x3F00,
|
||||||
lnChrPal0=0x3F01, lnChrPal1=0x3F05, lnChrPal2=0x3F09, lnChrPal3=0x3F0D,
|
lnChrPal0=0x3F01, lnChrPal1=0x3F05, lnChrPal2=0x3F09, lnChrPal3=0x3F0D,
|
||||||
lnSprPal0=0x3F11, lnSprPal1=0x3F15, lnSprPal2=0x3F19, lnSprPal3=0x3F1D;
|
lnSprPal0=0x3F11, lnSprPal1=0x3F15, lnSprPal2=0x3F19, lnSprPal3=0x3F1D;
|
||||||
|
|
||||||
// Scroll background
|
// Scroll background
|
||||||
// x: New horizotnal scrolling offset in pixels, allowed range: [0..511]
|
// x: New horizotnal scrolling offset in pixels, allowed range: [0..511]
|
||||||
|
49
src/test/kc/complex/lazynes/print.c
Normal file
49
src/test/kc/complex/lazynes/print.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// lazyNES print demo (using lnlist)
|
||||||
|
// lazyNES - As lazy as possible NES hardware support library for vbcc6502
|
||||||
|
// (happily cooperates with Shiru's famitone2 replay code)
|
||||||
|
// V1.0, 'Lazycow 2020
|
||||||
|
|
||||||
|
// Ported to KickC 2020 by Jesper Gravgaard
|
||||||
|
// Original Source VBCC alpha 2 http://www.ibaug.de/vbcc/vbcc6502_2.zip
|
||||||
|
|
||||||
|
#pragma target(nes)
|
||||||
|
#include "lazynes.h"
|
||||||
|
|
||||||
|
// A string in ROM
|
||||||
|
#pragma data_seg(Data)
|
||||||
|
ubyte b_init[]={0,0,10,'B','U','B','B','L','E','S',':',0,0,lfEnd};
|
||||||
|
|
||||||
|
// A string in RAM
|
||||||
|
#pragma data_seg(GameRam)
|
||||||
|
ubyte b[14];
|
||||||
|
|
||||||
|
// print some text in the static area using lnList
|
||||||
|
void Print(uword offset, ubyte value) {
|
||||||
|
b[0]=(ubyte)(offset>>8)|lfHor; b[1]=(ubyte)offset; b[11]=b[12]='0';
|
||||||
|
while (value>=10) { ++b[11]; value-=10; }
|
||||||
|
while (value>=1) { ++b[12]; value-=1; }
|
||||||
|
lnList(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int lnMain() {
|
||||||
|
// Copy string from ROM to RAM
|
||||||
|
for(char i=0;i<sizeof(b_init);i++)
|
||||||
|
b[i] = b_init[i];
|
||||||
|
static const ubyte bgColors[]={45,33,2};
|
||||||
|
ubyte objects=0;
|
||||||
|
uword tics=0;
|
||||||
|
lnSync(lfBlank); // blank screen to enable lnPush() usage
|
||||||
|
lnPush(lnBackCol,3,bgColors); // set background colors
|
||||||
|
for(;;) {
|
||||||
|
// update the number to display
|
||||||
|
tics+=1;
|
||||||
|
if (tics>8) {
|
||||||
|
tics=0;
|
||||||
|
objects = (objects+1)&0x3f;
|
||||||
|
}
|
||||||
|
// display a number
|
||||||
|
Print(lnNameTab0+32,objects+1);
|
||||||
|
lnSync(0); // sync with vblank
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -11,7 +11,8 @@
|
|||||||
"files.associations": {
|
"files.associations": {
|
||||||
"print.h": "c",
|
"print.h": "c",
|
||||||
"printf.h": "c",
|
"printf.h": "c",
|
||||||
"c64.h": "c"
|
"c64.h": "c",
|
||||||
|
"sstream": "c"
|
||||||
},
|
},
|
||||||
"kickassembler.assemblerJar": "/Applications/KickAssembler/KickAss.jar"
|
"kickassembler.assemblerJar": "/Applications/KickAssembler/KickAss.jar"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user