WIP: Shadowgate

Use this forum to share and discuss Uzebox games and demos.
uberlinuxguy
Posts: 86
Joined: Sun Jan 04, 2015 4:38 am

Re: WIP: Shadowgate

Post by uberlinuxguy » Mon Sep 14, 2015 1:26 am

Artcfox wrote:
uberlinuxguy wrote:
Artcfox wrote: I'm not sure how feasible it would be to use some sort of tri-state buffer chip so you can hook the 2 x QSPI RAM chips directly into the DAC lines, so you wouldn't need to devote an entire PORT on the ATmega644 for that purpose, and then you should be able to stream sequential bytes to the DAC at one per clock. This is just me brainstorming out loud; I'm not sure if it would even work.
Well, the DAC seems to have lines for RGB, so you would need to clock out the Red Green and Blue bytes (I think they are bytes, didn't look at the data sheet) separately to each line. But an interesting thought.
I thought that the DAC was already hooked up to a PORT on the ATmega644, and writing a single byte outputs 3 red bits, 3 green bits, and 2 blue bits to the R2R DAC, so once you set up the address you want to stream from on the SRAM, you should be able to write out an entire pixel (all colors) just by pulsing its clock line.
Yes, I checked again after I posted that and you are right, there are individual lines that make up the RGB intensities through the resistor network. I guess it is more feasible than I thought. Part of me wants to take my ATmega644 out of the uzebox and try to wire a couple of those SPI RAM chips inline to the DAC and see if I can stream pixles out of it. More for fun than for anything else. But hey, if you can stream pixles out of the SPI RAM just by pulsing the clock lines with 3 or 4 pins for the CE pins, that would be interesting, no? If I were to try it, I would move this to a different forum though. I don't really want to make it a requirement of Shadowgate. Making SPI RAM a requirement is tough enough for me to swallow, but I get why.

uberlinuxguy
Posts: 86
Joined: Sun Jan 04, 2015 4:38 am

Re: WIP: Shadowgate

Post by uberlinuxguy » Mon Sep 14, 2015 1:39 am

D3thAdd3r wrote:A quick demonstration to build motivation, 3 songs ripped from the NSF, press Up and Down to change songs. The first one I like and the 2nd and 3rd need some work, but there is definitely ways to get you the resources for this one. There are 13 songs and 13 sound effects used in the game. Most songs are < 25 seconds, some are much shorter as well, so it could be chipped away at until you had all of them. I will say, Shadowgate has some great music and it makes me want to play through it.
That is absolutely cool! I downloaded and played it. Nice touch with the splash screen!

This and your previous posts are why I love playing around with this thing and the community around it. I would say your posts are never "overboard." by the way. I really appreciate how indepth you guys go on this stuff. Helps noobs like me figure out the hard stuff. That is a shame about the NES->UZE missing palette.

User avatar
uze6666
Site Admin
Posts: 4449
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: WIP: Shadowgate

Post by uze6666 » Mon Sep 14, 2015 2:38 am

D3thAdd3r wrote:A quick demonstration to build motivation, 3 songs ripped from the NSF, press Up and Down to change songs. The first one I like and the 2nd and 3rd need some work, but there is definitely ways to get you the resources for this one. There are 13 songs and 13 sound effects used in the game. Most songs are < 25 seconds, some are much shorter as well, so it could be chipped away at until you had all of them. I will say, Shadowgate has some great music and it makes me want to play through it.
Very cool music demo! :mrgreen:

User avatar
D3thAdd3r
Posts: 2422
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: WIP: Shadowgate

Post by D3thAdd3r » Tue Sep 15, 2015 2:54 am

I too am a masochist for this stuff, so these are the goriest details I can dig up at the moment :)

I verified the address for the text in the previous post, by corrupting the first byte, saving a copy, and playing that copy in an emulator. It screwed up more than just the first letter on the first screen, so immediately you know it's compressed. I took some more outlandish guesses before I saw it's pretty straight forward and managed to get the first level screen to say "UZEBOX" as the first word. It is 5 bits per character, where 'A' is 0 and 'Z" is 25. 5 bits can only specify from 0-31 of course. Anything > 26(' ' space) is an escape character, or (\n, or scroll?) of some sort. Basically if you were to store the word "IF " with a space after it('I' is 8, 'F' is 5, and ' ' is 26) it would fit in 2 bytes, with 1 bit to spare to start off the next letter after space. The bit stream for "IF "(where 'I' is bold, 'F' is underlined, ' ' space is bold, and the remaining bit that starts whatever letter follows is italic) would be:

0b01000001 01110100

So that part is a simple piece of compression that saves ~38% of the space and probably much easier for a 6502 than Huffman Encoding, pretty elegant I think. Just using that rule doesn't get far though as you see:

Code: Select all

