C++14 på C64

Diskussioner om programmering

Moderatorer: Fanta_gbg, e5frog, stonan, Zlasher, hollowman

C++14 på C64

Inläggav carlsson » 4 november 2016, 10:40

En bekant till mig tipsade härom veckan om Jason Turners vlog "C++ Weekly" som i juli 2016 beskrev hur man kan kompilera ett C64-program i C++14. Kompilatorn genererar X86-kod, som han 12 minuter in i klippet kör in i en hemgjord omvandlare X86 till 6502! Sedan tar han bort indentering, klistrar in 6502-koden i Turbo Assembler (Turbo Macro Pro V1.2 by Style 2006) i emulerad C64 och lägger till ny indentering istället för att korsassemblera...


Det magiska är ju hans egen omvandlare från X86 till 6502, hur komplett den är då instruktionsuppsättningarna inte direkt är identiska. I princip använder han ju C++14 som en makroassembler, inte särskilt mycket komplex kod, och då är det förstås lätt att få det att fungera hela vägen men om han börjar skriva mer komplexa program måste han hela tiden ha i beaktning hur det behöver implementeras på C64 och vilken kod han kan förvänta sig att kompilatorn spottar ur sig för att det ska bli helt bra.

Men det är ett kul proof of concept. Hade han känt till DASM, CA65, XA, jASM och alla andra hade han inte behövt ta omvägen via Turbo Assembler. Hade han sedan en flagga på sin kodomvandlare som sätter ; på alla varningar och felmeddelanden kunde han pipa koden direkt till assemblatorn.
Användarvisningsbild
carlsson
VIC-20 Guru
VIC-20 Guru
 
Inlägg: 2325
Blev medlem: 10 oktober 2007, 16:24
Ort: Västerås

Re: C++14 på C64

Inläggav carlsson » 4 november 2016, 10:59

Åh, han gjorde en hel timmes föreläsning om detta i september, med ett mer avancerat Pong-spel:

Jag har inte kollat allt i detalj, men runt 1 timme och 1 minut in i klippet växlar han mellan X86 och 6502 i IDE:t, förmodligen har han byggt in sin omvandlare där.
Användarvisningsbild
carlsson
VIC-20 Guru
VIC-20 Guru
 
Inlägg: 2325
Blev medlem: 10 oktober 2007, 16:24
Ort: Västerås

Re: C++14 på C64

Inläggav bjonte » 4 november 2016, 11:22

Han har 8- och 16-bits-register i zeropage så det enda som demonstreras är i princip att läsa direkt från minne, skriva direkt till minne och hoppa runt. Skulle han göra lite funktioner med faktiska argument skulle det explodera i komplexitet och skita sig totalt då x86 skulle börja flytta runt i register och lagra på stacken och greja. Det är ett kul experiment som mest visar hur jäkla bra Clang är på att optimera bort kod men långt från att vara användbart i praktiken.
Användarvisningsbild
bjonte
Stormästare
Stormästare
 
Inlägg: 1858
Blev medlem: 17 april 2006, 23:12

Re: C++14 på C64

Inläggav carlsson » 4 november 2016, 13:58

Jo, vissa av kommentarerna till videoklippen är inne på samma spår. I bästa fall får man en X86-emulator, som bitvis kommer att vara en jättekludge och bitvis kommer att ha 1:1 mappning av instruktioner.
Användarvisningsbild
carlsson
VIC-20 Guru
VIC-20 Guru
 
Inlägg: 2325
Blev medlem: 10 oktober 2007, 16:24
Ort: Västerås

Re: C++14 på C64

Inläggav bjonte » 4 november 2016, 16:43

Jag skulle hävda att bara läsning/skrivning till absoluta adresser och loopar är möjliga att få bra. Notera att spritegenereringen blev 63 lda+sta. Det hade förmodligen sett hemskt ut i en loop, men jag gissar förstås bara.

Jag vill inte gnälla för mycket för poängen han gör är att en massa kodkonstruktioner som har kostat förr nu optimeras bort helt. Om någon skulle ge sig på att generera 6502-instruktioner i kompilatorn så skulle en modern kompilator verkligen kunna vara användbar.
Användarvisningsbild
bjonte
Stormästare
Stormästare
 
Inlägg: 1858
Blev medlem: 17 april 2006, 23:12

