From 09e7cfff4dc439cfb8e05b7c2e5882ad7ab32859 Mon Sep 17 00:00:00 2001 From: ifilot Date: Thu, 12 Sep 2024 16:00:38 +0200 Subject: [PATCH] Initial commit docview function --- .vscode/settings.json | 3 +- assets/fonts/font_8x8.psd | Bin 79237 -> 81624 bytes assets/scripts/create_fontmap.py | 6 +- assets/tiles/cx16-kakuro-tiles.pyxel | Bin 3524 -> 3519 bytes assets/tiles/font-tiles-8.png | Bin 2208 -> 2165 bytes assets/tiles/font-tiles.pyxel | Bin 2656 -> 2659 bytes assets/tiles/menu-tiles.pyxel | Bin 4579 -> 4579 bytes src/KAKURO.TXT | 17 +++ src/constants.h | 1 + src/docview.c | 150 +++++++++++++++++++++++++++ src/docview.h | 59 +++++++++++ src/main.c | 107 ++++++++----------- src/puzzle.c | 35 +++++++ src/puzzle.h | 12 +++ src/video.c | 21 ++-- src/video.h | 17 ++- 16 files changed, 345 insertions(+), 83 deletions(-) create mode 100644 src/KAKURO.TXT create mode 100644 src/docview.c create mode 100644 src/docview.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c79012..dd61a37 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "stdlib.h": "c", "menu.h": "c", "video.h": "c", - "random": "c" + "random": "c", + "docview.h": "c" } } \ No newline at end of file diff --git a/assets/fonts/font_8x8.psd b/assets/fonts/font_8x8.psd index 2395af5d19b2b930ba8518e147e2779ffa6ba15b..055cfb9a80b901a4671d0a0e0999f4dc11fd252a 100644 GIT binary patch delta 8408 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 diff --git a/assets/scripts/create_fontmap.py b/assets/scripts/create_fontmap.py index 554375b..ec8e88d 100644 --- a/assets/scripts/create_fontmap.py +++ b/assets/scripts/create_fontmap.py @@ -45,7 +45,7 @@ def create_fontmap_16(infile, outfile, rows): for k,x in enumerate(range(0,8)): px = img.getpixel((j*16+x, i*16+y)) if px[3] > 150: - b |= (1 << (8-k-1)) + b |= (1 << (7-k)) data.append(b) # last 8 columns @@ -53,7 +53,7 @@ def create_fontmap_16(infile, outfile, rows): for k,x in enumerate(range(8,16)): px = img.getpixel((j*16+x, i*16+y)) if px[3] > 150: - b |= (1 << (8-k-1)) + b |= (1 << (7-k)) data.append(b) with open(outfile, 'wb') as f: @@ -74,7 +74,7 @@ def create_fontmap_8(infile, outfile, rows): for k,x in enumerate(range(0,8)): px = img.getpixel((j*8+x, i*8+y)) if px[3] > 150: - b |= (1 << (8-k-1)) + b |= (1 << (7-k)) data.append(b) with open(outfile, 'wb') as f: diff --git a/assets/tiles/cx16-kakuro-tiles.pyxel b/assets/tiles/cx16-kakuro-tiles.pyxel index afd041c94d798cb84a82f967325f7d4529795ca2..52cc88937058a8896c55b6e234eb7cbef9f63fcb 100644 GIT binary patch delta 1886 zcmZuyc{m$r9!^EYZR@D6I9kRPTcYZSbKQ!ybxSp_ZC6ztjiba7)lp@f8`Moxp~MkN z;z-9;b%u7RmIMhpkpwk$HR_m{XJ(#f_u21z-uL(YzW4q8{(WDAd%;rIoq+t(0Dzz% zK#rgR*T>u%UdflbhW__S-~G!cF`?B`)(uNGXUh)FTOOMndVHmzx+bWK2pmNhpRp4Da(o=5 zcD{$Awvj6_iK85=?RLhvJR?0=c;p>1z0tR)KNK61vbleRhT67Uh_!O&l8jfw_V4yg z>>t_wbHd1dxwPaYN{>QG8+*G>Ma?aU-aLFlTis=rHK!-)DMx?ny`Z1Cu)O*AeWg3U zSZ5s!Ev;0HOAsHBTHrlTVc&wx{X4q`i*b7xo(M?2zsD7;B$FL~a)bw*_tW zH#<~0O0@cd{^;+ZnWaL!vBXq8=`^8z8o-PbIt`CUpYD9xBqUs+FlA~{N5 z$+E+m^R=ZlRG&#@e;_`dc*AqB_+ehc*Q@+Qbt5}+w|T#2lNU^cR!$$nhMX69s9=F? zjdTgnadwk5DyP$O|H7Z69@mxSx>RG7})vV%7ra-DETm|9 zRYFsJJYkjTvQ<>|L#Gz!K`I!oW9%1v`_-Mw=AxKqoMkziN z)a=21$0_5f=CwH(Wm?uOy*mB?%Os-H7U4UINln~uSmr0Uech#z?rH9hOB_29rDJ+V zqHQz!rukSmkUV3kst}>Et2(4f6I7z;`NV6}J4|J_>}E~qE!Zbl}MD~WE&R^WN-1)kmjxyVesCWR%yRk9d=#JL>00oQYSGbxL$|daG4_; z^Sg@|8kN0}Da*@EfZog}I*{ z1%1tdI9m0^c{JVPU&BlRZ=x3+cdtCTIU!qmPGwVMq2S!NG=q196J^y@`p1-f$$scd zpo%J=7BQg4Ccx9gRk`g8*5;OsO~wc$Q!?LE%klf~+RpI|h}fVSn?!d4)~1>|b4piv zG#;K+AQ%nSakTNWEO^q0)i?+5z}f_Sg19OZkah)6K3jSDp-~qznu|!#YR;H}9T;C3 zxxA9nydAWf7oMje%d(q8=7(!7O8T_IRNDH+z|TY)$ubFmMlyS&FH`J>V0#QpNWEn= z&!)vsGe0~}ASGG_0X0(g%^k!&97TsbEl<-+D_SaLkf`*^86}WNIl}!NW+T?RC%Sw z-8#iO_00MDVOGX6O|4s!V^CimN4j=)i2M(T#%7qCWoraRI1^pwaa~k?*T~E@R-b(z zr97quX@e+=OH?+-8S#4TZ#>}G94(2yoL~fLstuhRbPZutKQ@z(H#e#el(4UqU25&*BSs>JF^eiAv_STdcmPws5yL2#VtGf(O0xbdx0fkF~|r zSuZUrDa_A{y-D2TeLNcP9pN|0oI24>Huq-kY{wh#$>(f$$$vayH!GbFnU2DN%j|Uy z;~c0f$B-C=;v|z?vqv&j+u8*H0Oax@%mW4r3Ig&%>1844J^$$g6DE33=+BhGEQ{)zoOb^^ z#~c0qh=Blrdx7z{kx=c(@ZjrCXZWN6e`X!VMGWlw=nseP|8c+*YH~X4c)Of<5c*^3 eZ`D^60EiB`cl-CnX9Z4w`FWSYt0O!S0QeQ=U4^j# delta 1799 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 RwL1U+002ovPDHLkV1m|OZDRlc delta 1402 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 MWJfL;wuN9p0N*@{3;+NC diff --git a/assets/tiles/menu-tiles.pyxel b/assets/tiles/menu-tiles.pyxel index 6bd59def5895c1455a73a52e8875e784114f0b5f..79187303e29a43737468c9988c88c8e4ef130527 100644 GIT binary patch delta 1863 zcmV-N2e|m-BjY1~P)h>@6aWAS2ml(eC|TOMkt*Z{002lF000aC003lfV?<$eVJ>QO zZ*JXLO^@3)5WVlOSoquoA|;YiZbjOp0kTPu251ik0d)}^woTpoX1`7Y zyy*7FU2GS>$aKGL)BCg;ukeq;@3!l8>IQTZ+fz~#r+vFm>qjP5`?igT)1z~-J>10s zx6Ubaci%sHbQgCc+t(D^wE?={4&xNj{y4_2XAkk1y8czSP7lLDPs}uv<64;iS#FB| zo|`L`p~csK?Yh4kx%dgWOWRL({QxzL(B=PN)G)fbKhpI_T6`0u&iHG(az3HE-@Rt- z+N+7eB6izd?6><)lD_yd95f&lTJf}c+PE>S@v5iP%Tjop*pF`hfli;1JPij@3hN2m zY#-8^PwtQRDf8qq>{56CWIXju>JZ!1_en?%cX~d5sNx)ERm}2iET@l;fn~hdY>II# zK*0li9s=7lT-SJXd4^-$Y*G@qI>W0~RjpP6JHF*=<($A?n8YY>IKyceAqZTb;q|(% z^+lR9?0r>1I0eTOg1(BG;w;CZ@F~y`X2+{Yy;pd}nB z!RC0eE>_i7=bTwjcTt8$#58Sa_SjAvjzGrZ>e&hUosi@3|{ zcZM5TFFIalWxZ&gu9S75>*6X|7drpWiT<^IoEQCT{kXt9Q_}izO3ymaF6-Gj&C_Q+ zhoE`-tmmeI-kJ4$d#m~TtmpMw_c33|y3_gePI&5kdM`Wy53=rbT)vid2Y9Y;j5^+b zkn2l|Q@9a6nrENqxz7EHI+Mb4zoO2h@Z7JcGbubUPwGqxubC&srtn7crt{ep ztT*ad3OB+NaLf5b{WN*~QpZwwUcab+pT;qN%8|mo@ByB=zNo7vuV2(vlb^rT$+X|d z4`6C#dcv?GsF&#pE2+>WFhwaf1J6-ZQZy|hQ#h%berlV-OWE{e+Y~|a0luTCB_Uuu zibgU5blGZAN`S60k`kaRW{W86iIQCvs>!h38h(JB4Err(upb$d3trb?^u%$0#RvhK z968!l!=9@wXCBaIFFj+$uB#|e<%Vq+*+!sibL6OVV=FPwXjrqWMx`68S{YtS^)iTD z%omywBkl{`lo9)dHqo&EA|-<0*np7|!7#G}BP9YWwqT@0U{yL%BC_(LL}V32iO8xJ zB_gXvln6;=BSuODy6nVAiTI{cU`2^Qw<<-6K)0$yi9na#7%36xR$i2dtb!;JS=FLM zWYvfgft4#niNMMkQ6jzzS$XM!B)U@G!ho*Jk1=|%>Io-44(K{BMh@u)dEz47S{{?i z1RsBN=?N#V$&f^^UMZ1okOqKsYYwn1k!~Yv5a@;+xpP1_7+IV^H{=dCV--r709K)r zr3S2mlL=&%)lMr!PXw7jR@tu2Dky$!rYkXQGhK;eqaLRxvSp(lrzf)7XSx#8MrqU& zPTqQvRaQIoI6aZoPCZUfWVKU|(-Yab&2)by)@@cn@ouvUig}w=P~6+Bf@0rh6%_wA ztDqP->T!A^Kh>zm>4{oiQIS>laJcbg#lumL(-YalQIFFTR&u42XxYP2X*FHT9*#;2 z8#V0V$n(KY4SP89d`LIQI}XyVa8z2@6Ea=|hjfGNdLZ3ewmongtdV^W+y^UU;{&p5jqH3t zcC8g%0V`XIe4ysGl3i3_Wu5GbAS*B1B9L7hWM2fbJ9@b8zHJrMTtK65n?dFhvX@YK z300SnyM+8D6fU7l_9e524+;6Rfh~XXp7|;D{kHq0K3@I)aM&OFSG)Kry^CFHKOT;0 z^Y%+Rem!o-P4vb1`D04o+=GB{*%jNUGjbAQT55_5R&TdT2J!MP2;# z)E5JbH;;cu_~9w^jjA8Ng#4U-I>ck_(~IdN$CO7Z#nnIm0#Hi>1QY-O2nYZgu(KKm zZUO=tu(OH@{{{jYu#<}rZ3r5$C|TOMkt&iAG6EW~lQa=F0vfQBY!NmB8nBb35kI+t BpZEX( delta 1863 zcmV-N2e|m-BjY1~P)h>@6aWAS2mmmwC|T_la)aas002lF000aC003lfV?<$eVJ>QO zZ*JXL!H(ND5WVkLEPQSPkrGKMw<2xQ0NEr+1GEPN0oSIpMr7HrwaErS|GgSn!< za_Ox+?LNxVo0-SaBlZ32`g*a7-IsV;JiGor{5SmH#&79=DE|*gq5c{Ey=_yszS*zS z057`zaTnXgFEZV4+w?wd#yk9@@Vo7Low@TSY!7#F zz^!u%-QD+(Ufspr$o4hGc5Q&}x5GF^v_Foq>)As*rmlb0t<%GB(GxSxZ{(*izBY7Gwq!iW@ zw%I!0S1acP_QE7afx{V2!w5m(`V6nv zb**pGoMG>)3c@Kko)Gk1%oJxi4uwyFhA_KcMe4o6D<)spI$vgr^>!QzpMo{xQ1}$B z9f!hyr*NxrD13_7jYHL`;5^V!xZwiQQ1}#YGY*C4cxfm+mzIXY9hZfM!o5^cE5zn_ zF%LG!i*>Q8zB&(O!Es@{rD6UUZ)ur7##@%G6RcNRF(0f;>6j1lEIsp?@eIrd>s8jw zXU4zb{NRGC3g&}(s|@p*;d$XA|0>sahUfZ!VqBHu{LFCAd}cfY^O@l_KX-;V{9MFc zUcWQk$a>N7IxFi%^K_-G3tbmi$-2<_cTV)L_2azgU+c#O=9!Y#k5hWqd3IUP&S{=L z>p29?(`P+54fM{e=i6J&-)B9q*Se4SO4gmur+30r=hJ)P33!lor{nUqtUJJSePh&r z@rGPqQk=q#@XVo?% z>Z&&UzCc~omisErDZCUuI?r|PSJaslp8FMbCWYsIMV(3Efq7DAQh3cgDK>>Sk~f{t zreM8M$5OZvo`74z6u~!t?rnMg266`BRP*?u8HV%=JZGHF^D_uA2P*rB0^( zMt%WPE7KE(6+yjBPgqHXE`cdZsTp{VqLQL%5t+hC)%0826kf`vU)!b#k`M45MJ)*d z<54t{5unRfi&6q~jggc9T`^lkSx=Pgs!&aa?bh%I$jPwZG6wsRF}dJ%4MtCY99N7G zpvjS=O*QPf%5vrbZT8YLR_wZp0#$C}aJ1|lruwn~FN(5G=6D1-mFG@sKL6nHB zYEdGxYD9^UL^fiiM4-z~jFgB|I|VCB1iDozN(8!9B}xRk?8ZomK)3RuL}V32iO8xJ zB_gXvlnAU`AxZ>R&WI9mFJxuY14(qH?81Pq%datdvFZsYJ`U(QFGddO26^Km-CACg z$pjyNb?FHw+hj9gs-I@a|OQhS#8U(r_NA4WZ4Mr9x&<(l6%~*v}CV*9_ zWT^qG;A8?>Wwp}^(Gx)?kX5#8vkHn|o9Rjn+e}yD*r>~WB8Et?!Td=U>vEkK_V6>_Wr$4bV?xrX-rmOUJ8AK(Cg zi9HI4Uii2^lYfL%KmuJ&EX5y-9$axMbd9X(uk-?j>BE}+r3%^-6L*-NOr zgsMx(T|)j63YX9&`;ytihlKpuz!v#`%>0!4e%pOgAFqCYIP8!8t6lt*-o-Ap9}ma0 z`EZQg>2MSKK8+{ml*r14dT4k>&6|zKfBNStw!;(X7v`rIzWtJpUys}IpnfraV)^Oi z@8Wn`zxeIha{2E4+n4Wuy}5by=H+tv{BPrz%hiMNPd>-b_s9Km8Bar;r{z*LJ_`Kk zt}p0=Q$K#z`1y6io!&hDz2S$6NQZcgeR?r{FHlPZ1QY-O2nYZ$tg{*i zZUO=@th0&<{{{jutdolnZ3r-|C|T_la)Xi)G6FEHlQa=F0x+zTY!NmBFszfL5kEPM Br+@$e diff --git a/src/KAKURO.TXT b/src/KAKURO.TXT new file mode 100644 index 0000000..39ae80b --- /dev/null +++ b/src/KAKURO.TXT @@ -0,0 +1,17 @@ +KAKURO +------ + +Kakuro is a logic-based number puzzle game, often described as a cross between a +crossword and Sudoku. In this game, players fill a grid with digits from 1 to 9, +with the objective of matching the sum of numbers in each row or column to a +given target. However, no number can be repeated within a single sum. Each clue +is represented as a small number in a black cell, dictating the sum of the +digits to be placed in the adjacent white cells. + +For the Commander X16, Kakuro offers a nostalgic experience, blending the +puzzle's classic challenge with the retro charm of 8-bit computing. Players +navigate the grid using the mouse and inputting numbers via keyboard. The game +tests mathematical reasoning and strategic thinking, making it an engaging +pastime for puzzle enthusiasts and retro gaming fans alike. The simplistic yet +captivating design ensures that Kakuro on the Commander X16 is both a mental +workout and a tribute to vintage gaming. \ No newline at end of file diff --git a/src/constants.h b/src/constants.h index 9eb1f64..683a8fb 100644 --- a/src/constants.h +++ b/src/constants.h @@ -57,6 +57,7 @@ #define RAMBANK_TILE 0x03 #define RAMBANK_COLSWAP 0x04 #define RAMBANK_SCREEN 0x05 +#define RAMBANK_DOCVIEW 0x06 // puzzledata settings #define TLDT_REVEALED (1 << 4) diff --git a/src/docview.c b/src/docview.c new file mode 100644 index 0000000..66b14ec --- /dev/null +++ b/src/docview.c @@ -0,0 +1,150 @@ +/************************************************************************** + * * + * Author: Ivo Filot * + * * + * CX16-KAKURO is free software: * + * you can redistribute it and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * CX16-KAKURO is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see http://www.gnu.org/licenses/. * + * * + **************************************************************************/ + +#include "docview.h" + +/** + * @brief Initialize screen + * + */ +void docview_init_screen() { + // set scaling (resolution: 640 x 480) + VERA.display.hscale = 128; + VERA.display.vscale = 128; + + // layer 0 + // This layer contains the game background and the puzzle background; this + // includes all 'static' squares + set_tilebase_layer0(TILEBASE_MENU); + + // layer 1 + // On this layer, the values that the user fills in for the tiles are shown + VERA.layer1.config = (1 << 3) | (2 << 4) | (1 << 6); // T256C + VERA.layer1.tilebase = (TILEBASE_FONT8 >> 9); // 16 x 16 tiles + VERA.layer1.mapbase = MAPBASE1 >> 9; + + // enable both layers + VERA.display.video |= 0b00110000; + + // enable sprites + //VERA.display.video |= 0b01000000; + + docview_clear_screen(); +} + +/** + * @brief Prepare screen to write text to it + * + */ +void docview_clear_screen() { + fill_layer(TILE_BACKGROUND, LAYER0, PALETTEBYTE, 64, 64); + fill_layer(0x20, LAYER1, 0x00, 64, 128); +} + +/** + * @brief Write string to screen + * + * @param s + */ +void docview_write_string(const char* s) { + uint8_t x = 0; + uint8_t y = 0; + uint32_t map_base_addr = MAPBASE1 + (y << 7 + x) * 2; + + VERA.address = map_base_addr; + VERA.address_hi = map_base_addr >> 16; + VERA.address_hi |= 0b10000; + + + while(*s != '\0') { + VERA.data0 = *s - 0x20; + VERA.data0 = 0x02; + + x++; + if(x >= 80) { + x = 0; + y++; + map_base_addr = MAPBASE1 + (y << 7 + x) * 2; + VERA.address = map_base_addr; + VERA.address_hi = map_base_addr >> 16; + VERA.address_hi |= 0b10000; + } + + s++; + } +} + +/** + * @brief Load file into memory + * + * @param s + */ +void docview_load_file(const char* s) { + uint8_t *ptr; + asm("lda #%b", RAMBANK_DOCVIEW); + asm("sta 0"); + + // load puzzle into memory + cbm_k_setnam(s); + cbm_k_setlfs(0, 8, 2); + ptr = (uint8_t*)(cbm_k_load(0, BANKED_RAM)); + *ptr = 0x00; // write terminating byte + + asm("lda 0"); + asm("sta 0"); +} + +/** + * @brief Print file contents onto screen + */ +void docview_show_file() { + uint8_t x = 0; + uint8_t y = 0; + uint8_t *s = (uint8_t*)(BANKED_RAM); + uint32_t map_base_addr = MAPBASE1 + (y << 7 + x) * 2; + + // set docview ram bank + asm("lda #%b", RAMBANK_DOCVIEW); + asm("sta 0"); + + VERA.address = map_base_addr; + VERA.address_hi = map_base_addr >> 16; + VERA.address_hi |= 0b10000; + + while(*s != '\0') { + if(*s == 0x0A) { + x = 0; + y++; + map_base_addr = MAPBASE1 + (y << 7 + x) * 2; + VERA.address = map_base_addr; + VERA.address_hi = map_base_addr >> 16; + VERA.address_hi |= 0b10000; + } else { + VERA.data0 = *s - 0x20; + VERA.data0 = 0x12; + } + + s++; + } + + // return to original ram bank + asm("lda 0"); + asm("sta 0"); +} \ No newline at end of file diff --git a/src/docview.h b/src/docview.h new file mode 100644 index 0000000..8547fa6 --- /dev/null +++ b/src/docview.h @@ -0,0 +1,59 @@ +/************************************************************************** + * * + * Author: Ivo Filot * + * * + * CX16-KAKURO is free software: * + * you can redistribute it and/or modify it under the terms of the * + * GNU General Public License as published by the Free Software * + * Foundation, either version 3 of the License, or (at your option) * + * any later version. * + * * + * CX16-KAKURO is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see http://www.gnu.org/licenses/. * + * * + **************************************************************************/ + +#ifndef _DOCVIEW_H +#define _DOCVIEW_H + +#include + +#include "video.h" + +/** + * @brief Initialize screen + * + */ +void docview_init_screen(); + +/** + * @brief Prepare screen to write text to it + * + */ +void docview_clear_screen(); + +/** + * @brief Write string to screen + * + * @param s + */ +void docview_write_string(const char* s); + +/** + * @brief Load file into memory + * + * @param s + */ +void docview_load_file(const char* s); + +/** + * @brief Print file contents onto screen + */ +void docview_show_file(); + +#endif // _DOCVIEW_H \ No newline at end of file diff --git a/src/main.c b/src/main.c index 00ffe3f..8facee1 100644 --- a/src/main.c +++ b/src/main.c @@ -22,93 +22,70 @@ #include #include "video.h" +#include "docview.h" #include "puzzle.h" + #include "tile.h" #include "mouse.h" #include "menu.h" #include "sound.h" -uint16_t puzzle_filesize; // file size of the puzzle files - -void load_puzzles(); // forward declaration -void save_puzzles(); // forward declaration - void main() { // load assets into memory - init_screen(); + //init_screen(); // enable mouse init_mouse(); set_mouse_pointer(0x30); // load sound engine - init_sound(); - start_bgmusic(); + // init_sound(); + // start_bgmusic(); // load into VERA load_tiles("mtiles.dat", TILEBASE_MENU); - load_tiles("tiles.dat", TILEBASE_GAME); + load_tiles("tiles.dat", TILEBASE_GAME); load_tiles("font16.dat", TILEBASE_FONT16); - load_tiles("font8.dat", TILEBASE_FONT8); + load_tiles("font8.dat", TILEBASE_FONT8); // load assets load_small_digits(); - + + docview_init_screen(); + docview_load_file("KAKURO.TXT"); + docview_show_file(); while(1) { - clear_screen(); - - // load puzzles into memory - load_puzzles(); - - set_tilebase_layer0(TILEBASE_MENU); - build_menu(); - while(1) { - if(menu_handle_mouse() == 1) { - break; - } - sound_fill_buffers(); - } - - clear_screen(); - set_tilebase_layer0(TILEBASE_GAME); - build_puzzle(current_puzzle_id); - gamestate = GAME_PLAY; - while(!(gamestate & GAME_QUIT)) { - puzzle_handle_mouse(); - puzzle_handle_keyboard(); - show_game_time(); - - if(gamestate & GAME_COMPLETE) { - break; - } - sound_fill_buffers(); - } - save_puzzles(); } -} - -void load_puzzles() { - asm("lda #%b", RAMBANK_PUZZLE); - asm("sta 0"); - - // load puzzle into memory - cbm_k_setnam("puzzle.dat"); - cbm_k_setlfs(0, 8, 1); - puzzle_filesize = cbm_k_load(0, 0) - BANKED_RAM; - - asm("lda 0"); - asm("sta 0"); -} - -void save_puzzles() { - asm("lda #%b", RAMBANK_PUZZLE); - asm("sta 0"); - - // load puzzle into memory - cbm_k_setnam("@:puzzle.dat"); // force overwrite - cbm_k_setlfs(1, 8, 2); - cbm_k_save(BANKED_RAM, BANKED_RAM + puzzle_filesize); - asm("lda 0"); - asm("sta 0"); + // while(1) { + // clear_screen(); + + // // load puzzles into memory + // load_puzzles(); + + // set_tilebase_layer0(TILEBASE_MENU); + // build_menu(); + // while(1) { + // if(menu_handle_mouse() == 1) { + // break; + // } + // sound_fill_buffers(); + // } + + // clear_screen(); + // set_tilebase_layer0(TILEBASE_GAME); + // build_puzzle(current_puzzle_id); + // gamestate = GAME_PLAY; + // while(!(gamestate & GAME_QUIT)) { + // puzzle_handle_mouse(); + // puzzle_handle_keyboard(); + // show_game_time(); + + // if(gamestate & GAME_COMPLETE) { + // break; + // } + // sound_fill_buffers(); + // } + // save_puzzles(); + // } } \ No newline at end of file diff --git a/src/puzzle.c b/src/puzzle.c index cbfb909..84b57a6 100644 --- a/src/puzzle.c +++ b/src/puzzle.c @@ -38,6 +38,7 @@ uint8_t gamestate = 0; clock_t game_start_time = 0; clock_t prevtotal; char game_timebuffer[10]; +uint16_t puzzle_filesize; // file size of the puzzle files /** * @brief Build puzzle @@ -798,4 +799,38 @@ void print_clock(const char* s, uint8_t y, uint8_t x) { x++; s++; } +} + +/** + * @brief Load puzzles data into memory + * + */ +void load_puzzles() { + asm("lda #%b", RAMBANK_PUZZLE); + asm("sta 0"); + + // load puzzle into memory + cbm_k_setnam("puzzle.dat"); + cbm_k_setlfs(0, 8, 1); + puzzle_filesize = cbm_k_load(0, 0) - BANKED_RAM; + + asm("lda 0"); + asm("sta 0"); +} + +/** + * @brief Save puzzles data to SD-card + * + */ +void save_puzzles() { + asm("lda #%b", RAMBANK_PUZZLE); + asm("sta 0"); + + // load puzzle into memory + cbm_k_setnam("@:puzzle.dat"); // force overwrite + cbm_k_setlfs(1, 8, 2); + cbm_k_save(BANKED_RAM, BANKED_RAM + puzzle_filesize); + + asm("lda 0"); + asm("sta 0"); } \ No newline at end of file diff --git a/src/puzzle.h b/src/puzzle.h index 86fa454..2fb59ac 100644 --- a/src/puzzle.h +++ b/src/puzzle.h @@ -201,4 +201,16 @@ void print_clock_border(uint8_t y, uint8_t x); */ void print_clock(const char* s, uint8_t y, uint8_t x); +/** + * @brief Load puzzles data into memory + * + */ +void load_puzzles(); + +/** + * @brief Save puzzles data to SD-card + * + */ +void save_puzzles(); + #endif // _PUZZLE_H \ No newline at end of file diff --git a/src/video.c b/src/video.c index c15ec55..65da75c 100644 --- a/src/video.c +++ b/src/video.c @@ -20,14 +20,6 @@ #include "video.h" -/** - * MEMORY MAP - * ========== - * 0x0000 - 0x6000 - Tileset for menu - * 0x6000 - 0x8000 - Tileset for game - * - */ - /** * @brief Initialize screen * @@ -83,8 +75,8 @@ void load_tiles(const char* filename, uint32_t addr) { * */ void clear_screen() { - fill_layer(TILE_BACKGROUND, LAYER0, PALETTEBYTE); - fill_layer(0x20, LAYER1, 0x00); + fill_layer(TILE_BACKGROUND, LAYER0, PALETTEBYTE, 64, 64); + fill_layer(0x20, LAYER1, 0x00, 64, 64); } /** @@ -92,8 +84,11 @@ void clear_screen() { * * @param tile_id background tile index * @param layer which layer to fill + * @param b2 which tile info to use + * @param height height of the map + * @param width width of the map */ -void fill_layer(uint8_t tile_id, uint8_t layer, uint8_t b2) { +void fill_layer(uint8_t tile_id, uint8_t layer, uint8_t b2, uint8_t height, uint8_t width) { uint8_t i,j; uint32_t map_base_addr; @@ -103,8 +98,8 @@ void fill_layer(uint8_t tile_id, uint8_t layer, uint8_t b2) { VERA.address_hi = map_base_addr >> 16; VERA.address_hi |= 0b10000; - for (j=0; j