//All text in the entire game
THE LAST THING 43A5B TWERQRQESHGCLKKMBUNBU1UEQV ET1UB1EMQIR3FQFGEI4QGNDSNLAKSB3DUGNDQGRZPAN4GXLPOQAKQ HVQ3GDEIWL1FGBCQ NUBHUA1UI1HDRMBR1MOQEPUWQGFUBH3 AZAZRHLROQGRLUGEU5QG5EZZGQ2NCA5SUWVTUI2WUKDGXKDPXIBEARS4E 4GWITHIN 3THE CASTLE SHADOWGATE3LIES43AGCQSKPYDPWM2TIOEQAMQPKYCFNYGLGN EPWZBNPKSITI3CLIFMAGLGQAZALWN1KEBCIT1UBQSDSGHGT4SYXGPOQGGBCVUGI5GPF2BX1GOGUE2YCQ BGQ21U2LUORF GKQXUBDHFUA H3 AZUGAE5M EYDPSUWT1VREOVSC 5MVEGC4GQZEU2LWGVEWQC 5R45ODVGQEGHXIDLAST OF THE3LINE OF KINGS4F43AOIQQPVYXG4FZ22QLDL1UD1AGOSXISGXFR3CHGZNADHPAN4XGV2POQAEA1VFG25VGOG GKQXU2 GULC2ZUGBCUI Q N 3GDVM3CWHUK3CGKGD2PUKBCG1GOIGVMIWX2B2NXYNCRHGQ N3 AMZBEZ5ROWDVHMVRAEOQOHXIBGOD4KS NAME3THAT43ACZBNPIMSKOF1DWM2TKYCFNYGLGN EPY5P2RH2VF3 A2SVC 4TROUTTBHIUGAE3EGHQGSE2WTBADKDGXMRBDEWUFCEZGQSZAEPRGQZAEZ5K3EKUWSDMSAZHQG5Y 3GOQ NUOA44I IH2BX4B QI5Y5L1UDZGAIZZPD35QEWSBOQOGTABSAXROUZZHMSVC 4UKEREXQG5YMHKNBAG5FG3GQFCNEG5ANEG4QHXSAIZNGXNASNAGZQBDSB4ZXPOQHMAWX2PX4YOU CAN4KT DROP IT HERE4A15LDQG5OQAGO4IFGIHUOBE12VH OA44I IH2BX44GOUCH4H4G43AAGRR2QPGCPWZCM51UATSAB5D35QIT4KS A STONE WALL4A15CE5SUWQGUTAC 4SELTOSRGHQG5YDB TKIQRTKN1IETKYCKNBU1XB SHKNBQTYDP2CE5SUWQGRZAFOGVTTQZDOQ1TUPNSEZ4SELTOR DGREXQG5ZIPU2P2P3 AZKYDBGRMLTHMZZHXIEIS DYING OUT4H15BCPZKL1UBRXHI3FSABUGTOUGZXPOQGEBFGWG1EOAG3MMBGG2BX4BQ3GUEA12VHVEIIZVG3UKQ HUB UGQO2WG2BX4AEG5FGPOQGI1HCA EGVG31EOAG3MMBGG2B3 AAQDORZAEPNTS3GEWR1VS DGWQZBD4SDPMZZGRLUGEU4QGB DI4WDVHQHQHQG5ZGOGUKWAYGULC2Z3 A21UIR5GYEWQ BA4TVE5QG5Z2M2PU 32P2N3 AAUOHROXRTGHM1UIR4RYEWQ BA4TVE5R4SBPLTK4GSGRYA4S E4QDLUZZEPR5RW5YLEGTXKG3FUDDZ5C3MHKOZG GAVSNEG5OQGGBCU GFF2BX4CM2TIMCFGUSKLKERRBUOLLB TVYX1UBZGQIVSGGNGFECGOR IUGTPOQGGBCVUAMGF2BX4HRXXIHPITIFUL WIZARD3LAKMIR WAS A FOOL TO3SEND A BUFFOON LIKE YOU3TO STOP ME4A12YOU WILL SURELY REGRET3IT FOR43ANZVPDKM3BU1U2SETIV H1UAEGNAOTXIYUAVSNBSAGT5D5DN4GTSNGHKGR3HC3GAGUABAF4VQKDDZSI3CBDXCGNEG3MHKI4SAIZPAN5RQ3GVFGA HUQ1UBUW2 N E3DCQG3D2BUPIMGVFG2 G BCEPMBRFUWQ G3 AZDM EGHGYC 5QG5 E5SUWQGU1UIR5QGQDOTSC5MTQCRA4UIBWSEWVUID1ZA5IELVDI4SE5QG5YCM2T1UCEGNFUG5AN5QEG5FGNANASAKGUC FV2NLHKSG4Y DPAN5RGOGVDINVBIQEUXRUEBGEOGF 21UKRCGUA HUDGC1FUBMBR2BX4A43A ZZYMRXINZ HGCLWERBUV EIQPKZCM5I2QCXDWI2QSOLGYXKKMQRPYDP2B2MEWQEV2P2N3 A RGGVTUKRA5R5KE4VDK1QSRA5XIDDOOR4H15A4GTHUMP4H4G43AOG RUPUQI3YSLGBX1UBYXHGPAN5QSURXKM3 QY51UBBXHI3EGOXGV2NAG3EGRD3GTUBFPC3EG4UGNKSI2NGG IR2PAN5QGTSNBXHI3EGNFXBFCB5AN5SM2TGITDINYSGXZKPIVCPGBWN1WM2TGITA3ZMTY5P2MHKNDQKSNGXNHHSG3GTSORXHI3ASCXISPOQAM31GPC3IMPURH2BX4THE STONE WALLS SEEM3UNCOMFORTABLY CLOSE AS3YOU WALK DOWN THE3STAIRS4A15THE STONE PASSAGE WINDS3TO AN UNSEEN END4A15ARH2VFUBVEYAWXUEA GWG2L 4GCKIFHUK3DVCIAGQ N2BX4LDSG5OQBCIY3KG3 AYLTSXGMLTGSE2WTZAZEUYC5ROUZZHGK1TUOQTS YD2REXROQDI4WDVHGIC 4U1XXIBDEATH4A15AIT4KS AN ANCIENT TOME4A3IT SEEMS 43A3V1GZUTI2CLUNCKOSEEQPGCOLG2AYSLIV HUIRWOSFASLYDP2BVCIFGA NIWBDUO2WGUOBF CII1UFGHU3GHU2LVGOG Q1EQGGU2L3 AYLTSXQG5Z3 BSRGGQGAEMWQGUSVC 5QHPXIGMUST BE A SKELETON3KEY4A15APOQNFG2 GVEIIZFVG3UCG1EGHUW23EIXRUQ1VGOG Y3DGBD2BX4GDVGQQDORZAEPXIDSOUND3OF WIND4A43ACZZUMSHGAXWGZQSM3BU1IG RMPIETKRUMSHWM2TIVNZ HYDP2CM2SETGCLKGZQSM3BU1G SPVYX1UBXIRUGQI2NAAXKG4ZTUGPOQIDGH3 AAQDPSU5L3E4QGRKDGREOTTOSE5QG5YCM2T1UCA IWZNLEGT3AOZGYQGTCNLDUGSNCVQGCPAN5RGORF3 BEZ2LVUXIYDISDGWURYA1VUWQALVE5MZZGULTTHQG5YAGRYC 3QGGS BEWQELVDI5MZZGQTULGEPQG5YGTSNGGXGSNCQFVZNALAMNGXOYSKSAF3ANGCBISG3HQGGADCPD35SE5SUWU1TWQYEKWU1WURBHQG5YIT4KS A REMOVABLE STONE4A15EG5FGNANGGYQGTCNGXIRD5AN5Q2P2PUBF3 ABDMZEPROWDVHIQDOURBGQGUVTUI4QDI5IGUS DGWSDMSAZHQG51B TICETGBXIDKGQBNPUKEBR2QPIGN ISPYDP2AIT4KS A DOUBLE4BEDGED3BROADSWORD4A43AM2BUNMTU2CLIOGRANALKIKFB4PW FCOMRXKR3ZXGCPYDP2MHKNISG IW3EG3GXNEG5FGOSXIWCI3HVQBCPAN5QEG5FGNANGGAFV3FSAGTSI4ZFUGTPAPOQFM3IWHUE2YG Q1UOA HRUK3DUW2 N2DCA MG CBHGWGF2PX4ANKSI2NGG IR2NGDSFS4YSGGZNADAEGZG5OQHMAWX2BX4WAVING A SLING AROUND IN3THE AIR DOESN4KT SEEM TO3BE VERY USEFUL4A IT WON4KT3WORK WITHOUT STONES4A15BGOGVFG2 GFUQ1VGOGEG1MAWXFVMGCGU5C2CACXRUFGH DR3 AZYDI2WTRORDMSYFGA5LDVDMYCDOQ3QENGEXQG5Z3 BQ1TUOURBDEWU1WQGHLAAZGTROUTS A4TQCXQG54DVGQQDPSU4Q1WUZYE5R45ZGOGUKWAYGULC2Z3 A21UIR5GYEWRTTGGTVE5QG5YBVEOBCVVFMQZFUDRUBFUQL 4BHC2WWQ N3 AQQC1HL1TS5QG55XIGSUBTERRANEAN CAVERN3HAS BEEN CARVED BY3CENTURIES OF3SUPERNATURAL EROSION4A15CE5SUWQGUTAC 4QMIEUWSRGHQG5YDGNBQTIG USEQPKGIRMSNZXWKMCESLICP1UAGTYXKDD4SMCFSGGNGHBFCGZPAN5RCPGNZZKLGNBITIDKI2CFLZKLUVBXGBX1UBVQFCPAN5RGOGVMBGGDFU2LVGORF1FIDGGDCA IA1UWAUGUBCGUBF1FGQWXUBFUBUE3C5EG2BX4FB4TR5RPXIDWIND HAS3SUDDENLY DIED DOWN4H15THE LAKE HAS BECOME A3SOLID SHEET OF ICE4A15BQ3GUHC253 A2TZZEGGSDM1XMZZGSYCRGQDI4TLU ARGUZZHMKD1 ZEWQ EQD1ZAEOQEWUZZHNQEZEOU3ELMWSDM1WSARHQG5YEZZHXIEMELTS AWAY THE3ICE OVER43AOG22SETYXUBNN ZBU1GCPKN1IVNYCPKN1WM2TKKSEUAITYDPRV PKKSF4FCGBUZPDYXKM2TVMBITKCRAGGPDKEQWEQTESLYDP2ACL1UAGLEGNGXLAIR3GTSOZFCFSGXG5C5OQAKIIXVGOG SBNFU2LUBVEOBCVUNCADVQ3G A HU5IWX3 AFDIZEPQG5GDVGQVEMRGWDVEMRCZORLUPNESDGXXIBBODY AS BAIT4H12EVEN BEFORE43ANNAUTI2CLVMQWP1UAQXB2PC5OQGWAUG1MQWXUCGUKQWWIHVMRGPVQ3GD CW22H2BX4GTSNCSIY2GAG3IKEBFF2ORUGAHXSAIZPAN5WDVGQQDPSU4UGAAR4SE4RMLTHGZEGHQG5Y43AZQSMBPINZ HKI3  LWGAZVAVAIBWPKGAZWLGYXWGSKPYDP4M2TKYCMSHKCQRUI2QPLB SHWM3CGKPYDP2AAXGO3IMP3 A YCRGSEXITVGEGA4VSEZ4SARHROWDVHIQDOURBHXIDCRYSTAL3SPHERE TRAPPED WITHIN4A12YOU MUST FIND SOME WAY3OF FREEING43AOG22SETUWFZTGCOLGALDIIAYTYDP2BQ3GVMAWVU3KGDVG3VGOG1EUIWGG21UA HU4QEVVI5VGOG UGR2BX4ALAGSI3BAGBABSGNHKSI3AOZKAZSIYQGSAG3BFUCS3EGZXOQNBHHF5C3BFSAG3GGYSAGPAN5QMHKPFISNGGQGRUGTNEG3AORQIVPC3KGRSITIXKGR4RAKSIW5AN5QTSY4VQEZEOQQEQQAZEWQ1VTPIGQS BGOSDM1WQGUTAC 5MU2GADHQG55XIGLANDSLIDE LOOKS3LIKE IT OCCURRED AGES3AGO4A IT WOULD TAKE YOU3MONTHS TO CLEAR IT AWAY4A15POQNFG2 GURFUAWY3FH 4GCKIFGXRVC3I H2BX4AGTSNLAMNKH3GTUGNGGQEI1AMOUGNHAZGY BGSB3A2NAOVQGRZFUBSPAN5RGOGVMBRURFUCW2EUIHUDRUB WA HEWQGGUA HUGKI1VMRGP1Q3GDUYQMPH3 AAQDLLU5ISZAEOWDVEMRCZOQGTYEZ5QG5YMHKPFKSNH G5OQHEYAWX1FG2 GUQ13 A2S DGXQG5YRHURFVKGDRUGBCV2BX443A KNZUTKZ RMPGV PIETUZZYPIV HKGGB33BU1YDP2BGOGVMAWXFUQ13 AULTTHIEGGTFAR4U1TWQS1URGRLUPITTBLUM5QG5EZZGQYDD4VQC 2WTROUZ EXGBEKBGQQFGELOQEGGULVBR5IDI4SEMGBVCYEPQG5YMHKPFISNEG3ANBAKSNASDUGR4ZTSNLAGSISQFV5AN5QHXIGROCK GUST OUT FROM3THE WALL4A15CM2TKFYGLGCLKCRCMTGNZ ITYDP3Q3GUORH3 A2LQSWQEWRYEI5IEXXIACAN4A15BCPZKLIDGMQCM2SHG3 QI5Y5P2EG5FGNANLDUGSNGGXGSNHC4 GVGXLG3HIUDEG5ANANCUGSOZTUGTNGXNDAGAVSNALAMNEG4QNDHHB3BAIR3DAGCPD35SE5SUWQGRKDGGUGA4UNAOHR45CE2WQTS1UOUGDCDI2XXIAOF3YOUR ADVENTURE ACROSS3THE SEA OF BLOOD4A15BCPZKLIDIMCFLIFOQTUYRSKNZUTL1UDUGNAGNAUDOQGPOQG42YYIXU2LUB1FM3CH2PX5GOGUCANUE21GAQ1FVGPCIG WBCMGUSGMIXF2BX4BQ3GUI1GGDUBUE2WHVC22Z2B1GOGVFGI EPU2LUKWGEPUQ1 GIEBRU4GDKAGGF3 A2TAC 5IRYDAGEPQG5GDVGQGBSDOU1WUR FGEPQHMZ EXXIFIS REALLY3COLD4H15EZZGULTTGUU DKUWTRPMLU2ZDOTBAE5QG5YBCPZKLIDKGQBNPI3ZMTGBXKM2TWYBNPKGZQTKM4EQTGBUI2SLUMQR5YDP2GTSNDCGNGCCGGNGXNCUG3A G4WXGTUGTNDQHXSGZPAN5QTHE GEM FITS PERFECTLY3IN43AM3ZMTYDPQDKGQBNPIKHCKMBPKG22SETVQAZAIBNPDIB32QCGLGZXKM2TWKMBUPY5P2CE5SUWQGSYEGRGTZAZEUYC5NSEZ4SELTOU2KDHQG5Y43AYKHCKMBPKG22SETGCLUCLIGZMPICLGAITYDP2IT4KS A FINELY CRAFTED4F3WOODEN DOOR4A15IT4KS A SMALL TRAP DOOR3MADE OF POLISHED METAL4A15AANAYXFCG3CYQDGCGZ3HC3AO1HHBSG3FQBRSI3DQGTGNCYXGOZTSNHHSGUGTPAN4AGPOQAM3UG3M13 A22ID5I1TUPRPXIAREALIZE YOU3TOOK A BIG STEP4A THE3FALL IS QUITE FATAL4A15AGTSNGHHG3BAGGZNAOQYUFVUAGZ3GDQBXLNHKSI4ZTSNDIXKGRZNHC3GTSORHKIZ2AIR5AN5QGTSNGHTSISNDQGNH G3HKG4ZTSNCVQGCGPD35QD1UDGCCGGNGXNASNAOTSFWCG3HC5OQHE3DH E2YY2 XRVM3C1UDR O2CM2CWQ1F2BX4ARH2VFUA1UA EQI1HUM 2YG1MBDUOAYYGD2B3 AVRAD1TPI1REWTLU4UR1VXXIDSIGNS3OF BATTLE4A15CE5SUWQGRZAFOGUR BCY5QHMZZEGGQEGGTTK4GQGRGFXIZDM2WTTOSE5QG5 M2TKGKRNPGNZZKLGNBITGCPU2CLIEQRXIOFAQPIBUPUKEAGIQPIHDIS4OERQTI2QCPYDP2IT SEEMS TO BE43AOGKRNPVYXKGZQTKRUV GORUCMTVBUNCVAOQBPYDP51UDAXGSNDQGNASCG4XUBFCB3BFSAG5AN5QFV5OQAEA1VEIGUBCGVHM3 GQGFUQ13 AYYEKTGEUXQHMZZGGURBDGU1WQGGVQEYR DGXGFGEOGTDVGHXIAMAKE4A15FR1TUR5R4RKYDBEWUVAYZDK4HMR1TU4RMLTHXIDDRAGON4KS3MOUTH4H15IT4KS43AOYCHI2BRQSHYDP2AYOU RAISE43AGI3ARMPVGSKPGBXKNBQTKN1IFNYGLWM2TIOEAZZXIVMBQTYDP2A2IBTTORKYDBGRDGVCZMXODVEOQLQ4HQHXIAPAY FOR3YOUR CURIOSITY WITH YOUR3LIFE4A15GTSNFXHGCNIXBFNCQFVZORXLG3AGNEC3DUGTCB3GXNGTSO1AFV5AN5SY2CPKIQKESOLKZ RMPKM3CLWGKRNPKMRNP1UAEC3EG4RHKFR3GQFVPEN5ZTSNGDUCFR3GCFZZNKGRSI4ZTSNEGZSGZEG2NHC3GTSORYQDHG3CVQGCPAPOQCC2HR KBCGFU 3UCGHGGD2PXY 3HUGKI13 AIGEU5GMKBDI4QTVCY4UGATRTKGGHODVEOQNELKDGWQLQ4HQG5YEZZGXXQFAF IS OPEN4A15BGOGV32BIBOSEWQS1URA5QG5ZGOGV32BIBOVQEWUYCRDPQG5ZGOGV32BIBOSEWTTZDGA5QG5ZGOGV32BIBOSEWQS1URA5QG5ZGOGV32BIBOSEWU1VARZA5QG5YEZZGXXQFAF IS IN HAND4A15ATHE 44AUAXGCLGZ2RUQPIBUPUS2BRBUQPYDP3GOGV32BIBOSEWTTZDPQG5YMHKNGTY GG3PPAAKALUQ1G31Q3GDUEOGFH2PUCW22HUCIMQ1F1G3UKW3N2PVFIQEQGGVM212VH OIW5UQ1VQ3GDVBIGFH2PXZGOGVMBCW2EVUW3CHVMQWX1FGCIXRVHCRIY4PU 3N2PX4THE 44AUAXKYCLIOFZ32QPVBXKM2TGMBITYDGCPGCLIZZUTUV HIZZYPYDP2BGOGV32BIBOUU2KDGWVQEXNDM BA5QG5ZGOGV32BIBOVQEWUGAA5QG5YBGOGVE4IWXVMBFUEOA1GIH2B11VVVVV2N32ACQC5DN5QYOU PUT THE 44AUAXGBWM2TIVCETYDGCPKYRWPKR5VBXKGRZITYDP2ATHE 44AUAXKYCLIOFZ32QPVBXKM2TGZBPIBUPVBRQQNACMRPDKIBVLKN1WM2TIF ONZTYDP2AS THE SPELL WAS3CHANTED4F THE 44AKAL1BIQEUXRVKA REOIH2BX4AGTSNPPAKALVMBFUHC244IH Q1G3VGOGUK3I1GAQ1UA H QYYIGQBGIXRUYIXGIHUQ11GOGUAEQGQFUWRBIQH2BX4GKBRSGV2PD3GTSNIXHGNASDEGZOZXNCQBSPD3EG3GCCGGNGTQG4ZTSNGHTUG15FGNGADEBNDQGOZQFCG3MHKNGXNPPAAUAXYDP2EZZGXXQFAF IS WRITTEN3ON THE SCROLL4A15AEZZGXXQFAF HANDLE WAS3RAISED4A15EZZGXXQFAF HANDLE WAS3LOWERED4A15ATHE 44AUAXGCLIOFZ32QPVBWN1KM2TKYRNPYDP2ATHE SHAPE OF 44ACUC3EGORAI SB3EG3PPBIBPL C YEPQG5YVZZPY5LB TKM3BVLGDINZXZKPVGV 1KM2TIBWKYSHKN1KM2TWFAMNMTZDLKM2TIG GEQKPUBWKYSHGCLL1YFAF4A12EVEN IF YOU TRIED FOR A3HUNDRED YEARS4FYOU NEVER3COULD FOLL ME4H YOU4KRE AN3IGNORAMUS4H12HA4F HA4F HA4A TRY AGAIN3WHEN YOU BECOME MORE3LEARNED4A15GDVGU1UIRZA4UZZGXXQAKAL2BX4DB TIOEBVLKM2TL1YKAL2BX4DB TIGN IQPKM2TL1YBIBPQG5YGTSNPPAKALURFUEW3EIH2BX4GTUGNAXHFPFGNGUGVSNEGO5PBIBPQGWDVGTTZDOUZZHILTSWQDI4UGAA4SE5QG5YGKBRSGV2PD4ZTSNIXHGNASDEGZNGXNCQBSPD34EG3GCCGGNGTQG3GTSOZHTUG15FGNGADEBNDQGNGQFCG42HKNGXNGYXFV3AYUBTCPAN5RFIGGI XR2P1GOGVC22ZUCIMQ1FVG3UKAGG2PXYRHVEIIZFVGOBHVGOG1E4OQ1P2VFUYAMQFUOBF1GAUI1VQ3GVG3VGOGVC22Z1MRGPUBUKRCI4WAEG2BX4GTSNBHKSI3HC3LCFV3EGOXHSGSB5AN5QGTSNBHKSI3HC3LCFV3EGOXHSG5AN5QCM2TIG USHGYXKYRNPGCLUGN IQPYDP2CM2TIG USHGYXKYRNPGCLUGN IQPYDP2CM3CLIFZZLZKLKNCNMTGCLWM2TIICKNMTKI2AN YYCMTYDXB TGZ2RXKM2TIFZZLIBUPWEQAPGCPYDP2CM3CLIFZZLZKLKNCNMTGCLUFOQTIOEAZZXYDXB TGZ2RXKM2TIFZZLIBUPWEQAPGCPYDP2ATHIS BOOK4KS TITLE IS3THE CIRCLE OF TWELUE4A3YOU OPEN THE BOOK AND3READ IT4A15EZ EWQLTSXSUWU E ZGSEXMZZGR EU1UOGTROUZZGVQEPQHODVGTTZDOUZZGQLTSWQDI5MGAA4SE5QG52ZZGS A4TROQTRGKDOSEXLTZDPQG5YBGOGUWQHU2LUE2KKQ1URF EW3EIH2BX4BGOGUWQHU2LUE2KKQ1URF 24I IH2BX4BGOGUWQHU2LUE2KKQ1URF EW3EIH2BX4BQ3GUEA12VHVCIAEPURHULC2Z OGCG2BVFMQYYQ NVGOG1EOBCV2CQ KGFGIHU422X1M3IWHUCGVFIQEQGAX
I am using the following lookup table for the conversion above so you can see any time there is a '1','2',3',4','5' it is an escape character. I'm not using '\n', it is just wordwrap that did that.