Re: C++14 på C64

Inläggav carlsson » 4 november 2016, 17:39

Han använder ju den här syntaxen, där anropet till vic.make_sprite i sin tur anropar write_pixel, en rekursiv funktion som sätter en enskild minnesadress och anropar sig själv med resten av argumenten tills listan är tom. Då blir ju koden också så. Jag kan för lite C++ för att veta om templatesen kan avgöra hur många argument de anropas med och då generera en iterativ loop istället för att rekursera. Alternativet hade varit om vic.make_sprite visste att en sprite består av exakt 63 värden så den kunde stått för loopen och bara write_pixel på enstaka värde.

https://github.com/lefticus/presentatio ... nes/Source

Kod: Markera allt
vic.make_sprite(0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
              0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
              0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
              0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
              0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
              0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
              0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
              0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
              0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
              0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
              0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
              0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
              0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
              0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
             );
Användarvisningsbild
carlsson
VIC-20 Guru
VIC-20 Guru
 
Inlägg: 2325
Blev medlem: 10 oktober 2007, 16:24
Ort: Västerås

Re: C++14 på C64

Inläggav bjonte » 4 november 2016, 19:34

En template kan både ta reda på antalet argument och genom att definiera en lista göra något med alla element. Det hade alltså gått att definiera en array med 63 bytes och sedan kopiera den till i en loop till spritebanken.
Användarvisningsbild
bjonte
Stormästare
Stormästare
 
Inlägg: 1858
Blev medlem: 17 april 2006, 23:12

Re: C++14 på C64

Inläggav bjonte » 5 november 2016, 08:47

Jag provade att göra detta, men det var svårare än jag trodde. Jag försökte generera en array direkt med en initializerlista som bygger en byte och itererar över resten av templateargumenten men kompilatorn verkar bli förvirrad när åtta argument ska generera ett värde varje iteration. Jag skrev om det så att en array skapas först och sedan fylls och då funkar det. Ironiskt nog så unrollar kompilatorn loopen så att det bara blir 63 moveinstruktioner i alla fall! Det pushas på stacken och sedan loopar den över det för att skriva till minnet.

Kod: Markera allt
#include <array>

template<typename Array>
void store_bytes(Array &a, size_t index)
{
}

template<typename Array, typename T, typename ... Args>
void store_bytes(Array &a, size_t index, T b7, T b6, T b5, T b4, T b3, T b2, T b1, T b0, Args ... args)
{
   a[index] = static_cast<uint8_t>((b7 << 7) | (b6 << 6) | (b5 << 5) | (b4 << 4) |  (b3 << 3) | (b2 << 2) | (b1 << 1) | (b0 << 0));
   store_bytes(a, index + 1, args...);
}

template<typename ... Args>
std::array<uint8_t, 63> make_sprite_data(Args ... args)
{
   std::array<uint8_t, 63> a;
   store_bytes(a, 0, args...);
   return a;
}

int main()
{
   const std::array<uint8_t, 63> sprite = make_sprite_data(
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,
      0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
      0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
      0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
      0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
      0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
      0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,
      0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
      0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
   );

   uint8_t *memory = reinterpret_cast<uint8_t *>(0xc000);
   for(auto byte : sprite) {
      *memory++ = byte;
   }
 
   return 0;
}
Användarvisningsbild
bjonte
Stormästare
Stormästare
 
Inlägg: 1858
Blev medlem: 17 april 2006, 23:12

Re: C++14 på C64

Inläggav bjonte » 5 november 2016, 13:37

När jag tänker efter så gör ju programmet precis det som jag säger att den ska göra. Generera byte för byte och sedan kopiera allså. Jag hade hoppats att kompilatorn skulle lagra det statiskt eftersom det inte ändras. Det kan göra skillnad om detta går att göra direkt i en initieringslista.
Användarvisningsbild
bjonte
Stormästare
Stormästare
 
Inlägg: 1858
Blev medlem: 17 april 2006, 23:12


Återgå till Programmering/prog.-verktyg

Vilka är online

Användare som besöker denna kategori: Inga registrerade användare och 2 gäster

Banners

BOA Japon Mediapalatset Nostalgibutiken
Quartex Retro Overlays Retroplay Spel och sånt
Super Motaro Söders Serie & Skivhandel vintagegames.se RG 2016
cron