Code: Select all

['A','B','C','D','E','F','G','H','I','G','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',' ','1','2','3','4','5',]

Not sure, but my guess right now is that the escape codes indicate to use the next 8 bits as something(or some number of bits != 5), because it definitely stops the bitsream from making sense when they happen. That guessed method would have the effect of breaking the 5 bit alignment and so you would interpret unintended bits as characters and get gibberish, followed later by words, as is the case so far(since later escape codes would eventually "break it back" into alignment and show words out of the chaos.), that's my theory anyway. I'll try that at some point and see if all of a sudden the dump is fixed with better understanding of what the break codes are.

I very happy to be wrong on the separate table as compressed reusable words, which would have been a complicated thing to figure, they are pointers(though the address they point to doesn't make sense since it uses the MMC3 mapper to page pieces of memory in). I guess when you see something like:

Code: Select all

00 a2 b6 a3 ed a3 fa a3 07 a4....
it's a pointer. Note that the 6502 use Least Significant Byte first, so that first pointer would be 0xA200, A3B6, etc. Since our memory view in the rom is not what it is to the NES with the mapper running...and I happen to know the rom offset where the table is, I just consider that "A200" as 0, and anything above it in the following pointers, as an offset from the real byte location of the text(from my point of view, not the NES).

I guessed the first pointer would be for the first screen and it is. I copied the second pointer over the first, and the text for the first screen changed to the "LOOK" description of the skull above the door so that verifies it, can tell where every string starts and it's probably sequential for each level. There is something like 168 of these pointers, and it seems like it points to a whole section of text, so 1 pointer for all the story on the beginning screen. I think with the break codes figure out all the text would just come out on it's own and there would be no need to tediously play through every last detail of the game for the content.

User avatar
Artcfox
Posts: 944
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: WIP: Shadowgate

Post by Artcfox » Tue Sep 15, 2015 3:47 am

D3thAdd3r wrote:I too am a masochist for this stuff, so these are the goriest details I can dig up at the moment :)
...
...
That's a brilliant analysis! And I finally got your music demo to play for me. Very nice!

Initially I was getting the error:

Code: Select all

Error: Cannot load UZE ROM file 'shadowgt.uze'. Bad format header?
But once I renamed it from SHADOWGT.UZE to shadowgt.uze then uzem was able to load it just fine. I smell another case sensitive bug lurking in uzem.

uberlinuxguy
Posts: 86
Joined: Sun Jan 04, 2015 4:38 am

Re: WIP: Shadowgate

Post by uberlinuxguy » Tue Sep 15, 2015 2:20 pm

D3thAdd3r: You are indeed the mad hacker.

I went back and re-read through this post with a bit more understanding of things, but I still have some questions:

- In a previous post you talk about how the SPI RAM get won't fit in 6 clock cycles. I am wondering why that is important? Is there a limit of wiggle room of 6 clocks cycles per pixel where I can do things like that? Because that would explain some of the padding I have seen in the other video modes, but I'm curious as to the reason why that's in there per pixel. Can those be combined? I know you still need to fetch pixel data on a per pixel basis, but what if I were able to use some register space for that? Or a RAM buffer(probably not really doable, I'm mostly just thinking out loud.)

- You posted some assembly code that seemed to load pixels inter-mingled with SPI reads. Looks like you were loading palette colors at 3 bits per pixel which would give me only 8 colors to work with. I assume that's only 8 colors per full screen? And can be any 8 colors from the Uzebox Palette right? I kind of like that way of doing it.

I don't know if the other game that uses a similar format, "Deja Vu" will need more than 8 colors, I'm a bit curious how you would tell.

User avatar
D3thAdd3r
Posts: 2422
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: WIP: Shadowgate

Post by D3thAdd3r » Wed Sep 16, 2015 4:16 am

uberlinuxguy wrote:In a previous post you talk about how the SPI RAM get won't fit in 6 clock cycles. I am wondering why that is important?
SPI ram speed sets an upper limit on the resolution/color depth you an achieve in a given part of a scanline, if you were to rely on outputting data directly as it came off the chip. Of course the longer you wait to update a pixel, the further to the right it will be, so none of it can happen leisurely. You could draw wider pixels by only changing every 7,8,9,10,11,12,..20..etc cycles, but then something 112 pixels/changes takes nearly the entire scanline since each pixel is so wide; besides looking noticeably blocky. You can help by "stretching a byte" and using less than 8 bits per pixel, at which point what scheme is used is pretty important. Hopefully I understood the question correctly there.
uberlinuxguy wrote: but what if I were able to use some register space for that?
Desperate situations you can't win(like the SPI ram racing an electron gun), you still have to win. I don't know what the right "unfair tactic" is here, but it sure smells like precalculation, linebuffers, clever register usage, and bit trickery are involved. The nice thing about using the original graphics is we know limitations the NES had to honor to generate them. It's a 4 bit global pallet sure, but it's not an arbitrary 4 bits per pixel, in fact there can only every be 4 different colors per 16 pixels across because of the way tile attributes work. It's only the starting point(or Most Significant Bits) of those 4 colors can change every now and again(16 pixels). To be clear, any tile sounding terms I mean in the sense of converting into and entirely uninterrupted bitmap bitstream. There is no possible way to make cycle counts if you do anything but sequential reads. Also implied, any "sprites" have to be overlaid before rendering like in mode 3. These would also have to be "erased" before they move to a new location. The game logic should be pretty light on cycles, and VRAM_TILES_V=26 would help with cycles(the music demo looked good at 26 I think!). You could double buffer the screen if it came down to it, and work on 1 buffer until it's done..then show that one until the next one is done. That would need to be tight assembly code for sure.

To draw 16 2(+2 implied upper bits) bit pixels like that, then load the top 2 bits for the new pallet for the next 16 pixel span, would only require (2*16)+2= 34 bits. 16 pixels at 6 cycles per pixel lasts for 96 cycles. In 96 cycles the SPI ram can generate 40 bits, and during the time you wait for each SPI byte you can do whatever needs to be done to setup the next pallet, read out of a precalculated buffer, actually output a pixel, whatever. Of course that "other stuff" is the hard part, since the last 8 bits of the 40 bit stream would land exactly the moment you need to be outputting the 16th pixel(the naive way), so you have to start the whole thing "ahead of the gun" as common to most every video mode. Then pray you have enough during possible "dry times". The code would definitely need an entire scanline inlined without any loops also. Then while drawing normal tiles where you have some free cycles, start to pre-fill the SPI ram line buffer for the 112 pixel part of the next scanline where you might be be getting slowly behind. As long as you don't run out before you reach the safe normal tile area it would work. That would imply keeping the tile vram in the '644s fast ram(so you have the free cycles to prefill), since really it's going to be sitting mostly unused otherwise. Totally theoretical, I have not laid out 1 opcode to prove that concept works...for something where 1 wrong "fact" breaks the whole deal in practice :| If it did work out that way, like it does in my little version of reality, that wouldn't even be as complicated as some of the other video mode trickery already accomplished.

User avatar
D3thAdd3r
Posts: 2422
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: WIP: Shadowgate

Post by D3thAdd3r » Sat Sep 19, 2015 12:35 am

I figured out more of the text format, there is escape characters(0b11110) where the next 13bits are a pointer. The pointer(whos base I discovered at 0b1110000000000, and so can scale it to match the table I generated of plain text). The keywords all evenly break on 8 bytes so after I figured out what that pointer actually meant it wasn't bad to grab the list, what I mean is stuff like this:

Code: Select all

//...
"MUMMY"	//keyword 48
"BANSHEE"	//keyword 49
"DEVIL"	//keyword 50
"ROPE"	//keyword 51
"TORCH"	//keyword 52
"MAP"	//keyword 53
"SKULL"	//keyword 54
"BOOK"	//keyword 55
"BELLOWS"	//keyword 56
"POKER"	//keyword 57
"CUP"	//keyword 58
"TESTTUBE"	//keyword 59
"BOTTLE "	//keyword 60
//and lots of duplicate "TORCH" and empty strings
Basically you extract the word, which is terminated by a 0b11111, then insert that into the bitstream you are already processing at 5 bits per character and run through it like normal. There are a couple details I still have to figure, because ~20 of the entries are skipped and do not get counted(which makes me consider it is actually a counting scanning routine to find it..) so all words after an index gets off by 1..then it happens again so 2..though it could actually be my code screwing up but it definitely brought many new sentences out so far.

I dabbled with actually laying some cycles out for some kind of SPI bitmapped mode related to my previous post. As far as I can see it works fine without a linebuffer and could build up a buffer for next line even if it was a 240 pixel wide bitmap instead of the 112. If someone with more experience would take the time to do a sanity check on it I would appreciate it before I invest too much time. I believe it shows that we could draw exactly like the NES does backgrounds(using a large repeating pallet for speed). The problem is the NES has 2 planes, the BG and the sprites, where the BG follows the limits of this videomode exactly, but the sprites have their own pallet(0 is transparent, so really it is only 3 colors they can introduce into something). I have to think about it, but with a yet bigger pallet(using 2k to have a 3 bit attribute, and then clever sprite drawing that takes care to alter the attribute of any 16x16 pixel slice it blits too), that might work. That is pretty abstract in my head right now and I'd have to think if that is really true. If someone can shoot my code down right now they will save me the trouble :lol:

Code: Select all


render_bitmap_then_tile_line:
;	Begin drawing the 112 pixels wide bitmap, the SPI ram is ready to read
;	YH is already setup for the upper 2 pallet bits for pixels 0-15 2 bit "attribute"
;	Y is pointed at the color pallet, where each color is repeated 64 time
;	this allows the upper 2 bits of YL to select 1 of 4 possible colors
;	every 16 pixels YH can point to 16 colors new colors, so 4 different colors
;	out of a possible 16 for each 16 pixel slice.
;
;	pallet format:(YH can choose between 4 sets of these, so the pallet takes 64*4*4=1024 bytes of 644 ram
;	this lets the upper 2 bits of YL choose a color

;	c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,//color 0
;	c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,c0,
;
;	c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,//color 1
;	c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,c1,
;
;	c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,//color 2
;	c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,c2,
;
;	c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,//color 3
;	c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,c3,
;



;	do HSYNC and setup stuff, in the real mode we should actually start out
;	ahead. this is for illustration to see how much ahead we could be for 
;	the next line. We could probably gain quite a bit during the right side
;	tile section as well...etc.



	in YL,_SFR_IO_ADDR(SPDR);	read the SPI byte comprising of 4x2bit values(pixels 0,1,2,3)
	out _SFR_IO_ADDR(SPDR),25;	queue up the next SPI read(18 cycles)
	ld r16,Y;				get color for pixel 0(upper 2 bits of YL selects color)
	lsr YL;				prepare for pixel 1(start getting pixel 1 into the upper 2 bits)
	out _SFR_IO_ADDR(DATA_PORT),r16;	output the pixel color we just read(pixel 0)



	lsr YL;				prepare for pixel 1
	ld r16,Y;				get color value for pixel 1
	lsr YL;				prepare for pixel 2
	lsr YL;				prepare for pixel 2
	out _SFR_IO_ADDR(DATA_PORT),r16;		draw pixel 1



	ld r16,Y;				get color for pixel 2
	lsr YL;				prepare for pixel 3
	lsr YL;				prepare for pixel 3
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 2



	in r20,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 4,5,6,7(pixel 3 is still in YL)
	out _SFR_IO_ADDR(SPDR),25;	queue next read(18 cycles)
	ld r16,Y;				get color for pixel 3(now we can overwrite it)
	mov YL,r20;			set up for pixels 4,5,6,7
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 3



	ld r17,Y;				get color for pixel 4(upper 2 bits are already there)
	lsr YL;				prepare for pixel 5
	lsr YL;				prepare for pixel 5
	nop	
	out _SFR_IO_ADDR(DATA_PORT),r17;	draw pixel 4



	ld r16,Y;				get color for pixel 5
	lsr YL;				prepare for pixel 6
	lsr YL;				prepare for pixel 6
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 5



	in r20;	save SPI byte for pixels 8,9,10,11
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	ld r16,Y;				get color for pixel 6
	lsr YL;				prepare for pixel 7
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 6



	lsr YL;				prepare for pixel 7
	ld YL;				get color for pixel 7
	mov YL,r20;			set up for pixels 8,9,10,11
	lsr YL;				prepare for pixel 8
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 7



	lsr YL;				prepare for pixel 8
	ld YL;				get color for pixel 8
	lsr YL;				prepare for pixel 9
	lsr YL;				prepare for pixel 9
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 8



	in r20,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 12,13,14,15
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	ld YL;				get color for pixel 9
	lsr YL;				prepare for pixel 10
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 9



	lsr YL;				prepare for pixel 10
	ld r16,Y;				get color for pixel 10
	lsr YL;				prepare for pixel 11
	lsr YL;				prepare for pixel 11
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 10



	ld r16,Y;				get color for pixel 11
	mov YL,r20;			set up for pixels 12,13,14,15
	ld r16,Y;				get color for pixel 12
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 11



	in r20,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 16,17,18,19
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	lsr YL;				prepare for pixel 13
	lsr YL;				prepare for pixel 13
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 12



	ld r16,Y;				get color for pixel 13
	lsr YL;				prepare for pixel 14
	lsr YL;				prepare for pixel 14
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 13



	ld r16,Y;				get color for pixel 14
	lsr YL;				prepare for pixel 15
	lsr YL;				prepare for pixel 15
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 14



	in r21,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 20,21,22,23
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	ld r16,YL;				get color for pixel 15
	mov YL,r20;			set up for pixels 16,17,18,19
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 15



	pop YH;				get precalculated base for next "attribute"
	ld r16,Y;				get color for pixel 16
	lsr YL;				prepare for pixel 17
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 16



	lsr YL;				prepare for pixel 17
	ld r16,Y;				get color for pixel 17
	lsr YL;				prepare for pixel 18
	lsr YL;				prepare for pixel 18
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 17



	in r20,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 24,25,26,27
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read
	ld r16;				get color for pixel 18
	lsr YL;				prepare for pixel 19
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 18



	lsr YL;				prepare for pixel 19
	ld r16,Y;				get color for pixel 19
	mov YL,r21;			set up for pixels 20,21,22,23
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 19



	ld r16,Y;				get color for pixel 20
	lsr YL;				prepare for pixel 21
	lsr YL;				prepare for pixel 21
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 20



	in r21,_SFR_IO_ADDR(SPDR);	save pixels 28,29,30,31 for later
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles later)
	ld r16,Y;				get color for pixel 21
	lsr YL;				prepare for pixel 22
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 21



	lsr YL;				prepare for pixel 22
	ld r16,Y;				get color for pixel 22
	lsr YL;				prepare for pixel 23
	lsr YL;				prepare for pixel 23
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 22



	ld r16,Y;				get color for pixel 23
	mov YL,r20;			set up for pixels 24,25,26,27
	ld r16,Y;				get color for pixel 24
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 23



	in r20,_SFR_IO_ADDR(SPDR);	save pixels 32,33,34,35 for later
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	lsr YL;				prepare for pixel 25
	lsr YL;				prepare for pixel 25
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 24



	ld r16,Y;				get color for pixel 25
	lsr YL;				prepare for pixel 26
	lsr YL;				prepare for pixel 26
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 25


	ld r16,Y;				get color for pixel 26
	lsr YL;				prepare for pixel 27
	lsr YL;				prepare for pixel 27
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 26



	in r21,_SFR_IO_ADDR(SPDR);	save pixels 36,37,38,39 for later
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles later)
	ld r17,Y;				get color for pixel 27
	mov YL,r20;			set up for pixels 28,29,30,31
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 27


	ld r16,Y;				get color for pixel 28
	lsr YL;				prepare for pixel 29
	lsr YL;				prepare for pixel 29
	nop
	out _SFR_IO_ADDR(DATA_PORT),r17;	draw pixel 28


	ld r16,Y;				get color for pixel 29
	lsr YL;				prepare for pixel 30
	lsr YL;				prepare for pixel 30
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 29



	in r20,_SFR_IO_ADDR(SPDR);	save pixels 40,41,42,43 for later
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	ld r16,Y;				get color for pixel 30
	lsr YL;				prepare for pixel 31
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 30



	lsr YL;				prepare for pixel 31
	ld r16,Y;				get color for pixel 31
	mov YL,r21;			set up for pixels 32,33,34,35
	nop
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 31


	pop YH;				get precalculated base for next "attribute"
	ld r17,YL;				get color for pixel 32
	lsr YL;				prepare for pixel 33
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 32



	in r20,_SFR_IO_ADDR(SPDR);	save pixels 44,45,46,47 for later
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	lsr YL;				prepare for pixel 33
	ld r16,Y;				get color for pixel 33
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 33
	

	//etc up to 240 pixels
edit-r20 and r21 I might be corrupting towards the end where you might have to juggle in more registers to keep getting ahead. It's more a proof of concept that you start accumulating bytes pretty quickly, for whatever use that is. The attributes I'm popping off the stack, there is easily time to pull them off the SPI as bits(4 16pixel slices per byte), convert them to a real pointer base, and push them while you wait for the next during the checkerboard output.

User avatar
uze6666
Site Admin
Posts: 4449
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: WIP: Shadowgate

Post by uze6666 » Sat Sep 19, 2015 11:44 pm

That code seems right at first glance, though that makes only four colors global?


Btw, just an idea, do you really need to have an arbitrary bitmap in there? What's ususally the maximum number of unique tiles per map? IF the count is low enough could mode13 with 15 colors mode be used and load data straight to ram tiles? Perhaps even store in flash the most commons tiles among all maps and use them along the ram tilesfor a complete map.

User avatar
D3thAdd3r
Posts: 2422
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: WIP: Shadowgate

Post by D3thAdd3r » Sun Sep 20, 2015 1:59 am

As far as I can tell there are always exactly 7*16= 112 tiles unique to each screen which was what made me sad about Mode 13 here. I do not like the bitmap solution at all, just that I think it might be necessary versus the time it takes to redraw all the graphics. Still, perhaps there is some ram tiles based method doable based on some assumptions we can specifically make here?
shadowgate_tlp.jpg
shadowgate_tlp.jpg (239.27 KiB) Viewed 2434 times
shadowgate_ppu.jpg
shadowgate_ppu.jpg (115.98 KiB) Viewed 2433 times
On the global colors, this video mode would allow possible 16 on the screen, but there is only 4 possible colors you can use in a 16 pixel wide slice, as per the NES(see in the picture where there is blocks of the wrong pallet, it only requires 1 byte changed in NES memory). But the next 16 pixel slice can have a different 4 possible ones based on it's attribute, where the NES had this restriction on 16x16 pixel blocks not just a 16x1 section. It is arbitrary to make that 3+2 bits to allow 8 different 4 colors pallets for 32 colors on the screen, but still only 4 per 16x1 section. The idea of going with 32 would be to manipulate mostly duplicated pallets to the areas where sprites get drawn. But some real thought would be needed, as it could easily suffer attribute clash like ZX Spectrum stuff.
shadow_attribute.jpg
shadow_attribute.jpg (47.01 KiB) Viewed 2428 times
How bad are 7 cycle pixels? I think we could do a 3+3bit 64 color bitmap display at ~205x224 using the same basic idea and restrictions with the same pallet size, just less repeated colors.

Edit-that is a lot of cycles to wade through and the beginning assumes YH is already loaded with the upper 2 bits(which could be just as easily 3)

Code: Select all

	in r21,_SFR_IO_ADDR(SPDR);	save SPI byte for pixels 20,21,22,23
	out _SFR_IO_ADDR(SPDR),25;	queue next SPI read(18 cycles)
	ld r16,YL;				get color for pixel 15
	mov YL,r20;			set up for pixels 16,17,18,19
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 15



	pop YH;***********************get precalculated base for next "attribute"**************************
	ld r16,Y;				get color for pixel 16
	lsr YL;				prepare for pixel 17
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 16



	lsr YL;				prepare for pixel 17
	ld r16,Y;				get color for pixel 17
	lsr YL;				prepare for pixel 18
	lsr YL;				prepare for pixel 18
	out _SFR_IO_ADDR(DATA_PORT),r16;	draw pixel 17
That's basically how the new uppers bits every 16 pixels concept works.

Post Reply

Who is online

Users browsing this forum: No registered users and 27 guests